react-router 8.0.0-pre.0 → 8.0.0-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.
Files changed (168) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/development/dom-export.js +1 -1
  3. package/dist/development/index-react-server-client.js +1 -1
  4. package/dist/development/index-react-server.d.ts +9 -2
  5. package/dist/development/index-react-server.js +91 -88
  6. package/dist/development/index.d.ts +1 -2
  7. package/dist/development/index.js +2 -3
  8. package/dist/development/lib/actions.js +6 -18
  9. package/dist/development/lib/components.d.ts +11 -3
  10. package/dist/development/lib/components.js +8 -2
  11. package/dist/development/lib/context.js +1 -1
  12. package/dist/development/lib/dom/dom.js +1 -1
  13. package/dist/development/lib/dom/lib.d.ts +12 -1
  14. package/dist/development/lib/dom/lib.js +18 -6
  15. package/dist/development/lib/dom/server.js +2 -2
  16. package/dist/development/lib/dom/ssr/components.d.ts +4 -2
  17. package/dist/development/lib/dom/ssr/components.js +13 -3
  18. package/dist/development/lib/dom/ssr/data.js +1 -1
  19. package/dist/development/lib/dom/ssr/entry.d.ts +1 -0
  20. package/dist/development/lib/dom/ssr/errorBoundaries.js +7 -3
  21. package/dist/development/lib/dom/ssr/fallback.js +8 -3
  22. package/dist/development/lib/dom/ssr/fog-of-war.js +12 -2
  23. package/dist/development/lib/dom/ssr/hydration.js +1 -1
  24. package/dist/development/lib/dom/ssr/invariant.js +1 -1
  25. package/dist/development/lib/dom/ssr/links.js +1 -1
  26. package/dist/development/lib/dom/ssr/markup.js +1 -1
  27. package/dist/development/lib/dom/ssr/routeModules.js +1 -1
  28. package/dist/development/lib/dom/ssr/routes-test-stub.js +1 -1
  29. package/dist/development/lib/dom/ssr/routes.js +1 -1
  30. package/dist/development/lib/dom/ssr/server.d.ts +4 -1
  31. package/dist/development/lib/dom/ssr/server.js +2 -1
  32. package/dist/development/lib/dom/ssr/single-fetch.js +2 -3
  33. package/dist/development/lib/dom-export/dom-router-provider.js +1 -1
  34. package/dist/development/lib/dom-export/hydrated-router.d.ts +1 -1
  35. package/dist/development/lib/dom-export/hydrated-router.js +14 -17
  36. package/dist/development/lib/errors.js +1 -1
  37. package/dist/development/lib/hooks.js +6 -4
  38. package/dist/development/lib/href.js +1 -1
  39. package/dist/development/lib/router/history.js +3 -2
  40. package/dist/development/lib/router/instrumentation.js +1 -1
  41. package/dist/development/lib/router/links.d.ts +3 -2
  42. package/dist/development/lib/router/router.js +13 -6
  43. package/dist/development/lib/router/url.js +18 -0
  44. package/dist/development/lib/router/utils.d.ts +6 -0
  45. package/dist/development/lib/router/utils.js +27 -8
  46. package/dist/development/lib/rsc/browser.js +21 -17
  47. package/dist/development/lib/rsc/errorBoundaries.js +1 -1
  48. package/dist/development/lib/rsc/html-stream/browser.js +1 -1
  49. package/dist/development/lib/rsc/html-stream/server.js +1 -1
  50. package/dist/development/lib/rsc/route-modules.js +1 -1
  51. package/dist/development/lib/rsc/server.ssr.js +27 -11
  52. package/dist/development/lib/server-runtime/cookies.js +1 -1
  53. package/dist/development/lib/server-runtime/crypto.js +1 -1
  54. package/dist/development/lib/server-runtime/data.js +1 -1
  55. package/dist/development/lib/server-runtime/dev.js +1 -1
  56. package/dist/development/lib/server-runtime/entry.js +1 -1
  57. package/dist/development/lib/server-runtime/errors.js +2 -22
  58. package/dist/development/lib/server-runtime/headers.js +1 -1
  59. package/dist/development/lib/server-runtime/invariant.js +1 -1
  60. package/dist/development/lib/server-runtime/mode.js +1 -1
  61. package/dist/development/lib/server-runtime/routeMatching.js +1 -1
  62. package/dist/development/lib/server-runtime/routes.js +1 -1
  63. package/dist/development/lib/server-runtime/server.js +17 -23
  64. package/dist/development/lib/server-runtime/serverHandoff.js +1 -1
  65. package/dist/development/lib/server-runtime/sessions/cookieStorage.js +1 -1
  66. package/dist/development/lib/server-runtime/sessions/memoryStorage.js +1 -1
  67. package/dist/development/lib/server-runtime/sessions.js +1 -1
  68. package/dist/development/lib/server-runtime/single-fetch.js +4 -4
  69. package/dist/development/lib/server-runtime/urls.js +2 -5
  70. package/dist/development/lib/server-runtime/warnings.js +1 -1
  71. package/dist/development/lib/types/internal.js +1 -1
  72. package/dist/development/vendor/turbo-stream-v2/flatten.js +1 -1
  73. package/dist/development/vendor/turbo-stream-v2/turbo-stream.js +2 -1
  74. package/dist/development/vendor/turbo-stream-v2/unflatten.js +3 -2
  75. package/dist/development/vendor/turbo-stream-v2/utils.js +2 -10
  76. package/dist/production/dom-export.js +1 -1
  77. package/dist/production/index-react-server-client.js +1 -1
  78. package/dist/production/index-react-server.d.ts +9 -2
  79. package/dist/production/index-react-server.js +91 -88
  80. package/dist/production/index.d.ts +1 -2
  81. package/dist/production/index.js +2 -3
  82. package/dist/production/lib/actions.js +6 -18
  83. package/dist/production/lib/components.d.ts +11 -3
  84. package/dist/production/lib/components.js +8 -2
  85. package/dist/production/lib/context.js +1 -1
  86. package/dist/production/lib/dom/dom.js +1 -1
  87. package/dist/production/lib/dom/lib.d.ts +12 -1
  88. package/dist/production/lib/dom/lib.js +18 -6
  89. package/dist/production/lib/dom/server.js +2 -2
  90. package/dist/production/lib/dom/ssr/components.d.ts +4 -2
  91. package/dist/production/lib/dom/ssr/components.js +13 -3
  92. package/dist/production/lib/dom/ssr/data.js +1 -1
  93. package/dist/production/lib/dom/ssr/entry.d.ts +1 -0
  94. package/dist/production/lib/dom/ssr/errorBoundaries.js +7 -3
  95. package/dist/production/lib/dom/ssr/fallback.js +3 -1
  96. package/dist/production/lib/dom/ssr/fog-of-war.js +12 -2
  97. package/dist/production/lib/dom/ssr/hydration.js +1 -1
  98. package/dist/production/lib/dom/ssr/invariant.js +1 -1
  99. package/dist/production/lib/dom/ssr/links.js +1 -1
  100. package/dist/production/lib/dom/ssr/markup.js +1 -1
  101. package/dist/production/lib/dom/ssr/routeModules.js +1 -1
  102. package/dist/production/lib/dom/ssr/routes-test-stub.js +1 -1
  103. package/dist/production/lib/dom/ssr/routes.js +1 -1
  104. package/dist/production/lib/dom/ssr/server.d.ts +4 -1
  105. package/dist/production/lib/dom/ssr/server.js +2 -1
  106. package/dist/production/lib/dom/ssr/single-fetch.js +2 -3
  107. package/dist/production/lib/dom-export/dom-router-provider.js +1 -1
  108. package/dist/production/lib/dom-export/hydrated-router.d.ts +1 -1
  109. package/dist/production/lib/dom-export/hydrated-router.js +14 -17
  110. package/dist/production/lib/errors.js +1 -1
  111. package/dist/production/lib/hooks.js +6 -4
  112. package/dist/production/lib/href.js +1 -1
  113. package/dist/production/lib/router/history.js +3 -2
  114. package/dist/production/lib/router/instrumentation.js +1 -1
  115. package/dist/production/lib/router/links.d.ts +3 -2
  116. package/dist/production/lib/router/router.js +13 -6
  117. package/dist/production/lib/router/url.js +18 -0
  118. package/dist/production/lib/router/utils.d.ts +6 -0
  119. package/dist/production/lib/router/utils.js +27 -8
  120. package/dist/production/lib/rsc/browser.js +21 -17
  121. package/dist/production/lib/rsc/errorBoundaries.js +1 -1
  122. package/dist/production/lib/rsc/html-stream/browser.js +1 -1
  123. package/dist/production/lib/rsc/html-stream/server.js +1 -1
  124. package/dist/production/lib/rsc/route-modules.js +1 -1
  125. package/dist/production/lib/rsc/server.ssr.js +27 -11
  126. package/dist/production/lib/server-runtime/cookies.js +1 -1
  127. package/dist/production/lib/server-runtime/crypto.js +1 -1
  128. package/dist/production/lib/server-runtime/data.js +1 -1
  129. package/dist/production/lib/server-runtime/dev.js +1 -1
  130. package/dist/production/lib/server-runtime/entry.js +1 -1
  131. package/dist/production/lib/server-runtime/errors.js +2 -22
  132. package/dist/production/lib/server-runtime/headers.js +1 -1
  133. package/dist/production/lib/server-runtime/invariant.js +1 -1
  134. package/dist/production/lib/server-runtime/mode.js +1 -1
  135. package/dist/production/lib/server-runtime/routeMatching.js +1 -1
  136. package/dist/production/lib/server-runtime/routes.js +1 -1
  137. package/dist/production/lib/server-runtime/server.js +17 -23
  138. package/dist/production/lib/server-runtime/serverHandoff.js +1 -1
  139. package/dist/production/lib/server-runtime/sessions/cookieStorage.js +1 -1
  140. package/dist/production/lib/server-runtime/sessions/memoryStorage.js +1 -1
  141. package/dist/production/lib/server-runtime/sessions.js +1 -1
  142. package/dist/production/lib/server-runtime/single-fetch.js +4 -4
  143. package/dist/production/lib/server-runtime/urls.js +2 -5
  144. package/dist/production/lib/server-runtime/warnings.js +1 -1
  145. package/dist/production/lib/types/internal.js +1 -1
  146. package/dist/production/vendor/turbo-stream-v2/flatten.js +1 -1
  147. package/dist/production/vendor/turbo-stream-v2/turbo-stream.js +2 -1
  148. package/dist/production/vendor/turbo-stream-v2/unflatten.js +3 -2
  149. package/dist/production/vendor/turbo-stream-v2/utils.js +2 -10
  150. package/docs/explanation/code-splitting.md +1 -1
  151. package/docs/explanation/index-query-param.md +2 -2
  152. package/docs/explanation/type-safety.md +1 -1
  153. package/docs/how-to/data-strategy.md +5 -5
  154. package/docs/how-to/error-reporting.md +10 -2
  155. package/docs/how-to/headers.md +2 -1
  156. package/docs/how-to/security.md +9 -7
  157. package/docs/start/data/installation.md +4 -0
  158. package/docs/start/data/route-object.md +20 -0
  159. package/docs/start/framework/actions.md +0 -1
  160. package/docs/start/framework/data-loading.md +1 -1
  161. package/docs/start/framework/deploying.md +4 -0
  162. package/docs/start/framework/installation.md +0 -1
  163. package/docs/upgrading/v6.md +3 -0
  164. package/package.json +2 -2
  165. package/dist/development/lib/dom/ssr/errors.d.ts +0 -7
  166. package/dist/development/lib/dom/ssr/errors.js +0 -36
  167. package/dist/production/lib/dom/ssr/errors.d.ts +0 -7
  168. package/dist/production/lib/dom/ssr/errors.js +0 -36
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0-pre.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -8,6 +8,7 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
+ import { PROTOCOL_RELATIVE_URL_REGEX, normalizeProtocolRelativeUrl } from "./url.js";
11
12
  import { createBrowserURLImpl, createLocation, createPath, invariant, parsePath, warning } from "./history.js";
