@remix-run/router 1.0.2 → 1.0.3-pre.1
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 +22 -2
- package/dist/history.d.ts +9 -0
- package/dist/index.d.ts +2 -2
- package/dist/router.cjs.js +340 -169
- package/dist/router.cjs.js.map +1 -1
- package/dist/router.js +340 -170
- package/dist/router.js.map +1 -1
- package/dist/router.umd.js +3425 -0
- package/dist/router.umd.js.map +1 -0
- package/dist/router.umd.min.js +12 -0
- package/dist/router.umd.min.js.map +1 -0
- package/dist/utils.d.ts +24 -0
- package/history.ts +38 -2
- package/index.ts +5 -2
- package/package.json +2 -1
- package/router.ts +372 -171
- package/utils.ts +57 -1
package/dist/router.cjs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @remix-run/router v1.0.
|
|
2
|
+
* @remix-run/router v1.0.3-pre.1
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -113,6 +113,10 @@ function createMemoryHistory(options) {
|
|
|
113
113
|
return typeof to === "string" ? to : createPath(to);
|
|
114
114
|
},
|
|
115
115
|
|
|
116
|
+
encodeLocation(location) {
|
|
117
|
+
return location;
|
|
118
|
+
},
|
|
119
|
+
|
|
116
120
|
push(to, state) {
|
|
117
121
|
action = exports.Action.Push;
|
|
118
122
|
let nextLocation = createMemoryLocation(to, state);
|
|
@@ -370,6 +374,14 @@ function parsePath(path) {
|
|
|
370
374
|
|
|
371
375
|
return parsedPath;
|
|
372
376
|
}
|
|
377
|
+
function createURL(location) {
|
|
378
|
+
// window.location.origin is "null" (the literal string value) in Firefox
|
|
379
|
+
// under certain conditions, notably when serving from a local HTML file
|
|
380
|
+
// See https://bugzilla.mozilla.org/show_bug.cgi?id=878297
|
|
381
|
+
let base = typeof window !== "undefined" && typeof window.location !== "undefined" && window.location.origin !== "null" ? window.location.origin : "unknown://unknown";
|
|
382
|
+
let href = typeof location === "string" ? location : createPath(location);
|
|
383
|
+
return new URL(href, base);
|
|
384
|
+
}
|
|
373
385
|
|
|
374
386
|
function getUrlBasedHistory(getLocation, createHref, validateLocation, options) {
|
|
375
387
|
if (options === void 0) {
|
|
@@ -413,7 +425,7 @@ function getUrlBasedHistory(getLocation, createHref, validateLocation, options)
|
|
|
413
425
|
if (v5Compat && listener) {
|
|
414
426
|
listener({
|
|
415
427
|
action,
|
|
416
|
-
location
|
|
428
|
+
location: history.location
|
|
417
429
|
});
|
|
418
430
|
}
|
|
419
431
|
}
|
|
@@ -429,7 +441,7 @@ function getUrlBasedHistory(getLocation, createHref, validateLocation, options)
|
|
|
429
441
|
if (v5Compat && listener) {
|
|
430
442
|
listener({
|
|
431
443
|
action,
|
|
432
|
-
location: location
|
|
444
|
+
location: history.location
|
|
433
445
|
});
|
|
434
446
|
}
|
|
435
447
|
}
|
|
@@ -460,6 +472,16 @@ function getUrlBasedHistory(getLocation, createHref, validateLocation, options)
|
|
|
460
472
|
return createHref(window, to);
|
|
461
473
|
},
|
|
462
474
|
|
|
475
|
+
encodeLocation(location) {
|
|
476
|
+
// Encode a Location the same way window.location would
|
|
477
|
+
let url = createURL(createPath(location));
|
|
478
|
+
return _extends({}, location, {
|
|
479
|
+
pathname: url.pathname,
|
|
480
|
+
search: url.search,
|
|
481
|
+
hash: url.hash
|
|
482
|
+
});
|
|
483
|
+
},
|
|
484
|
+
|
|
463
485
|
push,
|
|
464
486
|
replace,
|
|
465
487
|
|
|
@@ -548,7 +570,13 @@ function matchRoutes(routes, locationArg, basename) {
|
|
|
548
570
|
let matches = null;
|
|
549
571
|
|
|
550
572
|
for (let i = 0; matches == null && i < branches.length; ++i) {
|
|
551
|
-
matches = matchRouteBranch(branches[i],
|
|
573
|
+
matches = matchRouteBranch(branches[i], // Incoming pathnames are generally encoded from either window.location
|
|
574
|
+
// or from router.navigate, but we want to match against the unencoded
|
|
575
|
+
// paths in the route definitions. Memory router locations won't be
|
|
576
|
+
// encoded here but there also shouldn't be anything to decode so this
|
|
577
|
+
// should be a safe operation. This avoids needing matchRoutes to be
|
|
578
|
+
// history-aware.
|
|
579
|
+
safelyDecodeURI(pathname));
|
|
552
580
|
}
|
|
553
581
|
|
|
554
582
|
return matches;
|
|
@@ -795,6 +823,15 @@ function compilePath(path, caseSensitive, end) {
|
|
|
795
823
|
return [matcher, paramNames];
|
|
796
824
|
}
|
|
797
825
|
|
|
826
|
+
function safelyDecodeURI(value) {
|
|
827
|
+
try {
|
|
828
|
+
return decodeURI(value);
|
|
829
|
+
} catch (error) {
|
|
830
|
+
warning(false, "The URL path \"" + value + "\" could not be decoded because it is is a " + "malformed URL segment. This is probably due to a bad percent " + ("encoding (" + error + ")."));
|
|
831
|
+
return value;
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
|
|
798
835
|
function safelyDecodeURIComponent(value, paramName) {
|
|
799
836
|
try {
|
|
800
837
|
return decodeURIComponent(value);
|
|
@@ -898,9 +935,36 @@ function getInvalidPathError(char, field, dest, path) {
|
|
|
898
935
|
}
|
|
899
936
|
/**
|
|
900
937
|
* @private
|
|
938
|
+
*
|
|
939
|
+
* When processing relative navigation we want to ignore ancestor routes that
|
|
940
|
+
* do not contribute to the path, such that index/pathless layout routes don't
|
|
941
|
+
* interfere.
|
|
942
|
+
*
|
|
943
|
+
* For example, when moving a route element into an index route and/or a
|
|
944
|
+
* pathless layout route, relative link behavior contained within should stay
|
|
945
|
+
* the same. Both of the following examples should link back to the root:
|
|
946
|
+
*
|
|
947
|
+
* <Route path="/">
|
|
948
|
+
* <Route path="accounts" element={<Link to=".."}>
|
|
949
|
+
* </Route>
|
|
950
|
+
*
|
|
951
|
+
* <Route path="/">
|
|
952
|
+
* <Route path="accounts">
|
|
953
|
+
* <Route element={<AccountsLayout />}> // <-- Does not contribute
|
|
954
|
+
* <Route index element={<Link to=".."} /> // <-- Does not contribute
|
|
955
|
+
* </Route
|
|
956
|
+
* </Route>
|
|
957
|
+
* </Route>
|
|
901
958
|
*/
|
|
902
959
|
|
|
903
960
|
|
|
961
|
+
function getPathContributingMatches(matches) {
|
|
962
|
+
return matches.filter((match, index) => index === 0 || match.route.path && match.route.path.length > 0);
|
|
963
|
+
}
|
|
964
|
+
/**
|
|
965
|
+
* @private
|
|
966
|
+
*/
|
|
967
|
+
|
|
904
968
|
function resolveTo(toArg, routePathnames, locationPathname, isPathRelative) {
|
|
905
969
|
if (isPathRelative === void 0) {
|
|
906
970
|
isPathRelative = false;
|
|
@@ -1228,7 +1292,9 @@ const IDLE_FETCHER = {
|
|
|
1228
1292
|
formAction: undefined,
|
|
1229
1293
|
formEncType: undefined,
|
|
1230
1294
|
formData: undefined
|
|
1231
|
-
};
|
|
1295
|
+
};
|
|
1296
|
+
const isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
|
|
1297
|
+
const isServer = !isBrowser; //#endregion
|
|
1232
1298
|
////////////////////////////////////////////////////////////////////////////////
|
|
1233
1299
|
//#region createRouter
|
|
1234
1300
|
////////////////////////////////////////////////////////////////////////////////
|
|
@@ -1435,7 +1501,13 @@ function createRouter(init) {
|
|
|
1435
1501
|
submission,
|
|
1436
1502
|
error
|
|
1437
1503
|
} = normalizeNavigateOptions(to, opts);
|
|
1438
|
-
let location = createLocation(state.location, path, opts && opts.state);
|
|
1504
|
+
let location = createLocation(state.location, path, opts && opts.state); // When using navigate as a PUSH/REPLACE we aren't reading an already-encoded
|
|
1505
|
+
// URL from window.location, so we need to encode it here so the behavior
|
|
1506
|
+
// remains the same as POP and non-data-router usages. new URL() does all
|
|
1507
|
+
// the same encoding we'd get from a history.pushState/window.location read
|
|
1508
|
+
// without having to touch history
|
|
1509
|
+
|
|
1510
|
+
location = init.history.encodeLocation(location);
|
|
1439
1511
|
let historyAction = (opts && opts.replace) === true || submission != null ? exports.Action.Replace : exports.Action.Push;
|
|
1440
1512
|
let preventScrollReset = opts && "preventScrollReset" in opts ? opts.preventScrollReset === true : undefined;
|
|
1441
1513
|
return await startNavigation(historyAction, location, {
|
|
@@ -1601,7 +1673,7 @@ function createRouter(init) {
|
|
|
1601
1673
|
if (!actionMatch.route.action) {
|
|
1602
1674
|
result = getMethodNotAllowedResult(location);
|
|
1603
1675
|
} else {
|
|
1604
|
-
result = await callLoaderOrAction("action", request, actionMatch);
|
|
1676
|
+
result = await callLoaderOrAction("action", request, actionMatch, matches, router.basename);
|
|
1605
1677
|
|
|
1606
1678
|
if (request.signal.aborted) {
|
|
1607
1679
|
return {
|
|
@@ -1696,7 +1768,7 @@ function createRouter(init) {
|
|
|
1696
1768
|
if (!isUninterruptedRevalidation) {
|
|
1697
1769
|
revalidatingFetchers.forEach(_ref2 => {
|
|
1698
1770
|
let [key] = _ref2;
|
|
1699
|
-
|
|
1771
|
+
let fetcher = state.fetchers.get(key);
|
|
1700
1772
|
let revalidatingFetcher = {
|
|
1701
1773
|
state: "loading",
|
|
1702
1774
|
data: fetcher && fetcher.data,
|
|
@@ -1724,7 +1796,7 @@ function createRouter(init) {
|
|
|
1724
1796
|
results,
|
|
1725
1797
|
loaderResults,
|
|
1726
1798
|
fetcherResults
|
|
1727
|
-
} = await callLoadersAndMaybeResolveData(state.matches, matchesToLoad, revalidatingFetchers, request);
|
|
1799
|
+
} = await callLoadersAndMaybeResolveData(state.matches, matches, matchesToLoad, revalidatingFetchers, request);
|
|
1728
1800
|
|
|
1729
1801
|
if (request.signal.aborted) {
|
|
1730
1802
|
return {
|
|
@@ -1782,7 +1854,7 @@ function createRouter(init) {
|
|
|
1782
1854
|
|
|
1783
1855
|
|
|
1784
1856
|
function fetch(key, routeId, href, opts) {
|
|
1785
|
-
if (
|
|
1857
|
+
if (isServer) {
|
|
1786
1858
|
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.");
|
|
1787
1859
|
}
|
|
1788
1860
|
|
|
@@ -1801,19 +1873,19 @@ function createRouter(init) {
|
|
|
1801
1873
|
let match = getTargetMatch(matches, path);
|
|
1802
1874
|
|
|
1803
1875
|
if (submission) {
|
|
1804
|
-
handleFetcherAction(key, routeId, path, match, submission);
|
|
1876
|
+
handleFetcherAction(key, routeId, path, match, matches, submission);
|
|
1805
1877
|
return;
|
|
1806
1878
|
} // Store off the match so we can call it's shouldRevalidate on subsequent
|
|
1807
1879
|
// revalidations
|
|
1808
1880
|
|
|
1809
1881
|
|
|
1810
|
-
fetchLoadMatches.set(key, [path, match]);
|
|
1811
|
-
handleFetcherLoader(key, routeId, path, match);
|
|
1882
|
+
fetchLoadMatches.set(key, [path, match, matches]);
|
|
1883
|
+
handleFetcherLoader(key, routeId, path, match, matches);
|
|
1812
1884
|
} // Call the action for the matched fetcher.submit(), and then handle redirects,
|
|
1813
1885
|
// errors, and revalidation
|
|
1814
1886
|
|
|
1815
1887
|
|
|
1816
|
-
async function handleFetcherAction(key, routeId, path, match, submission) {
|
|
1888
|
+
async function handleFetcherAction(key, routeId, path, match, requestMatches, submission) {
|
|
1817
1889
|
interruptActiveLoads();
|
|
1818
1890
|
fetchLoadMatches.delete(key);
|
|
1819
1891
|
|
|
@@ -1842,7 +1914,7 @@ function createRouter(init) {
|
|
|
1842
1914
|
let abortController = new AbortController();
|
|
1843
1915
|
let fetchRequest = createRequest(path, abortController.signal, submission);
|
|
1844
1916
|
fetchControllers.set(key, abortController);
|
|
1845
|
-
let actionResult = await callLoaderOrAction("action", fetchRequest, match);
|
|
1917
|
+
let actionResult = await callLoaderOrAction("action", fetchRequest, match, requestMatches, router.basename);
|
|
1846
1918
|
|
|
1847
1919
|
if (fetchRequest.signal.aborted) {
|
|
1848
1920
|
// We can delete this so long as we weren't aborted by ou our own fetcher
|
|
@@ -1934,7 +2006,7 @@ function createRouter(init) {
|
|
|
1934
2006
|
results,
|
|
1935
2007
|
loaderResults,
|
|
1936
2008
|
fetcherResults
|
|
1937
|
-
} = await callLoadersAndMaybeResolveData(state.matches, matchesToLoad, revalidatingFetchers, revalidationRequest);
|
|
2009
|
+
} = await callLoadersAndMaybeResolveData(state.matches, matches, matchesToLoad, revalidatingFetchers, revalidationRequest);
|
|
1938
2010
|
|
|
1939
2011
|
if (abortController.signal.aborted) {
|
|
1940
2012
|
return;
|
|
@@ -1996,7 +2068,7 @@ function createRouter(init) {
|
|
|
1996
2068
|
} // Call the matched loader for fetcher.load(), handling redirects, errors, etc.
|
|
1997
2069
|
|
|
1998
2070
|
|
|
1999
|
-
async function handleFetcherLoader(key, routeId, path, match) {
|
|
2071
|
+
async function handleFetcherLoader(key, routeId, path, match, matches) {
|
|
2000
2072
|
let existingFetcher = state.fetchers.get(key); // Put this fetcher into it's loading state
|
|
2001
2073
|
|
|
2002
2074
|
let loadingFetcher = {
|
|
@@ -2015,7 +2087,7 @@ function createRouter(init) {
|
|
|
2015
2087
|
let abortController = new AbortController();
|
|
2016
2088
|
let fetchRequest = createRequest(path, abortController.signal);
|
|
2017
2089
|
fetchControllers.set(key, abortController);
|
|
2018
|
-
let result = await callLoaderOrAction("loader", fetchRequest, match); // Deferred isn't supported or fetcher loads, await everything and treat it
|
|
2090
|
+
let result = await callLoaderOrAction("loader", fetchRequest, match, matches, router.basename); // Deferred isn't supported or fetcher loads, await everything and treat it
|
|
2019
2091
|
// as a normal load. resolveDeferredData will return undefined if this
|
|
2020
2092
|
// fetcher gets aborted, so we just leave result untouched and short circuit
|
|
2021
2093
|
// below if that happens
|
|
@@ -2108,13 +2180,13 @@ function createRouter(init) {
|
|
|
2108
2180
|
});
|
|
2109
2181
|
}
|
|
2110
2182
|
|
|
2111
|
-
async function callLoadersAndMaybeResolveData(currentMatches, matchesToLoad, fetchersToLoad, request) {
|
|
2183
|
+
async function callLoadersAndMaybeResolveData(currentMatches, matches, matchesToLoad, fetchersToLoad, request) {
|
|
2112
2184
|
// Call all navigation loaders and revalidating fetcher loaders in parallel,
|
|
2113
2185
|
// then slice off the results into separate arrays so we can handle them
|
|
2114
2186
|
// accordingly
|
|
2115
|
-
let results = await Promise.all([...matchesToLoad.map(
|
|
2116
|
-
let [, href, match] = _ref8;
|
|
2117
|
-
return callLoaderOrAction("loader", createRequest(href, request.signal), match);
|
|
2187
|
+
let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, router.basename)), ...fetchersToLoad.map(_ref8 => {
|
|
2188
|
+
let [, href, match, fetchMatches] = _ref8;
|
|
2189
|
+
return callLoaderOrAction("loader", createRequest(href, request.signal), match, fetchMatches, router.basename);
|
|
2118
2190
|
})]);
|
|
2119
2191
|
let loaderResults = results.slice(0, matchesToLoad.length);
|
|
2120
2192
|
let fetcherResults = results.slice(matchesToLoad.length);
|
|
@@ -2306,7 +2378,9 @@ function createRouter(init) {
|
|
|
2306
2378
|
navigate,
|
|
2307
2379
|
fetch,
|
|
2308
2380
|
revalidate,
|
|
2309
|
-
createHref
|
|
2381
|
+
// Passthrough to history-aware createHref used by useHref so we get proper
|
|
2382
|
+
// hash-aware URLs in DOM paths
|
|
2383
|
+
createHref: to => init.history.createHref(to),
|
|
2310
2384
|
getFetcher,
|
|
2311
2385
|
deleteFetcher,
|
|
2312
2386
|
dispose,
|
|
@@ -2319,15 +2393,75 @@ function createRouter(init) {
|
|
|
2319
2393
|
//#region createStaticHandler
|
|
2320
2394
|
////////////////////////////////////////////////////////////////////////////////
|
|
2321
2395
|
|
|
2396
|
+
const validActionMethods = new Set(["POST", "PUT", "PATCH", "DELETE"]);
|
|
2397
|
+
const validRequestMethods = new Set(["GET", "HEAD", ...validActionMethods]);
|
|
2322
2398
|
function unstable_createStaticHandler(routes) {
|
|
2323
2399
|
invariant(routes.length > 0, "You must provide a non-empty routes array to unstable_createStaticHandler");
|
|
2324
2400
|
let dataRoutes = convertRoutesToDataRoutes(routes);
|
|
2401
|
+
/**
|
|
2402
|
+
* The query() method is intended for document requests, in which we want to
|
|
2403
|
+
* call an optional action and potentially multiple loaders for all nested
|
|
2404
|
+
* routes. It returns a StaticHandlerContext object, which is very similar
|
|
2405
|
+
* to the router state (location, loaderData, actionData, errors, etc.) and
|
|
2406
|
+
* also adds SSR-specific information such as the statusCode and headers
|
|
2407
|
+
* from action/loaders Responses.
|
|
2408
|
+
*
|
|
2409
|
+
* It _should_ never throw and should report all errors through the
|
|
2410
|
+
* returned context.errors object, properly associating errors to their error
|
|
2411
|
+
* boundary. Additionally, it tracks _deepestRenderedBoundaryId which can be
|
|
2412
|
+
* used to emulate React error boundaries during SSr by performing a second
|
|
2413
|
+
* pass only down to the boundaryId.
|
|
2414
|
+
*
|
|
2415
|
+
* The one exception where we do not return a StaticHandlerContext is when a
|
|
2416
|
+
* redirect response is returned or thrown from any action/loader. We
|
|
2417
|
+
* propagate that out and return the raw Response so the HTTP server can
|
|
2418
|
+
* return it directly.
|
|
2419
|
+
*/
|
|
2325
2420
|
|
|
2326
2421
|
async function query(request) {
|
|
2327
|
-
let
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2422
|
+
let url = new URL(request.url);
|
|
2423
|
+
let location = createLocation("", createPath(url), null, "default");
|
|
2424
|
+
let matches = matchRoutes(dataRoutes, location);
|
|
2425
|
+
|
|
2426
|
+
if (!validRequestMethods.has(request.method)) {
|
|
2427
|
+
let {
|
|
2428
|
+
matches: methodNotAllowedMatches,
|
|
2429
|
+
route,
|
|
2430
|
+
error
|
|
2431
|
+
} = getMethodNotAllowedMatches(dataRoutes);
|
|
2432
|
+
return {
|
|
2433
|
+
location,
|
|
2434
|
+
matches: methodNotAllowedMatches,
|
|
2435
|
+
loaderData: {},
|
|
2436
|
+
actionData: null,
|
|
2437
|
+
errors: {
|
|
2438
|
+
[route.id]: error
|
|
2439
|
+
},
|
|
2440
|
+
statusCode: error.status,
|
|
2441
|
+
loaderHeaders: {},
|
|
2442
|
+
actionHeaders: {}
|
|
2443
|
+
};
|
|
2444
|
+
} else if (!matches) {
|
|
2445
|
+
let {
|
|
2446
|
+
matches: notFoundMatches,
|
|
2447
|
+
route,
|
|
2448
|
+
error
|
|
2449
|
+
} = getNotFoundMatches(dataRoutes);
|
|
2450
|
+
return {
|
|
2451
|
+
location,
|
|
2452
|
+
matches: notFoundMatches,
|
|
2453
|
+
loaderData: {},
|
|
2454
|
+
actionData: null,
|
|
2455
|
+
errors: {
|
|
2456
|
+
[route.id]: error
|
|
2457
|
+
},
|
|
2458
|
+
statusCode: error.status,
|
|
2459
|
+
loaderHeaders: {},
|
|
2460
|
+
actionHeaders: {}
|
|
2461
|
+
};
|
|
2462
|
+
}
|
|
2463
|
+
|
|
2464
|
+
let result = await queryImpl(request, location, matches);
|
|
2331
2465
|
|
|
2332
2466
|
if (result instanceof Response) {
|
|
2333
2467
|
return result;
|
|
@@ -2340,11 +2474,52 @@ function unstable_createStaticHandler(routes) {
|
|
|
2340
2474
|
location
|
|
2341
2475
|
}, result);
|
|
2342
2476
|
}
|
|
2477
|
+
/**
|
|
2478
|
+
* The queryRoute() method is intended for targeted route requests, either
|
|
2479
|
+
* for fetch ?_data requests or resource route requests. In this case, we
|
|
2480
|
+
* are only ever calling a single action or loader, and we are returning the
|
|
2481
|
+
* returned value directly. In most cases, this will be a Response returned
|
|
2482
|
+
* from the action/loader, but it may be a primitive or other value as well -
|
|
2483
|
+
* and in such cases the calling context should handle that accordingly.
|
|
2484
|
+
*
|
|
2485
|
+
* We do respect the throw/return differentiation, so if an action/loader
|
|
2486
|
+
* throws, then this method will throw the value. This is important so we
|
|
2487
|
+
* can do proper boundary identification in Remix where a thrown Response
|
|
2488
|
+
* must go to the Catch Boundary but a returned Response is happy-path.
|
|
2489
|
+
*
|
|
2490
|
+
* One thing to note is that any Router-initiated thrown Response (such as a
|
|
2491
|
+
* 404 or 405) will have a custom X-Remix-Router-Error: "yes" header on it
|
|
2492
|
+
* in order to differentiate from responses thrown from user actions/loaders.
|
|
2493
|
+
*/
|
|
2494
|
+
|
|
2343
2495
|
|
|
2344
2496
|
async function queryRoute(request, routeId) {
|
|
2345
|
-
let
|
|
2346
|
-
|
|
2347
|
-
|
|
2497
|
+
let url = new URL(request.url);
|
|
2498
|
+
let location = createLocation("", createPath(url), null, "default");
|
|
2499
|
+
let matches = matchRoutes(dataRoutes, location);
|
|
2500
|
+
|
|
2501
|
+
if (!validRequestMethods.has(request.method)) {
|
|
2502
|
+
throw createRouterErrorResponse(null, {
|
|
2503
|
+
status: 405,
|
|
2504
|
+
statusText: "Method Not Allowed"
|
|
2505
|
+
});
|
|
2506
|
+
} else if (!matches) {
|
|
2507
|
+
throw createRouterErrorResponse(null, {
|
|
2508
|
+
status: 404,
|
|
2509
|
+
statusText: "Not Found"
|
|
2510
|
+
});
|
|
2511
|
+
}
|
|
2512
|
+
|
|
2513
|
+
let match = routeId ? matches.find(m => m.route.id === routeId) : getTargetMatch(matches, location);
|
|
2514
|
+
|
|
2515
|
+
if (!match) {
|
|
2516
|
+
throw createRouterErrorResponse(null, {
|
|
2517
|
+
status: 404,
|
|
2518
|
+
statusText: "Not Found"
|
|
2519
|
+
});
|
|
2520
|
+
}
|
|
2521
|
+
|
|
2522
|
+
let result = await queryImpl(request, location, matches, match);
|
|
2348
2523
|
|
|
2349
2524
|
if (result instanceof Response) {
|
|
2350
2525
|
return result;
|
|
@@ -2353,77 +2528,48 @@ function unstable_createStaticHandler(routes) {
|
|
|
2353
2528
|
let error = result.errors ? Object.values(result.errors)[0] : undefined;
|
|
2354
2529
|
|
|
2355
2530
|
if (error !== undefined) {
|
|
2356
|
-
//
|
|
2357
|
-
// directly for route requests and prevent the unwrapping into an
|
|
2358
|
-
// ErrorResponse, we still need this for error cases _prior_ the
|
|
2359
|
-
// execution of the loader/action, such as a 404/405 error.
|
|
2360
|
-
if (isRouteErrorResponse(error)) {
|
|
2361
|
-
return new Response(error.data, {
|
|
2362
|
-
status: error.status,
|
|
2363
|
-
statusText: error.statusText
|
|
2364
|
-
});
|
|
2365
|
-
} // If we got back result.errors, that means the loader/action threw
|
|
2531
|
+
// If we got back result.errors, that means the loader/action threw
|
|
2366
2532
|
// _something_ that wasn't a Response, but it's not guaranteed/required
|
|
2367
2533
|
// to be an `instanceof Error` either, so we have to use throw here to
|
|
2368
2534
|
// preserve the "error" state outside of queryImpl.
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
2535
|
throw error;
|
|
2372
2536
|
} // Pick off the right state value to return
|
|
2373
2537
|
|
|
2374
2538
|
|
|
2375
2539
|
let routeData = [result.actionData, result.loaderData].find(v => v);
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
if (isRouteErrorResponse(value)) {
|
|
2379
|
-
return new Response(value.data, {
|
|
2380
|
-
status: value.status,
|
|
2381
|
-
statusText: value.statusText
|
|
2382
|
-
});
|
|
2383
|
-
}
|
|
2384
|
-
|
|
2385
|
-
return value;
|
|
2540
|
+
return Object.values(routeData || {})[0];
|
|
2386
2541
|
}
|
|
2387
2542
|
|
|
2388
|
-
async function queryImpl(request,
|
|
2389
|
-
invariant(request.method !== "HEAD", "query()/queryRoute() do not support HEAD requests");
|
|
2543
|
+
async function queryImpl(request, location, matches, routeMatch) {
|
|
2390
2544
|
invariant(request.signal, "query()/queryRoute() requests must contain an AbortController signal");
|
|
2391
|
-
let {
|
|
2392
|
-
location,
|
|
2393
|
-
matches,
|
|
2394
|
-
shortCircuitState
|
|
2395
|
-
} = matchRequest(request, routeId);
|
|
2396
2545
|
|
|
2397
2546
|
try {
|
|
2398
|
-
if (
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
result: shortCircuitState
|
|
2402
|
-
};
|
|
2547
|
+
if (validActionMethods.has(request.method)) {
|
|
2548
|
+
let result = await submit(request, matches, routeMatch || getTargetMatch(matches, location), routeMatch != null);
|
|
2549
|
+
return result;
|
|
2403
2550
|
}
|
|
2404
2551
|
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
};
|
|
2411
|
-
}
|
|
2412
|
-
|
|
2413
|
-
let result = await loadRouteData(request, matches, routeId != null);
|
|
2414
|
-
return {
|
|
2415
|
-
location,
|
|
2416
|
-
result: _extends({}, result, {
|
|
2417
|
-
actionData: null,
|
|
2418
|
-
actionHeaders: {}
|
|
2419
|
-
})
|
|
2420
|
-
};
|
|
2552
|
+
let result = await loadRouteData(request, matches, routeMatch);
|
|
2553
|
+
return result instanceof Response ? result : _extends({}, result, {
|
|
2554
|
+
actionData: null,
|
|
2555
|
+
actionHeaders: {}
|
|
2556
|
+
});
|
|
2421
2557
|
} catch (e) {
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2558
|
+
// If the user threw/returned a Response in callLoaderOrAction, we throw
|
|
2559
|
+
// it to bail out and then return or throw here based on whether the user
|
|
2560
|
+
// returned or threw
|
|
2561
|
+
if (isQueryRouteResponse(e)) {
|
|
2562
|
+
if (e.type === ResultType.error && !isRedirectResponse(e.response)) {
|
|
2563
|
+
throw e.response;
|
|
2564
|
+
}
|
|
2565
|
+
|
|
2566
|
+
return e.response;
|
|
2567
|
+
} // Redirects are always returned since they don't propagate to catch
|
|
2568
|
+
// boundaries
|
|
2569
|
+
|
|
2570
|
+
|
|
2571
|
+
if (isRedirectResponse(e)) {
|
|
2572
|
+
return e;
|
|
2427
2573
|
}
|
|
2428
2574
|
|
|
2429
2575
|
throw e;
|
|
@@ -2434,10 +2580,17 @@ function unstable_createStaticHandler(routes) {
|
|
|
2434
2580
|
let result;
|
|
2435
2581
|
|
|
2436
2582
|
if (!actionMatch.route.action) {
|
|
2437
|
-
|
|
2438
|
-
|
|
2583
|
+
if (isRouteRequest) {
|
|
2584
|
+
throw createRouterErrorResponse(null, {
|
|
2585
|
+
status: 405,
|
|
2586
|
+
statusText: "Method Not Allowed"
|
|
2587
|
+
});
|
|
2588
|
+
}
|
|
2589
|
+
|
|
2590
|
+
result = getMethodNotAllowedResult(request.url);
|
|
2439
2591
|
} else {
|
|
2440
|
-
result = await callLoaderOrAction("action", request, actionMatch,
|
|
2592
|
+
result = await callLoaderOrAction("action", request, actionMatch, matches, undefined, // Basename not currently supported in static handlers
|
|
2593
|
+
true, isRouteRequest);
|
|
2441
2594
|
|
|
2442
2595
|
if (request.signal.aborted) {
|
|
2443
2596
|
let method = isRouteRequest ? "queryRoute" : "query";
|
|
@@ -2447,7 +2600,7 @@ function unstable_createStaticHandler(routes) {
|
|
|
2447
2600
|
|
|
2448
2601
|
if (isRedirectResult(result)) {
|
|
2449
2602
|
// Uhhhh - this should never happen, we should always throw these from
|
|
2450
|
-
//
|
|
2603
|
+
// callLoaderOrAction, but the type narrowing here keeps TS happy and we
|
|
2451
2604
|
// can get back on the "throw all redirect responses" train here should
|
|
2452
2605
|
// this ever happen :/
|
|
2453
2606
|
throw new Response(null, {
|
|
@@ -2463,6 +2616,8 @@ function unstable_createStaticHandler(routes) {
|
|
|
2463
2616
|
}
|
|
2464
2617
|
|
|
2465
2618
|
if (isRouteRequest) {
|
|
2619
|
+
// Note: This should only be non-Response values if we get here, since
|
|
2620
|
+
// isRouteRequest should throw any Response received in callLoaderOrAction
|
|
2466
2621
|
if (isErrorResult(result)) {
|
|
2467
2622
|
let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id);
|
|
2468
2623
|
return {
|
|
@@ -2499,7 +2654,7 @@ function unstable_createStaticHandler(routes) {
|
|
|
2499
2654
|
// Store off the pending error - we use it to determine which loaders
|
|
2500
2655
|
// to call and will commit it when we complete the navigation
|
|
2501
2656
|
let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id);
|
|
2502
|
-
let context = await loadRouteData(request, matches,
|
|
2657
|
+
let context = await loadRouteData(request, matches, undefined, {
|
|
2503
2658
|
[boundaryMatch.route.id]: result.error
|
|
2504
2659
|
}); // action status codes take precedence over loader status codes
|
|
2505
2660
|
|
|
@@ -2512,7 +2667,7 @@ function unstable_createStaticHandler(routes) {
|
|
|
2512
2667
|
});
|
|
2513
2668
|
}
|
|
2514
2669
|
|
|
2515
|
-
let context = await loadRouteData(request, matches
|
|
2670
|
+
let context = await loadRouteData(request, matches);
|
|
2516
2671
|
return _extends({}, context, result.statusCode ? {
|
|
2517
2672
|
statusCode: result.statusCode
|
|
2518
2673
|
} : {}, {
|
|
@@ -2525,8 +2680,10 @@ function unstable_createStaticHandler(routes) {
|
|
|
2525
2680
|
});
|
|
2526
2681
|
}
|
|
2527
2682
|
|
|
2528
|
-
async function loadRouteData(request, matches,
|
|
2529
|
-
let
|
|
2683
|
+
async function loadRouteData(request, matches, routeMatch, pendingActionError) {
|
|
2684
|
+
let isRouteRequest = routeMatch != null;
|
|
2685
|
+
let requestMatches = routeMatch ? [routeMatch] : getLoaderMatchesUntilBoundary(matches, Object.keys(pendingActionError || {})[0]);
|
|
2686
|
+
let matchesToLoad = requestMatches.filter(m => m.route.loader); // Short circuit if we have no loaders to run
|
|
2530
2687
|
|
|
2531
2688
|
if (matchesToLoad.length === 0) {
|
|
2532
2689
|
return {
|
|
@@ -2538,7 +2695,8 @@ function unstable_createStaticHandler(routes) {
|
|
|
2538
2695
|
};
|
|
2539
2696
|
}
|
|
2540
2697
|
|
|
2541
|
-
let results = await Promise.all([...matchesToLoad.map(
|
|
2698
|
+
let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, undefined, // Basename not currently supported in static handlers
|
|
2699
|
+
true, isRouteRequest))]);
|
|
2542
2700
|
|
|
2543
2701
|
if (request.signal.aborted) {
|
|
2544
2702
|
let method = isRouteRequest ? "queryRoute" : "query";
|
|
@@ -2559,43 +2717,12 @@ function unstable_createStaticHandler(routes) {
|
|
|
2559
2717
|
});
|
|
2560
2718
|
}
|
|
2561
2719
|
|
|
2562
|
-
function
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
matches = matches.filter(m => m.route.id === routeId);
|
|
2569
|
-
} // Short circuit with a 404 if we match nothing
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
if (!matches) {
|
|
2573
|
-
let {
|
|
2574
|
-
matches: notFoundMatches,
|
|
2575
|
-
route,
|
|
2576
|
-
error
|
|
2577
|
-
} = getNotFoundMatches(dataRoutes);
|
|
2578
|
-
return {
|
|
2579
|
-
location,
|
|
2580
|
-
matches: notFoundMatches,
|
|
2581
|
-
shortCircuitState: {
|
|
2582
|
-
matches: notFoundMatches,
|
|
2583
|
-
loaderData: {},
|
|
2584
|
-
actionData: null,
|
|
2585
|
-
errors: {
|
|
2586
|
-
[route.id]: error
|
|
2587
|
-
},
|
|
2588
|
-
statusCode: 404,
|
|
2589
|
-
loaderHeaders: {},
|
|
2590
|
-
actionHeaders: {}
|
|
2591
|
-
}
|
|
2592
|
-
};
|
|
2593
|
-
}
|
|
2594
|
-
|
|
2595
|
-
return {
|
|
2596
|
-
location,
|
|
2597
|
-
matches
|
|
2598
|
-
};
|
|
2720
|
+
function createRouterErrorResponse(body, init) {
|
|
2721
|
+
return new Response(body, _extends({}, init, {
|
|
2722
|
+
headers: _extends({}, init.headers, {
|
|
2723
|
+
"X-Remix-Router-Error": "yes"
|
|
2724
|
+
})
|
|
2725
|
+
}));
|
|
2599
2726
|
}
|
|
2600
2727
|
|
|
2601
2728
|
return {
|
|
@@ -2644,7 +2771,7 @@ function normalizeNavigateOptions(to, opts, isFetcher) {
|
|
|
2644
2771
|
path,
|
|
2645
2772
|
submission: {
|
|
2646
2773
|
formMethod: opts.formMethod,
|
|
2647
|
-
formAction:
|
|
2774
|
+
formAction: stripHashFromPath(path),
|
|
2648
2775
|
formEncType: opts && opts.formEncType || "application/x-www-form-urlencoded",
|
|
2649
2776
|
formData: opts.formData
|
|
2650
2777
|
}
|
|
@@ -2727,16 +2854,16 @@ function getMatchesToLoad(state, matches, submission, location, isRevalidationRe
|
|
|
2727
2854
|
|
|
2728
2855
|
let revalidatingFetchers = [];
|
|
2729
2856
|
fetchLoadMatches && fetchLoadMatches.forEach((_ref10, key) => {
|
|
2730
|
-
let [href, match] = _ref10;
|
|
2857
|
+
let [href, match, fetchMatches] = _ref10;
|
|
2731
2858
|
|
|
2732
2859
|
// This fetcher was cancelled from a prior action submission - force reload
|
|
2733
2860
|
if (cancelledFetcherLoads.includes(key)) {
|
|
2734
|
-
revalidatingFetchers.push([key, href, match]);
|
|
2861
|
+
revalidatingFetchers.push([key, href, match, fetchMatches]);
|
|
2735
2862
|
} else if (isRevalidationRequired) {
|
|
2736
2863
|
let shouldRevalidate = shouldRevalidateLoader(href, match, submission, href, match, isRevalidationRequired, actionResult);
|
|
2737
2864
|
|
|
2738
2865
|
if (shouldRevalidate) {
|
|
2739
|
-
revalidatingFetchers.push([key, href, match]);
|
|
2866
|
+
revalidatingFetchers.push([key, href, match, fetchMatches]);
|
|
2740
2867
|
}
|
|
2741
2868
|
}
|
|
2742
2869
|
});
|
|
@@ -2798,9 +2925,9 @@ function shouldRevalidateLoader(currentLocation, currentMatch, submission, locat
|
|
|
2798
2925
|
return defaultShouldRevalidate;
|
|
2799
2926
|
}
|
|
2800
2927
|
|
|
2801
|
-
async function callLoaderOrAction(type, request, match,
|
|
2802
|
-
if (
|
|
2803
|
-
|
|
2928
|
+
async function callLoaderOrAction(type, request, match, matches, basename, isStaticRequest, isRouteRequest) {
|
|
2929
|
+
if (isStaticRequest === void 0) {
|
|
2930
|
+
isStaticRequest = false;
|
|
2804
2931
|
}
|
|
2805
2932
|
|
|
2806
2933
|
if (isRouteRequest === void 0) {
|
|
@@ -2832,20 +2959,30 @@ async function callLoaderOrAction(type, request, match, skipRedirects, isRouteRe
|
|
|
2832
2959
|
}
|
|
2833
2960
|
|
|
2834
2961
|
if (result instanceof Response) {
|
|
2835
|
-
// Process redirects
|
|
2836
|
-
let status = result.status;
|
|
2837
|
-
let location = result.headers.get("Location"); // For SSR single-route requests, we want to hand Responses back directly
|
|
2838
|
-
// without unwrapping
|
|
2962
|
+
let status = result.status; // Process redirects
|
|
2839
2963
|
|
|
2840
|
-
if (
|
|
2841
|
-
|
|
2842
|
-
|
|
2964
|
+
if (status >= 300 && status <= 399) {
|
|
2965
|
+
let location = result.headers.get("Location");
|
|
2966
|
+
invariant(location, "Redirects returned/thrown from loaders/actions must have a Location header"); // Support relative routing in redirects
|
|
2967
|
+
|
|
2968
|
+
let activeMatches = matches.slice(0, matches.indexOf(match) + 1);
|
|
2969
|
+
let routePathnames = getPathContributingMatches(activeMatches).map(match => match.pathnameBase);
|
|
2970
|
+
let requestPath = createURL(request.url).pathname;
|
|
2971
|
+
let resolvedLocation = resolveTo(location, routePathnames, requestPath);
|
|
2972
|
+
invariant(createPath(resolvedLocation), "Unable to resolve redirect location: " + result.headers.get("Location")); // Prepend the basename to the redirect location if we have one
|
|
2843
2973
|
|
|
2844
|
-
|
|
2845
|
-
|
|
2974
|
+
if (basename) {
|
|
2975
|
+
let path = resolvedLocation.pathname;
|
|
2976
|
+
resolvedLocation.pathname = path === "/" ? basename : joinPaths([basename, path]);
|
|
2977
|
+
}
|
|
2978
|
+
|
|
2979
|
+
location = createPath(resolvedLocation); // Don't process redirects in the router during static requests requests.
|
|
2846
2980
|
// Instead, throw the Response and let the server handle it with an HTTP
|
|
2847
|
-
// redirect
|
|
2848
|
-
|
|
2981
|
+
// redirect. We also update the Location header in place in this flow so
|
|
2982
|
+
// basename and relative routing is taken into account
|
|
2983
|
+
|
|
2984
|
+
if (isStaticRequest) {
|
|
2985
|
+
result.headers.set("Location", location);
|
|
2849
2986
|
throw result;
|
|
2850
2987
|
}
|
|
2851
2988
|
|
|
@@ -2855,6 +2992,17 @@ async function callLoaderOrAction(type, request, match, skipRedirects, isRouteRe
|
|
|
2855
2992
|
location,
|
|
2856
2993
|
revalidate: result.headers.get("X-Remix-Revalidate") !== null
|
|
2857
2994
|
};
|
|
2995
|
+
} // For SSR single-route requests, we want to hand Responses back directly
|
|
2996
|
+
// without unwrapping. We do this with the QueryRouteResponse wrapper
|
|
2997
|
+
// interface so we can know whether it was returned or thrown
|
|
2998
|
+
|
|
2999
|
+
|
|
3000
|
+
if (isRouteRequest) {
|
|
3001
|
+
// eslint-disable-next-line no-throw-literal
|
|
3002
|
+
throw {
|
|
3003
|
+
type: resultType || ResultType.data,
|
|
3004
|
+
response: result
|
|
3005
|
+
};
|
|
2858
3006
|
}
|
|
2859
3007
|
|
|
2860
3008
|
let data;
|
|
@@ -2903,7 +3051,7 @@ async function callLoaderOrAction(type, request, match, skipRedirects, isRouteRe
|
|
|
2903
3051
|
}
|
|
2904
3052
|
|
|
2905
3053
|
function createRequest(location, signal, submission) {
|
|
2906
|
-
let url = createURL(location).toString();
|
|
3054
|
+
let url = createURL(stripHashFromPath(location)).toString();
|
|
2907
3055
|
let init = {
|
|
2908
3056
|
signal
|
|
2909
3057
|
};
|
|
@@ -3070,10 +3218,10 @@ function findNearestBoundary(matches, routeId) {
|
|
|
3070
3218
|
return eligibleMatches.reverse().find(m => m.route.hasErrorBoundary === true) || matches[0];
|
|
3071
3219
|
}
|
|
3072
3220
|
|
|
3073
|
-
function
|
|
3221
|
+
function getShortCircuitMatches(routes, status, statusText) {
|
|
3074
3222
|
// Prefer a root layout route if present, otherwise shim in a route object
|
|
3075
|
-
let route = routes.find(r => r.index || r.path
|
|
3076
|
-
id: "__shim-
|
|
3223
|
+
let route = routes.find(r => r.index || !r.path || r.path === "/") || {
|
|
3224
|
+
id: "__shim-" + status + "-route__"
|
|
3077
3225
|
};
|
|
3078
3226
|
return {
|
|
3079
3227
|
matches: [{
|
|
@@ -3083,16 +3231,24 @@ function getNotFoundMatches(routes) {
|
|
|
3083
3231
|
route
|
|
3084
3232
|
}],
|
|
3085
3233
|
route,
|
|
3086
|
-
error: new ErrorResponse(
|
|
3234
|
+
error: new ErrorResponse(status, statusText, null)
|
|
3087
3235
|
};
|
|
3088
3236
|
}
|
|
3089
3237
|
|
|
3238
|
+
function getNotFoundMatches(routes) {
|
|
3239
|
+
return getShortCircuitMatches(routes, 404, "Not Found");
|
|
3240
|
+
}
|
|
3241
|
+
|
|
3242
|
+
function getMethodNotAllowedMatches(routes) {
|
|
3243
|
+
return getShortCircuitMatches(routes, 405, "Method Not Allowed");
|
|
3244
|
+
}
|
|
3245
|
+
|
|
3090
3246
|
function getMethodNotAllowedResult(path) {
|
|
3091
|
-
let href = typeof path === "string" ? path :
|
|
3247
|
+
let href = typeof path === "string" ? path : createPath(path);
|
|
3092
3248
|
console.warn("You're trying to submit to a route that does not have an action. To " + "fix this, please add an `action` function to the route for " + ("[" + href + "]"));
|
|
3093
3249
|
return {
|
|
3094
3250
|
type: ResultType.error,
|
|
3095
|
-
error: new ErrorResponse(405, "Method Not Allowed", "
|
|
3251
|
+
error: new ErrorResponse(405, "Method Not Allowed", "")
|
|
3096
3252
|
};
|
|
3097
3253
|
} // Find any returned redirect errors, starting from the lowest match
|
|
3098
3254
|
|
|
@@ -3105,11 +3261,13 @@ function findRedirect(results) {
|
|
|
3105
3261
|
return result;
|
|
3106
3262
|
}
|
|
3107
3263
|
}
|
|
3108
|
-
}
|
|
3109
|
-
|
|
3264
|
+
}
|
|
3110
3265
|
|
|
3111
|
-
function
|
|
3112
|
-
|
|
3266
|
+
function stripHashFromPath(path) {
|
|
3267
|
+
let parsedPath = typeof path === "string" ? parsePath(path) : path;
|
|
3268
|
+
return createPath(_extends({}, parsedPath, {
|
|
3269
|
+
hash: ""
|
|
3270
|
+
}));
|
|
3113
3271
|
}
|
|
3114
3272
|
|
|
3115
3273
|
function isHashChangeOnly(a, b) {
|
|
@@ -3128,6 +3286,20 @@ function isRedirectResult(result) {
|
|
|
3128
3286
|
return (result && result.type) === ResultType.redirect;
|
|
3129
3287
|
}
|
|
3130
3288
|
|
|
3289
|
+
function isRedirectResponse(result) {
|
|
3290
|
+
if (!(result instanceof Response)) {
|
|
3291
|
+
return false;
|
|
3292
|
+
}
|
|
3293
|
+
|
|
3294
|
+
let status = result.status;
|
|
3295
|
+
let location = result.headers.get("Location");
|
|
3296
|
+
return status >= 300 && status <= 399 && location != null;
|
|
3297
|
+
}
|
|
3298
|
+
|
|
3299
|
+
function isQueryRouteResponse(obj) {
|
|
3300
|
+
return obj && obj.response instanceof Response && (obj.type === ResultType.data || ResultType.error);
|
|
3301
|
+
}
|
|
3302
|
+
|
|
3131
3303
|
async function resolveDeferredResults(currentMatches, matchesToLoad, results, signal, isFetcher, currentLoaderData) {
|
|
3132
3304
|
for (let index = 0; index < results.length; index++) {
|
|
3133
3305
|
let result = results[index];
|
|
@@ -3204,17 +3376,15 @@ function createUseMatchesMatch(match, loaderData) {
|
|
|
3204
3376
|
function getTargetMatch(matches, location) {
|
|
3205
3377
|
let search = typeof location === "string" ? parsePath(location).search : location.search;
|
|
3206
3378
|
|
|
3207
|
-
if (matches[matches.length - 1].route.index &&
|
|
3208
|
-
|
|
3209
|
-
|
|
3379
|
+
if (matches[matches.length - 1].route.index && hasNakedIndexQuery(search || "")) {
|
|
3380
|
+
// Return the leaf index route when index is present
|
|
3381
|
+
return matches[matches.length - 1];
|
|
3382
|
+
} // Otherwise grab the deepest "path contributing" match (ignoring index and
|
|
3383
|
+
// pathless layout routes)
|
|
3210
3384
|
|
|
3211
|
-
return matches.slice(-1)[0];
|
|
3212
|
-
}
|
|
3213
3385
|
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
let href = typeof location === "string" ? location : createHref(location);
|
|
3217
|
-
return new URL(href, base);
|
|
3386
|
+
let pathMatches = getPathContributingMatches(matches);
|
|
3387
|
+
return pathMatches[pathMatches.length - 1];
|
|
3218
3388
|
} //#endregion
|
|
3219
3389
|
|
|
3220
3390
|
exports.AbortedDeferredError = AbortedDeferredError;
|
|
@@ -3222,6 +3392,7 @@ exports.ErrorResponse = ErrorResponse;
|
|
|
3222
3392
|
exports.IDLE_FETCHER = IDLE_FETCHER;
|
|
3223
3393
|
exports.IDLE_NAVIGATION = IDLE_NAVIGATION;
|
|
3224
3394
|
exports.UNSAFE_convertRoutesToDataRoutes = convertRoutesToDataRoutes;
|
|
3395
|
+
exports.UNSAFE_getPathContributingMatches = getPathContributingMatches;
|
|
3225
3396
|
exports.createBrowserHistory = createBrowserHistory;
|
|
3226
3397
|
exports.createHashHistory = createHashHistory;
|
|
3227
3398
|
exports.createMemoryHistory = createMemoryHistory;
|