Ignore:
Timestamp:
12/12/24 17:06:06 (5 weeks ago)
Author:
stefan toskovski <stefantoska84@…>
Branches:
main
Parents:
d565449
Message:

Pred finalna verzija

File:
1 edited

Legend:

Unmodified
Added
Removed
  • imaps-frontend/node_modules/@remix-run/router/dist/router.umd.js

    rd565449 r0c6b92a  
    11/**
    2  * @remix-run/router v1.19.0
     2 * @remix-run/router v1.21.0
    33 *
    44 * Copyright (c) Remix Software Inc.
     
    581581
    582582  /**
    583    * Result from a loader or action called via dataStrategy
    584    */
    585 
    586   /**
    587583   * Users can specify either lowercase or uppercase form methods on `<Form>`,
    588584   * useSubmit(), `<fetcher.Form>`, etc.
     
    648644   *
    649645   * @deprecated Use `mapRouteProperties` instead
     646   */
     647  /**
     648   * Result from a loader or action called via dataStrategy
    650649   */
    651650  /**
     
    748747   * Matches the given routes to a location and returns the match data.
    749748   *
    750    * @see https://reactrouter.com/utils/match-routes
     749   * @see https://reactrouter.com/v6/utils/match-routes
    751750   */
    752751  function matchRoutes(routes, locationArg, basename) {
     
    981980   * Returns a path with params interpolated.
    982981   *
    983    * @see https://reactrouter.com/utils/generate-path
     982   * @see https://reactrouter.com/v6/utils/generate-path
    984983   */
    985984  function generatePath(originalPath, params) {
     
    10331032   * the match.
    10341033   *
    1035    * @see https://reactrouter.com/utils/match-path
     1034   * @see https://reactrouter.com/v6/utils/match-path
    10361035   */
    10371036  function matchPath(pattern, pathname) {
     
    11481147   * Returns a resolved path object relative to the given pathname.
    11491148   *
    1150    * @see https://reactrouter.com/utils/resolve-path
     1149   * @see https://reactrouter.com/v6/utils/resolve-path
    11511150   */
    11521151  function resolvePath(to, fromPathname) {
     
    13141313   * This is a shortcut for creating `application/json` responses. Converts `data`
    13151314   * to JSON and sets the `Content-Type` header.
     1315   *
     1316   * @deprecated The `json` method is deprecated in favor of returning raw objects.
     1317   * This method will be removed in v7.
    13161318   */
    13171319  const json = function json(data, init) {
     
    14871489    return value._data;
    14881490  }
     1491  /**
     1492   * @deprecated The `defer` method is deprecated in favor of returning raw
     1493   * objects. This method will be removed in v7.
     1494   */
    14891495  const defer = function defer(data, init) {
    14901496    if (init === void 0) {
     
    17151721    let inFlightDataRoutes;
    17161722    let basename = init.basename || "/";
    1717     let dataStrategyImpl = init.unstable_dataStrategy || defaultDataStrategy;
    1718     let patchRoutesOnMissImpl = init.unstable_patchRoutesOnMiss;
     1723    let dataStrategyImpl = init.dataStrategy || defaultDataStrategy;
     1724    let patchRoutesOnNavigationImpl = init.patchRoutesOnNavigation;
    17191725
    17201726    // Config driven behavior flags
     
    17461752    let initialMatches = matchRoutes(dataRoutes, init.history.location, basename);
    17471753    let initialErrors = null;
    1748     if (initialMatches == null && !patchRoutesOnMissImpl) {
     1754    if (initialMatches == null && !patchRoutesOnNavigationImpl) {
    17491755      // If we do not match a user-provided-route, fall back to the root
    17501756      // to allow the error boundary to take over
     
    17621768    }
    17631769
    1764     // In SPA apps, if the user provided a patchRoutesOnMiss implementation and
     1770    // In SPA apps, if the user provided a patchRoutesOnNavigation implementation and
    17651771    // our initial match is a splat route, clear them out so we run through lazy
    17661772    // discovery on hydration in case there's a more accurate lazy route match.
     
    17801786
    17811787      // If partial hydration and fog of war is enabled, we will be running
    1782       // `patchRoutesOnMiss` during hydration so include any partial matches as
     1788      // `patchRoutesOnNavigation` during hydration so include any partial matches as
    17831789      // the initial matches so we can properly render `HydrateFallback`'s
    17841790      if (future.v7_partialHydration) {
     
    18011807      let loaderData = init.hydrationData ? init.hydrationData.loaderData : null;
    18021808      let errors = init.hydrationData ? init.hydrationData.errors : null;
    1803       let isRouteInitialized = m => {
    1804         // No loader, nothing to initialize
    1805         if (!m.route.loader) {
    1806           return true;
    1807         }
    1808         // Explicitly opting-in to running on hydration
    1809         if (typeof m.route.loader === "function" && m.route.loader.hydrate === true) {
    1810           return false;
    1811         }
    1812         // Otherwise, initialized if hydrated with data or an error
    1813         return loaderData && loaderData[m.route.id] !== undefined || errors && errors[m.route.id] !== undefined;
    1814       };
    1815 
    18161809      // If errors exist, don't consider routes below the boundary
    18171810      if (errors) {
    18181811        let idx = initialMatches.findIndex(m => errors[m.route.id] !== undefined);
    1819         initialized = initialMatches.slice(0, idx + 1).every(isRouteInitialized);
     1812        initialized = initialMatches.slice(0, idx + 1).every(m => !shouldLoadRouteOnHydration(m.route, loaderData, errors));
    18201813      } else {
    1821         initialized = initialMatches.every(isRouteInitialized);
     1814        initialized = initialMatches.every(m => !shouldLoadRouteOnHydration(m.route, loaderData, errors));
    18221815      }
    18231816    } else {
     
    19191912    let blockerFunctions = new Map();
    19201913
    1921     // Map of pending patchRoutesOnMiss() promises (keyed by path/matches) so
    1922     // that we only kick them off once for a given combo
    1923     let pendingPatchRoutes = new Map();
    1924 
    19251914    // Flag to ignore the next history update, so we can revert the URL change on
    19261915    // a POP navigation that was blocked by the user without touching router state
    1927     let ignoreNextHistoryUpdate = false;
     1916    let unblockBlockerHistoryUpdate = undefined;
    19281917
    19291918    // Initialize the router, all side effects should be kicked off from here.
     
    19411930        // Ignore this event if it was just us resetting the URL from a
    19421931        // blocked POP navigation
    1943         if (ignoreNextHistoryUpdate) {
    1944           ignoreNextHistoryUpdate = false;
     1932        if (unblockBlockerHistoryUpdate) {
     1933          unblockBlockerHistoryUpdate();
     1934          unblockBlockerHistoryUpdate = undefined;
    19451935          return;
    19461936        }
     
    19531943        if (blockerKey && delta != null) {
    19541944          // Restore the URL to match the current UI, but don't update router state
    1955           ignoreNextHistoryUpdate = true;
     1945          let nextHistoryUpdatePromise = new Promise(resolve => {
     1946            unblockBlockerHistoryUpdate = resolve;
     1947          });
    19561948          init.history.go(delta * -1);
    19571949
     
    19671959                location
    19681960              });
    1969               // Re-do the same POP navigation we just blocked
    1970               init.history.go(delta);
     1961              // Re-do the same POP navigation we just blocked, after the url
     1962              // restoration is also complete.  See:
     1963              // https://github.com/remix-run/react-router/issues/11613
     1964              nextHistoryUpdatePromise.then(() => init.history.go(delta));
    19711965            },
    19721966            reset() {
     
    20552049      [...subscribers].forEach(subscriber => subscriber(state, {
    20562050        deletedFetchers: deletedFetchersKeys,
    2057         unstable_viewTransitionOpts: opts.viewTransitionOpts,
    2058         unstable_flushSync: opts.flushSync === true
     2051        viewTransitionOpts: opts.viewTransitionOpts,
     2052        flushSync: opts.flushSync === true
    20592053      }));
    20602054
     
    22162210      }
    22172211      let preventScrollReset = opts && "preventScrollReset" in opts ? opts.preventScrollReset === true : undefined;
    2218       let flushSync = (opts && opts.unstable_flushSync) === true;
     2212      let flushSync = (opts && opts.flushSync) === true;
    22192213      let blockerKey = shouldBlockNavigation({
    22202214        currentLocation,
     
    22542248        preventScrollReset,
    22552249        replace: opts && opts.replace,
    2256         enableViewTransition: opts && opts.unstable_viewTransition,
     2250        enableViewTransition: opts && opts.viewTransition,
    22572251        flushSync
    22582252      });
     
    22882282      // revalidation so that history correctly updates once the navigation completes
    22892283      startNavigation(pendingAction || state.historyAction, state.navigation.location, {
    2290         overrideNavigation: state.navigation
     2284        overrideNavigation: state.navigation,
     2285        // Proxy through any rending view transition
     2286        enableViewTransition: pendingViewTransitionEnabled === true
    22912287      });
    22922288    }
     
    23402336      // mutation submission.
    23412337      //
    2342       // Ignore on initial page loads because since the initial load will always
     2338      // Ignore on initial page loads because since the initial hydration will always
    23432339      // be "same hash".  For example, on /page#hash and submit a <Form method="post">
    23442340      // which will default to a navigation to /page
     
    24472443          };
    24482444        } else if (discoverResult.type === "error") {
    2449           let {
    2450             boundaryId,
    2451             error
    2452           } = handleDiscoverRouteError(location.pathname, discoverResult);
     2445          let boundaryId = findNearestBoundary(discoverResult.partialMatches).route.id;
    24532446          return {
    24542447            matches: discoverResult.partialMatches,
    24552448            pendingActionResult: [boundaryId, {
    24562449              type: ResultType.error,
    2457               error
     2450              error: discoverResult.error
    24582451            }]
    24592452          };
     
    24892482        };
    24902483      } else {
    2491         let results = await callDataStrategy("action", request, [actionMatch], matches);
    2492         result = results[0];
     2484        let results = await callDataStrategy("action", state, request, [actionMatch], matches, null);
     2485        result = results[actionMatch.route.id];
    24932486        if (request.signal.aborted) {
    24942487          return {
     
    25082501          replace = location === state.location.pathname + state.location.search;
    25092502        }
    2510         await startRedirectNavigation(request, result, {
     2503        await startRedirectNavigation(request, result, true, {
    25112504          submission,
    25122505          replace
     
    25852578          };
    25862579        } else if (discoverResult.type === "error") {
    2587           let {
    2588             boundaryId,
    2589             error
    2590           } = handleDiscoverRouteError(location.pathname, discoverResult);
     2580          let boundaryId = findNearestBoundary(discoverResult.partialMatches).route.id;
    25912581          return {
    25922582            matches: discoverResult.partialMatches,
    25932583            loaderData: {},
    25942584            errors: {
    2595               [boundaryId]: error
     2585              [boundaryId]: discoverResult.error
    25962586            }
    25972587          };
     
    26592649      }
    26602650      revalidatingFetchers.forEach(rf => {
    2661         if (fetchControllers.has(rf.key)) {
    2662           abortFetcher(rf.key);
    2663         }
     2651        abortFetcher(rf.key);
    26642652        if (rf.controller) {
    26652653          // Fetchers use an independent AbortController so that aborting a fetcher
     
    26782666        loaderResults,
    26792667        fetcherResults
    2680       } = await callLoadersAndMaybeResolveData(state.matches, matches, matchesToLoad, revalidatingFetchers, request);
     2668      } = await callLoadersAndMaybeResolveData(state, matches, matchesToLoad, revalidatingFetchers, request);
    26812669      if (request.signal.aborted) {
    26822670        return {
     
    26942682
    26952683      // If any loaders returned a redirect Response, start a new REPLACE navigation
    2696       let redirect = findRedirect([...loaderResults, ...fetcherResults]);
     2684      let redirect = findRedirect(loaderResults);
    26972685      if (redirect) {
    2698         if (redirect.idx >= matchesToLoad.length) {
    2699           // If this redirect came from a fetcher make sure we mark it in
    2700           // fetchRedirectIds so it doesn't get revalidated on the next set of
    2701           // loader executions
    2702           let fetcherKey = revalidatingFetchers[redirect.idx - matchesToLoad.length].key;
    2703           fetchRedirectIds.add(fetcherKey);
    2704         }
    2705         await startRedirectNavigation(request, redirect.result, {
     2686        await startRedirectNavigation(request, redirect.result, true, {
    27062687          replace
    27072688        });
     
    27102691        };
    27112692      }
     2693      redirect = findRedirect(fetcherResults);
     2694      if (redirect) {
     2695        // If this redirect came from a fetcher make sure we mark it in
     2696        // fetchRedirectIds so it doesn't get revalidated on the next set of
     2697        // loader executions
     2698        fetchRedirectIds.add(redirect.key);
     2699        await startRedirectNavigation(request, redirect.result, true, {
     2700          replace
     2701        });
     2702        return {
     2703          shortCircuited: true
     2704        };
     2705      }
    27122706
    27132707      // Process and commit output from loaders
     
    27152709        loaderData,
    27162710        errors
    2717       } = processLoaderData(state, matches, matchesToLoad, loaderResults, pendingActionResult, revalidatingFetchers, fetcherResults, activeDeferreds);
     2711      } = processLoaderData(state, matches, loaderResults, pendingActionResult, revalidatingFetchers, fetcherResults, activeDeferreds);
    27182712
    27192713      // Wire up subscribers to update loaderData as promises settle
     
    27292723      });
    27302724
    2731       // During partial hydration, preserve SSR errors for routes that don't re-run
     2725      // Preserve SSR errors during partial hydration
    27322726      if (future.v7_partialHydration && initialHydration && state.errors) {
    2733         Object.entries(state.errors).filter(_ref2 => {
    2734           let [id] = _ref2;
    2735           return !matchesToLoad.some(m => m.route.id === id);
    2736         }).forEach(_ref3 => {
    2737           let [routeId, error] = _ref3;
    2738           errors = Object.assign(errors || {}, {
    2739             [routeId]: error
    2740           });
    2741         });
     2727        errors = _extends({}, state.errors, errors);
    27422728      }
    27432729      let updatedFetchers = markFetchRedirectsDone();
     
    27822768        throw new Error("router.fetch() was called during the server render, but it shouldn't be. " + "You are likely calling a useFetcher() method in the body of your component. " + "Try moving it to a useEffect or a callback.");
    27832769      }
    2784       if (fetchControllers.has(key)) abortFetcher(key);
    2785       let flushSync = (opts && opts.unstable_flushSync) === true;
     2770      abortFetcher(key);
     2771      let flushSync = (opts && opts.flushSync) === true;
    27862772      let routesToUse = inFlightDataRoutes || dataRoutes;
    27872773      let normalizedPath = normalizeTo(state.location, state.matches, basename, future.v7_prependBasename, href, future.v7_relativeSplatPath, routeId, opts == null ? void 0 : opts.relative);
     
    28112797      }
    28122798      let match = getTargetMatch(matches, path);
    2813       pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;
     2799      let preventScrollReset = (opts && opts.preventScrollReset) === true;
    28142800      if (submission && isMutationMethod(submission.formMethod)) {
    2815         handleFetcherAction(key, routeId, path, match, matches, fogOfWar.active, flushSync, submission);
     2801        handleFetcherAction(key, routeId, path, match, matches, fogOfWar.active, flushSync, preventScrollReset, submission);
    28162802        return;
    28172803      }
     
    28232809        path
    28242810      });
    2825       handleFetcherLoader(key, routeId, path, match, matches, fogOfWar.active, flushSync, submission);
     2811      handleFetcherLoader(key, routeId, path, match, matches, fogOfWar.active, flushSync, preventScrollReset, submission);
    28262812    }
    28272813
    28282814    // Call the action for the matched fetcher.submit(), and then handle redirects,
    28292815    // errors, and revalidation
    2830     async function handleFetcherAction(key, routeId, path, match, requestMatches, isFogOfWar, flushSync, submission) {
     2816    async function handleFetcherAction(key, routeId, path, match, requestMatches, isFogOfWar, flushSync, preventScrollReset, submission) {
    28312817      interruptActiveLoads();
    28322818      fetchLoadMatches.delete(key);
     
    28612847          return;
    28622848        } else if (discoverResult.type === "error") {
    2863           let {
    2864             error
    2865           } = handleDiscoverRouteError(path, discoverResult);
    2866           setFetcherError(key, routeId, error, {
     2849          setFetcherError(key, routeId, discoverResult.error, {
    28672850            flushSync
    28682851          });
     
    28872870      fetchControllers.set(key, abortController);
    28882871      let originatingLoadId = incrementingLoadId;
    2889       let actionResults = await callDataStrategy("action", fetchRequest, [match], requestMatches);
    2890       let actionResult = actionResults[0];
     2872      let actionResults = await callDataStrategy("action", state, fetchRequest, [match], requestMatches, key);
     2873      let actionResult = actionResults[match.route.id];
    28912874      if (fetchRequest.signal.aborted) {
    28922875        // We can delete this so long as we weren't aborted by our own fetcher
     
    29202903            fetchRedirectIds.add(key);
    29212904            updateFetcherState(key, getLoadingFetcher(submission));
    2922             return startRedirectNavigation(fetchRequest, actionResult, {
    2923               fetcherSubmission: submission
     2905            return startRedirectNavigation(fetchRequest, actionResult, false, {
     2906              fetcherSubmission: submission,
     2907              preventScrollReset
    29242908            });
    29252909          }
     
    29592943        let revalidatingFetcher = getLoadingFetcher(undefined, existingFetcher ? existingFetcher.data : undefined);
    29602944        state.fetchers.set(staleKey, revalidatingFetcher);
    2961         if (fetchControllers.has(staleKey)) {
    2962           abortFetcher(staleKey);
    2963         }
     2945        abortFetcher(staleKey);
    29642946        if (rf.controller) {
    29652947          fetchControllers.set(staleKey, rf.controller);
     
    29742956        loaderResults,
    29752957        fetcherResults
    2976       } = await callLoadersAndMaybeResolveData(state.matches, matches, matchesToLoad, revalidatingFetchers, revalidationRequest);
     2958      } = await callLoadersAndMaybeResolveData(state, matches, matchesToLoad, revalidatingFetchers, revalidationRequest);
    29772959      if (abortController.signal.aborted) {
    29782960        return;
     
    29822964      fetchControllers.delete(key);
    29832965      revalidatingFetchers.forEach(r => fetchControllers.delete(r.key));
    2984       let redirect = findRedirect([...loaderResults, ...fetcherResults]);
     2966      let redirect = findRedirect(loaderResults);
    29852967      if (redirect) {
    2986         if (redirect.idx >= matchesToLoad.length) {
    2987           // If this redirect came from a fetcher make sure we mark it in
    2988           // fetchRedirectIds so it doesn't get revalidated on the next set of
    2989           // loader executions
    2990           let fetcherKey = revalidatingFetchers[redirect.idx - matchesToLoad.length].key;
    2991           fetchRedirectIds.add(fetcherKey);
    2992         }
    2993         return startRedirectNavigation(revalidationRequest, redirect.result);
     2968        return startRedirectNavigation(revalidationRequest, redirect.result, false, {
     2969          preventScrollReset
     2970        });
     2971      }
     2972      redirect = findRedirect(fetcherResults);
     2973      if (redirect) {
     2974        // If this redirect came from a fetcher make sure we mark it in
     2975        // fetchRedirectIds so it doesn't get revalidated on the next set of
     2976        // loader executions
     2977        fetchRedirectIds.add(redirect.key);
     2978        return startRedirectNavigation(revalidationRequest, redirect.result, false, {
     2979          preventScrollReset
     2980        });
    29942981      }
    29952982
     
    29982985        loaderData,
    29992986        errors
    3000       } = processLoaderData(state, state.matches, matchesToLoad, loaderResults, undefined, revalidatingFetchers, fetcherResults, activeDeferreds);
     2987      } = processLoaderData(state, matches, loaderResults, undefined, revalidatingFetchers, fetcherResults, activeDeferreds);
    30012988
    30022989      // Since we let revalidations complete even if the submitting fetcher was
     
    30343021
    30353022    // Call the matched loader for fetcher.load(), handling redirects, errors, etc.
    3036     async function handleFetcherLoader(key, routeId, path, match, matches, isFogOfWar, flushSync, submission) {
     3023    async function handleFetcherLoader(key, routeId, path, match, matches, isFogOfWar, flushSync, preventScrollReset, submission) {
    30373024      let existingFetcher = state.fetchers.get(key);
    30383025      updateFetcherState(key, getLoadingFetcher(submission, existingFetcher ? existingFetcher.data : undefined), {
     
    30463033          return;
    30473034        } else if (discoverResult.type === "error") {
    3048           let {
    3049             error
    3050           } = handleDiscoverRouteError(path, discoverResult);
    3051           setFetcherError(key, routeId, error, {
     3035          setFetcherError(key, routeId, discoverResult.error, {
    30523036            flushSync
    30533037          });
     
    30693053      fetchControllers.set(key, abortController);
    30703054      let originatingLoadId = incrementingLoadId;
    3071       let results = await callDataStrategy("loader", fetchRequest, [match], matches);
    3072       let result = results[0];
     3055      let results = await callDataStrategy("loader", state, fetchRequest, [match], matches, key);
     3056      let result = results[match.route.id];
    30733057
    30743058      // Deferred isn't supported for fetcher loads, await everything and treat it
     
    31053089        } else {
    31063090          fetchRedirectIds.add(key);
    3107           await startRedirectNavigation(fetchRequest, result);
     3091          await startRedirectNavigation(fetchRequest, result, false, {
     3092            preventScrollReset
     3093          });
    31083094          return;
    31093095        }
     
    31403126     * the history action from the original navigation (PUSH or REPLACE).
    31413127     */
    3142     async function startRedirectNavigation(request, redirect, _temp2) {
     3128    async function startRedirectNavigation(request, redirect, isNavigation, _temp2) {
    31433129      let {
    31443130        submission,
    31453131        fetcherSubmission,
     3132        preventScrollReset,
    31463133        replace
    31473134      } = _temp2 === void 0 ? {} : _temp2;
     
    32033190            formAction: location
    32043191          }),
    3205           // Preserve this flag across redirects
    3206           preventScrollReset: pendingPreventScrollReset
     3192          // Preserve these flags across redirects
     3193          preventScrollReset: preventScrollReset || pendingPreventScrollReset,
     3194          enableViewTransition: isNavigation ? pendingViewTransitionEnabled : undefined
    32073195        });
    32083196      } else {
     
    32143202          // Send fetcher submissions through for shouldRevalidate
    32153203          fetcherSubmission,
    3216           // Preserve this flag across redirects
    3217           preventScrollReset: pendingPreventScrollReset
     3204          // Preserve these flags across redirects
     3205          preventScrollReset: preventScrollReset || pendingPreventScrollReset,
     3206          enableViewTransition: isNavigation ? pendingViewTransitionEnabled : undefined
    32183207        });
    32193208      }
     
    32223211    // Utility wrapper for calling dataStrategy client-side without having to
    32233212    // pass around the manifest, mapRouteProperties, etc.
    3224     async function callDataStrategy(type, request, matchesToLoad, matches) {
     3213    async function callDataStrategy(type, state, request, matchesToLoad, matches, fetcherKey) {
     3214      let results;
     3215      let dataResults = {};
    32253216      try {
    3226         let results = await callDataStrategyImpl(dataStrategyImpl, type, request, matchesToLoad, matches, manifest, mapRouteProperties);
    3227         return await Promise.all(results.map((result, i) => {
    3228           if (isRedirectHandlerResult(result)) {
    3229             let response = result.result;
    3230             return {
    3231               type: ResultType.redirect,
    3232               response: normalizeRelativeRoutingRedirectResponse(response, request, matchesToLoad[i].route.id, matches, basename, future.v7_relativeSplatPath)
    3233             };
    3234           }
    3235           return convertHandlerResultToDataResult(result);
    3236         }));
     3217        results = await callDataStrategyImpl(dataStrategyImpl, type, state, request, matchesToLoad, matches, fetcherKey, manifest, mapRouteProperties);
    32373218      } catch (e) {
    32383219        // If the outer dataStrategy method throws, just return the error for all
    32393220        // matches - and it'll naturally bubble to the root
    3240         return matchesToLoad.map(() => ({
    3241           type: ResultType.error,
    3242           error: e
    3243         }));
    3244       }
    3245     }
    3246     async function callLoadersAndMaybeResolveData(currentMatches, matches, matchesToLoad, fetchersToLoad, request) {
    3247       let [loaderResults, ...fetcherResults] = await Promise.all([matchesToLoad.length ? callDataStrategy("loader", request, matchesToLoad, matches) : [], ...fetchersToLoad.map(f => {
     3221        matchesToLoad.forEach(m => {
     3222          dataResults[m.route.id] = {
     3223            type: ResultType.error,
     3224            error: e
     3225          };
     3226        });
     3227        return dataResults;
     3228      }
     3229      for (let [routeId, result] of Object.entries(results)) {
     3230        if (isRedirectDataStrategyResultResult(result)) {
     3231          let response = result.result;
     3232          dataResults[routeId] = {
     3233            type: ResultType.redirect,
     3234            response: normalizeRelativeRoutingRedirectResponse(response, request, routeId, matches, basename, future.v7_relativeSplatPath)
     3235          };
     3236        } else {
     3237          dataResults[routeId] = await convertDataStrategyResultToDataResult(result);
     3238        }
     3239      }
     3240      return dataResults;
     3241    }
     3242    async function callLoadersAndMaybeResolveData(state, matches, matchesToLoad, fetchersToLoad, request) {
     3243      let currentMatches = state.matches;
     3244
     3245      // Kick off loaders and fetchers in parallel
     3246      let loaderResultsPromise = callDataStrategy("loader", state, request, matchesToLoad, matches, null);
     3247      let fetcherResultsPromise = Promise.all(fetchersToLoad.map(async f => {
    32483248        if (f.matches && f.match && f.controller) {
    3249           let fetcherRequest = createClientSideRequest(init.history, f.path, f.controller.signal);
    3250           return callDataStrategy("loader", fetcherRequest, [f.match], f.matches).then(r => r[0]);
     3249          let results = await callDataStrategy("loader", state, createClientSideRequest(init.history, f.path, f.controller.signal), [f.match], f.matches, f.key);
     3250          let result = results[f.match.route.id];
     3251          // Fetcher results are keyed by fetcher key from here on out, not routeId
     3252          return {
     3253            [f.key]: result
     3254          };
    32513255        } else {
    32523256          return Promise.resolve({
    3253             type: ResultType.error,
    3254             error: getInternalRouterError(404, {
    3255               pathname: f.path
    3256             })
     3257            [f.key]: {
     3258              type: ResultType.error,
     3259              error: getInternalRouterError(404, {
     3260                pathname: f.path
     3261              })
     3262            }
    32573263          });
    32583264        }
    3259       })]);
    3260       await Promise.all([resolveDeferredResults(currentMatches, matchesToLoad, loaderResults, loaderResults.map(() => request.signal), false, state.loaderData), resolveDeferredResults(currentMatches, fetchersToLoad.map(f => f.match), fetcherResults, fetchersToLoad.map(f => f.controller ? f.controller.signal : null), true)]);
     3265      }));
     3266      let loaderResults = await loaderResultsPromise;
     3267      let fetcherResults = (await fetcherResultsPromise).reduce((acc, r) => Object.assign(acc, r), {});
     3268      await Promise.all([resolveNavigationDeferredResults(matches, loaderResults, request.signal, currentMatches, state.loaderData), resolveFetcherDeferredResults(matches, fetcherResults, fetchersToLoad)]);
    32613269      return {
    32623270        loaderResults,
     
    32763284        if (fetchControllers.has(key)) {
    32773285          cancelledFetcherLoads.add(key);
    3278           abortFetcher(key);
    3279         }
     3286        }
     3287        abortFetcher(key);
    32803288      });
    32813289    }
     
    33503358    function abortFetcher(key) {
    33513359      let controller = fetchControllers.get(key);
    3352       invariant(controller, "Expected fetch controller: " + key);
    3353       controller.abort();
    3354       fetchControllers.delete(key);
     3360      if (controller) {
     3361        controller.abort();
     3362        fetchControllers.delete(key);
     3363      }
    33553364    }
    33563365    function markFetchersDone(keys) {
     
    34173426      });
    34183427    }
    3419     function shouldBlockNavigation(_ref4) {
     3428    function shouldBlockNavigation(_ref2) {
    34203429      let {
    34213430        currentLocation,
    34223431        nextLocation,
    34233432        historyAction
    3424       } = _ref4;
     3433      } = _ref2;
    34253434      if (blockerFunctions.size === 0) {
    34263435        return;
     
    34673476        route,
    34683477        error
    3469       };
    3470     }
    3471     function handleDiscoverRouteError(pathname, discoverResult) {
    3472       return {
    3473         boundaryId: findNearestBoundary(discoverResult.partialMatches).route.id,
    3474         error: getInternalRouterError(400, {
    3475           type: "route-discovery",
    3476           pathname,
    3477           message: discoverResult.error != null && "message" in discoverResult.error ? discoverResult.error : String(discoverResult.error)
    3478         })
    34793478      };
    34803479    }
     
    35433542    }
    35443543    function checkFogOfWar(matches, routesToUse, pathname) {
    3545       if (patchRoutesOnMissImpl) {
     3544      if (patchRoutesOnNavigationImpl) {
    35463545        if (!matches) {
    35473546          let fogMatches = matchRoutesImpl(routesToUse, pathname, basename, true);
     
    35513550          };
    35523551        } else {
    3553           let leafRoute = matches[matches.length - 1].route;
    3554           if (leafRoute.path && (leafRoute.path === "*" || leafRoute.path.endsWith("/*"))) {
    3555             // If we matched a splat, it might only be because we haven't yet fetched
    3556             // the children that would match with a higher score, so let's fetch
    3557             // around and find out
     3552          if (Object.keys(matches[0].params).length > 0) {
     3553            // If we matched a dynamic param or a splat, it might only be because
     3554            // we haven't yet discovered other routes that would match with a
     3555            // higher score.  Call patchRoutesOnNavigation just to be sure
    35583556            let partialMatches = matchRoutesImpl(routesToUse, pathname, basename, true);
    35593557            return {
     
    35703568    }
    35713569    async function discoverRoutes(matches, pathname, signal) {
     3570      if (!patchRoutesOnNavigationImpl) {
     3571        return {
     3572          type: "success",
     3573          matches
     3574        };
     3575      }
    35723576      let partialMatches = matches;
    3573       let route = partialMatches.length > 0 ? partialMatches[partialMatches.length - 1].route : null;
    35743577      while (true) {
    35753578        let isNonHMR = inFlightDataRoutes == null;
    35763579        let routesToUse = inFlightDataRoutes || dataRoutes;
     3580        let localManifest = manifest;
    35773581        try {
    3578           await loadLazyRouteChildren(patchRoutesOnMissImpl, pathname, partialMatches, routesToUse, manifest, mapRouteProperties, pendingPatchRoutes, signal);
     3582          await patchRoutesOnNavigationImpl({
     3583            path: pathname,
     3584            matches: partialMatches,
     3585            patch: (routeId, children) => {
     3586              if (signal.aborted) return;
     3587              patchRoutesImpl(routeId, children, routesToUse, localManifest, mapRouteProperties);
     3588            }
     3589          });
    35793590        } catch (e) {
    35803591          return {
     
    35903601          // HMR will already update the identity and reflow when it lands
    35913602          // `inFlightDataRoutes` in `completeNavigation`
    3592           if (isNonHMR) {
     3603          if (isNonHMR && !signal.aborted) {
    35933604            dataRoutes = [...dataRoutes];
    35943605          }
     
    36003611        }
    36013612        let newMatches = matchRoutes(routesToUse, pathname, basename);
    3602         let matchedSplat = false;
    36033613        if (newMatches) {
    3604           let leafRoute = newMatches[newMatches.length - 1].route;
    3605           if (leafRoute.index) {
    3606             // If we found an index route, we can stop
    3607             return {
    3608               type: "success",
    3609               matches: newMatches
    3610             };
    3611           }
    3612           if (leafRoute.path && leafRoute.path.length > 0) {
    3613             if (leafRoute.path === "*") {
    3614               // If we found a splat route, we can't be sure there's not a
    3615               // higher-scoring route down some partial matches trail so we need
    3616               // to check that out
    3617               matchedSplat = true;
    3618             } else {
    3619               // If we found a non-splat route, we can stop
    3620               return {
    3621                 type: "success",
    3622                 matches: newMatches
    3623               };
    3624             }
    3625           }
    3626         }
    3627         let newPartialMatches = matchRoutesImpl(routesToUse, pathname, basename, true);
    3628 
    3629         // If we are no longer partially matching anything, this was either a
    3630         // legit splat match above, or it's a 404.  Also avoid loops if the
    3631         // second pass results in the same partial matches
    3632         if (!newPartialMatches || partialMatches.map(m => m.route.id).join("-") === newPartialMatches.map(m => m.route.id).join("-")) {
    36333614          return {
    36343615            type: "success",
    3635             matches: matchedSplat ? newMatches : null
     3616            matches: newMatches
    36363617          };
    36373618        }
    3638         partialMatches = newPartialMatches;
    3639         route = partialMatches[partialMatches.length - 1].route;
    3640         if (route.path === "*") {
    3641           // The splat is still our most accurate partial, so run with it
     3619        let newPartialMatches = matchRoutesImpl(routesToUse, pathname, basename, true);
     3620
     3621        // Avoid loops if the second pass results in the same partial matches
     3622        if (!newPartialMatches || partialMatches.length === newPartialMatches.length && partialMatches.every((m, i) => m.route.id === newPartialMatches[i].route.id)) {
    36423623          return {
    36433624            type: "success",
    3644             matches: partialMatches
     3625            matches: null
    36453626          };
    36463627        }
     3628        partialMatches = newPartialMatches;
    36473629      }
    36483630    }
     
    37713753        requestContext,
    37723754        skipLoaderErrorBubbling,
    3773         unstable_dataStrategy
     3755        dataStrategy
    37743756      } = _temp3 === void 0 ? {} : _temp3;
    37753757      let url = new URL(request.url);
     
    38243806        };
    38253807      }
    3826       let result = await queryImpl(request, location, matches, requestContext, unstable_dataStrategy || null, skipLoaderErrorBubbling === true, null);
     3808      let result = await queryImpl(request, location, matches, requestContext, dataStrategy || null, skipLoaderErrorBubbling === true, null);
    38273809      if (isResponse(result)) {
    38283810        return result;
     
    38683850        routeId,
    38693851        requestContext,
    3870         unstable_dataStrategy
     3852        dataStrategy
    38713853      } = _temp4 === void 0 ? {} : _temp4;
    38723854      let url = new URL(request.url);
     
    38973879        });
    38983880      }
    3899       let result = await queryImpl(request, location, matches, requestContext, unstable_dataStrategy || null, false, match);
     3881      let result = await queryImpl(request, location, matches, requestContext, dataStrategy || null, false, match);
    39003882      if (isResponse(result)) {
    39013883        return result;
     
    39243906      return undefined;
    39253907    }
    3926     async function queryImpl(request, location, matches, requestContext, unstable_dataStrategy, skipLoaderErrorBubbling, routeMatch) {
     3908    async function queryImpl(request, location, matches, requestContext, dataStrategy, skipLoaderErrorBubbling, routeMatch) {
    39273909      invariant(request.signal, "query()/queryRoute() requests must contain an AbortController signal");
    39283910      try {
    39293911        if (isMutationMethod(request.method.toLowerCase())) {
    3930           let result = await submit(request, matches, routeMatch || getTargetMatch(matches, location), requestContext, unstable_dataStrategy, skipLoaderErrorBubbling, routeMatch != null);
     3912          let result = await submit(request, matches, routeMatch || getTargetMatch(matches, location), requestContext, dataStrategy, skipLoaderErrorBubbling, routeMatch != null);
    39313913          return result;
    39323914        }
    3933         let result = await loadRouteData(request, matches, requestContext, unstable_dataStrategy, skipLoaderErrorBubbling, routeMatch);
     3915        let result = await loadRouteData(request, matches, requestContext, dataStrategy, skipLoaderErrorBubbling, routeMatch);
    39343916        return isResponse(result) ? result : _extends({}, result, {
    39353917          actionData: null,
     
    39383920      } catch (e) {
    39393921        // If the user threw/returned a Response in callLoaderOrAction for a
    3940         // `queryRoute` call, we throw the `HandlerResult` to bail out early
     3922        // `queryRoute` call, we throw the `DataStrategyResult` to bail out early
    39413923        // and then return or throw the raw Response here accordingly
    3942         if (isHandlerResult(e) && isResponse(e.result)) {
     3924        if (isDataStrategyResult(e) && isResponse(e.result)) {
    39433925          if (e.type === ResultType.error) {
    39443926            throw e.result;
     
    39543936      }
    39553937    }
    3956     async function submit(request, matches, actionMatch, requestContext, unstable_dataStrategy, skipLoaderErrorBubbling, isRouteRequest) {
     3938    async function submit(request, matches, actionMatch, requestContext, dataStrategy, skipLoaderErrorBubbling, isRouteRequest) {
    39573939      let result;
    39583940      if (!actionMatch.route.action && !actionMatch.route.lazy) {
     
    39703952        };
    39713953      } else {
    3972         let results = await callDataStrategy("action", request, [actionMatch], matches, isRouteRequest, requestContext, unstable_dataStrategy);
    3973         result = results[0];
     3954        let results = await callDataStrategy("action", request, [actionMatch], matches, isRouteRequest, requestContext, dataStrategy);
     3955        result = results[actionMatch.route.id];
    39743956        if (request.signal.aborted) {
    39753957          throwStaticHandlerAbortedError(request, isRouteRequest, future);
     
    40324014        // to call and will commit it when we complete the navigation
    40334015        let boundaryMatch = skipLoaderErrorBubbling ? actionMatch : findNearestBoundary(matches, actionMatch.route.id);
    4034         let context = await loadRouteData(loaderRequest, matches, requestContext, unstable_dataStrategy, skipLoaderErrorBubbling, null, [boundaryMatch.route.id, result]);
     4016        let context = await loadRouteData(loaderRequest, matches, requestContext, dataStrategy, skipLoaderErrorBubbling, null, [boundaryMatch.route.id, result]);
    40354017
    40364018        // action status codes take precedence over loader status codes
     
    40434025        });
    40444026      }
    4045       let context = await loadRouteData(loaderRequest, matches, requestContext, unstable_dataStrategy, skipLoaderErrorBubbling, null);
     4027      let context = await loadRouteData(loaderRequest, matches, requestContext, dataStrategy, skipLoaderErrorBubbling, null);
    40464028      return _extends({}, context, {
    40474029        actionData: {
     
    40564038      });
    40574039    }
    4058     async function loadRouteData(request, matches, requestContext, unstable_dataStrategy, skipLoaderErrorBubbling, routeMatch, pendingActionResult) {
     4040    async function loadRouteData(request, matches, requestContext, dataStrategy, skipLoaderErrorBubbling, routeMatch, pendingActionResult) {
    40594041      let isRouteRequest = routeMatch != null;
    40604042
     
    40864068        };
    40874069      }
    4088       let results = await callDataStrategy("loader", request, matchesToLoad, matches, isRouteRequest, requestContext, unstable_dataStrategy);
     4070      let results = await callDataStrategy("loader", request, matchesToLoad, matches, isRouteRequest, requestContext, dataStrategy);
    40894071      if (request.signal.aborted) {
    40904072        throwStaticHandlerAbortedError(request, isRouteRequest, future);
     
    40934075      // Process and commit output from loaders
    40944076      let activeDeferreds = new Map();
    4095       let context = processRouteLoaderData(matches, matchesToLoad, results, pendingActionResult, activeDeferreds, skipLoaderErrorBubbling);
     4077      let context = processRouteLoaderData(matches, results, pendingActionResult, activeDeferreds, skipLoaderErrorBubbling);
    40964078
    40974079      // Add a null for any non-loader matches for proper revalidation on the client
     
    41104092    // Utility wrapper for calling dataStrategy server-side without having to
    41114093    // pass around the manifest, mapRouteProperties, etc.
    4112     async function callDataStrategy(type, request, matchesToLoad, matches, isRouteRequest, requestContext, unstable_dataStrategy) {
    4113       let results = await callDataStrategyImpl(unstable_dataStrategy || defaultDataStrategy, type, request, matchesToLoad, matches, manifest, mapRouteProperties, requestContext);
    4114       return await Promise.all(results.map((result, i) => {
    4115         if (isRedirectHandlerResult(result)) {
     4094    async function callDataStrategy(type, request, matchesToLoad, matches, isRouteRequest, requestContext, dataStrategy) {
     4095      let results = await callDataStrategyImpl(dataStrategy || defaultDataStrategy, type, null, request, matchesToLoad, matches, null, manifest, mapRouteProperties, requestContext);
     4096      let dataResults = {};
     4097      await Promise.all(matches.map(async match => {
     4098        if (!(match.route.id in results)) {
     4099          return;
     4100        }
     4101        let result = results[match.route.id];
     4102        if (isRedirectDataStrategyResultResult(result)) {
    41164103          let response = result.result;
    41174104          // Throw redirects and let the server handle them with an HTTP redirect
    4118           throw normalizeRelativeRoutingRedirectResponse(response, request, matchesToLoad[i].route.id, matches, basename, future.v7_relativeSplatPath);
     4105          throw normalizeRelativeRoutingRedirectResponse(response, request, match.route.id, matches, basename, future.v7_relativeSplatPath);
    41194106        }
    41204107        if (isResponse(result.result) && isRouteRequest) {
     
    41234110          throw result;
    41244111        }
    4125         return convertHandlerResultToDataResult(result);
     4112        dataResults[match.route.id] = await convertDataStrategyResultToDataResult(result);
    41264113      }));
     4114      return dataResults;
    41274115    }
    41284116    return {
     
    41924180    }
    41934181
    4194     // Add an ?index param for matched index routes if we don't already have one
    4195     if ((to == null || to === "" || to === ".") && activeRouteMatch && activeRouteMatch.route.index && !hasNakedIndexQuery(path.search)) {
    4196       path.search = path.search ? path.search.replace(/^\?/, "?index&") : "?index";
     4182    // Account for `?index` params when routing to the current location
     4183    if ((to == null || to === "" || to === ".") && activeRouteMatch) {
     4184      let nakedIndex = hasNakedIndexQuery(path.search);
     4185      if (activeRouteMatch.route.index && !nakedIndex) {
     4186        // Add one when we're targeting an index route
     4187        path.search = path.search ? path.search.replace(/^\?/, "?index&") : "?index";
     4188      } else if (!activeRouteMatch.route.index && nakedIndex) {
     4189        // Remove existing ones when we're not
     4190        let params = new URLSearchParams(path.search);
     4191        let indexValues = params.getAll("index");
     4192        params.delete("index");
     4193        indexValues.filter(v => v).forEach(v => params.append("index", v));
     4194        let qs = params.toString();
     4195        path.search = qs ? "?" + qs : "";
     4196      }
    41974197    }
    41984198
     
    42434243        let text = typeof opts.body === "string" ? opts.body : opts.body instanceof FormData || opts.body instanceof URLSearchParams ?
    42444244        // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#plain-text-form-data
    4245         Array.from(opts.body.entries()).reduce((acc, _ref5) => {
    4246           let [name, value] = _ref5;
     4245        Array.from(opts.body.entries()).reduce((acc, _ref3) => {
     4246          let [name, value] = _ref3;
    42474247          return "" + acc + name + "=" + value + "\n";
    42484248        }, "") : String(opts.body);
     
    43344334  }
    43354335
    4336   // Filter out all routes below any caught error as they aren't going to
     4336  // Filter out all routes at/below any caught error as they aren't going to
    43374337  // render so we don't need to load them
    4338   function getLoaderMatchesUntilBoundary(matches, boundaryId) {
    4339     let boundaryMatches = matches;
    4340     if (boundaryId) {
    4341       let index = matches.findIndex(m => m.route.id === boundaryId);
    4342       if (index >= 0) {
    4343         boundaryMatches = matches.slice(0, index);
    4344       }
    4345     }
    4346     return boundaryMatches;
    4347   }
    4348   function getMatchesToLoad(history, state, matches, submission, location, isInitialLoad, skipActionErrorRevalidation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, pendingActionResult) {
     4338  function getLoaderMatchesUntilBoundary(matches, boundaryId, includeBoundary) {
     4339    if (includeBoundary === void 0) {
     4340      includeBoundary = false;
     4341    }
     4342    let index = matches.findIndex(m => m.route.id === boundaryId);
     4343    if (index >= 0) {
     4344      return matches.slice(0, includeBoundary ? index + 1 : index);
     4345    }
     4346    return matches;
     4347  }
     4348  function getMatchesToLoad(history, state, matches, submission, location, initialHydration, skipActionErrorRevalidation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, pendingActionResult) {
    43494349    let actionResult = pendingActionResult ? isErrorResult(pendingActionResult[1]) ? pendingActionResult[1].error : pendingActionResult[1].data : undefined;
    43504350    let currentUrl = history.createURL(state.location);
     
    43524352
    43534353    // Pick navigation matches that are net-new or qualify for revalidation
    4354     let boundaryId = pendingActionResult && isErrorResult(pendingActionResult[1]) ? pendingActionResult[0] : undefined;
    4355     let boundaryMatches = boundaryId ? getLoaderMatchesUntilBoundary(matches, boundaryId) : matches;
     4354    let boundaryMatches = matches;
     4355    if (initialHydration && state.errors) {
     4356      // On initial hydration, only consider matches up to _and including_ the boundary.
     4357      // This is inclusive to handle cases where a server loader ran successfully,
     4358      // a child server loader bubbled up to this route, but this route has
     4359      // `clientLoader.hydrate` so we want to still run the `clientLoader` so that
     4360      // we have a complete version of `loaderData`
     4361      boundaryMatches = getLoaderMatchesUntilBoundary(matches, Object.keys(state.errors)[0], true);
     4362    } else if (pendingActionResult && isErrorResult(pendingActionResult[1])) {
     4363      // If an action threw an error, we call loaders up to, but not including the
     4364      // boundary
     4365      boundaryMatches = getLoaderMatchesUntilBoundary(matches, pendingActionResult[0]);
     4366    }
    43564367
    43574368    // Don't revalidate loaders by default after action 4xx/5xx responses
     
    43714382        return false;
    43724383      }
    4373       if (isInitialLoad) {
    4374         if (typeof route.loader !== "function" || route.loader.hydrate) {
    4375           return true;
    4376         }
    4377         return state.loaderData[route.id] === undefined && (
    4378         // Don't re-run if the loader ran and threw an error
    4379         !state.errors || state.errors[route.id] === undefined);
     4384      if (initialHydration) {
     4385        return shouldLoadRouteOnHydration(route, state.loaderData, state.errors);
    43804386      }
    43814387
     
    44114417    fetchLoadMatches.forEach((f, key) => {
    44124418      // Don't revalidate:
    4413       //  - on initial load (shouldn't be any fetchers then anyway)
     4419      //  - on initial hydration (shouldn't be any fetchers then anyway)
    44144420      //  - if fetcher won't be present in the subsequent render
    44154421      //    - no longer matches the URL (v7_fetcherPersist=false)
    44164422      //    - was unmounted but persisted due to v7_fetcherPersist=true
    4417       if (isInitialLoad || !matches.some(m => m.route.id === f.routeId) || deletedFetchers.has(key)) {
     4423      if (initialHydration || !matches.some(m => m.route.id === f.routeId) || deletedFetchers.has(key)) {
    44184424        return;
    44194425      }
     
    44814487    return [navigationMatches, revalidatingFetchers];
    44824488  }
     4489  function shouldLoadRouteOnHydration(route, loaderData, errors) {
     4490    // We dunno if we have a loader - gotta find out!
     4491    if (route.lazy) {
     4492      return true;
     4493    }
     4494
     4495    // No loader, nothing to initialize
     4496    if (!route.loader) {
     4497      return false;
     4498    }
     4499    let hasData = loaderData != null && loaderData[route.id] !== undefined;
     4500    let hasError = errors != null && errors[route.id] !== undefined;
     4501
     4502    // Don't run if we error'd during SSR
     4503    if (!hasData && hasError) {
     4504      return false;
     4505    }
     4506
     4507    // Explicitly opting-in to running on hydration
     4508    if (typeof route.loader === "function" && route.loader.hydrate === true) {
     4509      return true;
     4510    }
     4511
     4512    // Otherwise, run if we're not yet initialized with anything
     4513    return !hasData && !hasError;
     4514  }
    44834515  function isNewLoader(currentLoaderData, currentMatch, match) {
    44844516    let isNew =
     
    45144546    return arg.defaultShouldRevalidate;
    45154547  }
    4516 
    4517   /**
    4518    * Idempotent utility to execute patchRoutesOnMiss() to lazily load route
    4519    * definitions and update the routes/routeManifest
    4520    */
    4521   async function loadLazyRouteChildren(patchRoutesOnMissImpl, path, matches, routes, manifest, mapRouteProperties, pendingRouteChildren, signal) {
    4522     let key = [path, ...matches.map(m => m.route.id)].join("-");
    4523     try {
    4524       let pending = pendingRouteChildren.get(key);
    4525       if (!pending) {
    4526         pending = patchRoutesOnMissImpl({
    4527           path,
    4528           matches,
    4529           patch: (routeId, children) => {
    4530             if (!signal.aborted) {
    4531               patchRoutesImpl(routeId, children, routes, manifest, mapRouteProperties);
    4532             }
    4533           }
    4534         });
    4535         pendingRouteChildren.set(key, pending);
    4536       }
    4537       if (pending && isPromise(pending)) {
    4538         await pending;
    4539       }
    4540     } finally {
    4541       pendingRouteChildren.delete(key);
    4542     }
    4543   }
    45444548  function patchRoutesImpl(routeId, children, routesToUse, manifest, mapRouteProperties) {
     4549    var _childrenToPatch;
     4550    let childrenToPatch;
    45454551    if (routeId) {
    4546       var _route$children;
    45474552      let route = manifest[routeId];
    45484553      invariant(route, "No route found to patch children into: routeId = " + routeId);
    4549       let dataChildren = convertRoutesToDataRoutes(children, mapRouteProperties, [routeId, "patch", String(((_route$children = route.children) == null ? void 0 : _route$children.length) || "0")], manifest);
    4550       if (route.children) {
    4551         route.children.push(...dataChildren);
    4552       } else {
    4553         route.children = dataChildren;
    4554       }
     4554      if (!route.children) {
     4555        route.children = [];
     4556      }
     4557      childrenToPatch = route.children;
    45554558    } else {
    4556       let dataChildren = convertRoutesToDataRoutes(children, mapRouteProperties, ["patch", String(routesToUse.length || "0")], manifest);
    4557       routesToUse.push(...dataChildren);
    4558     }
     4559      childrenToPatch = routesToUse;
     4560    }
     4561
     4562    // Don't patch in routes we already know about so that `patch` is idempotent
     4563    // to simplify user-land code. This is useful because we re-call the
     4564    // `patchRoutesOnNavigation` function for matched routes with params.
     4565    let uniqueChildren = children.filter(newRoute => !childrenToPatch.some(existingRoute => isSameRoute(newRoute, existingRoute)));
     4566    let newRoutes = convertRoutesToDataRoutes(uniqueChildren, mapRouteProperties, [routeId || "_", "patch", String(((_childrenToPatch = childrenToPatch) == null ? void 0 : _childrenToPatch.length) || "0")], manifest);
     4567    childrenToPatch.push(...newRoutes);
     4568  }
     4569  function isSameRoute(newRoute, existingRoute) {
     4570    // Most optimal check is by id
     4571    if ("id" in newRoute && "id" in existingRoute && newRoute.id === existingRoute.id) {
     4572      return true;
     4573    }
     4574
     4575    // Second is by pathing differences
     4576    if (!(newRoute.index === existingRoute.index && newRoute.path === existingRoute.path && newRoute.caseSensitive === existingRoute.caseSensitive)) {
     4577      return false;
     4578    }
     4579
     4580    // Pathless layout routes are trickier since we need to check children.
     4581    // If they have no children then they're the same as far as we can tell
     4582    if ((!newRoute.children || newRoute.children.length === 0) && (!existingRoute.children || existingRoute.children.length === 0)) {
     4583      return true;
     4584    }
     4585
     4586    // Otherwise, we look to see if every child in the new route is already
     4587    // represented in the existing route's children
     4588    return newRoute.children.every((aChild, i) => {
     4589      var _existingRoute$childr;
     4590      return (_existingRoute$childr = existingRoute.children) == null ? void 0 : _existingRoute$childr.some(bChild => isSameRoute(aChild, bChild));
     4591    });
    45594592  }
    45604593
     
    46134646
    46144647  // Default implementation of `dataStrategy` which fetches all loaders in parallel
    4615   function defaultDataStrategy(opts) {
    4616     return Promise.all(opts.matches.map(m => m.resolve()));
    4617   }
    4618   async function callDataStrategyImpl(dataStrategyImpl, type, request, matchesToLoad, matches, manifest, mapRouteProperties, requestContext) {
    4619     let routeIdsToLoad = matchesToLoad.reduce((acc, m) => acc.add(m.route.id), new Set());
    4620     let loadedMatches = new Set();
     4648  async function defaultDataStrategy(_ref4) {
     4649    let {
     4650      matches
     4651    } = _ref4;
     4652    let matchesToLoad = matches.filter(m => m.shouldLoad);
     4653    let results = await Promise.all(matchesToLoad.map(m => m.resolve()));
     4654    return results.reduce((acc, result, i) => Object.assign(acc, {
     4655      [matchesToLoad[i].route.id]: result
     4656    }), {});
     4657  }
     4658  async function callDataStrategyImpl(dataStrategyImpl, type, state, request, matchesToLoad, matches, fetcherKey, manifest, mapRouteProperties, requestContext) {
     4659    let loadRouteDefinitionsPromises = matches.map(m => m.route.lazy ? loadLazyRouteModule(m.route, mapRouteProperties, manifest) : undefined);
     4660    let dsMatches = matches.map((match, i) => {
     4661      let loadRoutePromise = loadRouteDefinitionsPromises[i];
     4662      let shouldLoad = matchesToLoad.some(m => m.route.id === match.route.id);
     4663      // `resolve` encapsulates route.lazy(), executing the loader/action,
     4664      // and mapping return values/thrown errors to a `DataStrategyResult`.  Users
     4665      // can pass a callback to take fine-grained control over the execution
     4666      // of the loader/action
     4667      let resolve = async handlerOverride => {
     4668        if (handlerOverride && request.method === "GET" && (match.route.lazy || match.route.loader)) {
     4669          shouldLoad = true;
     4670        }
     4671        return shouldLoad ? callLoaderOrAction(type, request, match, loadRoutePromise, handlerOverride, requestContext) : Promise.resolve({
     4672          type: ResultType.data,
     4673          result: undefined
     4674        });
     4675      };
     4676      return _extends({}, match, {
     4677        shouldLoad,
     4678        resolve
     4679      });
     4680    });
    46214681
    46224682    // Send all matches here to allow for a middleware-type implementation.
     
    46244684    // back out below.
    46254685    let results = await dataStrategyImpl({
    4626       matches: matches.map(match => {
    4627         let shouldLoad = routeIdsToLoad.has(match.route.id);
    4628         // `resolve` encapsulates the route.lazy, executing the
    4629         // loader/action, and mapping return values/thrown errors to a
    4630         // HandlerResult.  Users can pass a callback to take fine-grained control
    4631         // over the execution of the loader/action
    4632         let resolve = handlerOverride => {
    4633           loadedMatches.add(match.route.id);
    4634           return shouldLoad ? callLoaderOrAction(type, request, match, manifest, mapRouteProperties, handlerOverride, requestContext) : Promise.resolve({
    4635             type: ResultType.data,
    4636             result: undefined
    4637           });
    4638         };
    4639         return _extends({}, match, {
    4640           shouldLoad,
    4641           resolve
    4642         });
    4643       }),
     4686      matches: dsMatches,
    46444687      request,
    46454688      params: matches[0].params,
     4689      fetcherKey,
    46464690      context: requestContext
    46474691    });
    46484692
    4649     // Throw if any loadRoute implementations not called since they are what
    4650     // ensures a route is fully loaded
    4651     matches.forEach(m => invariant(loadedMatches.has(m.route.id), "`match.resolve()` was not called for route id \"" + m.route.id + "\". " + "You must call `match.resolve()` on every match passed to " + "`dataStrategy` to ensure all routes are properly loaded."));
    4652 
    4653     // Filter out any middleware-only matches for which we didn't need to run handlers
    4654     return results.filter((_, i) => routeIdsToLoad.has(matches[i].route.id));
     4693    // Wait for all routes to load here but 'swallow the error since we want
     4694    // it to bubble up from the `await loadRoutePromise` in `callLoaderOrAction` -
     4695    // called from `match.resolve()`
     4696    try {
     4697      await Promise.all(loadRouteDefinitionsPromises);
     4698    } catch (e) {
     4699      // No-op
     4700    }
     4701    return results;
    46554702  }
    46564703
    46574704  // Default logic for calling a loader/action is the user has no specified a dataStrategy
    4658   async function callLoaderOrAction(type, request, match, manifest, mapRouteProperties, handlerOverride, staticContext) {
     4705  async function callLoaderOrAction(type, request, match, loadRoutePromise, handlerOverride, staticContext) {
    46594706    let result;
    46604707    let onReject;
     
    46624709      // Setup a promise we can race against so that abort signals short circuit
    46634710      let reject;
    4664       // This will never resolve so safe to type it as Promise<HandlerResult> to
     4711      // This will never resolve so safe to type it as Promise<DataStrategyResult> to
    46654712      // satisfy the function return value
    46664713      let abortPromise = new Promise((_, r) => reject = r);
     
    46774724        }, ...(ctx !== undefined ? [ctx] : []));
    46784725      };
    4679       let handlerPromise;
    4680       if (handlerOverride) {
    4681         handlerPromise = handlerOverride(ctx => actualHandler(ctx));
    4682       } else {
    4683         handlerPromise = (async () => {
    4684           try {
    4685             let val = await actualHandler();
    4686             return {
    4687               type: "data",
    4688               result: val
    4689             };
    4690           } catch (e) {
    4691             return {
    4692               type: "error",
    4693               result: e
    4694             };
    4695           }
    4696         })();
    4697       }
     4726      let handlerPromise = (async () => {
     4727        try {
     4728          let val = await (handlerOverride ? handlerOverride(ctx => actualHandler(ctx)) : actualHandler());
     4729          return {
     4730            type: "data",
     4731            result: val
     4732          };
     4733        } catch (e) {
     4734          return {
     4735            type: "error",
     4736            result: e
     4737          };
     4738        }
     4739      })();
    46984740      return Promise.race([handlerPromise, abortPromise]);
    46994741    };
    47004742    try {
    47014743      let handler = match.route[type];
    4702       if (match.route.lazy) {
     4744
     4745      // If we have a route.lazy promise, await that first
     4746      if (loadRoutePromise) {
    47034747        if (handler) {
    47044748          // Run statically defined handler in parallel with lazy()
     
    47104754          runHandler(handler).catch(e => {
    47114755            handlerError = e;
    4712           }), loadLazyRouteModule(match.route, mapRouteProperties, manifest)]);
     4756          }), loadRoutePromise]);
    47134757          if (handlerError !== undefined) {
    47144758            throw handlerError;
     
    47174761        } else {
    47184762          // Load lazy route module, then run any returned handler
    4719           await loadLazyRouteModule(match.route, mapRouteProperties, manifest);
     4763          await loadRoutePromise;
    47204764          handler = match.route[type];
    47214765          if (handler) {
     
    47534797    } catch (e) {
    47544798      // We should already be catching and converting normal handler executions to
    4755       // HandlerResults and returning them, so anything that throws here is an
     4799      // DataStrategyResults and returning them, so anything that throws here is an
    47564800      // unexpected error we still need to wrap
    47574801      return {
     
    47664810    return result;
    47674811  }
    4768   async function convertHandlerResultToDataResult(handlerResult) {
     4812  async function convertDataStrategyResultToDataResult(dataStrategyResult) {
    47694813    let {
    47704814      result,
    47714815      type
    4772     } = handlerResult;
     4816    } = dataStrategyResult;
    47734817    if (isResponse(result)) {
    47744818      let data;
     
    48194863        }
    48204864
    4821         // Convert thrown unstable_data() to ErrorResponse instances
     4865        // Convert thrown data() to ErrorResponse instances
    48224866        result = new ErrorResponseImpl(((_result$init2 = result.init) == null ? void 0 : _result$init2.status) || 500, undefined, result.data);
    48234867      }
     
    49264970    return formData;
    49274971  }
    4928   function processRouteLoaderData(matches, matchesToLoad, results, pendingActionResult, activeDeferreds, skipLoaderErrorBubbling) {
     4972  function processRouteLoaderData(matches, results, pendingActionResult, activeDeferreds, skipLoaderErrorBubbling) {
    49294973    // Fill in loaderData/errors from our loaders
    49304974    let loaderData = {};
     
    49364980
    49374981    // Process loader results into state.loaderData/state.errors
    4938     results.forEach((result, index) => {
    4939       let id = matchesToLoad[index].route.id;
     4982    matches.forEach(match => {
     4983      if (!(match.route.id in results)) {
     4984        return;
     4985      }
     4986      let id = match.route.id;
     4987      let result = results[id];
    49404988      invariant(!isRedirectResult(result), "Cannot handle redirect results in processLoaderData");
    49414989      if (isErrorResult(result)) {
     
    50155063    };
    50165064  }
    5017   function processLoaderData(state, matches, matchesToLoad, results, pendingActionResult, revalidatingFetchers, fetcherResults, activeDeferreds) {
     5065  function processLoaderData(state, matches, results, pendingActionResult, revalidatingFetchers, fetcherResults, activeDeferreds) {
    50185066    let {
    50195067      loaderData,
    50205068      errors
    5021     } = processRouteLoaderData(matches, matchesToLoad, results, pendingActionResult, activeDeferreds, false // This method is only called client side so we always want to bubble
     5069    } = processRouteLoaderData(matches, results, pendingActionResult, activeDeferreds, false // This method is only called client side so we always want to bubble
    50225070    );
    50235071
    50245072    // Process results from our revalidating fetchers
    5025     for (let index = 0; index < revalidatingFetchers.length; index++) {
     5073    revalidatingFetchers.forEach(rf => {
    50265074      let {
    50275075        key,
    50285076        match,
    50295077        controller
    5030       } = revalidatingFetchers[index];
    5031       invariant(fetcherResults !== undefined && fetcherResults[index] !== undefined, "Did not find corresponding fetcher result");
    5032       let result = fetcherResults[index];
     5078      } = rf;
     5079      let result = fetcherResults[key];
     5080      invariant(result, "Did not find corresponding fetcher result");
    50335081
    50345082      // Process fetcher non-redirect errors
    50355083      if (controller && controller.signal.aborted) {
    50365084        // Nothing to do for aborted fetchers
    5037         continue;
     5085        return;
    50385086      } else if (isErrorResult(result)) {
    50395087        let boundaryMatch = findNearestBoundary(state.matches, match == null ? void 0 : match.route.id);
     
    50565104        state.fetchers.set(key, doneFetcher);
    50575105      }
    5058     }
     5106    });
    50595107    return {
    50605108      loaderData,
     
    51305178    if (status === 400) {
    51315179      statusText = "Bad Request";
    5132       if (type === "route-discovery") {
    5133         errorMessage = "Unable to match URL \"" + pathname + "\" - the `unstable_patchRoutesOnMiss()` " + ("function threw the following error:\n" + message);
    5134       } else if (method && pathname && routeId) {
     5180      if (method && pathname && routeId) {
    51355181        errorMessage = "You made a " + method + " request to \"" + pathname + "\" but " + ("did not provide a `loader` for route \"" + routeId + "\", ") + "so there is no way to handle the request.";
    51365182      } else if (type === "defer-action") {
     
    51585204  // Find any returned redirect errors, starting from the lowest match
    51595205  function findRedirect(results) {
    5160     for (let i = results.length - 1; i >= 0; i--) {
    5161       let result = results[i];
     5206    let entries = Object.entries(results);
     5207    for (let i = entries.length - 1; i >= 0; i--) {
     5208      let [key, result] = entries[i];
    51625209      if (isRedirectResult(result)) {
    51635210        return {
    5164           result,
    5165           idx: i
     5211          key,
     5212          result
    51665213        };
    51675214      }
     
    51935240    return false;
    51945241  }
    5195   function isPromise(val) {
    5196     return typeof val === "object" && val != null && "then" in val;
    5197   }
    5198   function isHandlerResult(result) {
     5242  function isDataStrategyResult(result) {
    51995243    return result != null && typeof result === "object" && "type" in result && "result" in result && (result.type === ResultType.data || result.type === ResultType.error);
    52005244  }
    5201   function isRedirectHandlerResult(result) {
     5245  function isRedirectDataStrategyResultResult(result) {
    52025246    return isResponse(result.result) && redirectStatusCodes.has(result.result.status);
    52035247  }
     
    52355279    return validMutationMethods.has(method.toLowerCase());
    52365280  }
    5237   async function resolveDeferredResults(currentMatches, matchesToLoad, results, signals, isFetcher, currentLoaderData) {
    5238     for (let index = 0; index < results.length; index++) {
    5239       let result = results[index];
    5240       let match = matchesToLoad[index];
     5281  async function resolveNavigationDeferredResults(matches, results, signal, currentMatches, currentLoaderData) {
     5282    let entries = Object.entries(results);
     5283    for (let index = 0; index < entries.length; index++) {
     5284      let [routeId, result] = entries[index];
     5285      let match = matches.find(m => (m == null ? void 0 : m.route.id) === routeId);
    52415286      // If we don't have a match, then we can have a deferred result to do
    52425287      // anything with.  This is for revalidating fetchers where the route was
     
    52475292      let currentMatch = currentMatches.find(m => m.route.id === match.route.id);
    52485293      let isRevalidatingLoader = currentMatch != null && !isNewRouteInstance(currentMatch, match) && (currentLoaderData && currentLoaderData[match.route.id]) !== undefined;
    5249       if (isDeferredResult(result) && (isFetcher || isRevalidatingLoader)) {
     5294      if (isDeferredResult(result) && isRevalidatingLoader) {
    52505295        // Note: we do not have to touch activeDeferreds here since we race them
    52515296        // against the signal in resolveDeferredData and they'll get aborted
    52525297        // there if needed
    5253         let signal = signals[index];
    5254         invariant(signal, "Expected an AbortSignal for revalidating fetcher deferred result");
    5255         await resolveDeferredData(result, signal, isFetcher).then(result => {
     5298        await resolveDeferredData(result, signal, false).then(result => {
    52565299          if (result) {
    5257             results[index] = result || results[index];
     5300            results[routeId] = result;
     5301          }
     5302        });
     5303      }
     5304    }
     5305  }
     5306  async function resolveFetcherDeferredResults(matches, results, revalidatingFetchers) {
     5307    for (let index = 0; index < revalidatingFetchers.length; index++) {
     5308      let {
     5309        key,
     5310        routeId,
     5311        controller
     5312      } = revalidatingFetchers[index];
     5313      let result = results[key];
     5314      let match = matches.find(m => (m == null ? void 0 : m.route.id) === routeId);
     5315      // If we don't have a match, then we can have a deferred result to do
     5316      // anything with.  This is for revalidating fetchers where the route was
     5317      // removed during HMR
     5318      if (!match) {
     5319        continue;
     5320      }
     5321      if (isDeferredResult(result)) {
     5322        // Note: we do not have to touch activeDeferreds here since we race them
     5323        // against the signal in resolveDeferredData and they'll get aborted
     5324        // there if needed
     5325        invariant(controller, "Expected an AbortController for revalidating fetcher deferred result");
     5326        await resolveDeferredData(result, controller.signal, true).then(result => {
     5327          if (result) {
     5328            results[key] = result;
    52585329          }
    52595330        });
     
    54865557  exports.createRouter = createRouter;
    54875558  exports.createStaticHandler = createStaticHandler;
     5559  exports.data = data;
    54885560  exports.defer = defer;
    54895561  exports.generatePath = generatePath;
     
    55055577  exports.resolveTo = resolveTo;
    55065578  exports.stripBasename = stripBasename;
    5507   exports.unstable_data = data;
    55085579
    55095580  Object.defineProperty(exports, '__esModule', { value: true });
Note: See TracChangeset for help on using the changeset viewer.