12
13
  import { ErrorResponseImpl, RouterContextProvider, convertRouteMatchToUiMatch, convertRoutesToDataRoutes, flattenAndRankRoutes, getPathContributingMatches, getResolveToMatches, getRoutePattern, isAbsoluteUrl, isRouteErrorResponse, isUnsupportedLazyRouteFunctionKey, isUnsupportedLazyRouteObjectKey, matchRoutesImpl, prependBasename, removeDoubleSlashes, resolveTo, stripBasename } from "./utils.js";
13
14
  import { getRouteInstrumentationUpdates, instrumentClientSideRouter } from "./instrumentation.js";
@@ -2572,17 +2573,23 @@ const invalidProtocols = [
2572
2573
  "filesystem:",
2573
2574
  "javascript:"
2574
2575
  ];
2576
+ function hasInvalidProtocol(location) {
2577
+ try {
2578
+ return invalidProtocols.includes(new URL(location).protocol);
2579
+ } catch {
2580
+ return false;
2581
+ }
2582
+ }
2575
2583
  function normalizeRedirectLocation(location, currentUrl, basename, historyInstance) {
2576
2584
  if (isAbsoluteUrl(location)) {
2577
2585
  let normalizedLocation = location;
2578
- let url = normalizedLocation.startsWith("//") ? new URL(currentUrl.protocol + normalizedLocation) : new URL(normalizedLocation);
2579
- if (invalidProtocols.includes(url.protocol)) throw new Error("Invalid redirect location");
2586
+ let url = PROTOCOL_RELATIVE_URL_REGEX.test(normalizedLocation) ? new URL(normalizeProtocolRelativeUrl(normalizedLocation, currentUrl.protocol)) : new URL(normalizedLocation);
2587
+ if (hasInvalidProtocol(url.toString())) throw new Error("Invalid redirect location");
2580
2588
  let isSameBasename = stripBasename(url.pathname, basename) != null;
2581
2589
  if (url.origin === currentUrl.origin && isSameBasename) return removeDoubleSlashes(url.pathname) + url.search + url.hash;
2582
2590
  }
2583
2591
  try {
2584
- let url = historyInstance.createURL(location);
2585
- if (invalidProtocols.includes(url.protocol)) throw new Error("Invalid redirect location");
2592
+ if (hasInvalidProtocol(historyInstance.createURL(location).toString())) throw new Error("Invalid redirect location");
2586
2593
  } catch (e) {}
2587
2594
  return location;
2588
2595
  }
