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.cjs.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.
     
    579579
    580580/**
    581  * Result from a loader or action called via dataStrategy
    582  */
    583 
    584 /**
    585581 * Users can specify either lowercase or uppercase form methods on `<Form>`,
    586582 * useSubmit(), `<fetcher.Form>`, etc.
     
    646642 *
    647643 * @deprecated Use `mapRouteProperties` instead
     644 */
     645/**
     646 * Result from a loader or action called via dataStrategy
    648647 */
    649648/**
     
    746745 * Matches the given routes to a location and returns the match data.
    747746 *
    748  * @see https://reactrouter.com/utils/match-routes
     747 * @see https://reactrouter.com/v6/utils/match-routes
    749748 */
    750749function matchRoutes(routes, locationArg, basename) {
     
    979978 * Returns a path with params interpolated.
    980979 *
    981  * @see https://reactrouter.com/utils/generate-path
     980 * @see https://reactrouter.com/v6/utils/generate-path
    982981 */
    983982function generatePath(originalPath, params) {
     
    10311030 * the match.
    10321031 *
    1033  * @see https://reactrouter.com/utils/match-path
     1032 * @see https://reactrouter.com/v6/utils/match-path
    10341033 */
    10351034function matchPath(pattern, pathname) {
     
    11461145 * Returns a resolved path object relative to the given pathname.
    11471146 *
    1148  * @see https://reactrouter.com/utils/resolve-path
     1147 * @see https://reactrouter.com/v6/utils/resolve-path
    11491148 */
    11501149function resolvePath(to, fromPathname) {
     
    13121311 * This is a shortcut for creating `application/json` responses. Converts `data`
    13131312 * to JSON and sets the `Content-Type` header.
     1313 *
     1314 * @deprecated The `json` method is deprecated in favor of returning raw objects.
     1315 * This method will be removed in v7.
    13141316 */
    13151317const json = function json(data, init) {
     
    14851487  return value._data;
    14861488}
     1489/**
     1490 * @deprecated The `defer` method is deprecated in favor of returning raw
     1491 * objects. This method will be removed in v7.
     1492 */
    14871493const defer = function defer(data, init) {
    14881494  if (init === void 0) {
     
    17131719  let inFlightDataRoutes;
    17141720  let basename = init.basename || "/";
    1715   let dataStrategyImpl = init.unstable_dataStrategy || defaultDataStrategy;
    1716   let patchRoutesOnMissImpl = init.unstable_patchRoutesOnMiss;
     1721  let dataStrategyImpl = init.dataStrategy || defaultDataStrategy;
     1722  let patchRoutesOnNavigationImpl = init.patchRoutesOnNavigation;
    17171723
    17181724  // Config driven behavior flags
     
    17441750  let initialMatches = matchRoutes(dataRoutes, init.history.location, basename);
    17451751  let initialErrors = null;
    1746   if (initialMatches == null && !patchRoutesOnMissImpl) {
     1752  if (initialMatches == null && !patchRoutesOnNavigationImpl) {
    17471753    // If we do not match a user-provided-route, fall back to the root
    17481754    // to allow the error boundary to take over
     
    17601766  }
    17611767
    1762   // In SPA apps, if the user provided a patchRoutesOnMiss implementation and
     1768  // In SPA apps, if the user provided a patchRoutesOnNavigation implementation and
    17631769  // our initial match is a splat route, clear them out so we run through lazy
    17641770  // discovery on hydration in case there's a more accurate lazy route match.
     
    17781784
    17791785    // If partial hydration and fog of war is enabled, we will be running
    1780     // `patchRoutesOnMiss` during hydration so include any partial matches as
     1786    // `patchRoutesOnNavigation` during hydration so include any partial matches as
    17811787    // the initial matches so we can properly render `HydrateFallback`'s
    17821788    if (future.v7_partialHydration) {
     
    17991805    let loaderData = init.hydrationData ? init.hydrationData.loaderData : null;
    18001806    let errors = init.hydrationData ? init.hydrationData.errors : null;
    1801     let isRouteInitialized = m => {
    1802       // No loader, nothing to initialize
    1803       if (!m.route.loader) {
    1804         return true;
    1805       }
    1806       // Explicitly opting-in to running on hydration
    1807       if (typeof m.route.loader === "function" && m.route.loader.hydrate === true) {
    1808         return false;
    1809       }
    1810       // Otherwise, initialized if hydrated with data or an error
    1811       return loaderData && loaderData[m.route.id] !== undefined || errors && errors[m.route.id] !== undefined;
    1812     };
    1813 
    18141807    // If errors exist, don't consider routes below the boundary
    18151808    if (errors) {
    18161809      let idx = initialMatches.findIndex(m => errors[m.route.id] !== undefined);
    1817       initialized = initialMatches.slice(0, idx + 1).every(isRouteInitialized);
     1810      initialized = initialMatches.slice(0, idx + 1).every(m => !shouldLoadRouteOnHydration(m.route, loaderData, errors));
    18181811    } else {
    1819       initialized = initialMatches.every(isRouteInitialized);
     1812      initialized = initialMatches.every(m => !shouldLoadRouteOnHydration(m.route, loaderData, errors));
    18201813    }
    18211814  } else {
     
    19171910  let blockerFunctions = new Map();
    19181911
    1919   // Map of pending patchRoutesOnMiss() promises (keyed by path/matches) so
    1920   // that we only kick them off once for a given combo
    1921   let pendingPatchRoutes = new Map();
    1922 
    19231912  // Flag to ignore the next history update, so we can revert the URL change on
    19241913  // a POP navigation that was blocked by the user without touching router state
    1925   let ignoreNextHistoryUpdate = false;
     1914  let unblockBlockerHistoryUpdate = undefined;
    19261915
    19271916  // Initialize the router, all side effects should be kicked off from here.
     
    19391928      // Ignore this event if it was just us resetting the URL from a
    19401929      // blocked POP navigation
    1941       if (ignoreNextHistoryUpdate) {
    1942         ignoreNextHistoryUpdate = false;
     1930      if (unblockBlockerHistoryUpdate) {
     1931        unblockBlockerHistoryUpdate();
     1932        unblockBlockerHistoryUpdate = undefined;
    19431933        return;
    19441934      }
     
    19511941      if (blockerKey && delta != null) {
    19521942        // Restore the URL to match the current UI, but don't update router state
    1953         ignoreNextHistoryUpdate = true;
     1943        let nextHistoryUpdatePromise = new Promise(resolve => {
     1944          unblockBlockerHistoryUpdate = resolve;
     1945        });
    19541946        init.history.go(delta * -1);
    19551947
     
    19651957              location
    19661958            });
    1967             // Re-do the same POP navigation we just blocked
    1968             init.history.go(delta);
     1959            // Re-do the same POP navigation we just blocked, after the url
     1960            // restoration is also complete.  See:
     1961            // https://github.com/remix-run/react-router/issues/11613
     1962            nextHistoryUpdatePromise.then(() => init.history.go(delta));
    19691963          },
    19701964          reset() {
     
    20532047    [...subscribers].forEach(subscriber => subscriber(state, {
    20542048      deletedFetchers: deletedFetchersKeys,
    2055       unstable_viewTransitionOpts: opts.viewTransitionOpts,
    2056       unstable_flushSync: opts.flushSync === true
     2049      viewTransitionOpts: opts.viewTransitionOpts,
     2050      flushSync: opts.flushSync === true
    20572051    }));
    20582052
     
    22142208    }
    22152209    let preventScrollReset = opts && "preventScrollReset" in opts ? opts.preventScrollReset === true : undefined;
    2216     let flushSync = (opts && opts.unstable_flushSync) === true;
     2210    let flushSync = (opts && opts.flushSync) === true;
    22172211    let blockerKey = shouldBlockNavigation({
    22182212      currentLocation,
     
    22522246      preventScrollReset,
    22532247      replace: opts && opts.replace,
    2254       enableViewTransition: opts && opts.unstable_viewTransition,
     2248      enableViewTransition: opts && opts.viewTransition,
    22552249      flushSync
    22562250    });
     
    22862280    // revalidation so that history correctly updates once the navigation completes
    22872281    startNavigation(pendingAction || state.historyAction, state.navigation.location, {
    2288       overrideNavigation: state.navigation
     2282      overrideNavigation: state.navigation,
     2283      // Proxy through any rending view transition
     2284      enableViewTransition: pendingViewTransitionEnabled === true
    22892285    });
    22902286  }
     
    23382334    // mutation submission.
    23392335    //
    2340     // Ignore on initial page loads because since the initial load will always
     2336    // Ignore on initial page loads because since the initial hydration will always
    23412337    // be "same hash".  For example, on /page#hash and submit a <Form method="post">
    23422338    // which will default to a navigation to /page
     
    24452441        };
    24462442      } else if (discoverResult.type === "error") {
    2447         let {
    2448           boundaryId,
    2449           error
    2450         } = handleDiscoverRouteError(location.pathname, discoverResult);
     2443        let boundaryId = findNearestBoundary(discoverResult.partialMatches).route.id;
    24512444        return {
    24522445          matches: discoverResult.partialMatches,
    24532446          pendingActionResult: [boundaryId, {
    24542447            type: ResultType.error,
    2455             error
     2448            error: discoverResult.error
    24562449          }]
    24572450        };
     
    24872480      };
    24882481    } else {
    2489       let results = await callDataStrategy("action", request, [actionMatch], matches);
    2490       result = results[0];
     2482      let results = await callDataStrategy("action", state, request, [actionMatch], matches, null);
     2483      result = results[actionMatch.route.id];
    24912484      if (request.signal.aborted) {
    24922485        return {
     
    25062499        replace = location === state.location.pathname + state.location.search;
    25072500      }
    2508       await startRedirectNavigation(request, result, {
     2501      await startRedirectNavigation(request, result, true, {
    25092502        submission,
    25102503        replace
     
    25832576        };
    25842577      } else if (discoverResult.type === "error") {
    2585         let {
    2586           boundaryId,
    2587           error
    2588         } = handleDiscoverRouteError(location.pathname, discoverResult);
     2578        let boundaryId = findNearestBoundary(discoverResult.partialMatches).route.id;
    25892579        return {
    25902580          matches: discoverResult.partialMatches,
    25912581          loaderData: {},
    25922582          errors: {
    2593             [boundaryId]: error
     2583            [boundaryId]: discoverResult.error
    25942584          }
    25952585        };
     
    26572647    }
    26582648    revalidatingFetchers.forEach(rf => {
    2659       if (fetchControllers.has(rf.key)) {
    2660         abortFetcher(rf.key);
    2661       }
     2649      abortFetcher(rf.key);
    26622650      if (rf.controller) {
    26632651        // Fetchers use an independent AbortController so that aborting a fetcher
     
    26762664      loaderResults,
    26772665      fetcherResults
    2678     } = await callLoadersAndMaybeResolveData(state.matches, matches, matchesToLoad, revalidatingFetchers, request);
     2666    } = await callLoadersAndMaybeResolveData(state, matches, matchesToLoad, revalidatingFetchers, request);
    26792667    if (request.signal.aborted) {
    26802668      return {
     
    26922680
    26932681    // If any loaders returned a redirect Response, start a new REPLACE navigation
    2694     let redirect = findRedirect([...loaderResults, ...fetcherResults]);
     2682    let redirect = findRedirect(loaderResults);
    26952683    if (redirect) {
    2696       if (redirect.idx >= matchesToLoad.length) {
    2697         // If this redirect came from a fetcher make sure we mark it in
    2698         // fetchRedirectIds so it doesn't get revalidated on the next set of
    2699         // loader executions
    2700         let fetcherKey = revalidatingFetchers[redirect.idx - matchesToLoad.length].key;
    2701         fetchRedirectIds.add(fetcherKey);
    2702       }
    2703       await startRedirectNavigation(request, redirect.result, {
     2684      await startRedirectNavigation(request, redirect.result, true, {
    27042685        replace
    27052686      });
     
    27082689      };
    27092690    }
     2691    redirect = findRedirect(fetcherResults);
     2692    if (redirect) {
     2693      // If this redirect came from a fetcher make sure we mark it in
     2694      // fetchRedirectIds so it doesn't get revalidated on the next set of
     2695      // loader executions
     2696      fetchRedirectIds.add(redirect.key);
     2697      await startRedirectNavigation(request, redirect.result, true, {
     2698        replace
     2699      });
     2700      return {
     2701        shortCircuited: true
     2702      };
     2703    }
    27102704
    27112705    // Process and commit output from loaders
     
    27132707      loaderData,
    27142708      errors
    2715     } = processLoaderData(state, matches, matchesToLoad, loaderResults, pendingActionResult, revalidatingFetchers, fetcherResults, activeDeferreds);
     2709    } = processLoaderData(state, matches, loaderResults, pendingActionResult, revalidatingFetchers, fetcherResults, activeDeferreds);
    27162710
    27172711    // Wire up subscribers to update loaderData as promises settle
     
    27272721    });
    27282722
    2729     // During partial hydration, preserve SSR errors for routes that don't re-run
     2723    // Preserve SSR errors during partial hydration
    27302724    if (future.v7_partialHydration && initialHydration && state.errors) {
    2731       Object.entries(state.errors).filter(_ref2 => {
    2732         let [id] = _ref2;
    2733         return !matchesToLoad.some(m => m.route.id === id);
    2734       }).forEach(_ref3 => {
    2735         let [routeId, error] = _ref3;
    2736         errors = Object.assign(errors || {}, {
    2737           [routeId]: error
    2738         });
    2739       });
     2725      errors = _extends({}, state.errors, errors);
    27402726    }
    27412727    let updatedFetchers = markFetchRedirectsDone();
     
    27802766      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.");
    27812767    }
    2782     if (fetchControllers.has(key)) abortFetcher(key);
    2783     let flushSync = (opts && opts.unstable_flushSync) === true;
     2768    abortFetcher(key);
     2769    let flushSync = (opts && opts.flushSync) === true;
    27842770    let routesToUse = inFlightDataRoutes || dataRoutes;
    27852771    let normalizedPath = normalizeTo(state.location, state.matches, basename, future.v7_prependBasename, href, future.v7_relativeSplatPath, routeId, opts == null ? void 0 : opts.relative);
     
    28092795    }
    28102796    let match = getTargetMatch(matches, path);
    2811     pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;
     2797    let preventScrollReset = (opts && opts.preventScrollReset) === true;
    28122798    if (submission && isMutationMethod(submission.formMethod)) {
    2813       handleFetcherAction(key, routeId, path, match, matches, fogOfWar.active, flushSync, submission);
     2799      handleFetcherAction(key, routeId, path, match, matches, fogOfWar.active, flushSync, preventScrollReset, submission);
    28142800      return;
    28152801    }
     
    28212807      path
    28222808    });
    2823     handleFetcherLoader(key, routeId, path, match, matches, fogOfWar.active, flushSync, submission);
     2809    handleFetcherLoader(key, routeId, path, match, matches, fogOfWar.active, flushSync, preventScrollReset, submission);
    28242810  }
    28252811
    28262812  // Call the action for the matched fetcher.submit(), and then handle redirects,
    28272813  // errors, and revalidation
    2828   async function handleFetcherAction(key, routeId, path, match, requestMatches, isFogOfWar, flushSync, submission) {
     2814  async function handleFetcherAction(key, routeId, path, match, requestMatches, isFogOfWar, flushSync, preventScrollReset, submission) {
    28292815    interruptActiveLoads();
    28302816    fetchLoadMatches.delete(key);
     
    28592845        return;
    28602846      } else if (discoverResult.type === "error") {
    2861         let {
    2862           error
    2863         } = handleDiscoverRouteError(path, discoverResult);
    2864         setFetcherError(key, routeId, error, {
     2847        setFetcherError(key, routeId, discoverResult.error, {
    28652848          flushSync
    28662849        });
     
    28852868    fetchControllers.set(key, abortController);
    28862869    let originatingLoadId = incrementingLoadId;
    2887     let actionResults = await callDataStrategy("action", fetchRequest, [match], requestMatches);
    2888     let actionResult = actionResults[0];
     2870    let actionResults = await callDataStrategy("action", state, fetchRequest, [match], requestMatches, key);
     2871    let actionResult = actionResults[match.route.id];
    28892872    if (fetchRequest.signal.aborted) {
    28902873      // We can delete this so long as we weren't aborted by our own fetcher
     
    29182901          fetchRedirectIds.add(key);
    29192902          updateFetcherState(key, getLoadingFetcher(submission));
    2920           return startRedirectNavigation(fetchRequest, actionResult, {
    2921             fetcherSubmission: submission
     2903          return startRedirectNavigation(fetchRequest, actionResult, false, {
     2904            fetcherSubmission: submission,
     2905            preventScrollReset
    29222906          });
    29232907        }
     
    29572941      let revalidatingFetcher = getLoadingFetcher(undefined, existingFetcher ? existingFetcher.data : undefined);
    29582942      state.fetchers.set(staleKey, revalidatingFetcher);
    2959       if (fetchControllers.has(staleKey)) {
    2960         abortFetcher(staleKey);
    2961       }
     2943      abortFetcher(staleKey);
    29622944      if (rf.controller) {
    29632945        fetchControllers.set(staleKey, rf.controller);
     
    29722954      loaderResults,
    29732955      fetcherResults
    2974     } = await callLoadersAndMaybeResolveData(state.matches, matches, matchesToLoad, revalidatingFetchers, revalidationRequest);
     2956    } = await callLoadersAndMaybeResolveData(state, matches, matchesToLoad, revalidatingFetchers, revalidationRequest);
    29752957    if (abortController.signal.aborted) {
    29762958      return;
     
    29802962    fetchControllers.delete(key);
    29812963    revalidatingFetchers.forEach(r => fetchControllers.delete(r.key));
    2982     let redirect = findRedirect([...loaderResults, ...fetcherResults]);
     2964    let redirect = findRedirect(loaderResults);
    29832965    if (redirect) {
    2984       if (redirect.idx >= matchesToLoad.length) {
    2985         // If this redirect came from a fetcher make sure we mark it in
    2986         // fetchRedirectIds so it doesn't get revalidated on the next set of
    2987         // loader executions
    2988         let fetcherKey = revalidatingFetchers[redirect.idx - matchesToLoad.length].key;
    2989         fetchRedirectIds.add(fetcherKey);
    2990       }
    2991       return startRedirectNavigation(revalidationRequest, redirect.result);
     2966      return startRedirectNavigation(revalidationRequest, redirect.result, false, {
     2967        preventScrollReset
     2968      });
     2969    }
     2970    redirect = findRedirect(fetcherResults);
     2971    if (redirect) {
     2972      // If this redirect came from a fetcher make sure we mark it in
     2973      // fetchRedirectIds so it doesn't get revalidated on the next set of
     2974      // loader executions
     2975      fetchRedirectIds.add(redirect.key);
     2976      return startRedirectNavigation(revalidationRequest, redirect.result, false, {
     2977        preventScrollReset
     2978      });
    29922979    }
    29932980
     
    29962983      loaderData,
    29972984      errors
    2998     } = processLoaderData(state, state.matches, matchesToLoad, loaderResults, undefined, revalidatingFetchers, fetcherResults, activeDeferreds);
     2985    } = processLoaderData(state, matches, loaderResults, undefined, revalidatingFetchers, fetcherResults, activeDeferreds);
    29992986
    30002987    // Since we let revalidations complete even if the submitting fetcher was
     
    30323019
    30333020  // Call the matched loader for fetcher.load(), handling redirects, errors, etc.
    3034   async function handleFetcherLoader(key, routeId, path, match, matches, isFogOfWar, flushSync, submission) {
     3021  async function handleFetcherLoader(key, routeId, path, match, matches, isFogOfWar, flushSync, preventScrollReset, submission) {
    30353022    let existingFetcher = state.fetchers.get(key);
    30363023    updateFetcherState(key, getLoadingFetcher(submission, existingFetcher ? existingFetcher.data : undefined), {
     
    30443031        return;
    30453032      } else if (discoverResult.type === "error") {
    3046         let {
    3047           error
    3048         } = handleDiscoverRouteError(path, discoverResult);
    3049         setFetcherError(key, routeId, error, {
     3033        setFetcherError(key, routeId, discoverResult.error, {
    30503034          flushSync
    30513035        });
     
    30673051    fetchControllers.set(key, abortController);
    30683052    let originatingLoadId = incrementingLoadId;
    3069     let results = await callDataStrategy("loader", fetchRequest, [match], matches);
    3070     let result = results[0];
     3053    let results = await callDataStrategy("loader", state, fetchRequest, [match], matches, key);
     3054    let result = results[match.route.id];
    30713055
    30723056    // Deferred isn't supported for fetcher loads, await everything and treat it
     
    31033087      } else {
    31043088        fetchRedirectIds.add(key);
    3105         await startRedirectNavigation(fetchRequest, result);
     3089        await startRedirectNavigation(fetchRequest, result, false, {
     3090          preventScrollReset
     3091        });
    31063092        return;
    31073093      }
     
    31383124   * the history action from the original navigation (PUSH or REPLACE).
    31393125   */
    3140   async function startRedirectNavigation(request, redirect, _temp2) {
     3126  async function startRedirectNavigation(request, redirect, isNavigation, _temp2) {
    31413127    let {
    31423128      submission,
    31433129      fetcherSubmission,
     3130      preventScrollReset,
    31443131      replace
    31453132    } = _temp2 === void 0 ? {} : _temp2;
     
    32013188          formAction: location
    32023189        }),
    3203         // Preserve this flag across redirects
    3204         preventScrollReset: pendingPreventScrollReset
     3190        // Preserve these flags across redirects
     3191        preventScrollReset: preventScrollReset || pendingPreventScrollReset,
     3192        enableViewTransition: isNavigation ? pendingViewTransitionEnabled : undefined
    32053193      });
    32063194    } else {
     
    32123200        // Send fetcher submissions through for shouldRevalidate
    32133201        fetcherSubmission,
    3214         // Preserve this flag across redirects
    3215         preventScrollReset: pendingPreventScrollReset
     3202        // Preserve these flags across redirects
     3203        preventScrollReset: preventScrollReset || pendingPreventScrollReset,
     3204        enableViewTransition: isNavigation ? pendingViewTransitionEnabled : undefined
    32163205      });
    32173206    }
     
    32203209  // Utility wrapper for calling dataStrategy client-side without having to
    32213210  // pass around the manifest, mapRouteProperties, etc.
    3222   async function callDataStrategy(type, request, matchesToLoad, matches) {
     3211  async function callDataStrategy(type, state, request, matchesToLoad, matches, fetcherKey) {
     3212    let results;
     3213    let dataResults = {};
    32233214    try {
    3224       let results = await callDataStrategyImpl(dataStrategyImpl, type, request, matchesToLoad, matches, manifest, mapRouteProperties);
    3225       return await Promise.all(results.map((result, i) => {
    3226         if (isRedirectHandlerResult(result)) {
    3227           let response = result.result;
    3228           return {
    3229             type: ResultType.redirect,
    3230             response: normalizeRelativeRoutingRedirectResponse(response, request, matchesToLoad[i].route.id, matches, basename, future.v7_relativeSplatPath)
    3231           };
    3232         }
    3233         return convertHandlerResultToDataResult(result);
    3234       }));
     3215      results = await callDataStrategyImpl(dataStrategyImpl, type, state, request, matchesToLoad, matches, fetcherKey, manifest, mapRouteProperties);
    32353216    } catch (e) {
    32363217      // If the outer dataStrategy method throws, just return the error for all
    32373218      // matches - and it'll naturally bubble to the root
    3238       return matchesToLoad.map(() => ({
    3239         type: ResultType.error,
    3240         error: e
    3241       }));
    3242     }
    3243   }
    3244   async function callLoadersAndMaybeResolveData(currentMatches, matches, matchesToLoad, fetchersToLoad, request) {
    3245     let [loaderResults, ...fetcherResults] = await Promise.all([matchesToLoad.length ? callDataStrategy("loader", request, matchesToLoad, matches) : [], ...fetchersToLoad.map(f => {
     3219      matchesToLoad.forEach(m => {
     3220        dataResults[m.route.id] = {
     3221          type: ResultType.error,
     3222          error: e
     3223        };
     3224      });
     3225      return dataResults;
     3226    }
     3227    for (let [routeId, result] of Object.entries(results)) {
     3228      if (isRedirectDataStrategyResultResult(result)) {
     3229        let response = result.result;
     3230        dataResults[routeId] = {
     3231          type: ResultType.redirect,
     3232          response: normalizeRelativeRoutingRedirectResponse(response, request, routeId, matches, basename, future.v7_relativeSplatPath)
     3233        };
     3234      } else {
     3235        dataResults[routeId] = await convertDataStrategyResultToDataResult(result);
     3236      }
     3237    }
     3238    return dataResults;
     3239  }
     3240  async function callLoadersAndMaybeResolveData(state, matches, matchesToLoad, fetchersToLoad, request) {
     3241    let currentMatches = state.matches;
     3242
     3243    // Kick off loaders and fetchers in parallel
     3244    let loaderResultsPromise = callDataStrategy("loader", state, request, matchesToLoad, matches, null);
     3245    let fetcherResultsPromise = Promise.all(fetchersToLoad.map(async f => {
    32463246      if (f.matches && f.match && f.controller) {
    3247         let fetcherRequest = createClientSideRequest(init.history, f.path, f.controller.signal);
    3248         return callDataStrategy("loader", fetcherRequest, [f.match], f.matches).then(r => r[0]);
     3247        let results = await callDataStrategy("loader", state, createClientSideRequest(init.history, f.path, f.controller.signal), [f.match], f.matches, f.key);
     3248        let result = results[f.match.route.id];
     3249        // Fetcher results are keyed by fetcher key from here on out, not routeId
     3250        return {
     3251          [f.key]: result
     3252        };
    32493253      } else {
    32503254        return Promise.resolve({
    3251           type: ResultType.error,
    3252           error: getInternalRouterError(404, {
    3253             pathname: f.path
    3254           })
     3255          [f.key]: {
     3256            type: ResultType.error,
     3257            error: getInternalRouterError(404, {
     3258              pathname: f.path
     3259            })
     3260          }
    32553261        });
    32563262      }
    3257     })]);
    3258     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)]);
     3263    }));
     3264    let loaderResults = await loaderResultsPromise;
     3265    let fetcherResults = (await fetcherResultsPromise).reduce((acc, r) => Object.assign(acc, r), {});
     3266    await Promise.all([resolveNavigationDeferredResults(matches, loaderResults, request.signal, currentMatches, state.loaderData), resolveFetcherDeferredResults(matches, fetcherResults, fetchersToLoad)]);
    32593267    return {
    32603268      loaderResults,
     
    32743282      if (fetchControllers.has(key)) {
    32753283        cancelledFetcherLoads.add(key);
    3276         abortFetcher(key);
    3277       }
     3284      }
     3285      abortFetcher(key);
    32783286    });
    32793287  }
     
    33483356  function abortFetcher(key) {
    33493357    let controller = fetchControllers.get(key);
    3350     invariant(controller, "Expected fetch controller: " + key);
    3351     controller.abort();
    3352     fetchControllers.delete(key);
     3358    if (controller) {
     3359      controller.abort();
     3360      fetchControllers.delete(key);
     3361    }
    33533362  }
    33543363  function markFetchersDone(keys) {
     
    34153424    });
    34163425  }
    3417   function shouldBlockNavigation(_ref4) {
     3426  function shouldBlockNavigation(_ref2) {
    34183427    let {
    34193428      currentLocation,
    34203429      nextLocation,
    34213430      historyAction
    3422     } = _ref4;
     3431    } = _ref2;
    34233432    if (blockerFunctions.size === 0) {
    34243433      return;
     
    34653474      route,
    34663475      error
    3467     };
    3468   }
    3469   function handleDiscoverRouteError(pathname, discoverResult) {
    3470     return {
    3471       boundaryId: findNearestBoundary(discoverResult.partialMatches).route.id,
    3472       error: getInternalRouterError(400, {
    3473         type: "route-discovery",
    3474         pathname,
    3475         message: discoverResult.error != null && "message" in discoverResult.error ? discoverResult.error : String(discoverResult.error)
    3476       })
    34773476    };
    34783477  }
     
    35413540  }
    35423541  function checkFogOfWar(matches, routesToUse, pathname) {
    3543     if (patchRoutesOnMissImpl) {
     3542    if (patchRoutesOnNavigationImpl) {
    35443543      if (!matches) {
    35453544        let fogMatches = matchRoutesImpl(routesToUse, pathname, basename, true);
     
    35493548        };
    35503549      } else {
    3551         let leafRoute = matches[matches.length - 1].route;
    3552         if (leafRoute.path && (leafRoute.path === "*" || leafRoute.path.endsWith("/*"))) {
    3553           // If we matched a splat, it might only be because we haven't yet fetched
    3554           // the children that would match with a higher score, so let's fetch
    3555           // around and find out
     3550        if (Object.keys(matches[0].params).length > 0) {
     3551          // If we matched a dynamic param or a splat, it might only be because
     3552          // we haven't yet discovered other routes that would match with a
     3553          // higher score.  Call patchRoutesOnNavigation just to be sure
    35563554          let partialMatches = matchRoutesImpl(routesToUse, pathname, basename, true);
    35573555          return {
     
    35683566  }
    35693567  async function discoverRoutes(matches, pathname, signal) {
     3568    if (!patchRoutesOnNavigationImpl) {
     3569      return {
     3570        type: "success",
     3571        matches
     3572      };
     3573    }
    35703574    let partialMatches = matches;
    3571     let route = partialMatches.length > 0 ? partialMatches[partialMatches.length - 1].route : null;
    35723575    while (true) {
    35733576      let isNonHMR = inFlightDataRoutes == null;
    35743577      let routesToUse = inFlightDataRoutes || dataRoutes;
     3578      let localManifest = manifest;
    35753579      try {
    3576         await loadLazyRouteChildren(patchRoutesOnMissImpl, pathname, partialMatches, routesToUse, manifest, mapRouteProperties, pendingPatchRoutes, signal);
     3580        await patchRoutesOnNavigationImpl({
     3581          path: pathname,
     3582          matches: partialMatches,
     3583          patch: (routeId, children) => {
     3584            if (signal.aborted) return;
     3585            patchRoutesImpl(routeId, children, routesToUse, localManifest, mapRouteProperties);
     3586          }
     3587        });
    35773588      } catch (e) {
    35783589        return {
     
    35883599        // HMR will already update the identity and reflow when it lands
    35893600        // `inFlightDataRoutes` in `completeNavigation`
    3590         if (isNonHMR) {
     3601        if (isNonHMR && !signal.aborted) {
    35913602          dataRoutes = [...dataRoutes];
    35923603        }
     
    35983609      }
    35993610      let newMatches = matchRoutes(routesToUse, pathname, basename);
    3600       let matchedSplat = false;
    36013611      if (newMatches) {
    3602         let leafRoute = newMatches[newMatches.length - 1].route;
    3603         if (leafRoute.index) {
    3604           // If we found an index route, we can stop
    3605           return {
    3606             type: "success",
    3607             matches: newMatches
    3608           };
    3609         }
    3610         if (leafRoute.path && leafRoute.path.length > 0) {
    3611           if (leafRoute.path === "*") {
    3612             // If we found a splat route, we can't be sure there's not a
    3613             // higher-scoring route down some partial matches trail so we need
    3614             // to check that out
    3615             matchedSplat = true;
    3616           } else {
    3617             // If we found a non-splat route, we can stop
    3618             return {
    3619               type: "success",
    3620               matches: newMatches
    3621             };
    3622           }
    3623         }
    3624       }
    3625       let newPartialMatches = matchRoutesImpl(routesToUse, pathname, basename, true);
    3626 
    3627       // If we are no longer partially matching anything, this was either a
    3628       // legit splat match above, or it's a 404.  Also avoid loops if the
    3629       // second pass results in the same partial matches
    3630       if (!newPartialMatches || partialMatches.map(m => m.route.id).join("-") === newPartialMatches.map(m => m.route.id).join("-")) {
    36313612        return {
    36323613          type: "success",
    3633           matches: matchedSplat ? newMatches : null
     3614          matches: newMatches
    36343615        };
    36353616      }
    3636       partialMatches = newPartialMatches;
    3637       route = partialMatches[partialMatches.length - 1].route;
    3638       if (route.path === "*") {
    3639         // The splat is still our most accurate partial, so run with it
     3617      let newPartialMatches = matchRoutesImpl(routesToUse, pathname, basename, true);
     3618
     3619      // Avoid loops if the second pass results in the same partial matches
     3620      if (!newPartialMatches || partialMatches.length === newPartialMatches.length && partialMatches.every((m, i) => m.route.id === newPartialMatches[i].route.id)) {
    36403621        return {
    36413622          type: "success",
    3642           matches: partialMatches
     3623          matches: null
    36433624        };
    36443625      }
     3626      partialMatches = newPartialMatches;
    36453627    }
    36463628  }
     
    37693751      requestContext,
    37703752      skipLoaderErrorBubbling,
    3771       unstable_dataStrategy
     3753      dataStrategy
    37723754    } = _temp3 === void 0 ? {} : _temp3;
    37733755    let url = new URL(request.url);
     
    38223804      };
    38233805    }
    3824     let result = await queryImpl(request, location, matches, requestContext, unstable_dataStrategy || null, skipLoaderErrorBubbling === true, null);
     3806    let result = await queryImpl(request, location, matches, requestContext, dataStrategy || null, skipLoaderErrorBubbling === true, null);
    38253807    if (isResponse(result)) {
    38263808      return result;
     
    38663848      routeId,
    38673849      requestContext,
    3868       unstable_dataStrategy
     3850      dataStrategy
    38693851    } = _temp4 === void 0 ? {} : _temp4;
    38703852    let url = new URL(request.url);
     
    38953877      });
    38963878    }
    3897     let result = await queryImpl(request, location, matches, requestContext, unstable_dataStrategy || null, false, match);
     3879    let result = await queryImpl(request, location, matches, requestContext, dataStrategy || null, false, match);
    38983880    if (isResponse(result)) {
    38993881      return result;
     
    39223904    return undefined;
    39233905  }
    3924   async function queryImpl(request, location, matches, requestContext, unstable_dataStrategy, skipLoaderErrorBubbling, routeMatch) {
     3906  async function queryImpl(request, location, matches, requestContext, dataStrategy, skipLoaderErrorBubbling, routeMatch) {
    39253907    invariant(request.signal, "query()/queryRoute() requests must contain an AbortController signal");
    39263908    try {
    39273909      if (isMutationMethod(request.method.toLowerCase())) {
    3928         let result = await submit(request, matches, routeMatch || getTargetMatch(matches, location), requestContext, unstable_dataStrategy, skipLoaderErrorBubbling, routeMatch != null);
     3910        let result = await submit(request, matches, routeMatch || getTargetMatch(matches, location), requestContext, dataStrategy, skipLoaderErrorBubbling, routeMatch != null);
    39293911        return result;
    39303912      }
    3931       let result = await loadRouteData(request, matches, requestContext, unstable_dataStrategy, skipLoaderErrorBubbling, routeMatch);
     3913      let result = await loadRouteData(request, matches, requestContext, dataStrategy, skipLoaderErrorBubbling, routeMatch);
    39323914      return isResponse(result) ? result : _extends({}, result, {
    39333915        actionData: null,
     
    39363918    } catch (e) {
    39373919      // If the user threw/returned a Response in callLoaderOrAction for a
    3938       // `queryRoute` call, we throw the `HandlerResult` to bail out early
     3920      // `queryRoute` call, we throw the `DataStrategyResult` to bail out early
    39393921      // and then return or throw the raw Response here accordingly
    3940       if (isHandlerResult(e) && isResponse(e.result)) {
     3922      if (isDataStrategyResult(e) && isResponse(e.result)) {
    39413923        if (e.type === ResultType.error) {
    39423924          throw e.result;
     
    39523934    }
    39533935  }
    3954   async function submit(request, matches, actionMatch, requestContext, unstable_dataStrategy, skipLoaderErrorBubbling, isRouteRequest) {
     3936  async function submit(request, matches, actionMatch, requestContext, dataStrategy, skipLoaderErrorBubbling, isRouteRequest) {
    39553937    let result;
    39563938    if (!actionMatch.route.action && !actionMatch.route.lazy) {
     
    39683950      };
    39693951    } else {
    3970       let results = await callDataStrategy("action", request, [actionMatch], matches, isRouteRequest, requestContext, unstable_dataStrategy);
    3971       result = results[0];
     3952      let results = await callDataStrategy("action", request, [actionMatch], matches, isRouteRequest, requestContext, dataStrategy);
     3953      result = results[actionMatch.route.id];
    39723954      if (request.signal.aborted) {
    39733955        throwStaticHandlerAbortedError(request, isRouteRequest, future);
     
    40304012      // to call and will commit it when we complete the navigation
    40314013      let boundaryMatch = skipLoaderErrorBubbling ? actionMatch : findNearestBoundary(matches, actionMatch.route.id);
    4032       let context = await loadRouteData(loaderRequest, matches, requestContext, unstable_dataStrategy, skipLoaderErrorBubbling, null, [boundaryMatch.route.id, result]);
     4014      let context = await loadRouteData(loaderRequest, matches, requestContext, dataStrategy, skipLoaderErrorBubbling, null, [boundaryMatch.route.id, result]);
    40334015
    40344016      // action status codes take precedence over loader status codes
     
    40414023      });
    40424024    }
    4043     let context = await loadRouteData(loaderRequest, matches, requestContext, unstable_dataStrategy, skipLoaderErrorBubbling, null);
     4025    let context = await loadRouteData(loaderRequest, matches, requestContext, dataStrategy, skipLoaderErrorBubbling, null);
    40444026    return _extends({}, context, {
    40454027      actionData: {
     
    40544036    });
    40554037  }
    4056   async function loadRouteData(request, matches, requestContext, unstable_dataStrategy, skipLoaderErrorBubbling, routeMatch, pendingActionResult) {
     4038  async function loadRouteData(request, matches, requestContext, dataStrategy, skipLoaderErrorBubbling, routeMatch, pendingActionResult) {
    40574039    let isRouteRequest = routeMatch != null;
    40584040
     
    40844066      };
    40854067    }
    4086     let results = await callDataStrategy("loader", request, matchesToLoad, matches, isRouteRequest, requestContext, unstable_dataStrategy);
     4068    let results = await callDataStrategy("loader", request, matchesToLoad, matches, isRouteRequest, requestContext, dataStrategy);
    40874069    if (request.signal.aborted) {
    40884070      throwStaticHandlerAbortedError(request, isRouteRequest, future);
     
    40914073    // Process and commit output from loaders
    40924074    let activeDeferreds = new Map();
    4093     let context = processRouteLoaderData(matches, matchesToLoad, results, pendingActionResult, activeDeferreds, skipLoaderErrorBubbling);
     4075    let context = processRouteLoaderData(matches, results, pendingActionResult, activeDeferreds, skipLoaderErrorBubbling);
    40944076
    40954077    // Add a null for any non-loader matches for proper revalidation on the client
     
    41084090  // Utility wrapper for calling dataStrategy server-side without having to
    41094091  // pass around the manifest, mapRouteProperties, etc.
    4110   async function callDataStrategy(type, request, matchesToLoad, matches, isRouteRequest, requestContext, unstable_dataStrategy) {
    4111     let results = await callDataStrategyImpl(unstable_dataStrategy || defaultDataStrategy, type, request, matchesToLoad, matches, manifest, mapRouteProperties, requestContext);
    4112     return await Promise.all(results.map((result, i) => {
    4113       if (isRedirectHandlerResult(result)) {
     4092  async function callDataStrategy(type, request, matchesToLoad, matches, isRouteRequest, requestContext, dataStrategy) {
     4093    let results = await callDataStrategyImpl(dataStrategy || defaultDataStrategy, type, null, request, matchesToLoad, matches, null, manifest, mapRouteProperties, requestContext);
     4094    let dataResults = {};
     4095    await Promise.all(matches.map(async match => {
     4096      if (!(match.route.id in results)) {
     4097        return;
     4098      }
     4099      let result = results[match.route.id];
     4100      if (isRedirectDataStrategyResultResult(result)) {
    41144101        let response = result.result;
    41154102        // Throw redirects and let the server handle them with an HTTP redirect
    4116         throw normalizeRelativeRoutingRedirectResponse(response, request, matchesToLoad[i].route.id, matches, basename, future.v7_relativeSplatPath);
     4103        throw normalizeRelativeRoutingRedirectResponse(response, request, match.route.id, matches, basename, future.v7_relativeSplatPath);
    41174104      }
    41184105      if (isResponse(result.result) && isRouteRequest) {
     
    41214108        throw result;
    41224109      }
    4123       return convertHandlerResultToDataResult(result);
     4110      dataResults[match.route.id] = await convertDataStrategyResultToDataResult(result);
    41244111    }));
     4112    return dataResults;
    41254113  }
    41264114  return {
     
    41904178  }
    41914179
    4192   // Add an ?index param for matched index routes if we don't already have one
    4193   if ((to == null || to === "" || to === ".") && activeRouteMatch && activeRouteMatch.route.index && !hasNakedIndexQuery(path.search)) {
    4194     path.search = path.search ? path.search.replace(/^\?/, "?index&") : "?index";
     4180  // Account for `?index` params when routing to the current location
     4181  if ((to == null || to === "" || to === ".") && activeRouteMatch) {
     4182    let nakedIndex = hasNakedIndexQuery(path.search);
     4183    if (activeRouteMatch.route.index && !nakedIndex) {
     4184      // Add one when we're targeting an index route
     4185      path.search = path.search ? path.search.replace(/^\?/, "?index&") : "?index";
     4186    } else if (!activeRouteMatch.route.index && nakedIndex) {
     4187      // Remove existing ones when we're not
     4188      let params = new URLSearchParams(path.search);
     4189      let indexValues = params.getAll("index");
     4190      params.delete("index");
     4191      indexValues.filter(v => v).forEach(v => params.append("index", v));
     4192      let qs = params.toString();
     4193      path.search = qs ? "?" + qs : "";
     4194    }
    41954195  }
    41964196
     
    42414241      let text = typeof opts.body === "string" ? opts.body : opts.body instanceof FormData || opts.body instanceof URLSearchParams ?
    42424242      // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#plain-text-form-data
    4243       Array.from(opts.body.entries()).reduce((acc, _ref5) => {
    4244         let [name, value] = _ref5;
     4243      Array.from(opts.body.entries()).reduce((acc, _ref3) => {
     4244        let [name, value] = _ref3;
    42454245        return "" + acc + name + "=" + value + "\n";
    42464246      }, "") : String(opts.body);
     
    43324332}
    43334333
    4334 // Filter out all routes below any caught error as they aren't going to
     4334// Filter out all routes at/below any caught error as they aren't going to
    43354335// render so we don't need to load them
    4336 function getLoaderMatchesUntilBoundary(matches, boundaryId) {
    4337   let boundaryMatches = matches;
    4338   if (boundaryId) {
    4339     let index = matches.findIndex(m => m.route.id === boundaryId);
    4340     if (index >= 0) {
    4341       boundaryMatches = matches.slice(0, index);
    4342     }
    4343   }
    4344   return boundaryMatches;
    4345 }
    4346 function getMatchesToLoad(history, state, matches, submission, location, isInitialLoad, skipActionErrorRevalidation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, pendingActionResult) {
     4336function getLoaderMatchesUntilBoundary(matches, boundaryId, includeBoundary) {
     4337  if (includeBoundary === void 0) {
     4338    includeBoundary = false;
     4339  }
     4340  let index = matches.findIndex(m => m.route.id === boundaryId);
     4341  if (index >= 0) {
     4342    return matches.slice(0, includeBoundary ? index + 1 : index);
     4343  }
     4344  return matches;
     4345}
     4346function getMatchesToLoad(history, state, matches, submission, location, initialHydration, skipActionErrorRevalidation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, pendingActionResult) {
    43474347  let actionResult = pendingActionResult ? isErrorResult(pendingActionResult[1]) ? pendingActionResult[1].error : pendingActionResult[1].data : undefined;
    43484348  let currentUrl = history.createURL(state.location);
     
    43504350
    43514351  // Pick navigation matches that are net-new or qualify for revalidation
    4352   let boundaryId = pendingActionResult && isErrorResult(pendingActionResult[1]) ? pendingActionResult[0] : undefined;
    4353   let boundaryMatches = boundaryId ? getLoaderMatchesUntilBoundary(matches, boundaryId) : matches;
     4352  let boundaryMatches = matches;
     4353  if (initialHydration && state.errors) {
     4354    // On initial hydration, only consider matches up to _and including_ the boundary.
     4355    // This is inclusive to handle cases where a server loader ran successfully,
     4356    // a child server loader bubbled up to this route, but this route has
     4357    // `clientLoader.hydrate` so we want to still run the `clientLoader` so that
     4358    // we have a complete version of `loaderData`
     4359    boundaryMatches = getLoaderMatchesUntilBoundary(matches, Object.keys(state.errors)[0], true);
     4360  } else if (pendingActionResult && isErrorResult(pendingActionResult[1])) {
     4361    // If an action threw an error, we call loaders up to, but not including the
     4362    // boundary
     4363    boundaryMatches = getLoaderMatchesUntilBoundary(matches, pendingActionResult[0]);
     4364  }
    43544365
    43554366  // Don't revalidate loaders by default after action 4xx/5xx responses
     
    43694380      return false;
    43704381    }
    4371     if (isInitialLoad) {
    4372       if (typeof route.loader !== "function" || route.loader.hydrate) {
    4373         return true;
    4374       }
    4375       return state.loaderData[route.id] === undefined && (
    4376       // Don't re-run if the loader ran and threw an error
    4377       !state.errors || state.errors[route.id] === undefined);
     4382    if (initialHydration) {
     4383      return shouldLoadRouteOnHydration(route, state.loaderData, state.errors);
    43784384    }
    43794385
     
    44094415  fetchLoadMatches.forEach((f, key) => {
    44104416    // Don't revalidate:
    4411     //  - on initial load (shouldn't be any fetchers then anyway)
     4417    //  - on initial hydration (shouldn't be any fetchers then anyway)
    44124418    //  - if fetcher won't be present in the subsequent render
    44134419    //    - no longer matches the URL (v7_fetcherPersist=false)
    44144420    //    - was unmounted but persisted due to v7_fetcherPersist=true
    4415     if (isInitialLoad || !matches.some(m => m.route.id === f.routeId) || deletedFetchers.has(key)) {
     4421    if (initialHydration || !matches.some(m => m.route.id === f.routeId) || deletedFetchers.has(key)) {
    44164422      return;
    44174423    }
     
    44794485  return [navigationMatches, revalidatingFetchers];
    44804486}
     4487function shouldLoadRouteOnHydration(route, loaderData, errors) {
     4488  // We dunno if we have a loader - gotta find out!
     4489  if (route.lazy) {
     4490    return true;
     4491  }
     4492
     4493  // No loader, nothing to initialize
     4494  if (!route.loader) {
     4495    return false;
     4496  }
     4497  let hasData = loaderData != null && loaderData[route.id] !== undefined;
     4498  let hasError = errors != null && errors[route.id] !== undefined;
     4499
     4500  // Don't run if we error'd during SSR
     4501  if (!hasData && hasError) {
     4502    return false;
     4503  }
     4504
     4505  // Explicitly opting-in to running on hydration
     4506  if (typeof route.loader === "function" && route.loader.hydrate === true) {
     4507    return true;
     4508  }
     4509
     4510  // Otherwise, run if we're not yet initialized with anything
     4511  return !hasData && !hasError;
     4512}
    44814513function isNewLoader(currentLoaderData, currentMatch, match) {
    44824514  let isNew =
     
    45124544  return arg.defaultShouldRevalidate;
    45134545}
    4514 
    4515 /**
    4516  * Idempotent utility to execute patchRoutesOnMiss() to lazily load route
    4517  * definitions and update the routes/routeManifest
    4518  */
    4519 async function loadLazyRouteChildren(patchRoutesOnMissImpl, path, matches, routes, manifest, mapRouteProperties, pendingRouteChildren, signal) {
    4520   let key = [path, ...matches.map(m => m.route.id)].join("-");
    4521   try {
    4522     let pending = pendingRouteChildren.get(key);
    4523     if (!pending) {
    4524       pending = patchRoutesOnMissImpl({
    4525         path,
    4526         matches,
    4527         patch: (routeId, children) => {
    4528           if (!signal.aborted) {
    4529             patchRoutesImpl(routeId, children, routes, manifest, mapRouteProperties);
    4530           }
    4531         }
    4532       });
    4533       pendingRouteChildren.set(key, pending);
    4534     }
    4535     if (pending && isPromise(pending)) {
    4536       await pending;
    4537     }
    4538   } finally {
    4539     pendingRouteChildren.delete(key);
    4540   }
    4541 }
    45424546function patchRoutesImpl(routeId, children, routesToUse, manifest, mapRouteProperties) {
     4547  var _childrenToPatch;
     4548  let childrenToPatch;
    45434549  if (routeId) {
    4544     var _route$children;
    45454550    let route = manifest[routeId];
    45464551    invariant(route, "No route found to patch children into: routeId = " + routeId);
    4547     let dataChildren = convertRoutesToDataRoutes(children, mapRouteProperties, [routeId, "patch", String(((_route$children = route.children) == null ? void 0 : _route$children.length) || "0")], manifest);
    4548     if (route.children) {
    4549       route.children.push(...dataChildren);
    4550     } else {
    4551       route.children = dataChildren;
    4552     }
     4552    if (!route.children) {
     4553      route.children = [];
     4554    }
     4555    childrenToPatch = route.children;
    45534556  } else {
    4554     let dataChildren = convertRoutesToDataRoutes(children, mapRouteProperties, ["patch", String(routesToUse.length || "0")], manifest);
    4555     routesToUse.push(...dataChildren);
    4556   }
     4557    childrenToPatch = routesToUse;
     4558  }
     4559
     4560  // Don't patch in routes we already know about so that `patch` is idempotent
     4561  // to simplify user-land code. This is useful because we re-call the
     4562  // `patchRoutesOnNavigation` function for matched routes with params.
     4563  let uniqueChildren = children.filter(newRoute => !childrenToPatch.some(existingRoute => isSameRoute(newRoute, existingRoute)));
     4564  let newRoutes = convertRoutesToDataRoutes(uniqueChildren, mapRouteProperties, [routeId || "_", "patch", String(((_childrenToPatch = childrenToPatch) == null ? void 0 : _childrenToPatch.length) || "0")], manifest);
     4565  childrenToPatch.push(...newRoutes);
     4566}
     4567function isSameRoute(newRoute, existingRoute) {
     4568  // Most optimal check is by id
     4569  if ("id" in newRoute && "id" in existingRoute && newRoute.id === existingRoute.id) {
     4570    return true;
     4571  }
     4572
     4573  // Second is by pathing differences
     4574  if (!(newRoute.index === existingRoute.index && newRoute.path === existingRoute.path && newRoute.caseSensitive === existingRoute.caseSensitive)) {
     4575    return false;
     4576  }
     4577
     4578  // Pathless layout routes are trickier since we need to check children.
     4579  // If they have no children then they're the same as far as we can tell
     4580  if ((!newRoute.children || newRoute.children.length === 0) && (!existingRoute.children || existingRoute.children.length === 0)) {
     4581    return true;
     4582  }
     4583
     4584  // Otherwise, we look to see if every child in the new route is already
     4585  // represented in the existing route's children
     4586  return newRoute.children.every((aChild, i) => {
     4587    var _existingRoute$childr;
     4588    return (_existingRoute$childr = existingRoute.children) == null ? void 0 : _existingRoute$childr.some(bChild => isSameRoute(aChild, bChild));
     4589  });
    45574590}
    45584591
     
    46114644
    46124645// Default implementation of `dataStrategy` which fetches all loaders in parallel
    4613 function defaultDataStrategy(opts) {
    4614   return Promise.all(opts.matches.map(m => m.resolve()));
    4615 }
    4616 async function callDataStrategyImpl(dataStrategyImpl, type, request, matchesToLoad, matches, manifest, mapRouteProperties, requestContext) {
    4617   let routeIdsToLoad = matchesToLoad.reduce((acc, m) => acc.add(m.route.id), new Set());
    4618   let loadedMatches = new Set();
     4646async function defaultDataStrategy(_ref4) {
     4647  let {
     4648    matches
     4649  } = _ref4;
     4650  let matchesToLoad = matches.filter(m => m.shouldLoad);
     4651  let results = await Promise.all(matchesToLoad.map(m => m.resolve()));
     4652  return results.reduce((acc, result, i) => Object.assign(acc, {
     4653    [matchesToLoad[i].route.id]: result
     4654  }), {});
     4655}
     4656async function callDataStrategyImpl(dataStrategyImpl, type, state, request, matchesToLoad, matches, fetcherKey, manifest, mapRouteProperties, requestContext) {
     4657  let loadRouteDefinitionsPromises = matches.map(m => m.route.lazy ? loadLazyRouteModule(m.route, mapRouteProperties, manifest) : undefined);
     4658  let dsMatches = matches.map((match, i) => {
     4659    let loadRoutePromise = loadRouteDefinitionsPromises[i];
     4660    let shouldLoad = matchesToLoad.some(m => m.route.id === match.route.id);
     4661    // `resolve` encapsulates route.lazy(), executing the loader/action,
     4662    // and mapping return values/thrown errors to a `DataStrategyResult`.  Users
     4663    // can pass a callback to take fine-grained control over the execution
     4664    // of the loader/action
     4665    let resolve = async handlerOverride => {
     4666      if (handlerOverride && request.method === "GET" && (match.route.lazy || match.route.loader)) {
     4667        shouldLoad = true;
     4668      }
     4669      return shouldLoad ? callLoaderOrAction(type, request, match, loadRoutePromise, handlerOverride, requestContext) : Promise.resolve({
     4670        type: ResultType.data,
     4671        result: undefined
     4672      });
     4673    };
     4674    return _extends({}, match, {
     4675      shouldLoad,
     4676      resolve
     4677    });
     4678  });
    46194679
    46204680  // Send all matches here to allow for a middleware-type implementation.
     
    46224682  // back out below.
    46234683  let results = await dataStrategyImpl({
    4624     matches: matches.map(match => {
    4625       let shouldLoad = routeIdsToLoad.has(match.route.id);
    4626       // `resolve` encapsulates the route.lazy, executing the
    4627       // loader/action, and mapping return values/thrown errors to a
    4628       // HandlerResult.  Users can pass a callback to take fine-grained control
    4629       // over the execution of the loader/action
    4630       let resolve = handlerOverride => {
    4631         loadedMatches.add(match.route.id);
    4632         return shouldLoad ? callLoaderOrAction(type, request, match, manifest, mapRouteProperties, handlerOverride, requestContext) : Promise.resolve({
    4633           type: ResultType.data,
    4634           result: undefined
    4635         });
    4636       };
    4637       return _extends({}, match, {
    4638         shouldLoad,
    4639         resolve
    4640       });
    4641     }),
     4684    matches: dsMatches,
    46424685    request,
    46434686    params: matches[0].params,
     4687    fetcherKey,
    46444688    context: requestContext
    46454689  });
    46464690
    4647   // Throw if any loadRoute implementations not called since they are what
    4648   // ensures a route is fully loaded
    4649   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."));
    4650 
    4651   // Filter out any middleware-only matches for which we didn't need to run handlers
    4652   return results.filter((_, i) => routeIdsToLoad.has(matches[i].route.id));
     4691  // Wait for all routes to load here but 'swallow the error since we want
     4692  // it to bubble up from the `await loadRoutePromise` in `callLoaderOrAction` -
     4693  // called from `match.resolve()`
     4694  try {
     4695    await Promise.all(loadRouteDefinitionsPromises);
     4696  } catch (e) {
     4697    // No-op
     4698  }
     4699  return results;
    46534700}
    46544701
    46554702// Default logic for calling a loader/action is the user has no specified a dataStrategy
    4656 async function callLoaderOrAction(type, request, match, manifest, mapRouteProperties, handlerOverride, staticContext) {
     4703async function callLoaderOrAction(type, request, match, loadRoutePromise, handlerOverride, staticContext) {
    46574704  let result;
    46584705  let onReject;
     
    46604707    // Setup a promise we can race against so that abort signals short circuit
    46614708    let reject;
    4662     // This will never resolve so safe to type it as Promise<HandlerResult> to
     4709    // This will never resolve so safe to type it as Promise<DataStrategyResult> to
    46634710    // satisfy the function return value
    46644711    let abortPromise = new Promise((_, r) => reject = r);
     
    46754722      }, ...(ctx !== undefined ? [ctx] : []));
    46764723    };
    4677     let handlerPromise;
    4678     if (handlerOverride) {
    4679       handlerPromise = handlerOverride(ctx => actualHandler(ctx));
    4680     } else {
    4681       handlerPromise = (async () => {
    4682         try {
    4683           let val = await actualHandler();
    4684           return {
    4685             type: "data",
    4686             result: val
    4687           };
    4688         } catch (e) {
    4689           return {
    4690             type: "error",
    4691             result: e
    4692           };
    4693         }
    4694       })();
    4695     }
     4724    let handlerPromise = (async () => {
     4725      try {
     4726        let val = await (handlerOverride ? handlerOverride(ctx => actualHandler(ctx)) : actualHandler());
     4727        return {
     4728          type: "data",
     4729          result: val
     4730        };
     4731      } catch (e) {
     4732        return {
     4733          type: "error",
     4734          result: e
     4735        };
     4736      }
     4737    })();
    46964738    return Promise.race([handlerPromise, abortPromise]);
    46974739  };
    46984740  try {
    46994741    let handler = match.route[type];
    4700     if (match.route.lazy) {
     4742
     4743    // If we have a route.lazy promise, await that first
     4744    if (loadRoutePromise) {
    47014745      if (handler) {
    47024746        // Run statically defined handler in parallel with lazy()
     
    47084752        runHandler(handler).catch(e => {
    47094753          handlerError = e;
    4710         }), loadLazyRouteModule(match.route, mapRouteProperties, manifest)]);
     4754        }), loadRoutePromise]);
    47114755        if (handlerError !== undefined) {
    47124756          throw handlerError;
     
    47154759      } else {
    47164760        // Load lazy route module, then run any returned handler
    4717         await loadLazyRouteModule(match.route, mapRouteProperties, manifest);
     4761        await loadRoutePromise;
    47184762        handler = match.route[type];
    47194763        if (handler) {
     
    47514795  } catch (e) {
    47524796    // We should already be catching and converting normal handler executions to
    4753     // HandlerResults and returning them, so anything that throws here is an
     4797    // DataStrategyResults and returning them, so anything that throws here is an
    47544798    // unexpected error we still need to wrap
    47554799    return {
     
    47644808  return result;
    47654809}
    4766 async function convertHandlerResultToDataResult(handlerResult) {
     4810async function convertDataStrategyResultToDataResult(dataStrategyResult) {
    47674811  let {
    47684812    result,
    47694813    type
    4770   } = handlerResult;
     4814  } = dataStrategyResult;
    47714815  if (isResponse(result)) {
    47724816    let data;
     
    48174861      }
    48184862
    4819       // Convert thrown unstable_data() to ErrorResponse instances
     4863      // Convert thrown data() to ErrorResponse instances
    48204864      result = new ErrorResponseImpl(((_result$init2 = result.init) == null ? void 0 : _result$init2.status) || 500, undefined, result.data);
    48214865    }
     
    49244968  return formData;
    49254969}
    4926 function processRouteLoaderData(matches, matchesToLoad, results, pendingActionResult, activeDeferreds, skipLoaderErrorBubbling) {
     4970function processRouteLoaderData(matches, results, pendingActionResult, activeDeferreds, skipLoaderErrorBubbling) {
    49274971  // Fill in loaderData/errors from our loaders
    49284972  let loaderData = {};
     
    49344978
    49354979  // Process loader results into state.loaderData/state.errors
    4936   results.forEach((result, index) => {
    4937     let id = matchesToLoad[index].route.id;
     4980  matches.forEach(match => {
     4981    if (!(match.route.id in results)) {
     4982      return;
     4983    }
     4984    let id = match.route.id;
     4985    let result = results[id];
    49384986    invariant(!isRedirectResult(result), "Cannot handle redirect results in processLoaderData");
    49394987    if (isErrorResult(result)) {
     
    50135061  };
    50145062}
    5015 function processLoaderData(state, matches, matchesToLoad, results, pendingActionResult, revalidatingFetchers, fetcherResults, activeDeferreds) {
     5063function processLoaderData(state, matches, results, pendingActionResult, revalidatingFetchers, fetcherResults, activeDeferreds) {
    50165064  let {
    50175065    loaderData,
    50185066    errors
    5019   } = processRouteLoaderData(matches, matchesToLoad, results, pendingActionResult, activeDeferreds, false // This method is only called client side so we always want to bubble
     5067  } = processRouteLoaderData(matches, results, pendingActionResult, activeDeferreds, false // This method is only called client side so we always want to bubble
    50205068  );
    50215069
    50225070  // Process results from our revalidating fetchers
    5023   for (let index = 0; index < revalidatingFetchers.length; index++) {
     5071  revalidatingFetchers.forEach(rf => {
    50245072    let {
    50255073      key,
    50265074      match,
    50275075      controller
    5028     } = revalidatingFetchers[index];
    5029     invariant(fetcherResults !== undefined && fetcherResults[index] !== undefined, "Did not find corresponding fetcher result");
    5030     let result = fetcherResults[index];
     5076    } = rf;
     5077    let result = fetcherResults[key];
     5078    invariant(result, "Did not find corresponding fetcher result");
    50315079
    50325080    // Process fetcher non-redirect errors
    50335081    if (controller && controller.signal.aborted) {
    50345082      // Nothing to do for aborted fetchers
    5035       continue;
     5083      return;
    50365084    } else if (isErrorResult(result)) {
    50375085      let boundaryMatch = findNearestBoundary(state.matches, match == null ? void 0 : match.route.id);
     
    50545102      state.fetchers.set(key, doneFetcher);
    50555103    }
    5056   }
     5104  });
    50575105  return {
    50585106    loaderData,
     
    51285176  if (status === 400) {
    51295177    statusText = "Bad Request";
    5130     if (type === "route-discovery") {
    5131       errorMessage = "Unable to match URL \"" + pathname + "\" - the `unstable_patchRoutesOnMiss()` " + ("function threw the following error:\n" + message);
    5132     } else if (method && pathname && routeId) {
     5178    if (method && pathname && routeId) {
    51335179      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.";
    51345180    } else if (type === "defer-action") {
     
    51565202// Find any returned redirect errors, starting from the lowest match
    51575203function findRedirect(results) {
    5158   for (let i = results.length - 1; i >= 0; i--) {
    5159     let result = results[i];
     5204  let entries = Object.entries(results);
     5205  for (let i = entries.length - 1; i >= 0; i--) {
     5206    let [key, result] = entries[i];
    51605207    if (isRedirectResult(result)) {
    51615208      return {
    5162         result,
    5163         idx: i
     5209        key,
     5210        result
    51645211      };
    51655212    }
     
    51915238  return false;
    51925239}
    5193 function isPromise(val) {
    5194   return typeof val === "object" && val != null && "then" in val;
    5195 }
    5196 function isHandlerResult(result) {
     5240function isDataStrategyResult(result) {
    51975241  return result != null && typeof result === "object" && "type" in result && "result" in result && (result.type === ResultType.data || result.type === ResultType.error);
    51985242}
    5199 function isRedirectHandlerResult(result) {
     5243function isRedirectDataStrategyResultResult(result) {
    52005244  return isResponse(result.result) && redirectStatusCodes.has(result.result.status);
    52015245}
     
    52335277  return validMutationMethods.has(method.toLowerCase());
    52345278}
    5235 async function resolveDeferredResults(currentMatches, matchesToLoad, results, signals, isFetcher, currentLoaderData) {
    5236   for (let index = 0; index < results.length; index++) {
    5237     let result = results[index];
    5238     let match = matchesToLoad[index];
     5279async function resolveNavigationDeferredResults(matches, results, signal, currentMatches, currentLoaderData) {
     5280  let entries = Object.entries(results);
     5281  for (let index = 0; index < entries.length; index++) {
     5282    let [routeId, result] = entries[index];
     5283    let match = matches.find(m => (m == null ? void 0 : m.route.id) === routeId);
    52395284    // If we don't have a match, then we can have a deferred result to do
    52405285    // anything with.  This is for revalidating fetchers where the route was
     
    52455290    let currentMatch = currentMatches.find(m => m.route.id === match.route.id);
    52465291    let isRevalidatingLoader = currentMatch != null && !isNewRouteInstance(currentMatch, match) && (currentLoaderData && currentLoaderData[match.route.id]) !== undefined;
    5247     if (isDeferredResult(result) && (isFetcher || isRevalidatingLoader)) {
     5292    if (isDeferredResult(result) && isRevalidatingLoader) {
    52485293      // Note: we do not have to touch activeDeferreds here since we race them
    52495294      // against the signal in resolveDeferredData and they'll get aborted
    52505295      // there if needed
    5251       let signal = signals[index];
    5252       invariant(signal, "Expected an AbortSignal for revalidating fetcher deferred result");
    5253       await resolveDeferredData(result, signal, isFetcher).then(result => {
     5296      await resolveDeferredData(result, signal, false).then(result => {
    52545297        if (result) {
    5255           results[index] = result || results[index];
     5298          results[routeId] = result;
     5299        }
     5300      });
     5301    }
     5302  }
     5303}
     5304async function resolveFetcherDeferredResults(matches, results, revalidatingFetchers) {
     5305  for (let index = 0; index < revalidatingFetchers.length; index++) {
     5306    let {
     5307      key,
     5308      routeId,
     5309      controller
     5310    } = revalidatingFetchers[index];
     5311    let result = results[key];
     5312    let match = matches.find(m => (m == null ? void 0 : m.route.id) === routeId);
     5313    // If we don't have a match, then we can have a deferred result to do
     5314    // anything with.  This is for revalidating fetchers where the route was
     5315    // removed during HMR
     5316    if (!match) {
     5317      continue;
     5318    }
     5319    if (isDeferredResult(result)) {
     5320      // Note: we do not have to touch activeDeferreds here since we race them
     5321      // against the signal in resolveDeferredData and they'll get aborted
     5322      // there if needed
     5323      invariant(controller, "Expected an AbortController for revalidating fetcher deferred result");
     5324      await resolveDeferredData(result, controller.signal, true).then(result => {
     5325        if (result) {
     5326          results[key] = result;
    52565327        }
    52575328      });
     
    54845555exports.createRouter = createRouter;
    54855556exports.createStaticHandler = createStaticHandler;
     5557exports.data = data;
    54865558exports.defer = defer;
    54875559exports.generatePath = generatePath;
     
    55035575exports.resolveTo = resolveTo;
    55045576exports.stripBasename = stripBasename;
    5505 exports.unstable_data = data;
    55065577//# sourceMappingURL=router.cjs.js.map
Note: See TracChangeset for help on using the changeset viewer.