@remix-run/router 1.3.2 → 1.3.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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @remix-run/router v1.3.2
2
+ * @remix-run/router v1.3.3-pre.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1491,7 +1491,8 @@
1491
1491
 
1492
1492
  function createRouter(init) {
1493
1493
  invariant(init.routes.length > 0, "You must provide a non-empty routes array to createRouter");
1494
- let dataRoutes = convertRoutesToDataRoutes(init.routes); // Cleanup function for history
1494
+ let dataRoutes = convertRoutesToDataRoutes(init.routes);
1495
+ let inFlightDataRoutes; // Cleanup function for history
1495
1496
 
1496
1497
  let unlistenHistory = null; // Externally-provided functions to call on all state changes
1497
1498
 
@@ -1727,6 +1728,12 @@
1727
1728
 
1728
1729
 
1729
1730
  let preventScrollReset = pendingPreventScrollReset === true || state.navigation.formMethod != null && isMutationMethod(state.navigation.formMethod) && ((_location$state2 = location.state) == null ? void 0 : _location$state2._isRedirect) !== true;
1731
+
1732
+ if (inFlightDataRoutes) {
1733
+ dataRoutes = inFlightDataRoutes;
1734
+ inFlightDataRoutes = undefined;
1735
+ }
1736
+
1730
1737
  updateState(_extends({}, newState, {
1731
1738
  // matches, errors, fetchers go through as-is
1732
1739
  actionData,
@@ -1882,8 +1889,9 @@
1882
1889
 
1883
1890
  saveScrollPosition(state.location, state.matches);
1884
1891
  pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;
1892
+ let routesToUse = inFlightDataRoutes || dataRoutes;
1885
1893
  let loadingNavigation = opts && opts.overrideNavigation;
1886
- let matches = matchRoutes(dataRoutes, location, init.basename); // Short circuit with a 404 on the root error boundary if we match nothing
1894
+ let matches = matchRoutes(routesToUse, location, init.basename); // Short circuit with a 404 on the root error boundary if we match nothing
1887
1895
 
1888
1896
  if (!matches) {
1889
1897
  let error = getInternalRouterError(404, {
@@ -1892,7 +1900,7 @@
1892
1900
  let {
1893
1901
  matches: notFoundMatches,
1894
1902
  route
1895
- } = getShortCircuitMatches(dataRoutes); // Cancel all pending deferred on 404s since we don't keep any routes
1903
+ } = getShortCircuitMatches(routesToUse); // Cancel all pending deferred on 404s since we don't keep any routes
1896
1904
 
1897
1905
  cancelActiveDeferreds();
1898
1906
  completeNavigation(location, {
@@ -2097,7 +2105,8 @@
2097
2105
  formData: loadingNavigation.formData,
2098
2106
  formEncType: loadingNavigation.formEncType
2099
2107
  } : undefined;
2100
- let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, activeSubmission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, pendingActionData, pendingError, fetchLoadMatches); // Cancel pending deferreds for no-longer-matched routes or routes we're
2108
+ let routesToUse = inFlightDataRoutes || dataRoutes;
2109
+ let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, activeSubmission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, fetchLoadMatches, routesToUse, init.basename, pendingActionData, pendingError); // Cancel pending deferreds for no-longer-matched routes or routes we're
2101
2110
  // about to reload. Note that if this is an action reload we would have
2102
2111
  // already cancelled all pending deferreds so this would be a no-op
2103
2112
 
@@ -2214,7 +2223,8 @@
2214
2223
  }
2215
2224
 
2216
2225
  if (fetchControllers.has(key)) abortFetcher(key);
2217
- let matches = matchRoutes(dataRoutes, href, init.basename);
2226
+ let routesToUse = inFlightDataRoutes || dataRoutes;
2227
+ let matches = matchRoutes(routesToUse, href, init.basename);
2218
2228
 
2219
2229
  if (!matches) {
2220
2230
  setFetcherError(key, routeId, getInternalRouterError(404, {
@@ -2239,9 +2249,7 @@
2239
2249
 
2240
2250
  fetchLoadMatches.set(key, {
2241
2251
  routeId,
2242
- path,
2243
- match,
2244
- matches
2252
+ path
2245
2253
  });
2246
2254
  handleFetcherLoader(key, routeId, path, match, matches, submission);
2247
2255
  } // Call the action for the matched fetcher.submit(), and then handle redirects,
@@ -2328,7 +2336,8 @@
2328
2336
 
2329
2337
  let nextLocation = state.navigation.location || state.location;
2330
2338
  let revalidationRequest = createClientSideRequest(init.history, nextLocation, abortController.signal);
2331
- let matches = state.navigation.state !== "idle" ? matchRoutes(dataRoutes, state.navigation.location, init.basename) : state.matches;
2339
+ let routesToUse = inFlightDataRoutes || dataRoutes;
2340
+ let matches = state.navigation.state !== "idle" ? matchRoutes(routesToUse, state.navigation.location, init.basename) : state.matches;
2332
2341
  invariant(matches, "Didn't find any matches after fetcher action");
2333
2342
  let loadId = ++incrementingLoadId;
2334
2343
  fetchReloadIds.set(key, loadId);
@@ -2341,10 +2350,10 @@
2341
2350
  });
2342
2351
 
2343
2352
  state.fetchers.set(key, loadFetcher);
2344
- let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, submission, nextLocation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, {
2353
+ let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, submission, nextLocation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, fetchLoadMatches, routesToUse, init.basename, {
2345
2354
  [match.route.id]: actionResult.data
2346
- }, undefined, // No need to send through errors since we short circuit above
2347
- fetchLoadMatches); // Put all revalidating fetchers into the loading state, except for the
2355
+ }, undefined // No need to send through errors since we short circuit above
2356
+ ); // Put all revalidating fetchers into the loading state, except for the
2348
2357
  // current fetcher which we want to keep in it's current loading state which
2349
2358
  // contains it's action submission info + action data
2350
2359
 
@@ -2550,9 +2559,10 @@
2550
2559
  invariant(redirectLocation, "Expected a location on the redirect navigation"); // Check if this an absolute external redirect that goes to a new origin
2551
2560
 
2552
2561
  if (ABSOLUTE_URL_REGEX.test(redirect.location) && isBrowser && typeof ((_window = window) == null ? void 0 : _window.location) !== "undefined") {
2553
- let newOrigin = init.history.createURL(redirect.location).origin;
2562
+ let url = init.history.createURL(redirect.location);
2563
+ let isDifferentBasename = stripBasename(url.pathname, init.basename || "/") == null;
2554
2564
 
2555
- if (window.location.origin !== newOrigin) {
2565
+ if (window.location.origin !== url.origin || isDifferentBasename) {
2556
2566
  if (replace) {
2557
2567
  window.location.replace(redirect.location);
2558
2568
  } else {
@@ -2618,7 +2628,19 @@
2618
2628
  // Call all navigation loaders and revalidating fetcher loaders in parallel,
2619
2629
  // then slice off the results into separate arrays so we can handle them
2620
2630
  // accordingly
2621
- let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, router.basename)), ...fetchersToLoad.map(f => callLoaderOrAction("loader", createClientSideRequest(init.history, f.path, request.signal), f.match, f.matches, router.basename))]);
2631
+ let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, router.basename)), ...fetchersToLoad.map(f => {
2632
+ if (f.matches && f.match) {
2633
+ return callLoaderOrAction("loader", createClientSideRequest(init.history, f.path, request.signal), f.match, f.matches, router.basename);
2634
+ } else {
2635
+ let error = {
2636
+ type: ResultType.error,
2637
+ error: getInternalRouterError(404, {
2638
+ pathname: f.path
2639
+ })
2640
+ };
2641
+ return error;
2642
+ }
2643
+ })]);
2622
2644
  let loaderResults = results.slice(0, matchesToLoad.length);