@@ -2978,4 +2985,4 @@ function createDeferred() {
2978
2985
  };
2979
2986
  }
2980
2987
  //#endregion
2981
- export { IDLE_BLOCKER, IDLE_FETCHER, IDLE_NAVIGATION, createRouter, createStaticHandler, getStaticContextFromError, invalidProtocols, isDataWithResponseInit, isMutationMethod, isRedirectResponse, isRedirectStatusCode, isResponse };
2988
+ export { IDLE_BLOCKER, IDLE_FETCHER, IDLE_NAVIGATION, createRouter, createStaticHandler, getStaticContextFromError, hasInvalidProtocol, isDataWithResponseInit, isMutationMethod, isRedirectResponse, isRedirectStatusCode, isResponse };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * react-router v8.0.0-pre.1
3
+ *
4
+ * Copyright (c) Remix Software Inc.
5
+ *
6
+ * This source code is licensed under the MIT license found in the
7
+ * LICENSE.md file in the root directory of this source tree.
8
+ *
9
+ * @license MIT
10
+ */
11
+ //#region lib/router/url.ts
12
+ const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|[\\/]{2})/i;
13
+ const PROTOCOL_RELATIVE_URL_REGEX = /^[\\/]{2}/;
14
+ function normalizeProtocolRelativeUrl(url, protocol) {
15
+ return protocol + url.replace(/\\/g, "/");
16
+ }
17
+ //#endregion
18
+ export { ABSOLUTE_URL_REGEX, PROTOCOL_RELATIVE_URL_REGEX, normalizeProtocolRelativeUrl };
@@ -668,6 +668,8 @@ interface RouteMeta<RouteObjectType extends RouteObject = RouteObject> {
668
668
  caseSensitive: boolean;
669
669
  childrenIndex: number;
670
670
  route: RouteObjectType;
671
+ matcher?: RegExp;
672
+ compiledParams?: CompiledPathParam[];
671
673
  }
