@remix-run/router 1.11.0 → 1.12.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 CHANGED
@@ -1,5 +1,33 @@
1
1
  # `@remix-run/router`
2
2
 
3
+ ## 1.12.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Add `unstable_flushSync` option to `router.navigate` and `router.fetch` to tell the React Router layer to opt-out of `React.startTransition` and into `ReactDOM.flushSync` for state updates ([#11005](https://github.com/remix-run/react-router/pull/11005))
8
+
9
+ ### Patch Changes
10
+
11
+ - Fix `relative="path"` bug where relative path calculations started from the full location pathname, instead of from the current contextual route pathname. ([#11006](https://github.com/remix-run/react-router/pull/11006))
12
+
13
+ ```jsx
14
+ <Route path="/a">
15
+ <Route path="/b" element={<Component />}>
16
+ <Route path="/c" />
17
+ </Route>
18
+ </Route>;
19
+
20
+ function Component() {
21
+ return (
22
+ <>
23
+ {/* This is now correctly relative to /a/b, not /a/b/c */}
24
+ <Link to=".." relative="path" />
25
+ <Outlet />
26
+ </>
27
+ );
28
+ }
29
+ ```
30
+
3
31
  ## 1.11.0
4
32
 
5
33
  ### Minor Changes
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @remix-run/router v1.11.0
2
+ * @remix-run/router v1.12.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1221,16 +1221,30 @@ function resolveTo(toArg, routePathnames, locationPathname, isPathRelative) {
1221
1221
  // `to` values that do not provide a pathname. `to` can simply be a search or
1222
1222
  // hash string, in which case we should assume that the navigation is relative
1223
1223
  // to the current location's pathname and *not* the route pathname.
1224
- if (isPathRelative || toPathname == null) {
1224
+ if (toPathname == null) {
1225
1225
  from = locationPathname;
1226
+ } else if (isPathRelative) {
1227
+ let fromSegments = routePathnames[routePathnames.length - 1].replace(/^\//, "").split("/");
1228
+ if (toPathname.startsWith("..")) {
1229
+ let toSegments = toPathname.split("/");
1230
+
1231
+ // With relative="path", each leading .. segment means "go up one URL segment"
1232
+ while (toSegments[0] === "..") {
1233
+ toSegments.shift();
1234
+ fromSegments.pop();
1235
+ }
1236
+ to.pathname = toSegments.join("/");
1237
+ }
1238
+ from = "/" + fromSegments.join("/");
1226
1239
  } else {
1227
1240
  let routePathnameIndex = routePathnames.length - 1;
1228
1241
  if (toPathname.startsWith("..")) {
1229
1242
  let toSegments = toPathname.split("/");
1230
1243
 
1231
- // Each leading .. segment means "go up one route" instead of "go up one
1232
- // URL segment". This is a key difference from how <a href> works and a
1233
- // major reason we call this a "to" value instead of a "href".
1244
+ // With relative="route" (the default), each leading .. segment means
1245
+ // "go up one route" instead of "go up one URL segment". This is a key
1246
+ // difference from how <a href> works and a major reason we call this a
1247
+ // "to" value instead of a "href".
1234
1248
  while (toSegments[0] === "..") {
1235
1249
  toSegments.shift();
1236
1250
  routePathnameIndex -= 1;
@@ -1900,7 +1914,10 @@ function createRouter(init) {
1900
1914
  }
1901
1915
 
1902
1916
  // Update our state and notify the calling context of the change
1903
- function updateState(newState, viewTransitionOpts) {
1917
+ function updateState(newState, opts) {
1918
+ if (opts === void 0) {
1919
+ opts = {};
1920
+ }
1904
1921
  state = _extends({}, state, newState);
1905
1922
 
1906
1923
  // Prep fetcher cleanup so we can tell the UI which fetcher data entries
@@ -1921,9 +1938,14 @@ function createRouter(init) {
1921
1938
  }
1922
1939
  });
1923
1940
  }
1924
- subscribers.forEach(subscriber => subscriber(state, {
1941
+
1942
+ // Iterate over a local copy so that if flushSync is used and we end up
1943
+ // removing and adding a new subscriber due to the useCallback dependencies,
1944
+ // we don't get ourselves into a loop calling the new subscriber immediately
1945
+ [...subscribers].forEach(subscriber => subscriber(state, {
1925
1946
  deletedFetchers: deletedFetchersKeys,
1926
- unstable_viewTransitionOpts: viewTransitionOpts
1947
+ unstable_viewTransitionOpts: opts.viewTransitionOpts,
1948
+ unstable_flushSync: opts.flushSync === true
1927
1949
  }));
1928
1950
 
1929
1951
  // Remove idle fetchers from state since we only care about in-flight fetchers.
@@ -1938,8 +1960,11 @@ function createRouter(init) {
1938
1960
  // - Location is a required param
1939
1961
  // - Navigation will always be set to IDLE_NAVIGATION
1940
1962
  // - Can pass any other state in newState
1941
- function completeNavigation(location, newState) {
1963
+ function completeNavigation(location, newState, _temp) {
1942
1964
  var _location$state, _location$state2;
1965
+ let {
1966
+ flushSync
1967
+ } = _temp === void 0 ? {} : _temp;
1943
1968
  // Deduce if we're in a loading/actionReload state:
1944
1969
  // - We have committed actionData in the store
1945
1970
  // - The current navigation was a mutation submission
@@ -2030,7 +2055,10 @@ function createRouter(init) {
2030
2055
  restoreScrollPosition: getSavedScrollPosition(location, newState.matches || state.matches),
2031
2056
  preventScrollReset,
2032
2057
  blockers
2033
- }), viewTransitionOpts);
2058
+ }), {
2059
+ viewTransitionOpts,
2060
+ flushSync: flushSync === true
2061
+ });
2034
2062
 
2035
2063
  // Reset stateful navigation vars
2036
2064
  pendingAction = Action.Pop;
@@ -2076,6 +2104,7 @@ function createRouter(init) {
2076
2104
  historyAction = Action.Replace;
2077
2105
  }
2078
2106
  let preventScrollReset = opts && "preventScrollReset" in opts ? opts.preventScrollReset === true : undefined;
2107
+ let flushSync = (opts && opts.unstable_flushSync) === true;
2079
2108
  let blockerKey = shouldBlockNavigation({
2080
2109
  currentLocation,
2081
2110
  nextLocation,
@@ -2113,7 +2142,8 @@ function createRouter(init) {
2113
2142
  pendingError: error,
2114
2143
  preventScrollReset,
2115
2144
  replace: opts && opts.replace,
2116
- enableViewTransition: opts && opts.unstable_viewTransition
2145
+ enableViewTransition: opts && opts.unstable_viewTransition,
2146
+ flushSync
2117
2147
  });
2118
2148
  }
2119
2149
 
@@ -2170,6 +2200,7 @@ function createRouter(init) {
2170
2200
  let routesToUse = inFlightDataRoutes || dataRoutes;
2171
2201
  let loadingNavigation = opts && opts.overrideNavigation;
2172
2202
  let matches = matchRoutes(routesToUse, location, basename);
2203
+ let flushSync = (opts && opts.flushSync) === true;
2173
2204
 
2174
2205
  // Short circuit with a 404 on the root error boundary if we match nothing
2175
2206
  if (!matches) {
@@ -2188,6 +2219,8 @@ function createRouter(init) {
2188
2219
  errors: {
2189
2220
  [route.id]: error
2190
2221
  }
2222
+ }, {
2223
+ flushSync
2191
2224
  });
2192
2225
  return;
2193
2226
  }
@@ -2201,6 +2234,8 @@ function createRouter(init) {
2201
2234
  if (state.initialized && !isRevalidationRequired && isHashChangeOnly(state.location, location) && !(opts && opts.submission && isMutationMethod(opts.submission.formMethod))) {
2202
2235
  completeNavigation(location, {
2203
2236
  matches
2237
+ }, {
2238
+ flushSync
2204
2239
  });
2205
2240
  return;
2206
2241
  }
@@ -2221,7 +2256,8 @@ function createRouter(init) {
2221
2256
  } else if (opts && opts.submission && isMutationMethod(opts.submission.formMethod)) {
2222
2257
  // Call action if we received an action submission
2223
2258
  let actionOutput = await handleAction(request, location, opts.submission, matches, {
2224
- replace: opts.replace
2259
+ replace: opts.replace,
2260
+ flushSync
2225
2261
  });
2226
2262
  if (actionOutput.shortCircuited) {
2227
2263
  return;
@@ -2229,6 +2265,7 @@ function createRouter(init) {
2229
2265
  pendingActionData = actionOutput.pendingActionData;
2230
2266
  pendingError = actionOutput.pendingActionError;
2231
2267
  loadingNavigation = getLoadingNavigation(location, opts.submission);
2268
+ flushSync = false;
2232
2269
 
2233
2270
  // Create a GET request for the loaders
2234
2271
  request = new Request(request.url, {
@@ -2241,7 +2278,7 @@ function createRouter(init) {
2241
2278
  shortCircuited,
2242
2279
  loaderData,
2243
2280
  errors
2244
- } = await handleLoaders(request, location, matches, loadingNavigation, opts && opts.submission, opts && opts.fetcherSubmission, opts && opts.replace, pendingActionData, pendingError);
2281
+ } = await handleLoaders(request, location, matches, loadingNavigation, opts && opts.submission, opts && opts.fetcherSubmission, opts && opts.replace, flushSync, pendingActionData, pendingError);
2245
2282
  if (shortCircuited) {
2246
2283
  return;
2247
2284
  }
@@ -2272,6 +2309,8 @@ function createRouter(init) {
2272
2309
  let navigation = getSubmittingNavigation(location, submission);
2273
2310
  updateState({
2274
2311
  navigation
2312
+ }, {
2313
+ flushSync: opts.flushSync === true
2275
2314
  });
2276
2315
 
2277
2316
  // Call our action and get the result
@@ -2346,7 +2385,7 @@ function createRouter(init) {
2346
2385
 
2347
2386
  // Call all applicable loaders for the given matches, handling redirects,
2348
2387
  // errors, etc.
2349
- async function handleLoaders(request, location, matches, overrideNavigation, submission, fetcherSubmission, replace, pendingActionData, pendingError) {
2388
+ async function handleLoaders(request, location, matches, overrideNavigation, submission, fetcherSubmission, replace, flushSync, pendingActionData, pendingError) {
2350
2389
  // Figure out the right navigation we want to use for data loading
2351
2390
  let loadingNavigation = overrideNavigation || getLoadingNavigation(location, submission);
2352
2391
 
@@ -2374,7 +2413,9 @@ function createRouter(init) {
2374
2413
  actionData: pendingActionData
2375
2414
  } : {}, updatedFetchers ? {
2376
2415
  fetchers: new Map(state.fetchers)
2377
- } : {}));
2416
+ } : {}), {
2417
+ flushSync
2418
+ });
2378
2419
  return {
2379
2420
  shortCircuited: true
2380
2421
  };
@@ -2399,7 +2440,9 @@ function createRouter(init) {
2399
2440
  actionData
2400
2441
  } : {}, revalidatingFetchers.length > 0 ? {
2401
2442
  fetchers: new Map(state.fetchers)
2402
- } : {}));
2443
+ } : {}), {
2444
+ flushSync
2445
+ });
2403
2446
  }
2404
2447
  revalidatingFetchers.forEach(rf => {
2405
2448
  if (fetchControllers.has(rf.key)) {
@@ -2482,17 +2525,6 @@ function createRouter(init) {
2482
2525
  fetchers: new Map(state.fetchers)
2483
2526
  } : {});
2484
2527
  }
2485
- function getFetcher(key) {
2486
- if (future.v7_fetcherPersist) {
2487
- activeFetchers.set(key, (activeFetchers.get(key) || 0) + 1);
2488
- // If this fetcher was previously marked for deletion, unmark it since we
2489
- // have a new instance
2490
- if (deletedFetchers.has(key)) {
2491
- deletedFetchers.delete(key);
2492
- }
2493
- }
2494
- return state.fetchers.get(key) || IDLE_FETCHER;
2495
- }
2496
2528
 
2497
2529
  // Trigger a fetcher load/submit for the given fetcher key
2498
2530
  function fetch(key, routeId, href, opts) {
@@ -2500,13 +2532,16 @@ function createRouter(init) {
2500
2532
  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.");
2501
2533
  }
2502
2534
  if (fetchControllers.has(key)) abortFetcher(key);
2535
+ let flushSync = (opts && opts.unstable_flushSync) === true;
2503
2536
  let routesToUse = inFlightDataRoutes || dataRoutes;
2504
2537
  let normalizedPath = normalizeTo(state.location, state.matches, basename, future.v7_prependBasename, href, routeId, opts == null ? void 0 : opts.relative);
2505
2538
  let matches = matchRoutes(routesToUse, normalizedPath, basename);
2506
2539
  if (!matches) {
2507
2540
  setFetcherError(key, routeId, getInternalRouterError(404, {
2508
2541
  pathname: normalizedPath
2509
- }));
2542
+ }), {
2543
+ flushSync
2544
+ });
2510
2545
  return;
2511
2546
  }
2512
2547
  let {
@@ -2515,13 +2550,15 @@ function createRouter(init) {
2515
2550
  error
2516
2551
  } = normalizeNavigateOptions(future.v7_normalizeFormMethod, true, normalizedPath, opts);
2517
2552
  if (error) {
2518
- setFetcherError(key, routeId, error);
2553
+ setFetcherError(key, routeId, error, {
2554
+ flushSync
2555
+ });
2519
2556
  return;
2520
2557
  }
2521
2558
  let match = getTargetMatch(matches, path);
2522
2559
  pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;
2523
2560
  if (submission && isMutationMethod(submission.formMethod)) {
2524
- handleFetcherAction(key, routeId, path, match, matches, submission);
2561
+ handleFetcherAction(key, routeId, path, match, matches, flushSync, submission);
2525
2562
  return;
2526
2563
  }
2527
2564
 
@@ -2531,12 +2568,12 @@ function createRouter(init) {
2531
2568
  routeId,
2532
2569
  path
2533
2570
  });
2534
- handleFetcherLoader(key, routeId, path, match, matches, submission);
2571
+ handleFetcherLoader(key, routeId, path, match, matches, flushSync, submission);
2535
2572
  }
2536
2573
 
2537
2574
  // Call the action for the matched fetcher.submit(), and then handle redirects,
2538
2575
  // errors, and revalidation
2539
- async function handleFetcherAction(key, routeId, path, match, requestMatches, submission) {
2576
+ async function handleFetcherAction(key, routeId, path, match, requestMatches, flushSync, submission) {
2540
2577
  interruptActiveLoads();
2541
2578
  fetchLoadMatches.delete(key);
2542
2579
  if (!match.route.action && !match.route.lazy) {
@@ -2545,16 +2582,16 @@ function createRouter(init) {
2545
2582
  pathname: path,
2546
2583
  routeId: routeId
2547
2584
  });
2548
- setFetcherError(key, routeId, error);
2585
+ setFetcherError(key, routeId, error, {
2586
+ flushSync
2587
+ });
2549
2588
  return;
2550
2589
  }
2551
2590
 
2552
2591
  // Put this fetcher into it's submitting state
2553
2592
  let existingFetcher = state.fetchers.get(key);
2554
- let fetcher = getSubmittingFetcher(submission, existingFetcher);
2555
- state.fetchers.set(key, fetcher);
2556
- updateState({
2557
- fetchers: new Map(state.fetchers)
2593
+ updateFetcherState(key, getSubmittingFetcher(submission, existingFetcher), {
2594
+ flushSync
2558
2595
  });
2559
2596
 
2560
2597
  // Call the action for the fetcher
@@ -2572,10 +2609,7 @@ function createRouter(init) {
2572
2609
  return;
2573
2610
  }
2574
2611
  if (deletedFetchers.has(key)) {
2575
- state.fetchers.set(key, getDoneFetcher(undefined));
2576
- updateState({
2577
- fetchers: new Map(state.fetchers)
2578
- });
2612
+ updateFetcherState(key, getDoneFetcher(undefined));
2579
2613
  return;
2580
2614
  }
2581
2615
  if (isRedirectResult(actionResult)) {
@@ -2585,19 +2619,11 @@ function createRouter(init) {
2585
2619
  // should take precedence over this redirect navigation. We already
2586
2620
  // set isRevalidationRequired so all loaders for the new route should
2587
2621
  // fire unless opted out via shouldRevalidate
2588
- let doneFetcher = getDoneFetcher(undefined);
2589
- state.fetchers.set(key, doneFetcher);
2590
- updateState({
2591
- fetchers: new Map(state.fetchers)
2592
- });
2622
+ updateFetcherState(key, getDoneFetcher(undefined));
2593
2623
  return;
2594
2624
  } else {
2595
2625
  fetchRedirectIds.add(key);
2596
- let loadingFetcher = getLoadingFetcher(submission);
2597
- state.fetchers.set(key, loadingFetcher);
2598
- updateState({
2599
- fetchers: new Map(state.fetchers)
2600
- });
2626
+ updateFetcherState(key, getLoadingFetcher(submission));
2601
2627
  return startRedirectNavigation(state, actionResult, {
2602
2628
  fetcherSubmission: submission
2603
2629
  });
@@ -2715,13 +2741,10 @@ function createRouter(init) {
2715
2741
  }
2716
2742
 
2717
2743
  // Call the matched loader for fetcher.load(), handling redirects, errors, etc.
2718
- async function handleFetcherLoader(key, routeId, path, match, matches, submission) {
2744
+ async function handleFetcherLoader(key, routeId, path, match, matches, flushSync, submission) {
2719
2745
  let existingFetcher = state.fetchers.get(key);
2720
- // Put this fetcher into it's loading state
2721
- let loadingFetcher = getLoadingFetcher(submission, existingFetcher ? existingFetcher.data : undefined);
2722
- state.fetchers.set(key, loadingFetcher);
2723
- updateState({
2724
- fetchers: new Map(state.fetchers)
2746
+ updateFetcherState(key, getLoadingFetcher(submission, existingFetcher ? existingFetcher.data : undefined), {
2747
+ flushSync
2725
2748
  });
2726
2749
 
2727
2750
  // Call the loader for this fetcher route match
@@ -2748,10 +2771,7 @@ function createRouter(init) {
2748
2771
  return;
2749
2772
  }
2750
2773
  if (deletedFetchers.has(key)) {
2751
- state.fetchers.set(key, getDoneFetcher(undefined));
2752
- updateState({
2753
- fetchers: new Map(state.fetchers)
2754
- });
2774
+ updateFetcherState(key, getDoneFetcher(undefined));
2755
2775
  return;
2756
2776
  }
2757
2777
 
@@ -2760,11 +2780,7 @@ function createRouter(init) {
2760
2780
  if (pendingNavigationLoadId > originatingLoadId) {
2761
2781
  // A new navigation was kicked off after our loader started, so that
2762
2782
  // should take precedence over this redirect navigation
2763
- let doneFetcher = getDoneFetcher(undefined);
2764
- state.fetchers.set(key, doneFetcher);
2765
- updateState({
2766
- fetchers: new Map(state.fetchers)
2767
- });
2783
+ updateFetcherState(key, getDoneFetcher(undefined));
2768
2784
  return;
2769
2785
  } else {
2770
2786
  fetchRedirectIds.add(key);
@@ -2781,11 +2797,7 @@ function createRouter(init) {
2781
2797
  invariant(!isDeferredResult(result), "Unhandled fetcher deferred data");
2782
2798
 
2783
2799
  // Put the fetcher back into an idle state
2784
- let doneFetcher = getDoneFetcher(result.data);
2785
- state.fetchers.set(key, doneFetcher);
2786
- updateState({
2787
- fetchers: new Map(state.fetchers)
2788
- });
2800
+ updateFetcherState(key, getDoneFetcher(result.data));
2789
2801
  }
2790
2802
 
2791
2803
  /**
@@ -2807,12 +2819,12 @@ function createRouter(init) {
2807
2819
  * actually touch history until we've processed redirects, so we just use
2808
2820
  * the history action from the original navigation (PUSH or REPLACE).
2809
2821
  */
2810
- async function startRedirectNavigation(state, redirect, _temp) {
2822
+ async function startRedirectNavigation(state, redirect, _temp2) {
2811
2823
  let {
2812
2824
  submission,
2813
2825
  fetcherSubmission,
2814
2826
  replace
2815
- } = _temp === void 0 ? {} : _temp;
2827
+ } = _temp2 === void 0 ? {} : _temp2;
2816
2828
  if (redirect.revalidate) {
2817
2829
  isRevalidationRequired = true;
2818
2830
  }
@@ -2926,7 +2938,21 @@ function createRouter(init) {
2926
2938
  }
2927
2939
  });
2928
2940
  }
2929
- function setFetcherError(key, routeId, error) {
2941
+ function updateFetcherState(key, fetcher, opts) {
2942
+ if (opts === void 0) {
2943
+ opts = {};
2944
+ }
2945
+ state.fetchers.set(key, fetcher);
2946
+ updateState({
2947
+ fetchers: new Map(state.fetchers)
2948
+ }, {
2949
+ flushSync: (opts && opts.flushSync) === true
2950
+ });
2951
+ }
2952
+ function setFetcherError(key, routeId, error, opts) {
2953
+ if (opts === void 0) {
2954
+ opts = {};
2955
+ }
2930
2956
  let boundaryMatch = findNearestBoundary(state.matches, routeId);
2931
2957
  deleteFetcher(key);
2932
2958
  updateState({
@@ -2934,8 +2960,21 @@ function createRouter(init) {
2934
2960
  [boundaryMatch.route.id]: error
2935
2961
  },
2936
2962
  fetchers: new Map(state.fetchers)
2963
+ }, {
2964
+ flushSync: (opts && opts.flushSync) === true
2937
2965
  });
2938
2966
  }
2967
+ function getFetcher(key) {
2968
+ if (future.v7_fetcherPersist) {
2969
+ activeFetchers.set(key, (activeFetchers.get(key) || 0) + 1);
2970
+ // If this fetcher was previously marked for deletion, unmark it since we
2971
+ // have a new instance
2972
+ if (deletedFetchers.has(key)) {
2973
+ deletedFetchers.delete(key);
2974
+ }
2975
+ }
2976
+ return state.fetchers.get(key) || IDLE_FETCHER;
2977
+ }
2939
2978
  function deleteFetcher(key) {
2940
2979
  let fetcher = state.fetchers.get(key);
2941
2980
  // Don't abort the controller if this is a deletion of a fetcher.submit()
@@ -3216,10 +3255,10 @@ function createStaticHandler(routes, opts) {
3216
3255
  * propagate that out and return the raw Response so the HTTP server can
3217
3256
  * return it directly.
3218
3257
  */
3219
- async function query(request, _temp2) {
3258
+ async function query(request, _temp3) {
3220
3259
  let {
3221
3260
  requestContext
3222
- } = _temp2 === void 0 ? {} : _temp2;
3261
+ } = _temp3 === void 0 ? {} : _temp3;
3223
3262
  let url = new URL(request.url);
3224
3263
  let method = request.method;
3225
3264
  let location = createLocation("", createPath(url), null, "default");
@@ -3305,11 +3344,11 @@ function createStaticHandler(routes, opts) {
3305
3344
  * code. Examples here are 404 and 405 errors that occur prior to reaching
3306
3345
  * any user-defined loaders.
3307
3346
  */
3308
- async function queryRoute(request, _temp3) {
3347
+ async function queryRoute(request, _temp4) {
3309
3348
  let {
3310
3349
  routeId,
3311
3350
  requestContext
3312
- } = _temp3 === void 0 ? {} : _temp3;
3351
+ } = _temp4 === void 0 ? {} : _temp4;
3313
3352
  let url = new URL(request.url);
3314
3353
  let method = request.method;
3315
3354
  let location = createLocation("", createPath(url), null, "default");
@@ -3587,11 +3626,9 @@ function isSubmissionNavigation(opts) {
3587
3626
  function normalizeTo(location, matches, basename, prependBasename, to, fromRouteId, relative) {
3588
3627
  let contextualMatches;
3589
3628
  let activeRouteMatch;
3590
- if (fromRouteId != null && relative !== "path") {
3629
+ if (fromRouteId) {
3591
3630
  // Grab matches up to the calling route so our route-relative logic is
3592
- // relative to the correct source route. When using relative:path,
3593
- // fromRouteId is ignored since that is always relative to the current
3594
- // location path
3631
+ // relative to the correct source route
3595
3632
  contextualMatches = [];
3596
3633
  for (let match of matches) {
3597
3634
  contextualMatches.push(match);
@@ -4358,13 +4395,13 @@ function getShortCircuitMatches(routes) {
4358
4395
  route
4359
4396
  };
4360
4397
  }
4361
- function getInternalRouterError(status, _temp4) {
4398
+ function getInternalRouterError(status, _temp5) {
4362
4399
  let {
4363
4400
  pathname,
4364
4401
  routeId,
4365
4402
  method,
4366
4403
  type
4367
- } = _temp4 === void 0 ? {} : _temp4;
4404
+ } = _temp5 === void 0 ? {} : _temp5;
4368
4405
  let statusText = "Unknown Server Error";
4369
4406
  let errorMessage = "Unknown @remix-run/router error";
4370
4407
  if (status === 400) {