2623
2645
  let fetcherResults = results.slice(matchesToLoad.length);
2624
2646
  await Promise.all([resolveDeferredResults(currentMatches, matchesToLoad, loaderResults, request.signal, false, state.loaderData), resolveDeferredResults(currentMatches, fetchersToLoad.map(f => f.match), fetcherResults, request.signal, true)]);
@@ -2853,6 +2875,10 @@
2853
2875
  return null;
2854
2876
  }
2855
2877
 
2878
+ function _internalSetRoutes(newRoutes) {
2879
+ inFlightDataRoutes = newRoutes;
2880
+ }
2881
+
2856
2882
  router = {
2857
2883
  get basename() {
2858
2884
  return init.basename;
@@ -2882,7 +2908,10 @@
2882
2908
  getBlocker,
2883
2909
  deleteBlocker,
2884
2910
  _internalFetchControllers: fetchControllers,
2885
- _internalActiveDeferreds: activeDeferreds
2911
+ _internalActiveDeferreds: activeDeferreds,
2912
+ // TODO: Remove setRoutes, it's temporary to avoid dealing with
2913
+ // updating the tree while validating the update algorithm.
2914
+ _internalSetRoutes
2886
2915
  };
2887
2916
  return router;
2888
2917
  } //#endregion
@@ -3383,7 +3412,7 @@
3383
3412
  return boundaryMatches;
