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.
- package/CHANGELOG.md +21 -0
- package/dist/development/dom-export.js +1 -1
- package/dist/development/index-react-server-client.js +1 -1
- package/dist/development/index-react-server.d.ts +9 -2
- package/dist/development/index-react-server.js +91 -88
- package/dist/development/index.d.ts +1 -2
- package/dist/development/index.js +2 -3
- package/dist/development/lib/actions.js +6 -18
- package/dist/development/lib/components.d.ts +11 -3
- package/dist/development/lib/components.js +8 -2
- package/dist/development/lib/context.js +1 -1
- package/dist/development/lib/dom/dom.js +1 -1
- package/dist/development/lib/dom/lib.d.ts +12 -1
- package/dist/development/lib/dom/lib.js +18 -6
- package/dist/development/lib/dom/server.js +2 -2
- package/dist/development/lib/dom/ssr/components.d.ts +4 -2
- package/dist/development/lib/dom/ssr/components.js +13 -3
- package/dist/development/lib/dom/ssr/data.js +1 -1
- package/dist/development/lib/dom/ssr/entry.d.ts +1 -0
- package/dist/development/lib/dom/ssr/errorBoundaries.js +7 -3
- package/dist/development/lib/dom/ssr/fallback.js +8 -3
- package/dist/development/lib/dom/ssr/fog-of-war.js +12 -2
- package/dist/development/lib/dom/ssr/hydration.js +1 -1
- package/dist/development/lib/dom/ssr/invariant.js +1 -1
- package/dist/development/lib/dom/ssr/links.js +1 -1
- package/dist/development/lib/dom/ssr/markup.js +1 -1
- package/dist/development/lib/dom/ssr/routeModules.js +1 -1
- package/dist/development/lib/dom/ssr/routes-test-stub.js +1 -1
- package/dist/development/lib/dom/ssr/routes.js +1 -1
- package/dist/development/lib/dom/ssr/server.d.ts +4 -1
- package/dist/development/lib/dom/ssr/server.js +2 -1
- package/dist/development/lib/dom/ssr/single-fetch.js +2 -3
- package/dist/development/lib/dom-export/dom-router-provider.js +1 -1
- package/dist/development/lib/dom-export/hydrated-router.d.ts +1 -1
- package/dist/development/lib/dom-export/hydrated-router.js +14 -17
- package/dist/development/lib/errors.js +1 -1
- package/dist/development/lib/hooks.js +6 -4
- package/dist/development/lib/href.js +1 -1
- package/dist/development/lib/router/history.js +3 -2
- package/dist/development/lib/router/instrumentation.js +1 -1
- package/dist/development/lib/router/links.d.ts +3 -2
- package/dist/development/lib/router/router.js +13 -6
- package/dist/development/lib/router/url.js +18 -0
- package/dist/development/lib/router/utils.d.ts +6 -0
- package/dist/development/lib/router/utils.js +27 -8
- package/dist/development/lib/rsc/browser.js +21 -17
- package/dist/development/lib/rsc/errorBoundaries.js +1 -1
- package/dist/development/lib/rsc/html-stream/browser.js +1 -1
- package/dist/development/lib/rsc/html-stream/server.js +1 -1
- package/dist/development/lib/rsc/route-modules.js +1 -1
- package/dist/development/lib/rsc/server.ssr.js +27 -11
- package/dist/development/lib/server-runtime/cookies.js +1 -1
- package/dist/development/lib/server-runtime/crypto.js +1 -1
- package/dist/development/lib/server-runtime/data.js +1 -1
- package/dist/development/lib/server-runtime/dev.js +1 -1
- package/dist/development/lib/server-runtime/entry.js +1 -1
- package/dist/development/lib/server-runtime/errors.js +2 -22
- package/dist/development/lib/server-runtime/headers.js +1 -1
- package/dist/development/lib/server-runtime/invariant.js +1 -1
- package/dist/development/lib/server-runtime/mode.js +1 -1
- package/dist/development/lib/server-runtime/routeMatching.js +1 -1
- package/dist/development/lib/server-runtime/routes.js +1 -1
- package/dist/development/lib/server-runtime/server.js +17 -23
- package/dist/development/lib/server-runtime/serverHandoff.js +1 -1
- package/dist/development/lib/server-runtime/sessions/cookieStorage.js +1 -1
- package/dist/development/lib/server-runtime/sessions/memoryStorage.js +1 -1
- package/dist/development/lib/server-runtime/sessions.js +1 -1
- package/dist/development/lib/server-runtime/single-fetch.js +4 -4
- package/dist/development/lib/server-runtime/urls.js +2 -5
- package/dist/development/lib/server-runtime/warnings.js +1 -1
- package/dist/development/lib/types/internal.js +1 -1
- package/dist/development/vendor/turbo-stream-v2/flatten.js +1 -1
- package/dist/development/vendor/turbo-stream-v2/turbo-stream.js +2 -1
- package/dist/development/vendor/turbo-stream-v2/unflatten.js +3 -2
- package/dist/development/vendor/turbo-stream-v2/utils.js +2 -10
- package/dist/production/dom-export.js +1 -1
- package/dist/production/index-react-server-client.js +1 -1
- package/dist/production/index-react-server.d.ts +9 -2
- package/dist/production/index-react-server.js +91 -88
- package/dist/production/index.d.ts +1 -2
- package/dist/production/index.js +2 -3
- package/dist/production/lib/actions.js +6 -18
- package/dist/production/lib/components.d.ts +11 -3
- package/dist/production/lib/components.js +8 -2
- package/dist/production/lib/context.js +1 -1
- package/dist/production/lib/dom/dom.js +1 -1
- package/dist/production/lib/dom/lib.d.ts +12 -1
- package/dist/production/lib/dom/lib.js +18 -6
- package/dist/production/lib/dom/server.js +2 -2
- package/dist/production/lib/dom/ssr/components.d.ts +4 -2
- package/dist/production/lib/dom/ssr/components.js +13 -3
- package/dist/production/lib/dom/ssr/data.js +1 -1
- package/dist/production/lib/dom/ssr/entry.d.ts +1 -0
- package/dist/production/lib/dom/ssr/errorBoundaries.js +7 -3
- package/dist/production/lib/dom/ssr/fallback.js +3 -1
- package/dist/production/lib/dom/ssr/fog-of-war.js +12 -2
- package/dist/production/lib/dom/ssr/hydration.js +1 -1
- package/dist/production/lib/dom/ssr/invariant.js +1 -1
- package/dist/production/lib/dom/ssr/links.js +1 -1
- package/dist/production/lib/dom/ssr/markup.js +1 -1
- package/dist/production/lib/dom/ssr/routeModules.js +1 -1
- package/dist/production/lib/dom/ssr/routes-test-stub.js +1 -1
- package/dist/production/lib/dom/ssr/routes.js +1 -1
- package/dist/production/lib/dom/ssr/server.d.ts +4 -1
- package/dist/production/lib/dom/ssr/server.js +2 -1
- package/dist/production/lib/dom/ssr/single-fetch.js +2 -3
- package/dist/production/lib/dom-export/dom-router-provider.js +1 -1
- package/dist/production/lib/dom-export/hydrated-router.d.ts +1 -1
- package/dist/production/lib/dom-export/hydrated-router.js +14 -17
- package/dist/production/lib/errors.js +1 -1
- package/dist/production/lib/hooks.js +6 -4
- package/dist/production/lib/href.js +1 -1
- package/dist/production/lib/router/history.js +3 -2
- package/dist/production/lib/router/instrumentation.js +1 -1
- package/dist/production/lib/router/links.d.ts +3 -2
- package/dist/production/lib/router/router.js +13 -6
- package/dist/production/lib/router/url.js +18 -0
- package/dist/production/lib/router/utils.d.ts +6 -0
- package/dist/production/lib/router/utils.js +27 -8
- package/dist/production/lib/rsc/browser.js +21 -17
- package/dist/production/lib/rsc/errorBoundaries.js +1 -1
- package/dist/production/lib/rsc/html-stream/browser.js +1 -1
- package/dist/production/lib/rsc/html-stream/server.js +1 -1
- package/dist/production/lib/rsc/route-modules.js +1 -1
- package/dist/production/lib/rsc/server.ssr.js +27 -11
- package/dist/production/lib/server-runtime/cookies.js +1 -1
- package/dist/production/lib/server-runtime/crypto.js +1 -1
- package/dist/production/lib/server-runtime/data.js +1 -1
- package/dist/production/lib/server-runtime/dev.js +1 -1
- package/dist/production/lib/server-runtime/entry.js +1 -1
- package/dist/production/lib/server-runtime/errors.js +2 -22
- package/dist/production/lib/server-runtime/headers.js +1 -1
- package/dist/production/lib/server-runtime/invariant.js +1 -1
- package/dist/production/lib/server-runtime/mode.js +1 -1
- package/dist/production/lib/server-runtime/routeMatching.js +1 -1
- package/dist/production/lib/server-runtime/routes.js +1 -1
- package/dist/production/lib/server-runtime/server.js +17 -23
- package/dist/production/lib/server-runtime/serverHandoff.js +1 -1
- package/dist/production/lib/server-runtime/sessions/cookieStorage.js +1 -1
- package/dist/production/lib/server-runtime/sessions/memoryStorage.js +1 -1
- package/dist/production/lib/server-runtime/sessions.js +1 -1
- package/dist/production/lib/server-runtime/single-fetch.js +4 -4
- package/dist/production/lib/server-runtime/urls.js +2 -5
- package/dist/production/lib/server-runtime/warnings.js +1 -1
- package/dist/production/lib/types/internal.js +1 -1
- package/dist/production/vendor/turbo-stream-v2/flatten.js +1 -1
- package/dist/production/vendor/turbo-stream-v2/turbo-stream.js +2 -1
- package/dist/production/vendor/turbo-stream-v2/unflatten.js +3 -2
- package/dist/production/vendor/turbo-stream-v2/utils.js +2 -10
- package/docs/explanation/code-splitting.md +1 -1
- package/docs/explanation/index-query-param.md +2 -2
- package/docs/explanation/type-safety.md +1 -1
- package/docs/how-to/data-strategy.md +5 -5
- package/docs/how-to/error-reporting.md +10 -2
- package/docs/how-to/headers.md +2 -1
- package/docs/how-to/security.md +9 -7
- package/docs/start/data/installation.md +4 -0
- package/docs/start/data/route-object.md +20 -0
- package/docs/start/framework/actions.md +0 -1
- package/docs/start/framework/data-loading.md +1 -1
- package/docs/start/framework/deploying.md +4 -0
- package/docs/start/framework/installation.md +0 -1
- package/docs/upgrading/v6.md +3 -0
- package/package.json +2 -2
- package/dist/development/lib/dom/ssr/errors.d.ts +0 -7
- package/dist/development/lib/dom/ssr/errors.js +0 -36
- package/dist/production/lib/dom/ssr/errors.d.ts +0 -7
- package/dist/production/lib/dom/ssr/errors.js +0 -36
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* react-router v8.0.0-pre.
|
|
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 =
|
|
2579
|
-
if (
|
|
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
|
-
|
|
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,
|
|
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.
|
|
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
|
|
342
|
+
let pattern = {
|
|
335
343
|
path: meta.relativePath,
|
|
336
344
|
caseSensitive: meta.caseSensitive,
|
|
337
345
|
end
|
|
338
|
-
}
|
|
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(
|
|
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 =
|
|
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.
|
|
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,
|
|
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
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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(
|
|
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
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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(
|
|
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
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
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.
|
|
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)
|
|
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)
|
|
186
|
-
|
|
187
|
-
|
|
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)
|
|
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")
|
|
299
|
-
|
|
300
|
-
|
|
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.
|
|
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
|
|
75
|
+
export { sanitizeError, sanitizeErrors, serializeError };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* react-router v8.0.0-pre.
|
|
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
|
|
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
|
|
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.
|
|
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
|
|
169
|
-
|
|
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
|
|
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
|
|
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:
|
|
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:
|
|
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
|
|
301
|
+
normalizePath: (r) => getNormalizedPath(r)
|
|
308
302
|
}));
|
|
309
303
|
} catch (error) {
|
|
310
304
|
return handleQueryRouteError(error);
|