@remix-run/router 1.19.0 → 1.19.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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @remix-run/router v1.19.0
2
+ * @remix-run/router v1.19.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1715,7 +1715,7 @@
1715
1715
  let inFlightDataRoutes;
1716
1716
  let basename = init.basename || "/";
1717
1717
  let dataStrategyImpl = init.unstable_dataStrategy || defaultDataStrategy;
1718
- let patchRoutesOnMissImpl = init.unstable_patchRoutesOnMiss;
1718
+ let patchRoutesOnNavigationImpl = init.unstable_patchRoutesOnNavigation;
1719
1719
 
1720
1720
  // Config driven behavior flags
1721
1721
  let future = _extends({
@@ -1730,6 +1730,10 @@
1730
1730
  let unlistenHistory = null;
1731
1731
  // Externally-provided functions to call on all state changes
1732
1732
  let subscribers = new Set();
1733
+ // FIFO queue of previously discovered routes to prevent re-calling on
1734
+ // subsequent navigations to the same path
1735
+ let discoveredRoutesMaxSize = 1000;
1736
+ let discoveredRoutes = new Set();
1733
1737
  // Externally-provided object to hold scroll restoration locations during routing
1734
1738
  let savedScrollPositions = null;
1735
1739
  // Externally-provided function to get scroll restoration keys
@@ -1745,7 +1749,7 @@
1745
1749
  let initialScrollRestored = init.hydrationData != null;
1746
1750
  let initialMatches = matchRoutes(dataRoutes, init.history.location, basename);
1747
1751
  let initialErrors = null;
1748
- if (initialMatches == null && !patchRoutesOnMissImpl) {
1752
+ if (initialMatches == null && !patchRoutesOnNavigationImpl) {
1749
1753
  // If we do not match a user-provided-route, fall back to the root
1750
1754
  // to allow the error boundary to take over
1751
1755
  let error = getInternalRouterError(404, {
@@ -1761,7 +1765,7 @@
1761
1765
  };
1762
1766
  }
1763
1767
 
1764
- // In SPA apps, if the user provided a patchRoutesOnMiss implementation and
1768
+ // In SPA apps, if the user provided a patchRoutesOnNavigation implementation and
1765
1769
  // our initial match is a splat route, clear them out so we run through lazy
1766
1770
  // discovery on hydration in case there's a more accurate lazy route match.
1767
1771
  // In SSR apps (with `hydrationData`), we expect that the server will send
@@ -1779,7 +1783,7 @@
1779
1783
  initialMatches = [];
1780
1784
 
1781
1785
  // If partial hydration and fog of war is enabled, we will be running
1782
- // `patchRoutesOnMiss` during hydration so include any partial matches as
1786
+ // `patchRoutesOnNavigation` during hydration so include any partial matches as
1783
1787
  // the initial matches so we can properly render `HydrateFallback`'s
1784
1788
  if (future.v7_partialHydration) {
1785
1789
  let fogOfWar = checkFogOfWar(null, dataRoutes, init.history.location.pathname);
@@ -1918,7 +1922,7 @@
1918
1922
  // we don't need to update UI state if they change
1919
1923
  let blockerFunctions = new Map();
1920
1924
 
1921
- // Map of pending patchRoutesOnMiss() promises (keyed by path/matches) so
1925
+ // Map of pending patchRoutesOnNavigation() promises (keyed by path/matches) so
1922
1926
  // that we only kick them off once for a given combo
1923
1927
  let pendingPatchRoutes = new Map();
1924
1928
 
@@ -3542,7 +3546,16 @@
3542
3546
  return null;
3543
3547
  }
3544
3548
  function checkFogOfWar(matches, routesToUse, pathname) {
3545
- if (patchRoutesOnMissImpl) {
3549
+ if (patchRoutesOnNavigationImpl) {
3550
+ // Don't bother re-calling patchRouteOnMiss for a path we've already
3551
+ // processed. the last execution would have patched the route tree
3552
+ // accordingly so `matches` here are already accurate.
3553
+ if (discoveredRoutes.has(pathname)) {
3554
+ return {
3555
+ active: false,
3556
+ matches
3557
+ };
3558
+ }
3546
3559
  if (!matches) {
3547
3560
  let fogMatches = matchRoutesImpl(routesToUse, pathname, basename, true);
3548
3561
  return {
@@ -3550,11 +3563,10 @@
3550
3563
  matches: fogMatches || []
3551
3564
  };
3552
3565
  } else {
3553
- let leafRoute = matches[matches.length - 1].route;
3554
- if (leafRoute.path && (leafRoute.path === "*" || leafRoute.path.endsWith("/*"))) {
3555
- // If we matched a splat, it might only be because we haven't yet fetched
3556
- // the children that would match with a higher score, so let's fetch
3557
- // around and find out
3566
+ if (Object.keys(matches[0].params).length > 0) {
3567
+ // If we matched a dynamic param or a splat, it might only be because
3568
+ // we haven't yet discovered other routes that would match with a
3569
+ // higher score. Call patchRoutesOnNavigation just to be sure
3558
3570
  let partialMatches = matchRoutesImpl(routesToUse, pathname, basename, true);
3559
3571
  return {
3560
3572
  active: true,
@@ -3570,12 +3582,11 @@
3570
3582
  }
3571
3583
  async function discoverRoutes(matches, pathname, signal) {
3572
3584
  let partialMatches = matches;
3573
- let route = partialMatches.length > 0 ? partialMatches[partialMatches.length - 1].route : null;
3574
3585
  while (true) {
3575
3586
  let isNonHMR = inFlightDataRoutes == null;
3576
3587
  let routesToUse = inFlightDataRoutes || dataRoutes;
3577
3588
  try {
3578
- await loadLazyRouteChildren(patchRoutesOnMissImpl, pathname, partialMatches, routesToUse, manifest, mapRouteProperties, pendingPatchRoutes, signal);
3589
+ await loadLazyRouteChildren(patchRoutesOnNavigationImpl, pathname, partialMatches, routesToUse, manifest, mapRouteProperties, pendingPatchRoutes, signal);
3579
3590
  } catch (e) {
3580
3591
  return {
3581
3592
  type: "error",
@@ -3599,52 +3610,32 @@
3599
3610
  };
3600
3611
  }
3601
3612
  let newMatches = matchRoutes(routesToUse, pathname, basename);
3602
- let matchedSplat = false;
3603
3613
  if (newMatches) {
3604
- let leafRoute = newMatches[newMatches.length - 1].route;
3605
- if (leafRoute.index) {
3606
- // If we found an index route, we can stop
3607
- return {
3608
- type: "success",
3609
- matches: newMatches
3610
- };
3611
- }
3612
- if (leafRoute.path && leafRoute.path.length > 0) {
3613
- if (leafRoute.path === "*") {
3614
- // If we found a splat route, we can't be sure there's not a
3615
- // higher-scoring route down some partial matches trail so we need
3616
- // to check that out
3617
- matchedSplat = true;
3618
- } else {
3619
- // If we found a non-splat route, we can stop
3620
- return {
3621
- type: "success",
3622
- matches: newMatches
3623
- };
3624
- }
3625
- }
3626
- }
3627
- let newPartialMatches = matchRoutesImpl(routesToUse, pathname, basename, true);
3628
-
3629
- // If we are no longer partially matching anything, this was either a
3630
- // legit splat match above, or it's a 404. Also avoid loops if the
3631
- // second pass results in the same partial matches
3632
- if (!newPartialMatches || partialMatches.map(m => m.route.id).join("-") === newPartialMatches.map(m => m.route.id).join("-")) {
3614
+ addToFifoQueue(pathname, discoveredRoutes);
3633
3615
  return {
3634
3616
  type: "success",
3635
- matches: matchedSplat ? newMatches : null
3617
+ matches: newMatches
3636
3618
  };
3637
3619
  }
3638
- partialMatches = newPartialMatches;
3639
- route = partialMatches[partialMatches.length - 1].route;
3640
- if (route.path === "*") {
3641
- // The splat is still our most accurate partial, so run with it
3620
+ let newPartialMatches = matchRoutesImpl(routesToUse, pathname, basename, true);
3621
+
3622
+ // Avoid loops if the second pass results in the same partial matches
3623
+ if (!newPartialMatches || partialMatches.length === newPartialMatches.length && partialMatches.every((m, i) => m.route.id === newPartialMatches[i].route.id)) {
3624
+ addToFifoQueue(pathname, discoveredRoutes);
3642
3625
  return {
3643
3626
  type: "success",
3644
- matches: partialMatches
3627
+ matches: null
3645
3628
  };
3646
3629
  }
3630
+ partialMatches = newPartialMatches;
3631
+ }
3632
+ }
3633
+ function addToFifoQueue(path, queue) {
3634
+ if (queue.size >= discoveredRoutesMaxSize) {
3635
+ let first = queue.values().next().value;
3636
+ queue.delete(first);
3647
3637
  }
3638
+ queue.add(path);
3648
3639
  }
3649
3640
  function _internalSetRoutes(newRoutes) {
3650
3641
  manifest = {};
@@ -4515,15 +4506,15 @@
4515
4506
  }
4516
4507
 
4517
4508
  /**
4518
- * Idempotent utility to execute patchRoutesOnMiss() to lazily load route
4509
+ * Idempotent utility to execute patchRoutesOnNavigation() to lazily load route
4519
4510
  * definitions and update the routes/routeManifest
4520
4511
  */
4521
- async function loadLazyRouteChildren(patchRoutesOnMissImpl, path, matches, routes, manifest, mapRouteProperties, pendingRouteChildren, signal) {
4512
+ async function loadLazyRouteChildren(patchRoutesOnNavigationImpl, path, matches, routes, manifest, mapRouteProperties, pendingRouteChildren, signal) {
4522
4513
  let key = [path, ...matches.map(m => m.route.id)].join("-");
4523
4514
  try {
4524
4515
  let pending = pendingRouteChildren.get(key);
4525
4516
  if (!pending) {
4526
- pending = patchRoutesOnMissImpl({
4517
+ pending = patchRoutesOnNavigationImpl({
4527
4518
  path,
4528
4519
  matches,
4529
4520
  patch: (routeId, children) => {
@@ -5130,7 +5121,7 @@
5130
5121
  if (status === 400) {
5131
5122
  statusText = "Bad Request";
5132
5123
  if (type === "route-discovery") {
5133
- errorMessage = "Unable to match URL \"" + pathname + "\" - the `unstable_patchRoutesOnMiss()` " + ("function threw the following error:\n" + message);
5124
+ errorMessage = "Unable to match URL \"" + pathname + "\" - the `unstable_patchRoutesOnNavigation()` " + ("function threw the following error:\n" + message);
5134
5125
  } else if (method && pathname && routeId) {
5135
5126
  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.";
5136
5127
  } else if (type === "defer-action") {