672
674
  /**
673
675
  * @private
@@ -752,6 +754,10 @@ interface PathMatch<ParamKey extends string = string> {
752
754
  * or `null` if it does not match.
753
755
  */
754
756
  declare function matchPath<Path extends string>(pattern: PathPattern<Path> | Path, pathname: string): PathMatch<ParamParseKey<Path>> | null;
757
+ type CompiledPathParam = {
758
+ paramName: string;
759
+ isOptional?: boolean;
760
+ };
755
761
  /**
756
762
  * Returns a resolved {@link Path} object relative to the given pathname.
757
763
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0-pre.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -8,6 +8,7 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
+ import { ABSOLUTE_URL_REGEX, PROTOCOL_RELATIVE_URL_REGEX, normalizeProtocolRelativeUrl } from "./url.js";
11
12
  import { invariant, parsePath, warning } from "./history.js";
12
13
  import * as React$1 from "react";
13
14
  //#region lib/router/utils.ts
@@ -280,7 +281,14 @@ function flattenRoutes(routes, branches = [], parentsMeta = [], parentPath = "",
280
281
  branches.push({
281
282
  path,
282
283
  score: computeScore(path, route.index),
283
- routesMeta
284
+ routesMeta: routesMeta.map((meta, i) => {
285
+ let [matcher, params] = compilePath(meta.relativePath, meta.caseSensitive, i === routesMeta.length - 1);
286
+ return {
287
+ ...meta,
288
+ matcher,
289
+ compiledParams: params
290
+ };
291
+ })
284
292
  });
285
293
  };
286
294
  routes.forEach((route, index) => {
@@ -331,11 +339,12 @@ function matchRouteBranch(branch, pathname, allowPartial = false) {
331
339
  let meta = routesMeta[i];
332
340
  let end = i === routesMeta.length - 1;
333
341
  let remainingPathname = matchedPathname === "/" ? pathname : pathname.slice(matchedPathname.length) || "/";
334
- let match = matchPath({
342
+ let pattern = {
335
343
  path: meta.relativePath,
336
344
  caseSensitive: meta.caseSensitive,
337
345
  end
338
- }, remainingPathname);
346
+ };
347
+ let match = meta.matcher && meta.compiledParams ? matchPathImpl(pattern, remainingPathname, meta.matcher, meta.compiledParams) : matchPath(pattern, remainingPathname);
339
348
  let route = meta.route;
340
349
  if (!match && end && allowPartial && !routesMeta[routesMeta.length - 1].route.index) match = matchPath({
341
350
  path: meta.relativePath,
@@ -409,6 +418,9 @@ function matchPath(pattern, pathname) {
409
418
  end: true
410
419
  };
411
420
  let [matcher, compiledParams] = compilePath(pattern.path, pattern.caseSensitive, pattern.end);
421
+ return matchPathImpl(pattern, pathname, matcher, compiledParams);
422
+ }
423
+ function matchPathImpl(pattern, pathname, matcher, compiledParams) {
412
424
  let match = pathname.match(matcher);
413
425
  if (!match) return null;
414
426
  let matchedPathname = match[0];
@@ -471,7 +483,6 @@ function stripBasename(pathname, basename) {
471
483
  function prependBasename({ basename, pathname }) {
472
484
  return pathname === "/" ? basename : joinPaths([basename, pathname]);
473
485
  }
474
- const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
475
486
  const isAbsoluteUrl = (url) => ABSOLUTE_URL_REGEX.test(url);
476
487
  /**
477
488
  * Returns a resolved {@link Path} object relative to the given pathname.
@@ -547,7 +558,7 @@ function resolveTo(toArg, routePathnames, locationPathname, isPathRelative = fal
547
558
  if (!path.pathname.endsWith("/") && (hasExplicitTrailingSlash || hasCurrentTrailingSlash)) path.pathname += "/";
548
559
  return path;
549
560
  }
550
- const removeDoubleSlashes = (path) => path.replace(/\/\/+/g, "/");
561
+ const removeDoubleSlashes = (path) => path.replace(/[\\/]{2,}/g, "/");
551
562
  const joinPaths = (paths) => removeDoubleSlashes(paths.join("/"));
552
563
  const removeTrailingSlash = (path) => path.replace(/\/+$/, "");
553
564
  const normalizePathname = (pathname) => removeTrailingSlash(pathname).replace(/^\/*/, "/");
@@ -700,6 +711,14 @@ const replace = (url, init) => {
700
711
  response.headers.set("X-Remix-Replace", "true");
701
712
  return response;
702
713
  };