3384
3413
  }
3385
3414
 
3386
- function getMatchesToLoad(history, state, matches, submission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, pendingActionData, pendingError, fetchLoadMatches) {
3415
+ function getMatchesToLoad(history, state, matches, submission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, fetchLoadMatches, routesToUse, basename, pendingActionData, pendingError) {
3387
3416
  let actionResult = pendingError ? Object.values(pendingError)[0] : pendingActionData ? Object.values(pendingActionData)[0] : undefined;
3388
3417
  let currentUrl = history.createURL(state.location);
3389
3418
  let nextUrl = history.createURL(location);
@@ -3422,36 +3451,56 @@
3422
3451
  }); // Pick fetcher.loads that need to be revalidated
3423
3452
 
3424
3453
  let revalidatingFetchers = [];
3425
- fetchLoadMatches && fetchLoadMatches.forEach((f, key) => {
3454
+ fetchLoadMatches.forEach((f, key) => {
3455
+ // Don't revalidate if fetcher won't be present in the subsequent render
3426
3456
  if (!matches.some(m => m.route.id === f.routeId)) {
3427
- // This fetcher is not going to be present in the subsequent render so
3428
- // there's no need to revalidate it
3429
3457
  return;
3430
- } else if (cancelledFetcherLoads.includes(key)) {
3431
- // This fetcher was cancelled from a prior action submission - force reload
3458
+ }
3459
+
3460
+ let fetcherMatches = matchRoutes(routesToUse, f.path, basename); // If the fetcher path no longer matches, push it in with null matches so
3461
+ // we can trigger a 404 in callLoadersAndMaybeResolveData
3462
+
3463
+ if (!fetcherMatches) {
3432
3464
  revalidatingFetchers.push(_extends({
3433
3465
  key
3434
- }, f));
3435
- } else {
3436
- // Revalidating fetchers are decoupled from the route matches since they
3437
- // hit a static href, so they _always_ check shouldRevalidate and the
3438
- // default is strictly if a revalidation is explicitly required (action
3439
- // submissions, useRevalidator, X-Remix-Revalidate).
3440
- let shouldRevalidate = shouldRevalidateLoader(f.match, _extends({
3441
- currentUrl,
3442
- currentParams: state.matches[state.matches.length - 1].params,
3443
- nextUrl,
3444
- nextParams: matches[matches.length - 1].params
3445
- }, submission, {
3446
- actionResult,
3447
- defaultShouldRevalidate
3466
+ }, f, {
3467
+ matches: null,
3468
+ match: null
3448
3469
  }));
3470
+ return;
3471
+ }
3449
3472
 
3450
- if (shouldRevalidate) {
3451
- revalidatingFetchers.push(_extends({
3452
- key
3453
- }, f));
3454
- }
3473
+ let fetcherMatch = getTargetMatch(fetcherMatches, f.path);
3474
+
3475
+ if (cancelledFetcherLoads.includes(key)) {
3476
+ revalidatingFetchers.push(_extends({
3477
+ key,
3478
+ matches: fetcherMatches,
3479
+ match: fetcherMatch
3480
+ }, f));
3481
+ return;
3482
+ } // Revalidating fetchers are decoupled from the route matches since they
3483
+ // hit a static href, so they _always_ check shouldRevalidate and the
3484
+ // default is strictly if a revalidation is explicitly required (action
3485
+ // submissions, useRevalidator, X-Remix-Revalidate).
3486
+
3487
+
3488
+ let shouldRevalidate = shouldRevalidateLoader(fetcherMatch, _extends({
3489
+ currentUrl,
3490
+ currentParams: state.matches[state.matches.length - 1].params,
3491
+ nextUrl,
3492
+ nextParams: matches[matches.length - 1].params
3493
+ }, submission, {
3494
+ actionResult,
3495
+ defaultShouldRevalidate
3496
+ }));
3497
+
3498
+ if (shouldRevalidate) {
3499
+ revalidatingFetchers.push(_extends({
3500
+ key,
3501
+ matches: fetcherMatches,
3502
+ match: fetcherMatch
3503
+ }, f));
3455
3504
  }
3456
3505
  });
3457
3506
  return [navigationMatches, revalidatingFetchers];
@@ -3548,13 +3597,14 @@
3548
3597
 
3549
3598
  location = createPath(resolvedLocation);
3550
3599
  } else if (!isStaticRequest) {
3551
- // Strip off the protocol+origin for same-origin absolute redirects.
3552
- // If this is a static reques, we can let it go back to the browser
3553
- // as-is
3600
+ // Strip off the protocol+origin for same-origin + same-basename absolute
3601
+ // redirects. If this is a static request, we can let it go back to the
3602
+ // browser as-is
3554
3603
  let currentUrl = new URL(request.url);
3555
3604
  let url = location.startsWith("//") ? new URL(currentUrl.protocol + location) : new URL(location);
3605
+ let isSameBasename = stripBasename(url.pathname, basename) != null;
3556
3606
 
3557
- if (url.origin === currentUrl.origin) {
3607
+ if (url.origin === currentUrl.origin && isSameBasename) {
3558
3608
  location = url.pathname + url.search + url.hash;
3559
3609
  }
3560
3610
  } // Don't process redirects in the router during static requests requests.
@@ -3621,9 +3671,13 @@
3621
3671
  }
3622
3672
 
3623
3673
  if (result instanceof DeferredData) {
3674
+ var _result$init, _result$init2;
3675
+
3624
3676
  return {
3625
3677
  type: ResultType.deferred,
3626
- deferredData: result
3678
+ deferredData: result,
3679
+ statusCode: (_result$init = result.init) == null ? void 0 : _result$init.status,
3680
+ headers: ((_result$init2 = result.init) == null ? void 0 : _result$init2.headers) && new Headers(result.init.headers)
3627
3681
  };
3628
3682
  }
3629
3683
 
@@ -3760,7 +3814,7 @@
3760
3814
  let result = fetcherResults[index]; // Process fetcher non-redirect errors
3761
3815
 
3762
3816
  if (isErrorResult(result)) {
3763
- let boundaryMatch = findNearestBoundary(state.matches, match.route.id);
3817
+ let boundaryMatch = findNearestBoundary(state.matches, match == null ? void 0 : match.route.id);
3764
3818
 
3765
3819
  if (!(errors && errors[boundaryMatch.route.id])) {
3766
3820
  errors = _extends({}, errors, {
@@ -3807,7 +3861,9 @@
3807
3861
  if (newLoaderData[id] !== undefined) {
3808
3862
  mergedLoaderData[id] = newLoaderData[id];
3809
3863
  }
3810
- } else if (loaderData[id] !== undefined) {
3864
+ } else if (loaderData[id] !== undefined && match.route.loader) {
3865
+ // Preserve existing keys not included in newLoaderData and where a loader
3866
+ // wasn't removed by HMR
3811
3867
  mergedLoaderData[id] = loaderData[id];
3812
3868
  }
3813
3869
 
@@ -3944,7 +4000,14 @@
3944
4000
  async function resolveDeferredResults(currentMatches, matchesToLoad, results, signal, isFetcher, currentLoaderData) {
3945
4001
  for (let index = 0; index < results.length; index++) {
3946
4002
  let result = results[index];
3947
- let match = matchesToLoad[index];
4003
+ let match = matchesToLoad[index]; // If we don't have a match, then we can have a deferred result to do
4004
+ // anything with. This is for revalidating fetchers where the route was
4005
+ // removed during HMR
4006
+
4007
+ if (!match) {
4008
+ continue;
4009
+ }
4010
+
3948
4011
  let currentMatch = currentMatches.find(m => m.route.id === match.route.id);
3949
4012
  let isRevalidatingLoader = currentMatch != null && !isNewRouteInstance(currentMatch, match) && (currentLoaderData && currentLoaderData[match.route.id]) !== undefined;
3950
4013
 
@@ -4037,6 +4100,7 @@
4037
4100
  exports.UNSAFE_DeferredData = DeferredData;
4038
4101
  exports.UNSAFE_convertRoutesToDataRoutes = convertRoutesToDataRoutes;
4039
4102
  exports.UNSAFE_getPathContributingMatches = getPathContributingMatches;
4103
+ exports.UNSAFE_invariant = invariant;
4040
4104
  exports.createBrowserHistory = createBrowserHistory;
4041
4105
  exports.createHashHistory = createHashHistory;
4042
4106
  exports.createMemoryHistory = createMemoryHistory;
@@ -4047,7 +4111,6 @@
4047
4111
  exports.generatePath = generatePath;
4048
4112
  exports.getStaticContextFromError = getStaticContextFromError;
4049
4113
  exports.getToPathname = getToPathname;
4050
- exports.invariant = invariant;
4051
4114
  exports.isRouteErrorResponse = isRouteErrorResponse;
4052
4115
  exports.joinPaths = joinPaths;
4053
4116
  exports.json = json;