@remix-run/router 1.19.1 → 1.19.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/dist/index.d.ts +1 -1
- package/dist/router.cjs.js +246 -163
- package/dist/router.cjs.js.map +1 -1
- package/dist/router.js +241 -158
- package/dist/router.js.map +1 -1
- package/dist/router.umd.js +246 -163
- package/dist/router.umd.js.map +1 -1
- package/dist/router.umd.min.js +2 -2
- package/dist/router.umd.min.js.map +1 -1
- package/dist/utils.d.ts +10 -9
- package/index.ts +1 -1
- package/package.json +1 -1
- package/router.ts +334 -229
- package/utils.ts +12 -11
package/router.ts
CHANGED
|
@@ -22,7 +22,7 @@ import type {
|
|
|
22
22
|
FormEncType,
|
|
23
23
|
FormMethod,
|
|
24
24
|
HTMLFormMethod,
|
|
25
|
-
|
|
25
|
+
DataStrategyResult,
|
|
26
26
|
ImmutableRouteKey,
|
|
27
27
|
MapRoutePropertiesFunction,
|
|
28
28
|
MutationFormMethod,
|
|
@@ -1033,7 +1033,7 @@ export function createRouter(init: RouterInit): Router {
|
|
|
1033
1033
|
|
|
1034
1034
|
// Flag to ignore the next history update, so we can revert the URL change on
|
|
1035
1035
|
// a POP navigation that was blocked by the user without touching router state
|
|
1036
|
-
let
|
|
1036
|
+
let unblockBlockerHistoryUpdate: (() => void) | undefined = undefined;
|
|
1037
1037
|
|
|
1038
1038
|
// Initialize the router, all side effects should be kicked off from here.
|
|
1039
1039
|
// Implemented as a Fluent API for ease of:
|
|
@@ -1045,8 +1045,9 @@ export function createRouter(init: RouterInit): Router {
|
|
|
1045
1045
|
({ action: historyAction, location, delta }) => {
|
|
1046
1046
|
// Ignore this event if it was just us resetting the URL from a
|
|
1047
1047
|
// blocked POP navigation
|
|
1048
|
-
if (
|
|
1049
|
-
|
|
1048
|
+
if (unblockBlockerHistoryUpdate) {
|
|
1049
|
+
unblockBlockerHistoryUpdate();
|
|
1050
|
+
unblockBlockerHistoryUpdate = undefined;
|
|
1050
1051
|
return;
|
|
1051
1052
|
}
|
|
1052
1053
|
|
|
@@ -1068,7 +1069,9 @@ export function createRouter(init: RouterInit): Router {
|
|
|
1068
1069
|
|
|
1069
1070
|
if (blockerKey && delta != null) {
|
|
1070
1071
|
// Restore the URL to match the current UI, but don't update router state
|
|
1071
|
-
|
|
1072
|
+
let nextHistoryUpdatePromise = new Promise<void>((resolve) => {
|
|
1073
|
+
unblockBlockerHistoryUpdate = resolve;
|
|
1074
|
+
});
|
|
1072
1075
|
init.history.go(delta * -1);
|
|
1073
1076
|
|
|
1074
1077
|
// Put the blocker into a blocked state
|
|
@@ -1082,8 +1085,10 @@ export function createRouter(init: RouterInit): Router {
|
|
|
1082
1085
|
reset: undefined,
|
|
1083
1086
|
location,
|
|
1084
1087
|
});
|
|
1085
|
-
// Re-do the same POP navigation we just blocked
|
|
1086
|
-
|
|
1088
|
+
// Re-do the same POP navigation we just blocked, after the url
|
|
1089
|
+
// restoration is also complete. See:
|
|
1090
|
+
// https://github.com/remix-run/react-router/issues/11613
|
|
1091
|
+
nextHistoryUpdatePromise.then(() => init.history.go(delta));
|
|
1087
1092
|
},
|
|
1088
1093
|
reset() {
|
|
1089
1094
|
let blockers = new Map(state.blockers);
|
|
@@ -1479,7 +1484,11 @@ export function createRouter(init: RouterInit): Router {
|
|
|
1479
1484
|
startNavigation(
|
|
1480
1485
|
pendingAction || state.historyAction,
|
|
1481
1486
|
state.navigation.location,
|
|
1482
|
-
{
|
|
1487
|
+
{
|
|
1488
|
+
overrideNavigation: state.navigation,
|
|
1489
|
+
// Proxy through any rending view transition
|
|
1490
|
+
enableViewTransition: pendingViewTransitionEnabled === true,
|
|
1491
|
+
}
|
|
1483
1492
|
);
|
|
1484
1493
|
}
|
|
1485
1494
|
|
|
@@ -1749,11 +1758,13 @@ export function createRouter(init: RouterInit): Router {
|
|
|
1749
1758
|
} else {
|
|
1750
1759
|
let results = await callDataStrategy(
|
|
1751
1760
|
"action",
|
|
1761
|
+
state,
|
|
1752
1762
|
request,
|
|
1753
1763
|
[actionMatch],
|
|
1754
|
-
matches
|
|
1764
|
+
matches,
|
|
1765
|
+
null
|
|
1755
1766
|
);
|
|
1756
|
-
result = results[
|
|
1767
|
+
result = results[actionMatch.route.id];
|
|
1757
1768
|
|
|
1758
1769
|
if (request.signal.aborted) {
|
|
1759
1770
|
return { shortCircuited: true };
|
|
@@ -1775,7 +1786,7 @@ export function createRouter(init: RouterInit): Router {
|
|
|
1775
1786
|
);
|
|
1776
1787
|
replace = location === state.location.pathname + state.location.search;
|
|
1777
1788
|
}
|
|
1778
|
-
await startRedirectNavigation(request, result, {
|
|
1789
|
+
await startRedirectNavigation(request, result, true, {
|
|
1779
1790
|
submission,
|
|
1780
1791
|
replace,
|
|
1781
1792
|
});
|
|
@@ -1995,7 +2006,7 @@ export function createRouter(init: RouterInit): Router {
|
|
|
1995
2006
|
|
|
1996
2007
|
let { loaderResults, fetcherResults } =
|
|
1997
2008
|
await callLoadersAndMaybeResolveData(
|
|
1998
|
-
state
|
|
2009
|
+
state,
|
|
1999
2010
|
matches,
|
|
2000
2011
|
matchesToLoad,
|
|
2001
2012
|
revalidatingFetchers,
|
|
@@ -2018,17 +2029,21 @@ export function createRouter(init: RouterInit): Router {
|
|
|
2018
2029
|
revalidatingFetchers.forEach((rf) => fetchControllers.delete(rf.key));
|
|
2019
2030
|
|
|
2020
2031
|
// If any loaders returned a redirect Response, start a new REPLACE navigation
|
|
2021
|
-
let redirect = findRedirect(
|
|
2032
|
+
let redirect = findRedirect(loaderResults);
|
|
2022
2033
|
if (redirect) {
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2034
|
+
await startRedirectNavigation(request, redirect.result, true, {
|
|
2035
|
+
replace,
|
|
2036
|
+
});
|
|
2037
|
+
return { shortCircuited: true };
|
|
2038
|
+
}
|
|
2039
|
+
|
|
2040
|
+
redirect = findRedirect(fetcherResults);
|
|
2041
|
+
if (redirect) {
|
|
2042
|
+
// If this redirect came from a fetcher make sure we mark it in
|
|
2043
|
+
// fetchRedirectIds so it doesn't get revalidated on the next set of
|
|
2044
|
+
// loader executions
|
|
2045
|
+
fetchRedirectIds.add(redirect.key);
|
|
2046
|
+
await startRedirectNavigation(request, redirect.result, true, {
|
|
2032
2047
|
replace,
|
|
2033
2048
|
});
|
|
2034
2049
|
return { shortCircuited: true };
|
|
@@ -2287,11 +2302,13 @@ export function createRouter(init: RouterInit): Router {
|
|
|
2287
2302
|
let originatingLoadId = incrementingLoadId;
|
|
2288
2303
|
let actionResults = await callDataStrategy(
|
|
2289
2304
|
"action",
|
|
2305
|
+
state,
|
|
2290
2306
|
fetchRequest,
|
|
2291
2307
|
[match],
|
|
2292
|
-
requestMatches
|
|
2308
|
+
requestMatches,
|
|
2309
|
+
key
|
|
2293
2310
|
);
|
|
2294
|
-
let actionResult = actionResults[
|
|
2311
|
+
let actionResult = actionResults[match.route.id];
|
|
2295
2312
|
|
|
2296
2313
|
if (fetchRequest.signal.aborted) {
|
|
2297
2314
|
// We can delete this so long as we weren't aborted by our own fetcher
|
|
@@ -2324,7 +2341,7 @@ export function createRouter(init: RouterInit): Router {
|
|
|
2324
2341
|
} else {
|
|
2325
2342
|
fetchRedirectIds.add(key);
|
|
2326
2343
|
updateFetcherState(key, getLoadingFetcher(submission));
|
|
2327
|
-
return startRedirectNavigation(fetchRequest, actionResult, {
|
|
2344
|
+
return startRedirectNavigation(fetchRequest, actionResult, false, {
|
|
2328
2345
|
fetcherSubmission: submission,
|
|
2329
2346
|
});
|
|
2330
2347
|
}
|
|
@@ -2415,7 +2432,7 @@ export function createRouter(init: RouterInit): Router {
|
|
|
2415
2432
|
|
|
2416
2433
|
let { loaderResults, fetcherResults } =
|
|
2417
2434
|
await callLoadersAndMaybeResolveData(
|
|
2418
|
-
state
|
|
2435
|
+
state,
|
|
2419
2436
|
matches,
|
|
2420
2437
|
matchesToLoad,
|
|
2421
2438
|
revalidatingFetchers,
|
|
@@ -2435,23 +2452,32 @@ export function createRouter(init: RouterInit): Router {
|
|
|
2435
2452
|
fetchControllers.delete(key);
|
|
2436
2453
|
revalidatingFetchers.forEach((r) => fetchControllers.delete(r.key));
|
|
2437
2454
|
|
|
2438
|
-
let redirect = findRedirect(
|
|
2455
|
+
let redirect = findRedirect(loaderResults);
|
|
2439
2456
|
if (redirect) {
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2457
|
+
return startRedirectNavigation(
|
|
2458
|
+
revalidationRequest,
|
|
2459
|
+
redirect.result,
|
|
2460
|
+
false
|
|
2461
|
+
);
|
|
2462
|
+
}
|
|
2463
|
+
|
|
2464
|
+
redirect = findRedirect(fetcherResults);
|
|
2465
|
+
if (redirect) {
|
|
2466
|
+
// If this redirect came from a fetcher make sure we mark it in
|
|
2467
|
+
// fetchRedirectIds so it doesn't get revalidated on the next set of
|
|
2468
|
+
// loader executions
|
|
2469
|
+
fetchRedirectIds.add(redirect.key);
|
|
2470
|
+
return startRedirectNavigation(
|
|
2471
|
+
revalidationRequest,
|
|
2472
|
+
redirect.result,
|
|
2473
|
+
false
|
|
2474
|
+
);
|
|
2449
2475
|
}
|
|
2450
2476
|
|
|
2451
2477
|
// Process and commit output from loaders
|
|
2452
2478
|
let { loaderData, errors } = processLoaderData(
|
|
2453
2479
|
state,
|
|
2454
|
-
|
|
2480
|
+
matches,
|
|
2455
2481
|
matchesToLoad,
|
|
2456
2482
|
loaderResults,
|
|
2457
2483
|
undefined,
|
|
@@ -2564,11 +2590,13 @@ export function createRouter(init: RouterInit): Router {
|
|
|
2564
2590
|
let originatingLoadId = incrementingLoadId;
|
|
2565
2591
|
let results = await callDataStrategy(
|
|
2566
2592
|
"loader",
|
|
2593
|
+
state,
|
|
2567
2594
|
fetchRequest,
|
|
2568
2595
|
[match],
|
|
2569
|
-
matches
|
|
2596
|
+
matches,
|
|
2597
|
+
key
|
|
2570
2598
|
);
|
|
2571
|
-
let result = results[
|
|
2599
|
+
let result = results[match.route.id];
|
|
2572
2600
|
|
|
2573
2601
|
// Deferred isn't supported for fetcher loads, await everything and treat it
|
|
2574
2602
|
// as a normal load. resolveDeferredData will return undefined if this
|
|
@@ -2606,7 +2634,7 @@ export function createRouter(init: RouterInit): Router {
|
|
|
2606
2634
|
return;
|
|
2607
2635
|
} else {
|
|
2608
2636
|
fetchRedirectIds.add(key);
|
|
2609
|
-
await startRedirectNavigation(fetchRequest, result);
|
|
2637
|
+
await startRedirectNavigation(fetchRequest, result, false);
|
|
2610
2638
|
return;
|
|
2611
2639
|
}
|
|
2612
2640
|
}
|
|
@@ -2645,6 +2673,7 @@ export function createRouter(init: RouterInit): Router {
|
|
|
2645
2673
|
async function startRedirectNavigation(
|
|
2646
2674
|
request: Request,
|
|
2647
2675
|
redirect: RedirectResult,
|
|
2676
|
+
isNavigation: boolean,
|
|
2648
2677
|
{
|
|
2649
2678
|
submission,
|
|
2650
2679
|
fetcherSubmission,
|
|
@@ -2731,8 +2760,11 @@ export function createRouter(init: RouterInit): Router {
|
|
|
2731
2760
|
...activeSubmission,
|
|
2732
2761
|
formAction: location,
|
|
2733
2762
|
},
|
|
2734
|
-
// Preserve
|
|
2763
|
+
// Preserve these flags across redirects
|
|
2735
2764
|
preventScrollReset: pendingPreventScrollReset,
|
|
2765
|
+
enableViewTransition: isNavigation
|
|
2766
|
+
? pendingViewTransitionEnabled
|
|
2767
|
+
: undefined,
|
|
2736
2768
|
});
|
|
2737
2769
|
} else {
|
|
2738
2770
|
// If we have a navigation submission, we will preserve it through the
|
|
@@ -2745,8 +2777,11 @@ export function createRouter(init: RouterInit): Router {
|
|
|
2745
2777
|
overrideNavigation,
|
|
2746
2778
|
// Send fetcher submissions through for shouldRevalidate
|
|
2747
2779
|
fetcherSubmission,
|
|
2748
|
-
// Preserve
|
|
2780
|
+
// Preserve these flags across redirects
|
|
2749
2781
|
preventScrollReset: pendingPreventScrollReset,
|
|
2782
|
+
enableViewTransition: isNavigation
|
|
2783
|
+
? pendingViewTransitionEnabled
|
|
2784
|
+
: undefined,
|
|
2750
2785
|
});
|
|
2751
2786
|
}
|
|
2752
2787
|
}
|
|
@@ -2755,102 +2790,123 @@ export function createRouter(init: RouterInit): Router {
|
|
|
2755
2790
|
// pass around the manifest, mapRouteProperties, etc.
|
|
2756
2791
|
async function callDataStrategy(
|
|
2757
2792
|
type: "loader" | "action",
|
|
2793
|
+
state: RouterState,
|
|
2758
2794
|
request: Request,
|
|
2759
2795
|
matchesToLoad: AgnosticDataRouteMatch[],
|
|
2760
|
-
matches: AgnosticDataRouteMatch[]
|
|
2761
|
-
|
|
2796
|
+
matches: AgnosticDataRouteMatch[],
|
|
2797
|
+
fetcherKey: string | null
|
|
2798
|
+
): Promise<Record<string, DataResult>> {
|
|
2799
|
+
let results: Record<string, DataStrategyResult>;
|
|
2800
|
+
let dataResults: Record<string, DataResult> = {};
|
|
2762
2801
|
try {
|
|
2763
|
-
|
|
2802
|
+
results = await callDataStrategyImpl(
|
|
2764
2803
|
dataStrategyImpl,
|
|
2765
2804
|
type,
|
|
2805
|
+
state,
|
|
2766
2806
|
request,
|
|
2767
2807
|
matchesToLoad,
|
|
2768
2808
|
matches,
|
|
2809
|
+
fetcherKey,
|
|
2769
2810
|
manifest,
|
|
2770
2811
|
mapRouteProperties
|
|
2771
2812
|
);
|
|
2772
|
-
|
|
2773
|
-
return await Promise.all(
|
|
2774
|
-
results.map((result, i) => {
|
|
2775
|
-
if (isRedirectHandlerResult(result)) {
|
|
2776
|
-
let response = result.result as Response;
|
|
2777
|
-
return {
|
|
2778
|
-
type: ResultType.redirect,
|
|
2779
|
-
response: normalizeRelativeRoutingRedirectResponse(
|
|
2780
|
-
response,
|
|
2781
|
-
request,
|
|
2782
|
-
matchesToLoad[i].route.id,
|
|
2783
|
-
matches,
|
|
2784
|
-
basename,
|
|
2785
|
-
future.v7_relativeSplatPath
|
|
2786
|
-
),
|
|
2787
|
-
};
|
|
2788
|
-
}
|
|
2789
|
-
|
|
2790
|
-
return convertHandlerResultToDataResult(result);
|
|
2791
|
-
})
|
|
2792
|
-
);
|
|
2793
2813
|
} catch (e) {
|
|
2794
2814
|
// If the outer dataStrategy method throws, just return the error for all
|
|
2795
2815
|
// matches - and it'll naturally bubble to the root
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2816
|
+
matchesToLoad.forEach((m) => {
|
|
2817
|
+
dataResults[m.route.id] = {
|
|
2818
|
+
type: ResultType.error,
|
|
2819
|
+
error: e,
|
|
2820
|
+
};
|
|
2821
|
+
});
|
|
2822
|
+
return dataResults;
|
|
2823
|
+
}
|
|
2824
|
+
|
|
2825
|
+
for (let [routeId, result] of Object.entries(results)) {
|
|
2826
|
+
if (isRedirectDataStrategyResultResult(result)) {
|
|
2827
|
+
let response = result.result as Response;
|
|
2828
|
+
dataResults[routeId] = {
|
|
2829
|
+
type: ResultType.redirect,
|
|
2830
|
+
response: normalizeRelativeRoutingRedirectResponse(
|
|
2831
|
+
response,
|
|
2832
|
+
request,
|
|
2833
|
+
routeId,
|
|
2834
|
+
matches,
|
|
2835
|
+
basename,
|
|
2836
|
+
future.v7_relativeSplatPath
|
|
2837
|
+
),
|
|
2838
|
+
};
|
|
2839
|
+
} else {
|
|
2840
|
+
dataResults[routeId] = await convertDataStrategyResultToDataResult(
|
|
2841
|
+
result
|
|
2842
|
+
);
|
|
2843
|
+
}
|
|
2800
2844
|
}
|
|
2845
|
+
|
|
2846
|
+
return dataResults;
|
|
2801
2847
|
}
|
|
2802
2848
|
|
|
2803
2849
|
async function callLoadersAndMaybeResolveData(
|
|
2804
|
-
|
|
2850
|
+
state: RouterState,
|
|
2805
2851
|
matches: AgnosticDataRouteMatch[],
|
|
2806
2852
|
matchesToLoad: AgnosticDataRouteMatch[],
|
|
2807
2853
|
fetchersToLoad: RevalidatingFetcher[],
|
|
2808
2854
|
request: Request
|
|
2809
2855
|
) {
|
|
2810
|
-
let
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2856
|
+
let currentMatches = state.matches;
|
|
2857
|
+
|
|
2858
|
+
// Kick off loaders and fetchers in parallel
|
|
2859
|
+
let loaderResultsPromise = callDataStrategy(
|
|
2860
|
+
"loader",
|
|
2861
|
+
state,
|
|
2862
|
+
request,
|
|
2863
|
+
matchesToLoad,
|
|
2864
|
+
matches,
|
|
2865
|
+
null
|
|
2866
|
+
);
|
|
2867
|
+
|
|
2868
|
+
let fetcherResultsPromise = Promise.all(
|
|
2869
|
+
fetchersToLoad.map(async (f) => {
|
|
2815
2870
|
if (f.matches && f.match && f.controller) {
|
|
2816
|
-
let
|
|
2817
|
-
init.history,
|
|
2818
|
-
f.path,
|
|
2819
|
-
f.controller.signal
|
|
2820
|
-
);
|
|
2821
|
-
return callDataStrategy(
|
|
2871
|
+
let results = await callDataStrategy(
|
|
2822
2872
|
"loader",
|
|
2823
|
-
|
|
2873
|
+
state,
|
|
2874
|
+
createClientSideRequest(init.history, f.path, f.controller.signal),
|
|
2824
2875
|
[f.match],
|
|
2825
|
-
f.matches
|
|
2826
|
-
|
|
2876
|
+
f.matches,
|
|
2877
|
+
f.key
|
|
2878
|
+
);
|
|
2879
|
+
let result = results[f.match.route.id];
|
|
2880
|
+
// Fetcher results are keyed by fetcher key from here on out, not routeId
|
|
2881
|
+
return { [f.key]: result };
|
|
2827
2882
|
} else {
|
|
2828
|
-
return Promise.resolve
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2883
|
+
return Promise.resolve({
|
|
2884
|
+
[f.key]: {
|
|
2885
|
+
type: ResultType.error,
|
|
2886
|
+
error: getInternalRouterError(404, {
|
|
2887
|
+
pathname: f.path,
|
|
2888
|
+
}),
|
|
2889
|
+
} as ErrorResult,
|
|
2833
2890
|
});
|
|
2834
2891
|
}
|
|
2835
|
-
})
|
|
2836
|
-
|
|
2892
|
+
})
|
|
2893
|
+
);
|
|
2894
|
+
|
|
2895
|
+
let loaderResults = await loaderResultsPromise;
|
|
2896
|
+
let fetcherResults = (await fetcherResultsPromise).reduce(
|
|
2897
|
+
(acc, r) => Object.assign(acc, r),
|
|
2898
|
+
{}
|
|
2899
|
+
);
|
|
2837
2900
|
|
|
2838
2901
|
await Promise.all([
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
matchesToLoad,
|
|
2902
|
+
resolveNavigationDeferredResults(
|
|
2903
|
+
matches,
|
|
2842
2904
|
loaderResults,
|
|
2843
|
-
|
|
2844
|
-
false,
|
|
2845
|
-
state.loaderData
|
|
2846
|
-
),
|
|
2847
|
-
resolveDeferredResults(
|
|
2905
|
+
request.signal,
|
|
2848
2906
|
currentMatches,
|
|
2849
|
-
|
|
2850
|
-
fetcherResults,
|
|
2851
|
-
fetchersToLoad.map((f) => (f.controller ? f.controller.signal : null)),
|
|
2852
|
-
true
|
|
2907
|
+
state.loaderData
|
|
2853
2908
|
),
|
|
2909
|
+
resolveFetcherDeferredResults(matches, fetcherResults, fetchersToLoad),
|
|
2854
2910
|
]);
|
|
2855
2911
|
|
|
2856
2912
|
return {
|
|
@@ -3700,9 +3756,9 @@ export function createStaticHandler(
|
|
|
3700
3756
|
};
|
|
3701
3757
|
} catch (e) {
|
|
3702
3758
|
// If the user threw/returned a Response in callLoaderOrAction for a
|
|
3703
|
-
// `queryRoute` call, we throw the `
|
|
3759
|
+
// `queryRoute` call, we throw the `DataStrategyResult` to bail out early
|
|
3704
3760
|
// and then return or throw the raw Response here accordingly
|
|
3705
|
-
if (
|
|
3761
|
+
if (isDataStrategyResult(e) && isResponse(e.result)) {
|
|
3706
3762
|
if (e.type === ResultType.error) {
|
|
3707
3763
|
throw e.result;
|
|
3708
3764
|
}
|
|
@@ -3751,7 +3807,7 @@ export function createStaticHandler(
|
|
|
3751
3807
|
requestContext,
|
|
3752
3808
|
unstable_dataStrategy
|
|
3753
3809
|
);
|
|
3754
|
-
result = results[
|
|
3810
|
+
result = results[actionMatch.route.id];
|
|
3755
3811
|
|
|
3756
3812
|
if (request.signal.aborted) {
|
|
3757
3813
|
throwStaticHandlerAbortedError(request, isRouteRequest, future);
|
|
@@ -3942,7 +3998,6 @@ export function createStaticHandler(
|
|
|
3942
3998
|
let activeDeferreds = new Map<string, DeferredData>();
|
|
3943
3999
|
let context = processRouteLoaderData(
|
|
3944
4000
|
matches,
|
|
3945
|
-
matchesToLoad,
|
|
3946
4001
|
results,
|
|
3947
4002
|
pendingActionResult,
|
|
3948
4003
|
activeDeferreds,
|
|
@@ -3979,27 +4034,34 @@ export function createStaticHandler(
|
|
|
3979
4034
|
isRouteRequest: boolean,
|
|
3980
4035
|
requestContext: unknown,
|
|
3981
4036
|
unstable_dataStrategy: DataStrategyFunction | null
|
|
3982
|
-
): Promise<DataResult
|
|
4037
|
+
): Promise<Record<string, DataResult>> {
|
|
3983
4038
|
let results = await callDataStrategyImpl(
|
|
3984
4039
|
unstable_dataStrategy || defaultDataStrategy,
|
|
3985
4040
|
type,
|
|
4041
|
+
null,
|
|
3986
4042
|
request,
|
|
3987
4043
|
matchesToLoad,
|
|
3988
4044
|
matches,
|
|
4045
|
+
null,
|
|
3989
4046
|
manifest,
|
|
3990
4047
|
mapRouteProperties,
|
|
3991
4048
|
requestContext
|
|
3992
4049
|
);
|
|
3993
4050
|
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
4051
|
+
let dataResults: Record<string, DataResult> = {};
|
|
4052
|
+
await Promise.all(
|
|
4053
|
+
matches.map(async (match) => {
|
|
4054
|
+
if (!(match.route.id in results)) {
|
|
4055
|
+
return;
|
|
4056
|
+
}
|
|
4057
|
+
let result = results[match.route.id];
|
|
4058
|
+
if (isRedirectDataStrategyResultResult(result)) {
|
|
3997
4059
|
let response = result.result as Response;
|
|
3998
4060
|
// Throw redirects and let the server handle them with an HTTP redirect
|
|
3999
4061
|
throw normalizeRelativeRoutingRedirectResponse(
|
|
4000
4062
|
response,
|
|
4001
4063
|
request,
|
|
4002
|
-
|
|
4064
|
+
match.route.id,
|
|
4003
4065
|
matches,
|
|
4004
4066
|
basename,
|
|
4005
4067
|
future.v7_relativeSplatPath
|
|
@@ -4011,9 +4073,11 @@ export function createStaticHandler(
|
|
|
4011
4073
|
throw result;
|
|
4012
4074
|
}
|
|
4013
4075
|
|
|
4014
|
-
|
|
4076
|
+
dataResults[match.route.id] =
|
|
4077
|
+
await convertDataStrategyResultToDataResult(result);
|
|
4015
4078
|
})
|
|
4016
4079
|
);
|
|
4080
|
+
return dataResults;
|
|
4017
4081
|
}
|
|
4018
4082
|
|
|
4019
4083
|
return {
|
|
@@ -4704,77 +4768,91 @@ async function loadLazyRouteModule(
|
|
|
4704
4768
|
}
|
|
4705
4769
|
|
|
4706
4770
|
// Default implementation of `dataStrategy` which fetches all loaders in parallel
|
|
4707
|
-
function defaultDataStrategy(
|
|
4708
|
-
|
|
4709
|
-
): ReturnType<DataStrategyFunction> {
|
|
4710
|
-
|
|
4771
|
+
async function defaultDataStrategy({
|
|
4772
|
+
matches,
|
|
4773
|
+
}: DataStrategyFunctionArgs): ReturnType<DataStrategyFunction> {
|
|
4774
|
+
let matchesToLoad = matches.filter((m) => m.shouldLoad);
|
|
4775
|
+
let results = await Promise.all(matchesToLoad.map((m) => m.resolve()));
|
|
4776
|
+
return results.reduce(
|
|
4777
|
+
(acc, result, i) =>
|
|
4778
|
+
Object.assign(acc, { [matchesToLoad[i].route.id]: result }),
|
|
4779
|
+
{}
|
|
4780
|
+
);
|
|
4711
4781
|
}
|
|
4712
4782
|
|
|
4713
4783
|
async function callDataStrategyImpl(
|
|
4714
4784
|
dataStrategyImpl: DataStrategyFunction,
|
|
4715
4785
|
type: "loader" | "action",
|
|
4786
|
+
state: RouterState | null,
|
|
4716
4787
|
request: Request,
|
|
4717
4788
|
matchesToLoad: AgnosticDataRouteMatch[],
|
|
4718
4789
|
matches: AgnosticDataRouteMatch[],
|
|
4790
|
+
fetcherKey: string | null,
|
|
4719
4791
|
manifest: RouteManifest,
|
|
4720
4792
|
mapRouteProperties: MapRoutePropertiesFunction,
|
|
4721
4793
|
requestContext?: unknown
|
|
4722
|
-
): Promise<
|
|
4723
|
-
let
|
|
4724
|
-
|
|
4725
|
-
|
|
4794
|
+
): Promise<Record<string, DataStrategyResult>> {
|
|
4795
|
+
let loadRouteDefinitionsPromises = matches.map((m) =>
|
|
4796
|
+
m.route.lazy
|
|
4797
|
+
? loadLazyRouteModule(m.route, mapRouteProperties, manifest)
|
|
4798
|
+
: undefined
|
|
4726
4799
|
);
|
|
4727
|
-
|
|
4800
|
+
|
|
4801
|
+
let dsMatches = matches.map((match, i) => {
|
|
4802
|
+
let loadRoutePromise = loadRouteDefinitionsPromises[i];
|
|
4803
|
+
let shouldLoad = matchesToLoad.some((m) => m.route.id === match.route.id);
|
|
4804
|
+
// `resolve` encapsulates route.lazy(), executing the loader/action,
|
|
4805
|
+
// and mapping return values/thrown errors to a `DataStrategyResult`. Users
|
|
4806
|
+
// can pass a callback to take fine-grained control over the execution
|
|
4807
|
+
// of the loader/action
|
|
4808
|
+
let resolve: DataStrategyMatch["resolve"] = async (handlerOverride) => {
|
|
4809
|
+
if (
|
|
4810
|
+
handlerOverride &&
|
|
4811
|
+
request.method === "GET" &&
|
|
4812
|
+
(match.route.lazy || match.route.loader)
|
|
4813
|
+
) {
|
|
4814
|
+
shouldLoad = true;
|
|
4815
|
+
}
|
|
4816
|
+
return shouldLoad
|
|
4817
|
+
? callLoaderOrAction(
|
|
4818
|
+
type,
|
|
4819
|
+
request,
|
|
4820
|
+
match,
|
|
4821
|
+
loadRoutePromise,
|
|
4822
|
+
handlerOverride,
|
|
4823
|
+
requestContext
|
|
4824
|
+
)
|
|
4825
|
+
: Promise.resolve({ type: ResultType.data, result: undefined });
|
|
4826
|
+
};
|
|
4827
|
+
|
|
4828
|
+
return {
|
|
4829
|
+
...match,
|
|
4830
|
+
shouldLoad,
|
|
4831
|
+
resolve,
|
|
4832
|
+
};
|
|
4833
|
+
});
|
|
4728
4834
|
|
|
4729
4835
|
// Send all matches here to allow for a middleware-type implementation.
|
|
4730
4836
|
// handler will be a no-op for unneeded routes and we filter those results
|
|
4731
4837
|
// back out below.
|
|
4732
4838
|
let results = await dataStrategyImpl({
|
|
4733
|
-
matches:
|
|
4734
|
-
let shouldLoad = routeIdsToLoad.has(match.route.id);
|
|
4735
|
-
// `resolve` encapsulates the route.lazy, executing the
|
|
4736
|
-
// loader/action, and mapping return values/thrown errors to a
|
|
4737
|
-
// HandlerResult. Users can pass a callback to take fine-grained control
|
|
4738
|
-
// over the execution of the loader/action
|
|
4739
|
-
let resolve: DataStrategyMatch["resolve"] = (handlerOverride) => {
|
|
4740
|
-
loadedMatches.add(match.route.id);
|
|
4741
|
-
return shouldLoad
|
|
4742
|
-
? callLoaderOrAction(
|
|
4743
|
-
type,
|
|
4744
|
-
request,
|
|
4745
|
-
match,
|
|
4746
|
-
manifest,
|
|
4747
|
-
mapRouteProperties,
|
|
4748
|
-
handlerOverride,
|
|
4749
|
-
requestContext
|
|
4750
|
-
)
|
|
4751
|
-
: Promise.resolve({ type: ResultType.data, result: undefined });
|
|
4752
|
-
};
|
|
4753
|
-
|
|
4754
|
-
return {
|
|
4755
|
-
...match,
|
|
4756
|
-
shouldLoad,
|
|
4757
|
-
resolve,
|
|
4758
|
-
};
|
|
4759
|
-
}),
|
|
4839
|
+
matches: dsMatches,
|
|
4760
4840
|
request,
|
|
4761
4841
|
params: matches[0].params,
|
|
4842
|
+
fetcherKey,
|
|
4762
4843
|
context: requestContext,
|
|
4763
4844
|
});
|
|
4764
4845
|
|
|
4765
|
-
//
|
|
4766
|
-
//
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
)
|
|
4774
|
-
);
|
|
4846
|
+
// Wait for all routes to load here but 'swallow the error since we want
|
|
4847
|
+
// it to bubble up from the `await loadRoutePromise` in `callLoaderOrAction` -
|
|
4848
|
+
// called from `match.resolve()`
|
|
4849
|
+
try {
|
|
4850
|
+
await Promise.all(loadRouteDefinitionsPromises);
|
|
4851
|
+
} catch (e) {
|
|
4852
|
+
// No-op
|
|
4853
|
+
}
|
|
4775
4854
|
|
|
4776
|
-
|
|
4777
|
-
return results.filter((_, i) => routeIdsToLoad.has(matches[i].route.id));
|
|
4855
|
+
return results;
|
|
4778
4856
|
}
|
|
4779
4857
|
|
|
4780
4858
|
// Default logic for calling a loader/action is the user has no specified a dataStrategy
|
|
@@ -4782,22 +4860,21 @@ async function callLoaderOrAction(
|
|
|
4782
4860
|
type: "loader" | "action",
|
|
4783
4861
|
request: Request,
|
|
4784
4862
|
match: AgnosticDataRouteMatch,
|
|
4785
|
-
|
|
4786
|
-
mapRouteProperties: MapRoutePropertiesFunction,
|
|
4863
|
+
loadRoutePromise: Promise<void> | undefined,
|
|
4787
4864
|
handlerOverride: Parameters<DataStrategyMatch["resolve"]>[0],
|
|
4788
4865
|
staticContext?: unknown
|
|
4789
|
-
): Promise<
|
|
4790
|
-
let result:
|
|
4866
|
+
): Promise<DataStrategyResult> {
|
|
4867
|
+
let result: DataStrategyResult;
|
|
4791
4868
|
let onReject: (() => void) | undefined;
|
|
4792
4869
|
|
|
4793
4870
|
let runHandler = (
|
|
4794
4871
|
handler: AgnosticRouteObject["loader"] | AgnosticRouteObject["action"]
|
|
4795
|
-
): Promise<
|
|
4872
|
+
): Promise<DataStrategyResult> => {
|
|
4796
4873
|
// Setup a promise we can race against so that abort signals short circuit
|
|
4797
4874
|
let reject: () => void;
|
|
4798
|
-
// This will never resolve so safe to type it as Promise<
|
|
4875
|
+
// This will never resolve so safe to type it as Promise<DataStrategyResult> to
|
|
4799
4876
|
// satisfy the function return value
|
|
4800
|
-
let abortPromise = new Promise<
|
|
4877
|
+
let abortPromise = new Promise<DataStrategyResult>((_, r) => (reject = r));
|
|
4801
4878
|
onReject = () => reject();
|
|
4802
4879
|
request.signal.addEventListener("abort", onReject);
|
|
4803
4880
|
|
|
@@ -4820,19 +4897,16 @@ async function callLoaderOrAction(
|
|
|
4820
4897
|
);
|
|
4821
4898
|
};
|
|
4822
4899
|
|
|
4823
|
-
let handlerPromise: Promise<
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
|
|
4830
|
-
|
|
4831
|
-
|
|
4832
|
-
|
|
4833
|
-
}
|
|
4834
|
-
})();
|
|
4835
|
-
}
|
|
4900
|
+
let handlerPromise: Promise<DataStrategyResult> = (async () => {
|
|
4901
|
+
try {
|
|
4902
|
+
let val = await (handlerOverride
|
|
4903
|
+
? handlerOverride((ctx: unknown) => actualHandler(ctx))
|
|
4904
|
+
: actualHandler());
|
|
4905
|
+
return { type: "data", result: val };
|
|
4906
|
+
} catch (e) {
|
|
4907
|
+
return { type: "error", result: e };
|
|
4908
|
+
}
|
|
4909
|
+
})();
|
|
4836
4910
|
|
|
4837
4911
|
return Promise.race([handlerPromise, abortPromise]);
|
|
4838
4912
|
};
|
|
@@ -4840,7 +4914,8 @@ async function callLoaderOrAction(
|
|
|
4840
4914
|
try {
|
|
4841
4915
|
let handler = match.route[type];
|
|
4842
4916
|
|
|
4843
|
-
|
|
4917
|
+
// If we have a route.lazy promise, await that first
|
|
4918
|
+
if (loadRoutePromise) {
|
|
4844
4919
|
if (handler) {
|
|
4845
4920
|
// Run statically defined handler in parallel with lazy()
|
|
4846
4921
|
let handlerError;
|
|
@@ -4851,7 +4926,7 @@ async function callLoaderOrAction(
|
|
|
4851
4926
|
runHandler(handler).catch((e) => {
|
|
4852
4927
|
handlerError = e;
|
|
4853
4928
|
}),
|
|
4854
|
-
|
|
4929
|
+
loadRoutePromise,
|
|
4855
4930
|
]);
|
|
4856
4931
|
if (handlerError !== undefined) {
|
|
4857
4932
|
throw handlerError;
|
|
@@ -4859,7 +4934,7 @@ async function callLoaderOrAction(
|
|
|
4859
4934
|
result = value!;
|
|
4860
4935
|
} else {
|
|
4861
4936
|
// Load lazy route module, then run any returned handler
|
|
4862
|
-
await
|
|
4937
|
+
await loadRoutePromise;
|
|
4863
4938
|
|
|
4864
4939
|
handler = match.route[type];
|
|
4865
4940
|
if (handler) {
|
|
@@ -4899,7 +4974,7 @@ async function callLoaderOrAction(
|
|
|
4899
4974
|
);
|
|
4900
4975
|
} catch (e) {
|
|
4901
4976
|
// We should already be catching and converting normal handler executions to
|
|
4902
|
-
//
|
|
4977
|
+
// DataStrategyResults and returning them, so anything that throws here is an
|
|
4903
4978
|
// unexpected error we still need to wrap
|
|
4904
4979
|
return { type: ResultType.error, result: e };
|
|
4905
4980
|
} finally {
|
|
@@ -4911,10 +4986,10 @@ async function callLoaderOrAction(
|
|
|
4911
4986
|
return result;
|
|
4912
4987
|
}
|
|
4913
4988
|
|
|
4914
|
-
async function
|
|
4915
|
-
|
|
4989
|
+
async function convertDataStrategyResultToDataResult(
|
|
4990
|
+
dataStrategyResult: DataStrategyResult
|
|
4916
4991
|
): Promise<DataResult> {
|
|
4917
|
-
let { result, type } =
|
|
4992
|
+
let { result, type } = dataStrategyResult;
|
|
4918
4993
|
|
|
4919
4994
|
if (isResponse(result)) {
|
|
4920
4995
|
let data: any;
|
|
@@ -5116,8 +5191,7 @@ function convertSearchParamsToFormData(
|
|
|
5116
5191
|
|
|
5117
5192
|
function processRouteLoaderData(
|
|
5118
5193
|
matches: AgnosticDataRouteMatch[],
|
|
5119
|
-
|
|
5120
|
-
results: DataResult[],
|
|
5194
|
+
results: Record<string, DataResult>,
|
|
5121
5195
|
pendingActionResult: PendingActionResult | undefined,
|
|
5122
5196
|
activeDeferreds: Map<string, DeferredData>,
|
|
5123
5197
|
skipLoaderErrorBubbling: boolean
|
|
@@ -5139,8 +5213,12 @@ function processRouteLoaderData(
|
|
|
5139
5213
|
: undefined;
|
|
5140
5214
|
|
|
5141
5215
|
// Process loader results into state.loaderData/state.errors
|
|
5142
|
-
|
|
5143
|
-
|
|
5216
|
+
matches.forEach((match) => {
|
|
5217
|
+
if (!(match.route.id in results)) {
|
|
5218
|
+
return;
|
|
5219
|
+
}
|
|
5220
|
+
let id = match.route.id;
|
|
5221
|
+
let result = results[id];
|
|
5144
5222
|
invariant(
|
|
5145
5223
|
!isRedirectResult(result),
|
|
5146
5224
|
"Cannot handle redirect results in processLoaderData"
|
|
@@ -5233,10 +5311,10 @@ function processLoaderData(
|
|
|
5233
5311
|
state: RouterState,
|
|
5234
5312
|
matches: AgnosticDataRouteMatch[],
|
|
5235
5313
|
matchesToLoad: AgnosticDataRouteMatch[],
|
|
5236
|
-
results: DataResult
|
|
5314
|
+
results: Record<string, DataResult>,
|
|
5237
5315
|
pendingActionResult: PendingActionResult | undefined,
|
|
5238
5316
|
revalidatingFetchers: RevalidatingFetcher[],
|
|
5239
|
-
fetcherResults: DataResult
|
|
5317
|
+
fetcherResults: Record<string, DataResult>,
|
|
5240
5318
|
activeDeferreds: Map<string, DeferredData>
|
|
5241
5319
|
): {
|
|
5242
5320
|
loaderData: RouterState["loaderData"];
|
|
@@ -5244,7 +5322,6 @@ function processLoaderData(
|
|
|
5244
5322
|
} {
|
|
5245
5323
|
let { loaderData, errors } = processRouteLoaderData(
|
|
5246
5324
|
matches,
|
|
5247
|
-
matchesToLoad,
|
|
5248
5325
|
results,
|
|
5249
5326
|
pendingActionResult,
|
|
5250
5327
|
activeDeferreds,
|
|
@@ -5252,18 +5329,15 @@ function processLoaderData(
|
|
|
5252
5329
|
);
|
|
5253
5330
|
|
|
5254
5331
|
// Process results from our revalidating fetchers
|
|
5255
|
-
|
|
5256
|
-
let { key, match, controller } =
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
"Did not find corresponding fetcher result"
|
|
5260
|
-
);
|
|
5261
|
-
let result = fetcherResults[index];
|
|
5332
|
+
revalidatingFetchers.forEach((rf) => {
|
|
5333
|
+
let { key, match, controller } = rf;
|
|
5334
|
+
let result = fetcherResults[key];
|
|
5335
|
+
invariant(result, "Did not find corresponding fetcher result");
|
|
5262
5336
|
|
|
5263
5337
|
// Process fetcher non-redirect errors
|
|
5264
5338
|
if (controller && controller.signal.aborted) {
|
|
5265
5339
|
// Nothing to do for aborted fetchers
|
|
5266
|
-
|
|
5340
|
+
return;
|
|
5267
5341
|
} else if (isErrorResult(result)) {
|
|
5268
5342
|
let boundaryMatch = findNearestBoundary(state.matches, match?.route.id);
|
|
5269
5343
|
if (!(errors && errors[boundaryMatch.route.id])) {
|
|
@@ -5285,7 +5359,7 @@ function processLoaderData(
|
|
|
5285
5359
|
let doneFetcher = getDoneFetcher(result.data);
|
|
5286
5360
|
state.fetchers.set(key, doneFetcher);
|
|
5287
5361
|
}
|
|
5288
|
-
}
|
|
5362
|
+
});
|
|
5289
5363
|
|
|
5290
5364
|
return { loaderData, errors };
|
|
5291
5365
|
}
|
|
@@ -5443,12 +5517,13 @@ function getInternalRouterError(
|
|
|
5443
5517
|
|
|
5444
5518
|
// Find any returned redirect errors, starting from the lowest match
|
|
5445
5519
|
function findRedirect(
|
|
5446
|
-
results: DataResult
|
|
5447
|
-
): {
|
|
5448
|
-
|
|
5449
|
-
|
|
5520
|
+
results: Record<string, DataResult>
|
|
5521
|
+
): { key: string; result: RedirectResult } | undefined {
|
|
5522
|
+
let entries = Object.entries(results);
|
|
5523
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
5524
|
+
let [key, result] = entries[i];
|
|
5450
5525
|
if (isRedirectResult(result)) {
|
|
5451
|
-
return {
|
|
5526
|
+
return { key, result };
|
|
5452
5527
|
}
|
|
5453
5528
|
}
|
|
5454
5529
|
}
|
|
@@ -5483,7 +5558,7 @@ function isPromise<T = unknown>(val: unknown): val is Promise<T> {
|
|
|
5483
5558
|
return typeof val === "object" && val != null && "then" in val;
|
|
5484
5559
|
}
|
|
5485
5560
|
|
|
5486
|
-
function
|
|
5561
|
+
function isDataStrategyResult(result: unknown): result is DataStrategyResult {
|
|
5487
5562
|
return (
|
|
5488
5563
|
result != null &&
|
|
5489
5564
|
typeof result === "object" &&
|
|
@@ -5493,7 +5568,7 @@ function isHandlerResult(result: unknown): result is HandlerResult {
|
|
|
5493
5568
|
);
|
|
5494
5569
|
}
|
|
5495
5570
|
|
|
5496
|
-
function
|
|
5571
|
+
function isRedirectDataStrategyResultResult(result: DataStrategyResult) {
|
|
5497
5572
|
return (
|
|
5498
5573
|
isResponse(result.result) && redirectStatusCodes.has(result.result.status)
|
|
5499
5574
|
);
|
|
@@ -5566,17 +5641,17 @@ function isMutationMethod(
|
|
|
5566
5641
|
return validMutationMethods.has(method.toLowerCase() as MutationFormMethod);
|
|
5567
5642
|
}
|
|
5568
5643
|
|
|
5569
|
-
async function
|
|
5644
|
+
async function resolveNavigationDeferredResults(
|
|
5645
|
+
matches: (AgnosticDataRouteMatch | null)[],
|
|
5646
|
+
results: Record<string, DataResult>,
|
|
5647
|
+
signal: AbortSignal,
|
|
5570
5648
|
currentMatches: AgnosticDataRouteMatch[],
|
|
5571
|
-
|
|
5572
|
-
results: DataResult[],
|
|
5573
|
-
signals: (AbortSignal | null)[],
|
|
5574
|
-
isFetcher: boolean,
|
|
5575
|
-
currentLoaderData?: RouteData
|
|
5649
|
+
currentLoaderData: RouteData
|
|
5576
5650
|
) {
|
|
5577
|
-
|
|
5578
|
-
|
|
5579
|
-
let
|
|
5651
|
+
let entries = Object.entries(results);
|
|
5652
|
+
for (let index = 0; index < entries.length; index++) {
|
|
5653
|
+
let [routeId, result] = entries[index];
|
|
5654
|
+
let match = matches.find((m) => m?.route.id === routeId);
|
|
5580
5655
|
// If we don't have a match, then we can have a deferred result to do
|
|
5581
5656
|
// anything with. This is for revalidating fetchers where the route was
|
|
5582
5657
|
// removed during HMR
|
|
@@ -5592,24 +5667,54 @@ async function resolveDeferredResults(
|
|
|
5592
5667
|
!isNewRouteInstance(currentMatch, match) &&
|
|
5593
5668
|
(currentLoaderData && currentLoaderData[match.route.id]) !== undefined;
|
|
5594
5669
|
|
|
5595
|
-
if (isDeferredResult(result) &&
|
|
5670
|
+
if (isDeferredResult(result) && isRevalidatingLoader) {
|
|
5596
5671
|
// Note: we do not have to touch activeDeferreds here since we race them
|
|
5597
5672
|
// against the signal in resolveDeferredData and they'll get aborted
|
|
5598
5673
|
// there if needed
|
|
5599
|
-
|
|
5600
|
-
invariant(
|
|
5601
|
-
signal,
|
|
5602
|
-
"Expected an AbortSignal for revalidating fetcher deferred result"
|
|
5603
|
-
);
|
|
5604
|
-
await resolveDeferredData(result, signal, isFetcher).then((result) => {
|
|
5674
|
+
await resolveDeferredData(result, signal, false).then((result) => {
|
|
5605
5675
|
if (result) {
|
|
5606
|
-
results[
|
|
5676
|
+
results[routeId] = result;
|
|
5607
5677
|
}
|
|
5608
5678
|
});
|
|
5609
5679
|
}
|
|
5610
5680
|
}
|
|
5611
5681
|
}
|
|
5612
5682
|
|
|
5683
|
+
async function resolveFetcherDeferredResults(
|
|
5684
|
+
matches: (AgnosticDataRouteMatch | null)[],
|
|
5685
|
+
results: Record<string, DataResult>,
|
|
5686
|
+
revalidatingFetchers: RevalidatingFetcher[]
|
|
5687
|
+
) {
|
|
5688
|
+
for (let index = 0; index < revalidatingFetchers.length; index++) {
|
|
5689
|
+
let { key, routeId, controller } = revalidatingFetchers[index];
|
|
5690
|
+
let result = results[key];
|
|
5691
|
+
let match = matches.find((m) => m?.route.id === routeId);
|
|
5692
|
+
// If we don't have a match, then we can have a deferred result to do
|
|
5693
|
+
// anything with. This is for revalidating fetchers where the route was
|
|
5694
|
+
// removed during HMR
|
|
5695
|
+
if (!match) {
|
|
5696
|
+
continue;
|
|
5697
|
+
}
|
|
5698
|
+
|
|
5699
|
+
if (isDeferredResult(result)) {
|
|
5700
|
+
// Note: we do not have to touch activeDeferreds here since we race them
|
|
5701
|
+
// against the signal in resolveDeferredData and they'll get aborted
|
|
5702
|
+
// there if needed
|
|
5703
|
+
invariant(
|
|
5704
|
+
controller,
|
|
5705
|
+
"Expected an AbortController for revalidating fetcher deferred result"
|
|
5706
|
+
);
|
|
5707
|
+
await resolveDeferredData(result, controller.signal, true).then(
|
|
5708
|
+
(result) => {
|
|
5709
|
+
if (result) {
|
|
5710
|
+
results[key] = result;
|
|
5711
|
+
}
|
|
5712
|
+
}
|
|
5713
|
+
);
|
|
5714
|
+
}
|
|
5715
|
+
}
|
|
5716
|
+
}
|
|
5717
|
+
|
|
5613
5718
|
async function resolveDeferredData(
|
|
5614
5719
|
result: DeferredResult,
|
|
5615
5720
|
signal: AbortSignal,
|