714
+ const SUPPORTED_ERROR_TYPES = [
715
+ "EvalError",
716
+ "RangeError",
717
+ "ReferenceError",
718
+ "SyntaxError",
719
+ "TypeError",
720
+ "URIError"
721
+ ];
703
722
  var ErrorResponseImpl = class {
704
723
  status;
705
724
  statusText;
@@ -765,7 +784,7 @@ function parseToInfo(_to, basename) {
765
784
  let isExternal = false;
766
785
  if (isBrowser) try {
767
786
  let currentUrl = new URL(window.location.href);
768
- let targetUrl = to.startsWith("//") ? new URL(currentUrl.protocol + to) : new URL(to);
787
+ let targetUrl = PROTOCOL_RELATIVE_URL_REGEX.test(to) ? new URL(normalizeProtocolRelativeUrl(to, currentUrl.protocol)) : new URL(to);
769
788
  let path = stripBasename(targetUrl.pathname, basename);
770
789
  if (targetUrl.origin === currentUrl.origin && path != null) to = path + targetUrl.search + targetUrl.hash;
771
790
  else isExternal = true;
@@ -779,4 +798,4 @@ function parseToInfo(_to, basename) {
779
798
  };
780
799
  }
781
800
  //#endregion
782
- export { ErrorResponseImpl, RouterContextProvider, compilePath, convertRouteMatchToUiMatch, convertRoutesToDataRoutes, createContext, data, decodePath, defaultMapRouteProperties, flattenAndRankRoutes, generatePath, getPathContributingMatches, getResolveToMatches, getRoutePattern, isAbsoluteUrl, isBrowser, isRouteErrorResponse, isUnsupportedLazyRouteFunctionKey, isUnsupportedLazyRouteObjectKey, joinPaths, matchPath, matchRoutes, matchRoutesImpl, parseToInfo, prependBasename, redirect, redirectDocument, removeDoubleSlashes, replace, resolvePath, resolveTo, stripBasename };
801
+ export { ErrorResponseImpl, RouterContextProvider, SUPPORTED_ERROR_TYPES, compilePath, convertRouteMatchToUiMatch, convertRoutesToDataRoutes, createContext, data, decodePath, defaultMapRouteProperties, flattenAndRankRoutes, generatePath, getPathContributingMatches, getResolveToMatches, getRoutePattern, isAbsoluteUrl, isBrowser, isRouteErrorResponse, isUnsupportedLazyRouteFunctionKey, isUnsupportedLazyRouteObjectKey, joinPaths, matchPath, matchRoutes, matchRoutesImpl, parseToInfo, prependBasename, redirect, redirectDocument, removeDoubleSlashes, removeTrailingSlash, replace, resolvePath, resolveTo, stripBasename };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0-pre.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -8,15 +8,16 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
+ import { PROTOCOL_RELATIVE_URL_REGEX } from "../router/url.js";
11
12
  import { createBrowserHistory, invariant } from "../router/history.js";
12
- import { ErrorResponseImpl, createContext } from "../router/utils.js";
13
- import { createRouter, invalidProtocols, isMutationMethod } from "../router/router.js";
13
+ import { ErrorResponseImpl, createContext, resolvePath } from "../router/utils.js";
14
+ import { createRouter, hasInvalidProtocol, isMutationMethod } from "../router/router.js";
14
15
  import { RSCRouterContext } from "../context.js";
15
16
  import { RouterProvider } from "../components.js";
16
17
  import { createRequestInit } from "../dom/ssr/data.js";
17
18
  import { getSingleFetchDataStrategyImpl, singleFetchUrl, stripIndexParam } from "../dom/ssr/single-fetch.js";
18
19
  import { noActionDefinedError, shouldHydrateRouteLoader } from "../dom/ssr/routes.js";
19
- import "../dom/ssr/fog-of-war.js";
20
+ import { getPathsWithAncestors } from "../dom/ssr/fog-of-war.js";
20
21
  import { FrameworkContext, setIsHydrated } from "../dom/ssr/components.js";
21
22
  import { RSCRouterGlobalErrorBoundary } from "./errorBoundaries.js";
22
23
  import { populateRSCRouteModules } from "./route-modules.js";
@@ -80,13 +81,14 @@ function createCallServer({ createFromReadableStream, createTemporaryReferenceSe
80
81
  });
81
82
  React$1.startTransition(() => Promise.resolve(payloadPromise).then(async (payload) => {
82
83
  if (payload.type === "redirect") {
83
- if (payload.reload || isExternalLocation(payload.location)) {
84
- if (hasInvalidProtocol(payload.location)) throw new Error("Invalid redirect location");
85
- window.location.href = payload.location;
84
+ let location = normalizeRedirectLocation(payload.location);
85
+ if (payload.reload || isExternalLocation(location)) {
86
+ if (hasInvalidProtocol(location)) throw new Error("Invalid redirect location");
87
+ window.location.href = location;
86
88
  return;
87
89
  }
88
90
  React$1.startTransition(() => {
89
- globalVar.__reactRouterDataRouter.navigate(payload.location, { replace: payload.replace });
91
+ globalVar.__reactRouterDataRouter.navigate(location, { replace: payload.replace });
90
92
  });
91
93
  return;
92
94
  }
@@ -94,13 +96,14 @@ function createCallServer({ createFromReadableStream, createTemporaryReferenceSe
94
96
  const rerender = await payload.rerender;
95
97
  if (rerender && landedActionId < actionId && globalVar.__routerActionID <= actionId) {
96
98
  if (rerender.type === "redirect") {
97
- if (rerender.reload || isExternalLocation(rerender.location)) {
98
- if (hasInvalidProtocol(rerender.location)) throw new Error("Invalid redirect location");
99
- window.location.href = rerender.location;
99
+ let location = normalizeRedirectLocation(rerender.location);
100
+ if (rerender.reload || isExternalLocation(location)) {
101
+ if (hasInvalidProtocol(location)) throw new Error("Invalid redirect location");
102
+ window.location.href = location;
100
103
  return;
101
104
  }
102
105
  React$1.startTransition(() => {
103
- globalVar.__reactRouterDataRouter.navigate(rerender.location, { replace: rerender.replace });
106
+ globalVar.__reactRouterDataRouter.navigate(location, { replace: rerender.replace });
104
107
  });
105
108
  return;
106
109
  }
@@ -533,6 +536,7 @@ function getManifestUrl(paths) {
533
536
  return url;
534
537
  }
535
538
  async function fetchAndApplyManifestPatches(paths, createFromReadableStream, fetchImplementation, signal) {
539
+ paths = getPathsWithAncestors(paths);
536
540
  let url = getManifestUrl(paths);
537
541
  if (url == null) return;
538
542
  if (url.toString().length > 7680) {
@@ -568,12 +572,12 @@ function debounce(callback, wait) {
568
572
  function isExternalLocation(location) {
569
573
  return new URL(location, window.location.href).origin !== window.location.origin;
570
574
  }
571
- function hasInvalidProtocol(location) {
572
- try {
573
- return invalidProtocols.includes(new URL(location).protocol);
574
- } catch {
575
- return false;
575
+ function normalizeRedirectLocation(location) {
576
+ if (PROTOCOL_RELATIVE_URL_REGEX.test(location)) {
577
+ let path = resolvePath(location);
578
+ return path.pathname + path.search + path.hash;
576
579
  }
580
+ return location;
577
581
  }
578
582
  function cloneRoutes(routes) {
579
583
  if (!routes) return void 0;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0-pre.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0-pre.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0-pre.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0-pre.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0-pre.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -9,6 +9,7 @@
9
9
  * @license MIT
10
10
  */
11
11
  import { isRouteErrorResponse } from "../router/utils.js";
12
+ import { hasInvalidProtocol } from "../router/router.js";
12
13
  import { RSCRouterContext } from "../context.js";
13
14
  import { decodeRedirectErrorDigest, decodeRouteErrorResponseDigest } from "../errors.js";
14
15
  import { escapeHtml } from "../dom/ssr/markup.js";
@@ -122,6 +123,7 @@ async function routeRSCServerRequest({ request, serverResponse, createFromReadab
122
123
  if (!detectRedirectResponse.body) throw new Error("Failed to clone server response");
123
124
  const payload = await createFromReadableStream(detectRedirectResponse.body);
124
125
  if (serverResponse.status === 202 && payload.type === "redirect") {
126
+ if (hasInvalidProtocol(payload.location)) throw new Error("Invalid redirect location");
125
127
  const headers = new Headers(serverResponse.headers);
126
128
  headers.delete("Content-Encoding");
127
129
  headers.delete("Content-Length");
@@ -159,6 +161,7 @@ async function routeRSCServerRequest({ request, serverResponse, createFromReadab
159
161
  for (const [key, value] of serverResponse.headers) headers.append(key, value);
160
162
  headers.set("Content-Type", "text/html; charset=utf-8");
161
163
  if (renderRedirect) {
164
+ if (hasInvalidProtocol(renderRedirect.location)) throw new Error("Invalid redirect location");
162
165
  headers.set("Location", renderRedirect.location);
163
166
  return new Response(html, {
164
167
  status: renderRedirect.status,
@@ -166,7 +169,10 @@ async function routeRSCServerRequest({ request, serverResponse, createFromReadab
166
169
  });
167
170
  }
168
171
  const redirectTransform = new TransformStream({ flush(controller) {
169
- if (renderRedirect) controller.enqueue(new TextEncoder().encode(`<meta http-equiv="refresh" content="0;url=${escapeHtml(renderRedirect.location)}"/>`));
172
+ if (renderRedirect) {
173
+ if (hasInvalidProtocol(renderRedirect.location)) return;
174
+ controller.enqueue(new TextEncoder().encode(`<meta http-equiv="refresh" content="0;url=${escapeHtml(renderRedirect.location)}"/>`));
175
+ }
170
176
  } });
171
177
  if (!hydrate) return new Response(html.pipeThrough(redirectTransform), {
172
178
  status,
@@ -182,10 +188,13 @@ async function routeRSCServerRequest({ request, serverResponse, createFromReadab
182
188
  });
183
189
  } catch (error) {
184
190
  if (error instanceof Response) return error;
185
- if (renderRedirect) return new Response(`Redirect: ${renderRedirect.location}`, {
186
- status: renderRedirect.status,
187
- headers: { Location: renderRedirect.location }
188
- });
191
+ if (renderRedirect) {
192
+ if (hasInvalidProtocol(renderRedirect.location)) throw new Error("Invalid redirect location");
193
+ return new Response(`Redirect: ${renderRedirect.location}`, {
194
+ status: renderRedirect.status,
195
+ headers: { Location: renderRedirect.location }
196
+ });
197
+ }
189
198
  try {
190
199
  let normalizedError = renderError ?? error;
191
200
  let [status, statusText] = isRouteErrorResponse(normalizedError) ? [normalizedError.status, normalizedError.statusText] : [500, ""];
@@ -230,6 +239,7 @@ async function routeRSCServerRequest({ request, serverResponse, createFromReadab
230
239
  for (const [key, value] of serverResponse.headers) headers.append(key, value);
231
240
  headers.set("Content-Type", "text/html; charset=utf-8");
232
241
  if (retryRedirect) {
242
+ if (hasInvalidProtocol(retryRedirect.location)) throw new Error("Invalid redirect location");
233
243
  headers.set("Location", retryRedirect.location);
234
244
  return new Response(html, {
235
245
  status: retryRedirect.status,
@@ -237,7 +247,10 @@ async function routeRSCServerRequest({ request, serverResponse, createFromReadab
237
247
  });
238
248
  }
239
249
  const retryRedirectTransform = new TransformStream({ flush(controller) {
240
- if (retryRedirect) controller.enqueue(new TextEncoder().encode(`<meta http-equiv="refresh" content="0;url=${escapeHtml(retryRedirect.location)}"/>`));
250
+ if (retryRedirect) {
251
+ if (hasInvalidProtocol(retryRedirect.location)) return;
252
+ controller.enqueue(new TextEncoder().encode(`<meta http-equiv="refresh" content="0;url=${escapeHtml(retryRedirect.location)}"/>`));
253
+ }
241
254
  } });
242
255
  if (!hydrate) return new Response(html.pipeThrough(retryRedirectTransform), {
243
256
  status,
@@ -295,10 +308,13 @@ async function routeRSCServerRequest({ request, serverResponse, createFromReadab
295
308
  function RSCStaticRouter({ getPayload }) {
296
309
  const decoded = getPayload();
297
310
  const payload = React$1.use(decoded);
298
- if (payload.type === "redirect") throw new Response(null, {
299
- status: payload.status,
300
- headers: { Location: payload.location }
301
- });
311
+ if (payload.type === "redirect") {
312
+ if (hasInvalidProtocol(payload.location)) throw new Error("Invalid redirect location");
313
+ throw new Response(null, {
314
+ status: payload.status,
315
+ headers: { Location: payload.location }
316
+ });
317
+ }
302
318
  if (payload.type !== "render") return null;
303
319
  let patchedLoaderData = { ...payload.loaderData };
304
320
  for (const match of payload.matches) if (shouldHydrateRouteLoader(match.id, match.clientLoader, match.hasLoader, false) && (match.hydrateFallbackElement || !match.hasLoader)) delete patchedLoaderData[match.id];
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0-pre.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0-pre.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0-pre.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0-pre.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0-pre.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0-pre.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -8,7 +8,6 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import { isRouteErrorResponse } from "../router/utils.js";
12
11
  import "./mode.js";
13
12
  //#region lib/server-runtime/errors.ts
14
13
  /**
@@ -72,24 +71,5 @@ function serializeError(error, serverMode) {
72
71
  stack: sanitized.stack
73
72
  };
74
73
  }
75
- function serializeErrors(errors, serverMode) {
76
- if (!errors) return null;
77
- let entries = Object.entries(errors);
78
- let serialized = {};
79
- for (let [key, val] of entries) if (isRouteErrorResponse(val)) serialized[key] = {
80
- ...val,
81
- __type: "RouteErrorResponse"
82
- };
83
- else if (val instanceof Error) {
84
- let sanitized = sanitizeError(val, serverMode);
85
- serialized[key] = {
86
- message: sanitized.message,
87
- stack: sanitized.stack,
88
- __type: "Error",
89
- ...sanitized.name !== "Error" ? { __subType: sanitized.name } : {}
90
- };
91
- } else serialized[key] = val;
92
- return serialized;
93
- }
94
74
  //#endregion
95
- export { sanitizeError, sanitizeErrors, serializeError, serializeErrors };
75
+ export { sanitizeError, sanitizeErrors, serializeError };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0-pre.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0-pre.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0-pre.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0-pre.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0-pre.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0-pre.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -8,13 +8,13 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import { ErrorResponseImpl, RouterContextProvider, defaultMapRouteProperties, isRouteErrorResponse, stripBasename } from "../router/utils.js";
11
+ import { ErrorResponseImpl, RouterContextProvider, defaultMapRouteProperties, isRouteErrorResponse, removeTrailingSlash, stripBasename } from "../router/utils.js";
12
12
  import { instrumentHandler } from "../router/instrumentation.js";
13
13
  import { createStaticHandler, getStaticContextFromError, isMutationMethod, isRedirectResponse, isResponse } from "../router/router.js";
14
14
  import { getManifestPath } from "../dom/ssr/fog-of-war.js";
15
15
  import { createEntryRouteModules } from "./entry.js";
16
16
  import { isServerMode } from "./mode.js";
17
- import { sanitizeErrors, serializeError, serializeErrors } from "./errors.js";
17
+ import { sanitizeErrors, serializeError } from "./errors.js";
18
18
  import { matchServerRoutes } from "./routeMatching.js";
19
19
  import { getBuildTimeHeader, getDevServerHooks } from "./dev.js";
20
20
  import { createStaticHandlerDataRoutes } from "./routes.js";
@@ -54,7 +54,7 @@ function derive(build, mode) {
54
54
  }
55
55
  loadContext = initialContext || new RouterContextProvider();
56
56
  let requestUrl = new URL(request.url);
57
- let normalizedPathname = getNormalizedPath(request, build.basename).pathname;
57
+ let normalizedPathname = getNormalizedPath(request).pathname;
58
58
  let isSpaMode = getBuildTimeHeader(request, "X-React-Router-SPA-Mode") === "yes";
59
59
  if (!build.ssr) {
60
60
  let decodedPath = decodeURI(normalizedPathname);
@@ -74,7 +74,7 @@ function derive(build, mode) {
74
74
  decodedPath = strippedPath;
75
75
  }
76
76
  if (build.prerender.length === 0) isSpaMode = true;
77
- else if (!build.prerender.includes(decodedPath) && !build.prerender.includes(decodedPath + "/")) if (requestUrl.pathname.endsWith(".data")) {
77
+ else if (!build.prerender.some((p) => removeTrailingSlash(p) === removeTrailingSlash(decodedPath))) if (requestUrl.pathname.endsWith(".data")) {
78
78
  errorHandler(new ErrorResponseImpl(404, "Not Found", `Refusing to SSR the path \`${decodedPath}\` because \`ssr:false\` is set and the path is not included in the \`prerender\` config, so in production the path will be a 404.`), {
79
79
  context: loadContext,
80
80
  params,
@@ -155,26 +155,20 @@ const createRequestHandler = (build, mode) => {
155
155
  };
156
156
  };
157
157
  async function handleManifestRequest(build, dataRoutes, branches, url) {
158
- if (build.assets.version !== url.searchParams.get("version")) return new Response(null, {
159
- status: 204,
160
- headers: { "X-Remix-Reload-Document": "true" }
161
- });
162
158
  if (url.toString().length > 7680) return new Response(null, {
163
159
  statusText: "Bad Request",
164
160
  status: 400
165
161
  });
162
+ if (build.assets.version !== url.searchParams.get("version")) return new Response(null, {
163
+ status: 204,
164
+ headers: { "X-Remix-Reload-Document": "true" }
165
+ });
166
166
  let patches = {};
167
167
  if (url.searchParams.has("paths")) {
168
- let paths = /* @__PURE__ */ new Set();
169
- (url.searchParams.get("paths") || "").split(",").filter(Boolean).forEach((path) => {
170
- if (!path.startsWith("/")) path = `/${path}`;
171
- let segments = path.split("/").slice(1);
172
- segments.forEach((_, i) => {
173
- let partialPath = segments.slice(0, i + 1).join("/");
174
- paths.add(`/${partialPath}`);
175
- });
176
- });
168
+ let pathParam = url.searchParams.get("paths") || "";
169
+ let paths = new Set(pathParam.split(",").filter(Boolean));
177
170
  for (let path of paths) {
171
+ if (!path.startsWith("/")) path = `/${path}`;
178
172
  let matches = matchServerRoutes(build.routes, dataRoutes, branches, path, build.basename);
179
173
  if (matches) for (let match of matches) {
180
174
  let routeId = match.route.id;
@@ -192,7 +186,7 @@ async function handleSingleFetchRequest(serverMode, build, staticHandler, reques
192
186
  async function handleDocumentRequest(serverMode, build, staticHandler, request, loadContext, handleError, isSpaMode, criticalCss) {
193
187
  try {
194
188
  if (isMutationMethod(request.method)) try {
195
- throwIfPotentialCSRFAttack(request.headers, Array.isArray(build.allowedActionOrigins) ? build.allowedActionOrigins : []);
189
+ throwIfPotentialCSRFAttack(request, Array.isArray(build.allowedActionOrigins) ? build.allowedActionOrigins : []);
196
190
  } catch (e) {
197
191
  handleError(e);
198
192
  return new Response("Bad Request", { status: 400 });
@@ -209,7 +203,7 @@ async function handleDocumentRequest(serverMode, build, staticHandler, request,
209
203
  return new Response(null, { status: 500 });
210
204
  }
211
205
  },
212
- normalizePath: (r) => getNormalizedPath(r, build.basename)
206
+ normalizePath: (r) => getNormalizedPath(r)
213
207
  });
214
208
  if (!isResponse(result)) result = await renderHtml(result, isSpaMode);
215
209
  return result;
@@ -232,7 +226,7 @@ async function handleDocumentRequest(serverMode, build, staticHandler, request,
232
226
  let state = {
233
227
  loaderData: context.loaderData,
234
228
  actionData: context.actionData,
235
- errors: serializeErrors(context.errors, serverMode)
229
+ errors: context.errors
236
230
  };
237
231
  let baseServerHandoff = {
238
232
  basename: build.basename,
@@ -274,7 +268,7 @@ async function handleDocumentRequest(serverMode, build, staticHandler, request,
274
268
  let state = {
275
269
  loaderData: context.loaderData,
276
270
  actionData: context.actionData,
277
- errors: serializeErrors(context.errors, serverMode)
271
+ errors: context.errors
278
272
  };
279
273
  entryContext = {
280
274
  ...entryContext,
@@ -304,7 +298,7 @@ async function handleResourceRequest(serverMode, build, staticHandler, routeId,
304
298
  return handleQueryRouteError(error);
305
299
  }
306
300
  },
307
- normalizePath: (r) => getNormalizedPath(r, build.basename)
301
+ normalizePath: (r) => getNormalizedPath(r)
308
302
  }));
309
303
  } catch (error) {
310
304
  return handleQueryRouteError(error);
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router v8.0.0-pre.0
2
+ * react-router v8.0.0-pre.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *