@remix-run/router 1.16.1 → 1.17.0
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 +9 -0
- package/dist/index.d.ts +1 -1
- package/dist/router.cjs.js +467 -80
- package/dist/router.cjs.js.map +1 -1
- package/dist/router.d.ts +11 -1
- package/dist/router.js +457 -76
- package/dist/router.js.map +1 -1
- package/dist/router.umd.js +467 -80
- 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 +9 -1
- package/index.ts +1 -0
- package/package.json +1 -1
- package/router.ts +586 -73
- package/utils.ts +51 -8
package/dist/router.cjs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @remix-run/router v1.
|
|
2
|
+
* @remix-run/router v1.17.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -718,7 +718,7 @@ function convertRoutesToDataRoutes(routes, mapRouteProperties, parentPath, manif
|
|
|
718
718
|
manifest = {};
|
|
719
719
|
}
|
|
720
720
|
return routes.map((route, index) => {
|
|
721
|
-
let treePath = [...parentPath, index];
|
|
721
|
+
let treePath = [...parentPath, String(index)];
|
|
722
722
|
let id = typeof route.id === "string" ? route.id : treePath.join("-");
|
|
723
723
|
invariant(route.index !== true || !route.children, "Cannot specify children on an index route");
|
|
724
724
|
invariant(!manifest[id], "Found a route id collision on id \"" + id + "\". Route " + "id's must be globally unique within Data Router usages");
|
|
@@ -751,6 +751,9 @@ function matchRoutes(routes, locationArg, basename) {
|
|
|
751
751
|
if (basename === void 0) {
|
|
752
752
|
basename = "/";
|
|
753
753
|
}
|
|
754
|
+
return matchRoutesImpl(routes, locationArg, basename, false);
|
|
755
|
+
}
|
|
756
|
+
function matchRoutesImpl(routes, locationArg, basename, allowPartial) {
|
|
754
757
|
let location = typeof locationArg === "string" ? parsePath(locationArg) : locationArg;
|
|
755
758
|
let pathname = stripBasename(location.pathname || "/", basename);
|
|
756
759
|
if (pathname == null) {
|
|
@@ -767,7 +770,7 @@ function matchRoutes(routes, locationArg, basename) {
|
|
|
767
770
|
// should be a safe operation. This avoids needing matchRoutes to be
|
|
768
771
|
// history-aware.
|
|
769
772
|
let decoded = decodePath(pathname);
|
|
770
|
-
matches = matchRouteBranch(branches[i], decoded);
|
|
773
|
+
matches = matchRouteBranch(branches[i], decoded, allowPartial);
|
|
771
774
|
}
|
|
772
775
|
return matches;
|
|
773
776
|
}
|
|
@@ -927,7 +930,10 @@ function compareIndexes(a, b) {
|
|
|
927
930
|
// so they sort equally.
|
|
928
931
|
0;
|
|
929
932
|
}
|
|
930
|
-
function matchRouteBranch(branch, pathname) {
|
|
933
|
+
function matchRouteBranch(branch, pathname, allowPartial) {
|
|
934
|
+
if (allowPartial === void 0) {
|
|
935
|
+
allowPartial = false;
|
|
936
|
+
}
|
|
931
937
|
let {
|
|
932
938
|
routesMeta
|
|
933
939
|
} = branch;
|
|
@@ -943,9 +949,18 @@ function matchRouteBranch(branch, pathname) {
|
|
|
943
949
|
caseSensitive: meta.caseSensitive,
|
|
944
950
|
end
|
|
945
951
|
}, remainingPathname);
|
|
946
|
-
if (!match) return null;
|
|
947
|
-
Object.assign(matchedParams, match.params);
|
|
948
952
|
let route = meta.route;
|
|
953
|
+
if (!match && end && allowPartial && !routesMeta[routesMeta.length - 1].route.index) {
|
|
954
|
+
match = matchPath({
|
|
955
|
+
path: meta.relativePath,
|
|
956
|
+
caseSensitive: meta.caseSensitive,
|
|
957
|
+
end: false
|
|
958
|
+
}, remainingPathname);
|
|
959
|
+
}
|
|
960
|
+
if (!match) {
|
|
961
|
+
return null;
|
|
962
|
+
}
|
|
963
|
+
Object.assign(matchedParams, match.params);
|
|
949
964
|
matches.push({
|
|
950
965
|
// TODO: Can this as be avoided?
|
|
951
966
|
params: matchedParams,
|
|
@@ -1669,6 +1684,8 @@ function createRouter(init) {
|
|
|
1669
1684
|
let inFlightDataRoutes;
|
|
1670
1685
|
let basename = init.basename || "/";
|
|
1671
1686
|
let dataStrategyImpl = init.unstable_dataStrategy || defaultDataStrategy;
|
|
1687
|
+
let patchRoutesOnMissImpl = init.unstable_patchRoutesOnMiss;
|
|
1688
|
+
|
|
1672
1689
|
// Config driven behavior flags
|
|
1673
1690
|
let future = _extends({
|
|
1674
1691
|
v7_fetcherPersist: false,
|
|
@@ -1697,7 +1714,7 @@ function createRouter(init) {
|
|
|
1697
1714
|
let initialScrollRestored = init.hydrationData != null;
|
|
1698
1715
|
let initialMatches = matchRoutes(dataRoutes, init.history.location, basename);
|
|
1699
1716
|
let initialErrors = null;
|
|
1700
|
-
if (initialMatches == null) {
|
|
1717
|
+
if (initialMatches == null && !patchRoutesOnMissImpl) {
|
|
1701
1718
|
// If we do not match a user-provided-route, fall back to the root
|
|
1702
1719
|
// to allow the error boundary to take over
|
|
1703
1720
|
let error = getInternalRouterError(404, {
|
|
@@ -1713,13 +1730,15 @@ function createRouter(init) {
|
|
|
1713
1730
|
};
|
|
1714
1731
|
}
|
|
1715
1732
|
let initialized;
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1733
|
+
if (!initialMatches) {
|
|
1734
|
+
// We need to run patchRoutesOnMiss in initialize()
|
|
1735
|
+
initialized = false;
|
|
1736
|
+
initialMatches = [];
|
|
1737
|
+
} else if (initialMatches.some(m => m.route.lazy)) {
|
|
1719
1738
|
// All initialMatches need to be loaded before we're ready. If we have lazy
|
|
1720
1739
|
// functions around still then we'll need to run them in initialize()
|
|
1721
1740
|
initialized = false;
|
|
1722
|
-
} else if (!
|
|
1741
|
+
} else if (!initialMatches.some(m => m.route.loader)) {
|
|
1723
1742
|
// If we've got no loaders to run, then we're good to go
|
|
1724
1743
|
initialized = true;
|
|
1725
1744
|
} else if (future.v7_partialHydration) {
|
|
@@ -1846,6 +1865,10 @@ function createRouter(init) {
|
|
|
1846
1865
|
// we don't need to update UI state if they change
|
|
1847
1866
|
let blockerFunctions = new Map();
|
|
1848
1867
|
|
|
1868
|
+
// Map of pending patchRoutesOnMiss() promises (keyed by path/matches) so
|
|
1869
|
+
// that we only kick them off once for a given combo
|
|
1870
|
+
let pendingPatchRoutes = new Map();
|
|
1871
|
+
|
|
1849
1872
|
// Flag to ignore the next history update, so we can revert the URL change on
|
|
1850
1873
|
// a POP navigation that was blocked by the user without touching router state
|
|
1851
1874
|
let ignoreNextHistoryUpdate = false;
|
|
@@ -2235,18 +2258,18 @@ function createRouter(init) {
|
|
|
2235
2258
|
let loadingNavigation = opts && opts.overrideNavigation;
|
|
2236
2259
|
let matches = matchRoutes(routesToUse, location, basename);
|
|
2237
2260
|
let flushSync = (opts && opts.flushSync) === true;
|
|
2261
|
+
let fogOfWar = checkFogOfWar(matches, routesToUse, location.pathname);
|
|
2262
|
+
if (fogOfWar.active && fogOfWar.matches) {
|
|
2263
|
+
matches = fogOfWar.matches;
|
|
2264
|
+
}
|
|
2238
2265
|
|
|
2239
2266
|
// Short circuit with a 404 on the root error boundary if we match nothing
|
|
2240
2267
|
if (!matches) {
|
|
2241
|
-
let error = getInternalRouterError(404, {
|
|
2242
|
-
pathname: location.pathname
|
|
2243
|
-
});
|
|
2244
2268
|
let {
|
|
2245
|
-
|
|
2269
|
+
error,
|
|
2270
|
+
notFoundMatches,
|
|
2246
2271
|
route
|
|
2247
|
-
} =
|
|
2248
|
-
// Cancel all pending deferred on 404s since we don't keep any routes
|
|
2249
|
-
cancelActiveDeferreds();
|
|
2272
|
+
} = handleNavigational404(location.pathname);
|
|
2250
2273
|
completeNavigation(location, {
|
|
2251
2274
|
matches: notFoundMatches,
|
|
2252
2275
|
loaderData: {},
|
|
@@ -2289,16 +2312,36 @@ function createRouter(init) {
|
|
|
2289
2312
|
}];
|
|
2290
2313
|
} else if (opts && opts.submission && isMutationMethod(opts.submission.formMethod)) {
|
|
2291
2314
|
// Call action if we received an action submission
|
|
2292
|
-
let actionResult = await handleAction(request, location, opts.submission, matches, {
|
|
2315
|
+
let actionResult = await handleAction(request, location, opts.submission, matches, fogOfWar.active, {
|
|
2293
2316
|
replace: opts.replace,
|
|
2294
2317
|
flushSync
|
|
2295
2318
|
});
|
|
2296
2319
|
if (actionResult.shortCircuited) {
|
|
2297
2320
|
return;
|
|
2298
2321
|
}
|
|
2322
|
+
|
|
2323
|
+
// If we received a 404 from handleAction, it's because we couldn't lazily
|
|
2324
|
+
// discover the destination route so we don't want to call loaders
|
|
2325
|
+
if (actionResult.pendingActionResult) {
|
|
2326
|
+
let [routeId, result] = actionResult.pendingActionResult;
|
|
2327
|
+
if (isErrorResult(result) && isRouteErrorResponse(result.error) && result.error.status === 404) {
|
|
2328
|
+
pendingNavigationController = null;
|
|
2329
|
+
completeNavigation(location, {
|
|
2330
|
+
matches: actionResult.matches,
|
|
2331
|
+
loaderData: {},
|
|
2332
|
+
errors: {
|
|
2333
|
+
[routeId]: result.error
|
|
2334
|
+
}
|
|
2335
|
+
});
|
|
2336
|
+
return;
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2339
|
+
matches = actionResult.matches || matches;
|
|
2299
2340
|
pendingActionResult = actionResult.pendingActionResult;
|
|
2300
2341
|
loadingNavigation = getLoadingNavigation(location, opts.submission);
|
|
2301
2342
|
flushSync = false;
|
|
2343
|
+
// No need to do fog of war matching again on loader execution
|
|
2344
|
+
fogOfWar.active = false;
|
|
2302
2345
|
|
|
2303
2346
|
// Create a GET request for the loaders
|
|
2304
2347
|
request = createClientSideRequest(init.history, request.url, request.signal);
|
|
@@ -2307,9 +2350,10 @@ function createRouter(init) {
|
|
|
2307
2350
|
// Call loaders
|
|
2308
2351
|
let {
|
|
2309
2352
|
shortCircuited,
|
|
2353
|
+
matches: updatedMatches,
|
|
2310
2354
|
loaderData,
|
|
2311
2355
|
errors
|
|
2312
|
-
} = await handleLoaders(request, location, matches, loadingNavigation, opts && opts.submission, opts && opts.fetcherSubmission, opts && opts.replace, opts && opts.initialHydration === true, flushSync, pendingActionResult);
|
|
2356
|
+
} = await handleLoaders(request, location, matches, fogOfWar.active, loadingNavigation, opts && opts.submission, opts && opts.fetcherSubmission, opts && opts.replace, opts && opts.initialHydration === true, flushSync, pendingActionResult);
|
|
2313
2357
|
if (shortCircuited) {
|
|
2314
2358
|
return;
|
|
2315
2359
|
}
|
|
@@ -2319,7 +2363,7 @@ function createRouter(init) {
|
|
|
2319
2363
|
// been assigned to a new controller for the next navigation
|
|
2320
2364
|
pendingNavigationController = null;
|
|
2321
2365
|
completeNavigation(location, _extends({
|
|
2322
|
-
matches
|
|
2366
|
+
matches: updatedMatches || matches
|
|
2323
2367
|
}, getActionDataForCommit(pendingActionResult), {
|
|
2324
2368
|
loaderData,
|
|
2325
2369
|
errors
|
|
@@ -2328,7 +2372,7 @@ function createRouter(init) {
|
|
|
2328
2372
|
|
|
2329
2373
|
// Call the action matched by the leaf route for this navigation and handle
|
|
2330
2374
|
// redirects/errors
|
|
2331
|
-
async function handleAction(request, location, submission, matches, opts) {
|
|
2375
|
+
async function handleAction(request, location, submission, matches, isFogOfWar, opts) {
|
|
2332
2376
|
if (opts === void 0) {
|
|
2333
2377
|
opts = {};
|
|
2334
2378
|
}
|
|
@@ -2341,6 +2385,42 @@ function createRouter(init) {
|
|
|
2341
2385
|
}, {
|
|
2342
2386
|
flushSync: opts.flushSync === true
|
|
2343
2387
|
});
|
|
2388
|
+
if (isFogOfWar) {
|
|
2389
|
+
let discoverResult = await discoverRoutes(matches, location.pathname, request.signal);
|
|
2390
|
+
if (discoverResult.type === "aborted") {
|
|
2391
|
+
return {
|
|
2392
|
+
shortCircuited: true
|
|
2393
|
+
};
|
|
2394
|
+
} else if (discoverResult.type === "error") {
|
|
2395
|
+
let {
|
|
2396
|
+
error,
|
|
2397
|
+
notFoundMatches,
|
|
2398
|
+
route
|
|
2399
|
+
} = handleDiscoverRouteError(location.pathname, discoverResult);
|
|
2400
|
+
return {
|
|
2401
|
+
matches: notFoundMatches,
|
|
2402
|
+
pendingActionResult: [route.id, {
|
|
2403
|
+
type: ResultType.error,
|
|
2404
|
+
error
|
|
2405
|
+
}]
|
|
2406
|
+
};
|
|
2407
|
+
} else if (!discoverResult.matches) {
|
|
2408
|
+
let {
|
|
2409
|
+
notFoundMatches,
|
|
2410
|
+
error,
|
|
2411
|
+
route
|
|
2412
|
+
} = handleNavigational404(location.pathname);
|
|
2413
|
+
return {
|
|
2414
|
+
matches: notFoundMatches,
|
|
2415
|
+
pendingActionResult: [route.id, {
|
|
2416
|
+
type: ResultType.error,
|
|
2417
|
+
error
|
|
2418
|
+
}]
|
|
2419
|
+
};
|
|
2420
|
+
} else {
|
|
2421
|
+
matches = discoverResult.matches;
|
|
2422
|
+
}
|
|
2423
|
+
}
|
|
2344
2424
|
|
|
2345
2425
|
// Call our action and get the result
|
|
2346
2426
|
let result;
|
|
@@ -2392,31 +2472,94 @@ function createRouter(init) {
|
|
|
2392
2472
|
// to call and will commit it when we complete the navigation
|
|
2393
2473
|
let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id);
|
|
2394
2474
|
|
|
2395
|
-
// By default, all submissions
|
|
2396
|
-
// action threw an error that'll be rendered in
|
|
2397
|
-
// back to PUSH so that the user can use the
|
|
2398
|
-
// the pre-submission form location to try
|
|
2475
|
+
// By default, all submissions to the current location are REPLACE
|
|
2476
|
+
// navigations, but if the action threw an error that'll be rendered in
|
|
2477
|
+
// an errorElement, we fall back to PUSH so that the user can use the
|
|
2478
|
+
// back button to get back to the pre-submission form location to try
|
|
2479
|
+
// again
|
|
2399
2480
|
if ((opts && opts.replace) !== true) {
|
|
2400
2481
|
pendingAction = Action.Push;
|
|
2401
2482
|
}
|
|
2402
2483
|
return {
|
|
2484
|
+
matches,
|
|
2403
2485
|
pendingActionResult: [boundaryMatch.route.id, result]
|
|
2404
2486
|
};
|
|
2405
2487
|
}
|
|
2406
2488
|
return {
|
|
2489
|
+
matches,
|
|
2407
2490
|
pendingActionResult: [actionMatch.route.id, result]
|
|
2408
2491
|
};
|
|
2409
2492
|
}
|
|
2410
2493
|
|
|
2411
2494
|
// Call all applicable loaders for the given matches, handling redirects,
|
|
2412
2495
|
// errors, etc.
|
|
2413
|
-
async function handleLoaders(request, location, matches, overrideNavigation, submission, fetcherSubmission, replace, initialHydration, flushSync, pendingActionResult) {
|
|
2496
|
+
async function handleLoaders(request, location, matches, isFogOfWar, overrideNavigation, submission, fetcherSubmission, replace, initialHydration, flushSync, pendingActionResult) {
|
|
2414
2497
|
// Figure out the right navigation we want to use for data loading
|
|
2415
2498
|
let loadingNavigation = overrideNavigation || getLoadingNavigation(location, submission);
|
|
2416
2499
|
|
|
2417
2500
|
// If this was a redirect from an action we don't have a "submission" but
|
|
2418
2501
|
// we have it on the loading navigation so use that if available
|
|
2419
2502
|
let activeSubmission = submission || fetcherSubmission || getSubmissionFromNavigation(loadingNavigation);
|
|
2503
|
+
|
|
2504
|
+
// If this is an uninterrupted revalidation, we remain in our current idle
|
|
2505
|
+
// state. If not, we need to switch to our loading state and load data,
|
|
2506
|
+
// preserving any new action data or existing action data (in the case of
|
|
2507
|
+
// a revalidation interrupting an actionReload)
|
|
2508
|
+
// If we have partialHydration enabled, then don't update the state for the
|
|
2509
|
+
// initial data load since it's not a "navigation"
|
|
2510
|
+
let shouldUpdateNavigationState = !isUninterruptedRevalidation && (!future.v7_partialHydration || !initialHydration);
|
|
2511
|
+
|
|
2512
|
+
// When fog of war is enabled, we enter our `loading` state earlier so we
|
|
2513
|
+
// can discover new routes during the `loading` state. We skip this if
|
|
2514
|
+
// we've already run actions since we would have done our matching already.
|
|
2515
|
+
// If the children() function threw then, we want to proceed with the
|
|
2516
|
+
// partial matches it discovered.
|
|
2517
|
+
if (isFogOfWar) {
|
|
2518
|
+
if (shouldUpdateNavigationState) {
|
|
2519
|
+
let actionData = getUpdatedActionData(pendingActionResult);
|
|
2520
|
+
updateState(_extends({
|
|
2521
|
+
navigation: loadingNavigation
|
|
2522
|
+
}, actionData !== undefined ? {
|
|
2523
|
+
actionData
|
|
2524
|
+
} : {}), {
|
|
2525
|
+
flushSync
|
|
2526
|
+
});
|
|
2527
|
+
}
|
|
2528
|
+
let discoverResult = await discoverRoutes(matches, location.pathname, request.signal);
|
|
2529
|
+
if (discoverResult.type === "aborted") {
|
|
2530
|
+
return {
|
|
2531
|
+
shortCircuited: true
|
|
2532
|
+
};
|
|
2533
|
+
} else if (discoverResult.type === "error") {
|
|
2534
|
+
let {
|
|
2535
|
+
error,
|
|
2536
|
+
notFoundMatches,
|
|
2537
|
+
route
|
|
2538
|
+
} = handleDiscoverRouteError(location.pathname, discoverResult);
|
|
2539
|
+
return {
|
|
2540
|
+
matches: notFoundMatches,
|
|
2541
|
+
loaderData: {},
|
|
2542
|
+
errors: {
|
|
2543
|
+
[route.id]: error
|
|
2544
|
+
}
|
|
2545
|
+
};
|
|
2546
|
+
} else if (!discoverResult.matches) {
|
|
2547
|
+
let {
|
|
2548
|
+
error,
|
|
2549
|
+
notFoundMatches,
|
|
2550
|
+
route
|
|
2551
|
+
} = handleNavigational404(location.pathname);
|
|
2552
|
+
return {
|
|
2553
|
+
matches: notFoundMatches,
|
|
2554
|
+
loaderData: {},
|
|
2555
|
+
errors: {
|
|
2556
|
+
[route.id]: error
|
|
2557
|
+
}
|
|
2558
|
+
};
|
|
2559
|
+
} else {
|
|
2560
|
+
matches = discoverResult.matches;
|
|
2561
|
+
}
|
|
2562
|
+
}
|
|
2420
2563
|
let routesToUse = inFlightDataRoutes || dataRoutes;
|
|
2421
2564
|
let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, activeSubmission, location, future.v7_partialHydration && initialHydration === true, future.unstable_skipActionErrorRevalidation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, pendingActionResult);
|
|
2422
2565
|
|
|
@@ -2445,41 +2588,20 @@ function createRouter(init) {
|
|
|
2445
2588
|
shortCircuited: true
|
|
2446
2589
|
};
|
|
2447
2590
|
}
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
revalidatingFetchers.forEach(rf => {
|
|
2457
|
-
let fetcher = state.fetchers.get(rf.key);
|
|
2458
|
-
let revalidatingFetcher = getLoadingFetcher(undefined, fetcher ? fetcher.data : undefined);
|
|
2459
|
-
state.fetchers.set(rf.key, revalidatingFetcher);
|
|
2460
|
-
});
|
|
2461
|
-
let actionData;
|
|
2462
|
-
if (pendingActionResult && !isErrorResult(pendingActionResult[1])) {
|
|
2463
|
-
// This is cast to `any` currently because `RouteData`uses any and it
|
|
2464
|
-
// would be a breaking change to use any.
|
|
2465
|
-
// TODO: v7 - change `RouteData` to use `unknown` instead of `any`
|
|
2466
|
-
actionData = {
|
|
2467
|
-
[pendingActionResult[0]]: pendingActionResult[1].data
|
|
2468
|
-
};
|
|
2469
|
-
} else if (state.actionData) {
|
|
2470
|
-
if (Object.keys(state.actionData).length === 0) {
|
|
2471
|
-
actionData = null;
|
|
2472
|
-
} else {
|
|
2473
|
-
actionData = state.actionData;
|
|
2591
|
+
if (shouldUpdateNavigationState) {
|
|
2592
|
+
let updates = {};
|
|
2593
|
+
if (!isFogOfWar) {
|
|
2594
|
+
// Only update navigation/actionNData if we didn't already do it above
|
|
2595
|
+
updates.navigation = loadingNavigation;
|
|
2596
|
+
let actionData = getUpdatedActionData(pendingActionResult);
|
|
2597
|
+
if (actionData !== undefined) {
|
|
2598
|
+
updates.actionData = actionData;
|
|
2474
2599
|
}
|
|
2475
2600
|
}
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
}
|
|
2479
|
-
|
|
2480
|
-
} : {}, revalidatingFetchers.length > 0 ? {
|
|
2481
|
-
fetchers: new Map(state.fetchers)
|
|
2482
|
-
} : {}), {
|
|
2601
|
+
if (revalidatingFetchers.length > 0) {
|
|
2602
|
+
updates.fetchers = getUpdatedRevalidatingFetchers(revalidatingFetchers);
|
|
2603
|
+
}
|
|
2604
|
+
updateState(updates, {
|
|
2483
2605
|
flushSync
|
|
2484
2606
|
});
|
|
2485
2607
|
}
|
|
@@ -2570,12 +2692,37 @@ function createRouter(init) {
|
|
|
2570
2692
|
let didAbortFetchLoads = abortStaleFetchLoads(pendingNavigationLoadId);
|
|
2571
2693
|
let shouldUpdateFetchers = updatedFetchers || didAbortFetchLoads || revalidatingFetchers.length > 0;
|
|
2572
2694
|
return _extends({
|
|
2695
|
+
matches,
|
|
2573
2696
|
loaderData,
|
|
2574
2697
|
errors
|
|
2575
2698
|
}, shouldUpdateFetchers ? {
|
|
2576
2699
|
fetchers: new Map(state.fetchers)
|
|
2577
2700
|
} : {});
|
|
2578
2701
|
}
|
|
2702
|
+
function getUpdatedActionData(pendingActionResult) {
|
|
2703
|
+
if (pendingActionResult && !isErrorResult(pendingActionResult[1])) {
|
|
2704
|
+
// This is cast to `any` currently because `RouteData`uses any and it
|
|
2705
|
+
// would be a breaking change to use any.
|
|
2706
|
+
// TODO: v7 - change `RouteData` to use `unknown` instead of `any`
|
|
2707
|
+
return {
|
|
2708
|
+
[pendingActionResult[0]]: pendingActionResult[1].data
|
|
2709
|
+
};
|
|
2710
|
+
} else if (state.actionData) {
|
|
2711
|
+
if (Object.keys(state.actionData).length === 0) {
|
|
2712
|
+
return null;
|
|
2713
|
+
} else {
|
|
2714
|
+
return state.actionData;
|
|
2715
|
+
}
|
|
2716
|
+
}
|
|
2717
|
+
}
|
|
2718
|
+
function getUpdatedRevalidatingFetchers(revalidatingFetchers) {
|
|
2719
|
+
revalidatingFetchers.forEach(rf => {
|
|
2720
|
+
let fetcher = state.fetchers.get(rf.key);
|
|
2721
|
+
let revalidatingFetcher = getLoadingFetcher(undefined, fetcher ? fetcher.data : undefined);
|
|
2722
|
+
state.fetchers.set(rf.key, revalidatingFetcher);
|
|
2723
|
+
});
|
|
2724
|
+
return new Map(state.fetchers);
|
|
2725
|
+
}
|
|
2579
2726
|
|
|
2580
2727
|
// Trigger a fetcher load/submit for the given fetcher key
|
|
2581
2728
|
function fetch(key, routeId, href, opts) {
|
|
@@ -2587,6 +2734,10 @@ function createRouter(init) {
|
|
|
2587
2734
|
let routesToUse = inFlightDataRoutes || dataRoutes;
|
|
2588
2735
|
let normalizedPath = normalizeTo(state.location, state.matches, basename, future.v7_prependBasename, href, future.v7_relativeSplatPath, routeId, opts == null ? void 0 : opts.relative);
|
|
2589
2736
|
let matches = matchRoutes(routesToUse, normalizedPath, basename);
|
|
2737
|
+
let fogOfWar = checkFogOfWar(matches, routesToUse, normalizedPath);
|
|
2738
|
+
if (fogOfWar.active && fogOfWar.matches) {
|
|
2739
|
+
matches = fogOfWar.matches;
|
|
2740
|
+
}
|
|
2590
2741
|
if (!matches) {
|
|
2591
2742
|
setFetcherError(key, routeId, getInternalRouterError(404, {
|
|
2592
2743
|
pathname: normalizedPath
|
|
@@ -2609,7 +2760,7 @@ function createRouter(init) {
|
|
|
2609
2760
|
let match = getTargetMatch(matches, path);
|
|
2610
2761
|
pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;
|
|
2611
2762
|
if (submission && isMutationMethod(submission.formMethod)) {
|
|
2612
|
-
handleFetcherAction(key, routeId, path, match, matches, flushSync, submission);
|
|
2763
|
+
handleFetcherAction(key, routeId, path, match, matches, fogOfWar.active, flushSync, submission);
|
|
2613
2764
|
return;
|
|
2614
2765
|
}
|
|
2615
2766
|
|
|
@@ -2619,23 +2770,29 @@ function createRouter(init) {
|
|
|
2619
2770
|
routeId,
|
|
2620
2771
|
path
|
|
2621
2772
|
});
|
|
2622
|
-
handleFetcherLoader(key, routeId, path, match, matches, flushSync, submission);
|
|
2773
|
+
handleFetcherLoader(key, routeId, path, match, matches, fogOfWar.active, flushSync, submission);
|
|
2623
2774
|
}
|
|
2624
2775
|
|
|
2625
2776
|
// Call the action for the matched fetcher.submit(), and then handle redirects,
|
|
2626
2777
|
// errors, and revalidation
|
|
2627
|
-
async function handleFetcherAction(key, routeId, path, match, requestMatches, flushSync, submission) {
|
|
2778
|
+
async function handleFetcherAction(key, routeId, path, match, requestMatches, isFogOfWar, flushSync, submission) {
|
|
2628
2779
|
interruptActiveLoads();
|
|
2629
2780
|
fetchLoadMatches.delete(key);
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2781
|
+
function detectAndHandle405Error(m) {
|
|
2782
|
+
if (!m.route.action && !m.route.lazy) {
|
|
2783
|
+
let error = getInternalRouterError(405, {
|
|
2784
|
+
method: submission.formMethod,
|
|
2785
|
+
pathname: path,
|
|
2786
|
+
routeId: routeId
|
|
2787
|
+
});
|
|
2788
|
+
setFetcherError(key, routeId, error, {
|
|
2789
|
+
flushSync
|
|
2790
|
+
});
|
|
2791
|
+
return true;
|
|
2792
|
+
}
|
|
2793
|
+
return false;
|
|
2794
|
+
}
|
|
2795
|
+
if (!isFogOfWar && detectAndHandle405Error(match)) {
|
|
2639
2796
|
return;
|
|
2640
2797
|
}
|
|
2641
2798
|
|
|
@@ -2644,10 +2801,37 @@ function createRouter(init) {
|
|
|
2644
2801
|
updateFetcherState(key, getSubmittingFetcher(submission, existingFetcher), {
|
|
2645
2802
|
flushSync
|
|
2646
2803
|
});
|
|
2647
|
-
|
|
2648
|
-
// Call the action for the fetcher
|
|
2649
2804
|
let abortController = new AbortController();
|
|
2650
2805
|
let fetchRequest = createClientSideRequest(init.history, path, abortController.signal, submission);
|
|
2806
|
+
if (isFogOfWar) {
|
|
2807
|
+
let discoverResult = await discoverRoutes(requestMatches, path, fetchRequest.signal);
|
|
2808
|
+
if (discoverResult.type === "aborted") {
|
|
2809
|
+
return;
|
|
2810
|
+
} else if (discoverResult.type === "error") {
|
|
2811
|
+
let {
|
|
2812
|
+
error
|
|
2813
|
+
} = handleDiscoverRouteError(path, discoverResult);
|
|
2814
|
+
setFetcherError(key, routeId, error, {
|
|
2815
|
+
flushSync
|
|
2816
|
+
});
|
|
2817
|
+
return;
|
|
2818
|
+
} else if (!discoverResult.matches) {
|
|
2819
|
+
setFetcherError(key, routeId, getInternalRouterError(404, {
|
|
2820
|
+
pathname: path
|
|
2821
|
+
}), {
|
|
2822
|
+
flushSync
|
|
2823
|
+
});
|
|
2824
|
+
return;
|
|
2825
|
+
} else {
|
|
2826
|
+
requestMatches = discoverResult.matches;
|
|
2827
|
+
match = getTargetMatch(requestMatches, path);
|
|
2828
|
+
if (detectAndHandle405Error(match)) {
|
|
2829
|
+
return;
|
|
2830
|
+
}
|
|
2831
|
+
}
|
|
2832
|
+
}
|
|
2833
|
+
|
|
2834
|
+
// Call the action for the fetcher
|
|
2651
2835
|
fetchControllers.set(key, abortController);
|
|
2652
2836
|
let originatingLoadId = incrementingLoadId;
|
|
2653
2837
|
let actionResults = await callDataStrategy("action", fetchRequest, [match], requestMatches);
|
|
@@ -2797,15 +2981,39 @@ function createRouter(init) {
|
|
|
2797
2981
|
}
|
|
2798
2982
|
|
|
2799
2983
|
// Call the matched loader for fetcher.load(), handling redirects, errors, etc.
|
|
2800
|
-
async function handleFetcherLoader(key, routeId, path, match, matches, flushSync, submission) {
|
|
2984
|
+
async function handleFetcherLoader(key, routeId, path, match, matches, isFogOfWar, flushSync, submission) {
|
|
2801
2985
|
let existingFetcher = state.fetchers.get(key);
|
|
2802
2986
|
updateFetcherState(key, getLoadingFetcher(submission, existingFetcher ? existingFetcher.data : undefined), {
|
|
2803
2987
|
flushSync
|
|
2804
2988
|
});
|
|
2805
|
-
|
|
2806
|
-
// Call the loader for this fetcher route match
|
|
2807
2989
|
let abortController = new AbortController();
|
|
2808
2990
|
let fetchRequest = createClientSideRequest(init.history, path, abortController.signal);
|
|
2991
|
+
if (isFogOfWar) {
|
|
2992
|
+
let discoverResult = await discoverRoutes(matches, path, fetchRequest.signal);
|
|
2993
|
+
if (discoverResult.type === "aborted") {
|
|
2994
|
+
return;
|
|
2995
|
+
} else if (discoverResult.type === "error") {
|
|
2996
|
+
let {
|
|
2997
|
+
error
|
|
2998
|
+
} = handleDiscoverRouteError(path, discoverResult);
|
|
2999
|
+
setFetcherError(key, routeId, error, {
|
|
3000
|
+
flushSync
|
|
3001
|
+
});
|
|
3002
|
+
return;
|
|
3003
|
+
} else if (!discoverResult.matches) {
|
|
3004
|
+
setFetcherError(key, routeId, getInternalRouterError(404, {
|
|
3005
|
+
pathname: path
|
|
3006
|
+
}), {
|
|
3007
|
+
flushSync
|
|
3008
|
+
});
|
|
3009
|
+
return;
|
|
3010
|
+
} else {
|
|
3011
|
+
matches = discoverResult.matches;
|
|
3012
|
+
match = getTargetMatch(matches, path);
|
|
3013
|
+
}
|
|
3014
|
+
}
|
|
3015
|
+
|
|
3016
|
+
// Call the loader for this fetcher route match
|
|
2809
3017
|
fetchControllers.set(key, abortController);
|
|
2810
3018
|
let originatingLoadId = incrementingLoadId;
|
|
2811
3019
|
let results = await callDataStrategy("loader", fetchRequest, [match], matches);
|
|
@@ -3189,6 +3397,39 @@ function createRouter(init) {
|
|
|
3189
3397
|
return blockerKey;
|
|
3190
3398
|
}
|
|
3191
3399
|
}
|
|
3400
|
+
function handleNavigational404(pathname) {
|
|
3401
|
+
let error = getInternalRouterError(404, {
|
|
3402
|
+
pathname
|
|
3403
|
+
});
|
|
3404
|
+
let routesToUse = inFlightDataRoutes || dataRoutes;
|
|
3405
|
+
let {
|
|
3406
|
+
matches,
|
|
3407
|
+
route
|
|
3408
|
+
} = getShortCircuitMatches(routesToUse);
|
|
3409
|
+
|
|
3410
|
+
// Cancel all pending deferred on 404s since we don't keep any routes
|
|
3411
|
+
cancelActiveDeferreds();
|
|
3412
|
+
return {
|
|
3413
|
+
notFoundMatches: matches,
|
|
3414
|
+
route,
|
|
3415
|
+
error
|
|
3416
|
+
};
|
|
3417
|
+
}
|
|
3418
|
+
function handleDiscoverRouteError(pathname, discoverResult) {
|
|
3419
|
+
let matches = discoverResult.partialMatches;
|
|
3420
|
+
let route = matches[matches.length - 1].route;
|
|
3421
|
+
let error = getInternalRouterError(400, {
|
|
3422
|
+
type: "route-discovery",
|
|
3423
|
+
routeId: route.id,
|
|
3424
|
+
pathname,
|
|
3425
|
+
message: discoverResult.error != null && "message" in discoverResult.error ? discoverResult.error : String(discoverResult.error)
|
|
3426
|
+
});
|
|
3427
|
+
return {
|
|
3428
|
+
notFoundMatches: matches,
|
|
3429
|
+
route,
|
|
3430
|
+
error
|
|
3431
|
+
};
|
|
3432
|
+
}
|
|
3192
3433
|
function cancelActiveDeferreds(predicate) {
|
|
3193
3434
|
let cancelledRouteIds = [];
|
|
3194
3435
|
activeDeferreds.forEach((dfd, routeId) => {
|
|
@@ -3252,6 +3493,100 @@ function createRouter(init) {
|
|
|
3252
3493
|
}
|
|
3253
3494
|
return null;
|
|
3254
3495
|
}
|
|
3496
|
+
function checkFogOfWar(matches, routesToUse, pathname) {
|
|
3497
|
+
if (patchRoutesOnMissImpl) {
|
|
3498
|
+
if (!matches) {
|
|
3499
|
+
let fogMatches = matchRoutesImpl(routesToUse, pathname, basename, true);
|
|
3500
|
+
return {
|
|
3501
|
+
active: true,
|
|
3502
|
+
matches: fogMatches || []
|
|
3503
|
+
};
|
|
3504
|
+
} else {
|
|
3505
|
+
let leafRoute = matches[matches.length - 1].route;
|
|
3506
|
+
if (leafRoute.path === "*") {
|
|
3507
|
+
// If we matched a splat, it might only be because we haven't yet fetched
|
|
3508
|
+
// the children that would match with a higher score, so let's fetch
|
|
3509
|
+
// around and find out
|
|
3510
|
+
let partialMatches = matchRoutesImpl(routesToUse, pathname, basename, true);
|
|
3511
|
+
return {
|
|
3512
|
+
active: true,
|
|
3513
|
+
matches: partialMatches
|
|
3514
|
+
};
|
|
3515
|
+
}
|
|
3516
|
+
}
|
|
3517
|
+
}
|
|
3518
|
+
return {
|
|
3519
|
+
active: false,
|
|
3520
|
+
matches: null
|
|
3521
|
+
};
|
|
3522
|
+
}
|
|
3523
|
+
async function discoverRoutes(matches, pathname, signal) {
|
|
3524
|
+
let partialMatches = matches;
|
|
3525
|
+
let route = partialMatches.length > 0 ? partialMatches[partialMatches.length - 1].route : null;
|
|
3526
|
+
while (true) {
|
|
3527
|
+
try {
|
|
3528
|
+
await loadLazyRouteChildren(patchRoutesOnMissImpl, pathname, partialMatches, dataRoutes || inFlightDataRoutes, manifest, mapRouteProperties, pendingPatchRoutes, signal);
|
|
3529
|
+
} catch (e) {
|
|
3530
|
+
return {
|
|
3531
|
+
type: "error",
|
|
3532
|
+
error: e,
|
|
3533
|
+
partialMatches
|
|
3534
|
+
};
|
|
3535
|
+
}
|
|
3536
|
+
if (signal.aborted) {
|
|
3537
|
+
return {
|
|
3538
|
+
type: "aborted"
|
|
3539
|
+
};
|
|
3540
|
+
}
|
|
3541
|
+
let routesToUse = inFlightDataRoutes || dataRoutes;
|
|
3542
|
+
let newMatches = matchRoutes(routesToUse, pathname, basename);
|
|
3543
|
+
let matchedSplat = false;
|
|
3544
|
+
if (newMatches) {
|
|
3545
|
+
let leafRoute = newMatches[newMatches.length - 1].route;
|
|
3546
|
+
if (leafRoute.index) {
|
|
3547
|
+
// If we found an index route, we can stop
|
|
3548
|
+
return {
|
|
3549
|
+
type: "success",
|
|
3550
|
+
matches: newMatches
|
|
3551
|
+
};
|
|
3552
|
+
}
|
|
3553
|
+
if (leafRoute.path && leafRoute.path.length > 0) {
|
|
3554
|
+
if (leafRoute.path === "*") {
|
|
3555
|
+
// If we found a splat route, we can't be sure there's not a
|
|
3556
|
+
// higher-scoring route down some partial matches trail so we need
|
|
3557
|
+
// to check that out
|
|
3558
|
+
matchedSplat = true;
|
|
3559
|
+
} else {
|
|
3560
|
+
// If we found a non-splat route, we can stop
|
|
3561
|
+
return {
|
|
3562
|
+
type: "success",
|
|
3563
|
+
matches: newMatches
|
|
3564
|
+
};
|
|
3565
|
+
}
|
|
3566
|
+
}
|
|
3567
|
+
}
|
|
3568
|
+
let newPartialMatches = matchRoutesImpl(routesToUse, pathname, basename, true);
|
|
3569
|
+
|
|
3570
|
+
// If we are no longer partially matching anything, this was either a
|
|
3571
|
+
// legit splat match above, or it's a 404. Also avoid loops if the
|
|
3572
|
+
// second pass results in the same partial matches
|
|
3573
|
+
if (!newPartialMatches || partialMatches.map(m => m.route.id).join("-") === newPartialMatches.map(m => m.route.id).join("-")) {
|
|
3574
|
+
return {
|
|
3575
|
+
type: "success",
|
|
3576
|
+
matches: matchedSplat ? newMatches : null
|
|
3577
|
+
};
|
|
3578
|
+
}
|
|
3579
|
+
partialMatches = newPartialMatches;
|
|
3580
|
+
route = partialMatches[partialMatches.length - 1].route;
|
|
3581
|
+
if (route.path === "*") {
|
|
3582
|
+
// The splat is still our most accurate partial, so run with it
|
|
3583
|
+
return {
|
|
3584
|
+
type: "success",
|
|
3585
|
+
matches: partialMatches
|
|
3586
|
+
};
|
|
3587
|
+
}
|
|
3588
|
+
}
|
|
3589
|
+
}
|
|
3255
3590
|
function _internalSetRoutes(newRoutes) {
|
|
3256
3591
|
manifest = {};
|
|
3257
3592
|
inFlightDataRoutes = convertRoutesToDataRoutes(newRoutes, mapRouteProperties, undefined, manifest);
|
|
@@ -3287,6 +3622,9 @@ function createRouter(init) {
|
|
|
3287
3622
|
dispose,
|
|
3288
3623
|
getBlocker,
|
|
3289
3624
|
deleteBlocker,
|
|
3625
|
+
patchRoutes(routeId, children) {
|
|
3626
|
+
return patchRoutes(routeId, children, dataRoutes || inFlightDataRoutes, manifest, mapRouteProperties);
|
|
3627
|
+
},
|
|
3290
3628
|
_internalFetchControllers: fetchControllers,
|
|
3291
3629
|
_internalActiveDeferreds: activeDeferreds,
|
|
3292
3630
|
// TODO: Remove setRoutes, it's temporary to avoid dealing with
|
|
@@ -4103,6 +4441,50 @@ function shouldRevalidateLoader(loaderMatch, arg) {
|
|
|
4103
4441
|
return arg.defaultShouldRevalidate;
|
|
4104
4442
|
}
|
|
4105
4443
|
|
|
4444
|
+
/**
|
|
4445
|
+
* Idempotent utility to execute route.children() method to lazily load route
|
|
4446
|
+
* definitions and update the routes/routeManifest
|
|
4447
|
+
*/
|
|
4448
|
+
async function loadLazyRouteChildren(patchRoutesOnMissImpl, path, matches, routes, manifest, mapRouteProperties, pendingRouteChildren, signal) {
|
|
4449
|
+
let key = [path, ...matches.map(m => m.route.id)].join("-");
|
|
4450
|
+
try {
|
|
4451
|
+
let pending = pendingRouteChildren.get(key);
|
|
4452
|
+
if (!pending) {
|
|
4453
|
+
pending = patchRoutesOnMissImpl({
|
|
4454
|
+
path,
|
|
4455
|
+
matches,
|
|
4456
|
+
patch: (routeId, children) => {
|
|
4457
|
+
if (!signal.aborted) {
|
|
4458
|
+
patchRoutes(routeId, children, routes, manifest, mapRouteProperties);
|
|
4459
|
+
}
|
|
4460
|
+
}
|
|
4461
|
+
});
|
|
4462
|
+
pendingRouteChildren.set(key, pending);
|
|
4463
|
+
}
|
|
4464
|
+
if (pending && isPromise(pending)) {
|
|
4465
|
+
await pending;
|
|
4466
|
+
}
|
|
4467
|
+
} finally {
|
|
4468
|
+
pendingRouteChildren.delete(key);
|
|
4469
|
+
}
|
|
4470
|
+
}
|
|
4471
|
+
function patchRoutes(routeId, children, routes, manifest, mapRouteProperties) {
|
|
4472
|
+
if (routeId) {
|
|
4473
|
+
var _route$children;
|
|
4474
|
+
let route = manifest[routeId];
|
|
4475
|
+
invariant(route, "No route found to patch children into: routeId = " + routeId);
|
|
4476
|
+
let dataChildren = convertRoutesToDataRoutes(children, mapRouteProperties, [routeId, "patch", String(((_route$children = route.children) == null ? void 0 : _route$children.length) || "0")], manifest);
|
|
4477
|
+
if (route.children) {
|
|
4478
|
+
route.children.push(...dataChildren);
|
|
4479
|
+
} else {
|
|
4480
|
+
route.children = dataChildren;
|
|
4481
|
+
}
|
|
4482
|
+
} else {
|
|
4483
|
+
let dataChildren = convertRoutesToDataRoutes(children, mapRouteProperties, ["patch", String(routes.length || "0")], manifest);
|
|
4484
|
+
routes.push(...dataChildren);
|
|
4485
|
+
}
|
|
4486
|
+
}
|
|
4487
|
+
|
|
4106
4488
|
/**
|
|
4107
4489
|
* Execute route.lazy() methods to lazily load route modules (loader, action,
|
|
4108
4490
|
* shouldRevalidate) and update the routeManifest in place which shares objects
|
|
@@ -4646,13 +5028,16 @@ function getInternalRouterError(status, _temp5) {
|
|
|
4646
5028
|
pathname,
|
|
4647
5029
|
routeId,
|
|
4648
5030
|
method,
|
|
4649
|
-
type
|
|
5031
|
+
type,
|
|
5032
|
+
message
|
|
4650
5033
|
} = _temp5 === void 0 ? {} : _temp5;
|
|
4651
5034
|
let statusText = "Unknown Server Error";
|
|
4652
5035
|
let errorMessage = "Unknown @remix-run/router error";
|
|
4653
5036
|
if (status === 400) {
|
|
4654
5037
|
statusText = "Bad Request";
|
|
4655
|
-
if (
|
|
5038
|
+
if (type === "route-discovery") {
|
|
5039
|
+
errorMessage = "Unable to match URL \"" + pathname + "\" - the `children()` function for " + ("route `" + routeId + "` threw the following error:\n" + message);
|
|
5040
|
+
} else if (method && pathname && routeId) {
|
|
4656
5041
|
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.";
|
|
4657
5042
|
} else if (type === "defer-action") {
|
|
4658
5043
|
errorMessage = "defer() is not supported in actions";
|
|
@@ -4713,6 +5098,9 @@ function isHashChangeOnly(a, b) {
|
|
|
4713
5098
|
// /page#hash -> /page
|
|
4714
5099
|
return false;
|
|
4715
5100
|
}
|
|
5101
|
+
function isPromise(val) {
|
|
5102
|
+
return typeof val === "object" && val != null && "then" in val;
|
|
5103
|
+
}
|
|
4716
5104
|
function isHandlerResult(result) {
|
|
4717
5105
|
return result != null && typeof result === "object" && "type" in result && "result" in result && (result.type === ResultType.data || result.type === ResultType.error);
|
|
4718
5106
|
}
|
|
@@ -4978,7 +5366,6 @@ function persistAppliedTransitions(_window, transitions) {
|
|
|
4978
5366
|
}
|
|
4979
5367
|
}
|
|
4980
5368
|
}
|
|
4981
|
-
|
|
4982
5369
|
//#endregion
|
|
4983
5370
|
|
|
4984
5371
|
exports.AbortedDeferredError = AbortedDeferredError;
|