vinext 1.2.0 → 1.2.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/README.md +1 -1
- package/dist/build/output-root-externals.d.ts +21 -0
- package/dist/build/output-root-externals.js +40 -0
- package/dist/build/prerender-paths.js +1 -1
- package/dist/build/prerender.js +1 -1
- package/dist/check.js +5 -6
- package/dist/cli-dev-config.js +3 -3
- package/dist/cli.js +1 -1
- package/dist/config/config-matchers.js +12 -7
- package/dist/index.js +113 -94
- package/dist/init.d.ts +1 -1
- package/dist/init.js +86 -6
- package/dist/plugins/ast-utils.d.ts +53 -2
- package/dist/plugins/ast-utils.js +90 -2
- package/dist/plugins/cloudflare-dev-module-urls.d.ts +41 -0
- package/dist/plugins/cloudflare-dev-module-urls.js +271 -0
- package/dist/plugins/commonjs-esm-facade.js +2 -2
- package/dist/plugins/css-module-imports.js +13 -20
- package/dist/plugins/dynamic-preload-metadata.js +2 -3
- package/dist/plugins/extensionless-dynamic-import.js +2 -3
- package/dist/plugins/fonts.d.ts +1 -1
- package/dist/plugins/fonts.js +3 -3
- package/dist/plugins/ignore-dynamic-requests.js +2 -3
- package/dist/plugins/import-meta-url.js +3 -4
- package/dist/plugins/instrumentation-client.js +3 -2
- package/dist/plugins/middleware-export-validation.js +2 -3
- package/dist/plugins/og-harfbuzz.js +2 -3
- package/dist/plugins/optimize-imports.js +3 -4
- package/dist/plugins/pages-node-externals.js +2 -3
- package/dist/plugins/remove-console.js +2 -18
- package/dist/plugins/require-condition-resolution.js +3 -3
- package/dist/plugins/require-context.js +2 -3
- package/dist/plugins/strip-server-exports.js +3 -4
- package/dist/plugins/styled-jsx.js +2 -3
- package/dist/plugins/use-cache-callable.d.ts +21 -2
- package/dist/plugins/use-cache-callable.js +76 -33
- package/dist/plugins/worker-image-imports.js +30 -33
- package/dist/plugins/worker-use-server.js +38 -14
- package/dist/server/api-handler.js +1 -1
- package/dist/server/app-action-forwarding.js +2 -2
- package/dist/server/app-browser-entry.js +3 -3
- package/dist/server/app-browser-interception-context.js +1 -1
- package/dist/server/app-browser-prefetch-response.js +2 -2
- package/dist/server/app-browser-state.js +1 -1
- package/dist/server/app-browser-supplemental-refresh.js +1 -1
- package/dist/server/app-optimistic-routing.js +1 -1
- package/dist/server/app-page-dispatch.js +1 -1
- package/dist/server/app-page-render.js +1 -1
- package/dist/server/app-pages-bridge.js +1 -1
- package/dist/server/app-prerender-endpoints.js +1 -1
- package/dist/server/app-render-abort-error.d.ts +19 -0
- package/dist/server/app-render-abort-error.js +31 -1
- package/dist/server/app-request-stage-independent-entry.js +5 -5
- package/dist/server/app-response-stage-entry.js +2 -2
- package/dist/server/app-route-handler-runtime.js +1 -1
- package/dist/server/app-router-entry.js +5 -5
- package/dist/server/app-rsc-cache-busting.d.ts +16 -0
- package/dist/server/app-rsc-cache-busting.js +29 -12
- package/dist/server/app-rsc-handler.js +5 -5
- package/dist/server/app-rsc-request-normalization.js +3 -3
- package/dist/server/app-rsc-response-stage.js +2 -2
- package/dist/server/app-server-action-execution.js +1 -1
- package/dist/server/app-ssr-entry.js +5 -4
- package/dist/server/app-visited-response-cache.js +2 -2
- package/dist/server/config-headers.js +1 -1
- package/dist/server/defer-until-stream-consumed.d.ts +2 -1
- package/dist/server/defer-until-stream-consumed.js +3 -1
- package/dist/server/dev-server.js +1 -1
- package/dist/server/image-optimization.js +1 -0
- package/dist/server/metadata-route-response.js +2 -2
- package/dist/server/middleware-path-to-regexp.js +1 -1
- package/dist/server/middleware-runtime.js +5 -5
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/open-redirect.d.ts +11 -4
- package/dist/server/open-redirect.js +11 -4
- package/dist/server/pages-api-route.js +2 -2
- package/dist/server/pages-data-route.js +2 -1
- package/dist/server/pages-page-data.js +1 -1
- package/dist/server/pages-page-handler.js +1 -1
- package/dist/server/pages-page-response.js +1 -1
- package/dist/server/pages-request-pipeline.js +5 -5
- package/dist/server/pages-request-stage-entry.js +4 -4
- package/dist/server/pages-revalidate.js +2 -2
- package/dist/server/pages-router-entry.js +1 -1
- package/dist/server/prod-server.js +5 -5
- package/dist/server/rsc-stream-hints.d.ts +1 -1
- package/dist/server/rsc-stream-hints.js +21 -3
- package/dist/server/worker-image-optimization.js +19 -6
- package/dist/shims/head.js +1 -1
- package/dist/shims/headers.js +2 -2
- package/dist/shims/internal/hybrid-client-route-owner-direct.js +1 -1
- package/dist/shims/internal/hybrid-client-route-owner.js +1 -0
- package/dist/shims/link-prefetch.js +5 -4
- package/dist/shims/link.js +2 -2
- package/dist/shims/navigation.js +4 -5
- package/dist/shims/router.js +9 -12
- package/dist/shims/server.d.ts +11 -4
- package/dist/shims/server.js +41 -5
- package/dist/shims/url-utils.d.ts +7 -0
- package/dist/shims/url-utils.js +12 -3
- package/dist/utils/domain-locale.js +1 -1
- package/dist/utils/plugin-rsc-version.d.ts +2 -0
- package/dist/utils/plugin-rsc-version.js +28 -2
- package/dist/utils/react-version.d.ts +7 -0
- package/dist/utils/react-version.js +39 -16
- package/package.json +6 -6
- package/dist/build/nitro-route-rules.d.ts +0 -47
- package/dist/build/nitro-route-rules.js +0 -79
- package/dist/plugins/cache-flight-codec.d.ts +0 -19
- package/dist/plugins/cache-flight-codec.js +0 -68
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { matchHeaders } from "../config/config-matchers.js";
|
|
2
1
|
import "./headers.js";
|
|
2
|
+
import { matchHeaders } from "../config/config-matchers.js";
|
|
3
3
|
import { markRouteCacheabilityConfigCdnCachePolicy, markRouteCacheabilityDynamic, markRouteCacheabilityFinalResponseUncacheable } from "../shims/cacheability-classification.js";
|
|
4
4
|
import { isCdnResponsePolicyHeader, isNonCacheableCdnResponsePolicy } from "./cache-control.js";
|
|
5
5
|
import { mergeVaryHeader } from "./middleware-response-headers.js";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
//#region src/server/defer-until-stream-consumed.d.ts
|
|
2
2
|
/**
|
|
3
3
|
* Defers cleanup until the downstream consumer drains or cancels the stream.
|
|
4
|
+
* `onCancel` runs before the cancellation reaches the source stream.
|
|
4
5
|
*/
|
|
5
|
-
export declare function deferUntilStreamConsumed(stream: ReadableStream<Uint8Array>, onFlush: () => void, onError?: (error: unknown) => void): ReadableStream<Uint8Array>;
|
|
6
|
+
export declare function deferUntilStreamConsumed(stream: ReadableStream<Uint8Array>, onFlush: () => void, onError?: (error: unknown) => void, onCancel?: (reason: unknown) => void): ReadableStream<Uint8Array>;
|
|
6
7
|
//#endregion
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
//#region src/server/defer-until-stream-consumed.ts
|
|
2
2
|
/**
|
|
3
3
|
* Defers cleanup until the downstream consumer drains or cancels the stream.
|
|
4
|
+
* `onCancel` runs before the cancellation reaches the source stream.
|
|
4
5
|
*/
|
|
5
|
-
function deferUntilStreamConsumed(stream, onFlush, onError) {
|
|
6
|
+
function deferUntilStreamConsumed(stream, onFlush, onError, onCancel) {
|
|
6
7
|
let called = false;
|
|
7
8
|
const once = () => {
|
|
8
9
|
if (!called) {
|
|
@@ -26,6 +27,7 @@ function deferUntilStreamConsumed(stream, onFlush, onError) {
|
|
|
26
27
|
});
|
|
27
28
|
},
|
|
28
29
|
cancel(reason) {
|
|
30
|
+
onCancel?.(reason);
|
|
29
31
|
once();
|
|
30
32
|
return reader.cancel(reason);
|
|
31
33
|
}
|
|
@@ -2,10 +2,10 @@ import { closeAfterResponse, createRequestContext, runWithRequestContext } from
|
|
|
2
2
|
import { createValidFileMatcher, findFileWithExts } from "../routing/file-matcher.js";
|
|
3
3
|
import { isBotUserAgent } from "../utils/html-limited-bots.js";
|
|
4
4
|
import { PRERENDER_REVALIDATE_HEADER } from "../utils/protocol-headers.js";
|
|
5
|
+
import { NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER } from "./headers.js";
|
|
5
6
|
import { sanitizeDestination } from "../config/config-matchers.js";
|
|
6
7
|
import { patternToNextFormat } from "../routing/route-validation.js";
|
|
7
8
|
import { matchRoute } from "../routing/pages-router.js";
|
|
8
|
-
import { NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER } from "./headers.js";
|
|
9
9
|
import { isDangerousScheme } from "../shims/url-safety.js";
|
|
10
10
|
import { extractLocaleFromUrl as extractLocaleFromUrl$1, resolvePagesI18nRequest } from "./pages-i18n.js";
|
|
11
11
|
import { importModule, reportRequestError } from "./instrumentation.js";
|
|
@@ -202,6 +202,7 @@ function parseImageParams(url, allowedWidths = [...DEFAULT_DEVICE_SIZES, ...DEFA
|
|
|
202
202
|
const base = "https://localhost";
|
|
203
203
|
const resolved = new URL(normalizedUrl, base);
|
|
204
204
|
if (resolved.origin !== base) return null;
|
|
205
|
+
if (resolved.pathname.startsWith("//")) return null;
|
|
205
206
|
if (RECURSIVE_IMAGE_URL_RE.test(decodeURIComponent(resolved.pathname))) return null;
|
|
206
207
|
} catch {
|
|
207
208
|
return null;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { markFullyBufferedBody } from "./fully-buffered-response.js";
|
|
2
2
|
import { closeAfterResponse, createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
|
|
3
|
+
import { VINEXT_METADATA_ROUTE_CACHE_HEADER } from "./headers.js";
|
|
4
|
+
import { notFoundResponse } from "./http-error-responses.js";
|
|
3
5
|
import { decodeMatchedParams } from "../routing/utils.js";
|
|
4
6
|
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
5
|
-
import { VINEXT_METADATA_ROUTE_CACHE_HEADER } from "./headers.js";
|
|
6
7
|
import { runInWorkStoreScope } from "../shims/internal/work-store-scope.js";
|
|
7
|
-
import { notFoundResponse } from "./http-error-responses.js";
|
|
8
8
|
import { beginRouteCacheability, markRouteCacheabilityExplicitResponsePolicy, markRouteCacheabilityResponseBodyComplete, recordRouteCacheability } from "../shims/cacheability-classification.js";
|
|
9
9
|
import { NEVER_CACHE_CONTROL, applyCdnResponseHeaders, hasCdnResponsePolicy } from "./cache-control.js";
|
|
10
10
|
import { buildAppRouteMissIsrCacheControl } from "./isr-decision.js";
|
|
@@ -224,7 +224,7 @@ function middlewarePathTokensToRegExp(tokens) {
|
|
|
224
224
|
} else route += `(?:${prefix}${suffix})${token.modifier}`;
|
|
225
225
|
}
|
|
226
226
|
route += `${delimiterRegex}?$`;
|
|
227
|
-
return new RegExp(route
|
|
227
|
+
return new RegExp(route);
|
|
228
228
|
}
|
|
229
229
|
//#endregion
|
|
230
230
|
export { middlewarePathTokensToRegExp, normalizeMiddlewarePathTokens, parseMiddlewarePath };
|
|
@@ -2,18 +2,18 @@ import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
|
2
2
|
import "../utils/protocol-headers.js";
|
|
3
3
|
import { shouldKeepMiddlewareHeader } from "../utils/middleware-request-headers.js";
|
|
4
4
|
import { normalizeHost } from "../config/request-context.js";
|
|
5
|
-
import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
|
|
6
5
|
import { addBasePathToPathname, hasBasePath, removeTrailingSlash, stripBasePath } from "../utils/base-path.js";
|
|
6
|
+
import { MIDDLEWARE_REWRITE_HEADER } from "./headers.js";
|
|
7
|
+
import { badRequestResponse, internalServerErrorResponse } from "./http-error-responses.js";
|
|
8
|
+
import { isOpenRedirectShaped } from "./open-redirect.js";
|
|
9
|
+
import { processMiddlewareHeaders } from "./request-pipeline.js";
|
|
10
|
+
import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
|
|
7
11
|
import { getRequestExecutionContext, runWithExecutionContext } from "../shims/request-context.js";
|
|
8
12
|
import "./server-globals.js";
|
|
9
|
-
import { MIDDLEWARE_REWRITE_HEADER } from "./headers.js";
|
|
10
13
|
import { NextFetchEvent, NextRequest } from "../shims/server.js";
|
|
11
14
|
import { runInWorkStoreScope } from "../shims/internal/work-store-scope.js";
|
|
12
15
|
import { normalizePath } from "./normalize-path.js";
|
|
13
16
|
import { matchesMiddleware, matchesMiddlewarePathname } from "./middleware-matcher.js";
|
|
14
|
-
import { badRequestResponse, internalServerErrorResponse } from "./http-error-responses.js";
|
|
15
|
-
import { isOpenRedirectShaped } from "./open-redirect.js";
|
|
16
|
-
import { processMiddlewareHeaders } from "./request-pipeline.js";
|
|
17
17
|
import { normalizeDefaultLocalePathname } from "./pages-i18n.js";
|
|
18
18
|
import { nextDataMiddlewareMatchPathname } from "./pages-data-route.js";
|
|
19
19
|
import { reportRequestError } from "./instrumentation.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { splitPathnameForRouteMatch } from "../routing/utils.js";
|
|
2
1
|
import { stripBasePath } from "../utils/base-path.js";
|
|
2
|
+
import { splitPathnameForRouteMatch } from "../routing/utils.js";
|
|
3
3
|
import { matchRoutePattern, matchRoutePatternPrefix, matchRoutePatternWithOptionalDynamicSegments } from "../routing/route-pattern.js";
|
|
4
4
|
import { AppElementsWire, compareAppElementsSlotIds } from "./app-elements-wire.js";
|
|
5
5
|
import "./app-elements.js";
|
|
@@ -11,7 +11,7 @@ export declare function isOpenRedirectShaped(rawPathname: string): boolean;
|
|
|
11
11
|
/**
|
|
12
12
|
* What a request entry answers for a raw path containing a backslash or a
|
|
13
13
|
* repeated slash: Next.js's 308, or a 404 when the collapsed path would still
|
|
14
|
-
* be open-redirect shaped.
|
|
14
|
+
* be open-redirect shaped or the raw target is not origin-form.
|
|
15
15
|
*/
|
|
16
16
|
export type RepeatedSlashRedirect = {
|
|
17
17
|
status: 308;
|
|
@@ -33,17 +33,24 @@ export type RepeatedSlashRedirect = {
|
|
|
33
33
|
* `//evil.com` → `/evil.com`. Percent-encoded `%2F`/`%5C` are not touched and
|
|
34
34
|
* keep falling through to `isOpenRedirectShaped` (404), as in Next.js.
|
|
35
35
|
*
|
|
36
|
-
* The Location is always same-origin.
|
|
37
|
-
* (`GET http://host//x`) are left alone. A collapsed path that still starts
|
|
36
|
+
* The Location is always same-origin. A collapsed path that still starts
|
|
38
37
|
* with an encoded slash or backslash (`//%2Fevil.com`, `/.//%2Fevil.com`) is
|
|
39
38
|
* never echoed into a Location or routed: it gets a 404 instead.
|
|
40
39
|
*
|
|
40
|
+
* A raw Node request target that is not origin-form (`GET http://evil.example/x`,
|
|
41
|
+
* which Node's parser accepts, or `OPTIONS *`) also gets a 404. Next.js never
|
|
42
|
+
* routes these either: it 308s absolute-form targets to their own URL (the
|
|
43
|
+
* `//` after the scheme trips the same check) and 500s `OPTIONS *`. Routing
|
|
44
|
+
* them would let the request line choose the origin of `request.url` that
|
|
45
|
+
* middleware and handlers see, bypassing the Host trust policy. Request-based
|
|
46
|
+
* entries always pass a pathname.
|
|
47
|
+
*
|
|
41
48
|
* @param rawUrl - The raw request target: pathname plus optional `?query`
|
|
42
49
|
*/
|
|
43
50
|
export declare function getRepeatedSlashRedirect(rawUrl: string): RepeatedSlashRedirect | null;
|
|
44
51
|
/**
|
|
45
52
|
* Build the Response for a raw request path containing a backslash or a
|
|
46
|
-
* repeated slash. See `getRepeatedSlashRedirect`.
|
|
53
|
+
* repeated slash, or a non-origin-form target. See `getRepeatedSlashRedirect`.
|
|
47
54
|
*/
|
|
48
55
|
export declare function repeatedSlashRedirectResponse(rawUrl: string): Response | null;
|
|
49
56
|
/**
|
|
@@ -34,15 +34,22 @@ const REDIRECT_LOCATION_BASE = "http://vinext.invalid";
|
|
|
34
34
|
* `//evil.com` → `/evil.com`. Percent-encoded `%2F`/`%5C` are not touched and
|
|
35
35
|
* keep falling through to `isOpenRedirectShaped` (404), as in Next.js.
|
|
36
36
|
*
|
|
37
|
-
* The Location is always same-origin.
|
|
38
|
-
* (`GET http://host//x`) are left alone. A collapsed path that still starts
|
|
37
|
+
* The Location is always same-origin. A collapsed path that still starts
|
|
39
38
|
* with an encoded slash or backslash (`//%2Fevil.com`, `/.//%2Fevil.com`) is
|
|
40
39
|
* never echoed into a Location or routed: it gets a 404 instead.
|
|
41
40
|
*
|
|
41
|
+
* A raw Node request target that is not origin-form (`GET http://evil.example/x`,
|
|
42
|
+
* which Node's parser accepts, or `OPTIONS *`) also gets a 404. Next.js never
|
|
43
|
+
* routes these either: it 308s absolute-form targets to their own URL (the
|
|
44
|
+
* `//` after the scheme trips the same check) and 500s `OPTIONS *`. Routing
|
|
45
|
+
* them would let the request line choose the origin of `request.url` that
|
|
46
|
+
* middleware and handlers see, bypassing the Host trust policy. Request-based
|
|
47
|
+
* entries always pass a pathname.
|
|
48
|
+
*
|
|
42
49
|
* @param rawUrl - The raw request target: pathname plus optional `?query`
|
|
43
50
|
*/
|
|
44
51
|
function getRepeatedSlashRedirect(rawUrl) {
|
|
45
|
-
if (!rawUrl.startsWith("/")) return
|
|
52
|
+
if (!rawUrl.startsWith("/")) return { status: 404 };
|
|
46
53
|
const urlParts = rawUrl.split("?");
|
|
47
54
|
const pathname = urlParts[0];
|
|
48
55
|
if (!REPEATED_SLASH_OR_BACKSLASH_RE.test(pathname)) return null;
|
|
@@ -62,7 +69,7 @@ function repeatedSlashRedirectHeaders(location) {
|
|
|
62
69
|
}
|
|
63
70
|
/**
|
|
64
71
|
* Build the Response for a raw request path containing a backslash or a
|
|
65
|
-
* repeated slash. See `getRepeatedSlashRedirect`.
|
|
72
|
+
* repeated slash, or a non-origin-form target. See `getRepeatedSlashRedirect`.
|
|
66
73
|
*/
|
|
67
74
|
function repeatedSlashRedirectResponse(rawUrl) {
|
|
68
75
|
const redirect = getRepeatedSlashRedirect(rawUrl);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { internalServerErrorResponse } from "./http-error-responses.js";
|
|
2
|
+
import { cloneRequestWithUrl } from "./request-pipeline.js";
|
|
1
3
|
import { getRequestExecutionContext, runWithExecutionContext } from "../shims/request-context.js";
|
|
2
4
|
import "./server-globals.js";
|
|
3
5
|
import { NextRequest } from "../shims/server.js";
|
|
4
|
-
import { internalServerErrorResponse } from "./http-error-responses.js";
|
|
5
|
-
import { cloneRequestWithUrl } from "./request-pipeline.js";
|
|
6
6
|
import { markRouteCacheabilityExplicitResponsePolicy } from "../shims/cacheability-classification.js";
|
|
7
7
|
import { hasCdnResponsePolicy } from "./cache-control.js";
|
|
8
8
|
import { mergeRouteParamsIntoQuery, parseQueryString, urlQueryToSearchParams } from "../utils/query.js";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { MIDDLEWARE_SKIP_HEADER } from "../utils/protocol-headers.js";
|
|
2
2
|
import { addBasePathToPathname, hasBasePath, stripBasePath } from "../utils/base-path.js";
|
|
3
3
|
import { NEXTJS_DEPLOYMENT_ID_HEADER } from "./headers.js";
|
|
4
|
+
import { cloneRequestWithUrl } from "./request-pipeline.js";
|
|
4
5
|
//#region src/server/pages-data-route.ts
|
|
5
6
|
/**
|
|
6
7
|
* Helpers for the Pages Router `/_next/data/{buildId}/{...page}.json` endpoint.
|
|
@@ -191,7 +192,7 @@ function normalizePagesDataRequest(request, buildId, basePath = "", trailingSlas
|
|
|
191
192
|
normalizedUrl.pathname = hadBasePath ? addBasePathToPathname(pagePathname, basePath) : pagePathname;
|
|
192
193
|
return {
|
|
193
194
|
isDataReq: true,
|
|
194
|
-
request:
|
|
195
|
+
request: cloneRequestWithUrl(request, normalizedUrl.href),
|
|
195
196
|
normalizedPathname: pagePathname,
|
|
196
197
|
search: reqUrl.search,
|
|
197
198
|
notFoundResponse: null
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isUnknownRecord } from "../utils/record.js";
|
|
2
2
|
import { isBotUserAgent } from "../utils/html-limited-bots.js";
|
|
3
|
-
import { normalizePathnameForRouteMatch } from "../routing/utils.js";
|
|
4
3
|
import { NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER } from "./headers.js";
|
|
4
|
+
import { normalizePathnameForRouteMatch } from "../routing/utils.js";
|
|
5
5
|
import { isDangerousScheme } from "../shims/url-safety.js";
|
|
6
6
|
import { extractLocaleFromUrl } from "./pages-i18n.js";
|
|
7
7
|
import { buildNextDataPropsJsonResponse } from "./pages-data-route.js";
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { preserveFullyBufferedBodyMetadata } from "./fully-buffered-response.js";
|
|
2
2
|
import { closeAfterResponse, closeAfterResponseWithBody, createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
|
|
3
3
|
import { PRERENDER_REVALIDATE_HEADER } from "../utils/protocol-headers.js";
|
|
4
|
+
import { NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, VINEXT_CACHE_HEADER, VINEXT_REVALIDATED_CACHE_TAG_HEADER } from "./headers.js";
|
|
4
5
|
import { normalizePathnameForRouteMatch } from "../routing/utils.js";
|
|
5
6
|
import { patternToNextFormat } from "../routing/route-validation.js";
|
|
6
7
|
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
7
|
-
import { NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, VINEXT_CACHE_HEADER, VINEXT_REVALIDATED_CACHE_TAG_HEADER } from "./headers.js";
|
|
8
8
|
import { extractLocaleFromUrl, resolvePagesI18nRequest } from "./pages-i18n.js";
|
|
9
9
|
import { buildNextDataNotFoundResponse, buildNextDataPropsJsonResponse, normalizePagesDataRequest, parseNextDataPathname } from "./pages-data-route.js";
|
|
10
10
|
import { reportRequestError } from "./instrumentation.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isBotUserAgent } from "../utils/html-limited-bots.js";
|
|
2
|
-
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
3
2
|
import { NEXTJS_CACHE_HEADER, VINEXT_REVALIDATED_CACHE_TAG_HEADER } from "./headers.js";
|
|
3
|
+
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
4
4
|
import { reportRequestError } from "./instrumentation.js";
|
|
5
5
|
import { getCdnCacheAdapter } from "../shims/cdn-cache.js";
|
|
6
6
|
import { markRouteCacheabilityExplicitResponsePolicy } from "../shims/cacheability-classification.js";
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { PRERENDER_REVALIDATE_HEADER } from "../utils/protocol-headers.js";
|
|
2
2
|
import { requestContextFromRequest } from "../config/request-context.js";
|
|
3
3
|
import { isExternalUrl } from "../utils/external-url.js";
|
|
4
|
-
import { applyMiddlewareRequestHeaders, matchRedirect, matchRewrite, preserveRedirectDestinationQuery, proxyExternalRequest, sanitizeDestination } from "../config/config-matchers.js";
|
|
5
|
-
import { assetPrefixPathname, isNextStaticPath } from "../utils/asset-prefix.js";
|
|
6
|
-
import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
|
|
7
4
|
import { addBasePathToPathname, hasBasePath } from "../utils/base-path.js";
|
|
8
|
-
import { patternToNextFormat } from "../routing/route-validation.js";
|
|
9
5
|
import { VINEXT_PRERENDER_REWRITTEN_HEADER } from "./headers.js";
|
|
10
6
|
import { methodNotAllowedResponse, notFoundStaticAssetResponse, sanitizeMethodNotAllowedHeaders } from "./http-error-responses.js";
|
|
11
7
|
import { cloneRequestWithUrl, normalizeTrailingSlash } from "./request-pipeline.js";
|
|
8
|
+
import { applyMiddlewareRequestHeaders, matchRedirect, matchRewrite, preserveRedirectDestinationQuery, proxyExternalRequest, sanitizeDestination } from "../config/config-matchers.js";
|
|
9
|
+
import { assetPrefixPathname, isNextStaticPath } from "../utils/asset-prefix.js";
|
|
10
|
+
import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
|
|
11
|
+
import { patternToNextFormat } from "../routing/route-validation.js";
|
|
12
12
|
import { detectPathnameLocale, normalizeDefaultLocalePathname, stripI18nLocaleForApiRoute } from "./pages-i18n.js";
|
|
13
13
|
import { buildMiddlewarePrefetchSkipResponse } from "./pages-data-route.js";
|
|
14
14
|
import { markRouteCacheabilityDynamic } from "../shims/cacheability-classification.js";
|
|
@@ -79,7 +79,7 @@ function wrapMiddlewareWithBasePath(runMiddleware, basePath, hadBasePath) {
|
|
|
79
79
|
return (request, ctx, opts) => {
|
|
80
80
|
const mwUrl = new URL(request.url);
|
|
81
81
|
mwUrl.pathname = addBasePathToPathname(mwUrl.pathname, basePath);
|
|
82
|
-
return runMiddleware(
|
|
82
|
+
return runMiddleware(cloneRequestWithUrl(request, mwUrl.toString()), ctx, opts);
|
|
83
83
|
};
|
|
84
84
|
}
|
|
85
85
|
/**
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { VINEXT_PRERENDER_SECRET_HEADER, VINEXT_REVALIDATE_HOST_HEADER } from "../utils/protocol-headers.js";
|
|
2
2
|
import { requestContextFromRequest } from "../config/request-context.js";
|
|
3
|
-
import { assetPrefixPathname, isNextStaticPath } from "../utils/asset-prefix.js";
|
|
4
|
-
import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
|
|
5
3
|
import { hasBasePath, stripBasePath } from "../utils/base-path.js";
|
|
6
|
-
import { runWithExecutionContext } from "../shims/request-context.js";
|
|
7
4
|
import { VINEXT_CACHEABILITY_PROBE_QUERY_PARAM, VINEXT_EXPECTED_WORKER_VERSION_HEADER } from "./headers.js";
|
|
8
5
|
import { notFoundStaticAssetResponse } from "./http-error-responses.js";
|
|
9
6
|
import { attachRequestCfMetadata, cloneRequestWithHeaders, cloneRequestWithUrl, filterInternalHeaders, guardProtocolRelativeUrl } from "./request-pipeline.js";
|
|
7
|
+
import { assetPrefixPathname, isNextStaticPath } from "../utils/asset-prefix.js";
|
|
8
|
+
import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
|
|
9
|
+
import { runWithExecutionContext } from "../shims/request-context.js";
|
|
10
10
|
import { normalizeDefaultLocalePathname } from "./pages-i18n.js";
|
|
11
11
|
import { isNextDataPathname } from "./pages-data-route.js";
|
|
12
12
|
import { getExplicitCdnCacheAdapter } from "../shims/cdn-cache-state.js";
|
|
@@ -128,7 +128,7 @@ async function handleRequestImpl(request, env, platformCtx, dispatchResponseStag
|
|
|
128
128
|
probeRoute = readWorkerCacheabilityProbeRoute(request);
|
|
129
129
|
const probeUrl = new URL(request.url);
|
|
130
130
|
probeUrl.searchParams.delete(VINEXT_CACHEABILITY_PROBE_QUERY_PARAM);
|
|
131
|
-
request =
|
|
131
|
+
request = cloneRequestWithUrl(request, probeUrl.href);
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
134
|
let responseStageDispatched = false;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { PRERENDER_REVALIDATE_HEADER, PRERENDER_REVALIDATE_ONLY_GENERATED_HEADER, VINEXT_REVALIDATE_HOST_HEADER } from "../utils/protocol-headers.js";
|
|
2
|
-
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
3
2
|
import { VINEXT_REVALIDATED_CACHE_TAG_HEADER } from "./headers.js";
|
|
3
|
+
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
4
|
+
import { resolveRequestHost, resolveRequestProtocol } from "./proxy-trust.js";
|
|
4
5
|
import { normalizeDomainHostname } from "../utils/domain-locale.js";
|
|
5
6
|
import { getCdnCacheAdapter } from "../shims/cdn-cache.js";
|
|
6
7
|
import { getRevalidateSecret, isOnDemandRevalidateRequest } from "./revalidation-request.js";
|
|
7
8
|
import "./isr-cache.js";
|
|
8
|
-
import { resolveRequestHost, resolveRequestProtocol } from "./proxy-trust.js";
|
|
9
9
|
//#region src/server/pages-revalidate.ts
|
|
10
10
|
async function performOnDemandRevalidate(source, urlPath, opts = {}, trustedOrigin, allowedRevalidateHeaderKeys = [], dev = false) {
|
|
11
11
|
if (typeof urlPath !== "string" || !urlPath.startsWith("/")) throw new Error(`Invalid urlPath provided to revalidate(), must be a path e.g. /blog/post-1, received ${urlPath}`);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { runWithExecutionContext } from "../shims/request-context.js";
|
|
2
1
|
import { VINEXT_CACHEABILITY_PROBE_HEADER, VINEXT_CACHEABILITY_PROBE_QUERY_PARAM } from "./headers.js";
|
|
3
2
|
import { cloneRequestWithHeaders, cloneRequestWithUrl } from "./request-pipeline.js";
|
|
3
|
+
import { runWithExecutionContext } from "../shims/request-context.js";
|
|
4
4
|
import { getCdnCacheAdapter } from "../shims/cdn-cache.js";
|
|
5
5
|
import { validateCdnRequest } from "./cache-control.js";
|
|
6
6
|
import { createWorkerRevalidationContext } from "./worker-revalidation-context.js";
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
2
2
|
import { isUnknownRecord } from "../utils/record.js";
|
|
3
3
|
import { VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_SPECULATIVE_HEADER } from "../utils/protocol-headers.js";
|
|
4
|
-
import { ASSET_PREFIX_URL_DIR, assetPrefixPathname, isAbsoluteAssetPrefix } from "../utils/asset-prefix.js";
|
|
5
|
-
import { StaticFileCache, contentTypeForPath, etagFromFilenameHash } from "./static-file-cache.js";
|
|
6
|
-
import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
|
|
7
4
|
import { hasBasePath, stripBasePath } from "../utils/base-path.js";
|
|
8
5
|
import { VINEXT_PRERENDER_RENDER_ERROR_HEADER, VINEXT_PRERENDER_SPECIAL_ERROR_HEADER } from "./headers.js";
|
|
9
|
-
import { normalizePath } from "./normalize-path.js";
|
|
10
6
|
import { notFoundResponse } from "./http-error-responses.js";
|
|
11
7
|
import { getRepeatedSlashRedirect, isOpenRedirectShaped, sendRepeatedSlashRedirect } from "./open-redirect.js";
|
|
12
8
|
import { readStaticFileSignal } from "./static-file-signal.js";
|
|
13
9
|
import { canonicalizeRequestPathname, filterInternalHeaders } from "./request-pipeline.js";
|
|
10
|
+
import { ASSET_PREFIX_URL_DIR, assetPrefixPathname, isAbsoluteAssetPrefix } from "../utils/asset-prefix.js";
|
|
11
|
+
import { StaticFileCache, contentTypeForPath, etagFromFilenameHash } from "./static-file-cache.js";
|
|
12
|
+
import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
|
|
13
|
+
import { resolveRequestHost, resolveRequestProtocol, trustProxy, trustedHosts } from "./proxy-trust.js";
|
|
14
|
+
import { normalizePath } from "./normalize-path.js";
|
|
14
15
|
import { buildNextDataNotFoundResponse, encodeUrlParserIgnoredCharacters, isNextDataPathname, normalizeNextDataPagePathname, parseNextDataPathname, shouldAddTrailingSlashToPagesDataPath, urlParserCreatesPagesDataPath } from "./pages-data-route.js";
|
|
15
16
|
import { buildCacheStateHeaders } from "./cache-headers.js";
|
|
16
17
|
import { parseHttpDate } from "./http-date.js";
|
|
17
18
|
import { evaluateStaticPreconditions } from "./http-conditional.js";
|
|
18
19
|
import { setPagesClientAssets } from "./pages-client-assets.js";
|
|
19
|
-
import { resolveRequestHost, resolveRequestProtocol, trustProxy, trustedHosts } from "./proxy-trust.js";
|
|
20
20
|
import { signalFromNodeResponse } from "./node-response-signal.js";
|
|
21
21
|
import { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, IMAGE_RESPONSE_CACHE_STATE, INVALID_IMAGE_SOURCE_MESSAGE, isImageOptimizationPath, isImageSourceBodyStatus, isSafeImageContentType, parseImageParams, readImageOptimizationSignal } from "./image-optimization.js";
|
|
22
22
|
import { installSocketErrorBackstop } from "./socket-error-backstop.js";
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* tag is `HL` are decoded and inspected. Length-prefixed bodies remain separate
|
|
12
12
|
* so binary bytes do not force adjacent text through the embed's base64 path.
|
|
13
13
|
*/
|
|
14
|
-
export declare function normalizeReactFlightPreloadHints(stream: ReadableStream<Uint8Array
|
|
14
|
+
export declare function normalizeReactFlightPreloadHints(stream: ReadableStream<Uint8Array>, onCancel?: (reason: unknown) => void): ReadableStream<Uint8Array>;
|
|
15
15
|
export type RscRawRenderer = (model: unknown, options?: unknown) => ReadableStream<Uint8Array>;
|
|
16
16
|
export type RscRawPrerenderer = (model: unknown, options?: unknown) => Promise<{
|
|
17
17
|
prelude: ReadableStream<Uint8Array>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createRenderStreamCancellation } from "./app-render-abort-error.js";
|
|
1
2
|
//#region src/server/rsc-stream-hints.ts
|
|
2
3
|
const REACT_FLIGHT_STYLESHEET_PRELOAD_HINT = /^([0-9a-f]*:HL\[.*?),"stylesheet"(\]|,)/;
|
|
3
4
|
const STYLESHEET_TO_STYLE_JSON_PADDING = " ".repeat(5);
|
|
@@ -106,7 +107,7 @@ function isTagInTable(table, byte) {
|
|
|
106
107
|
* tag is `HL` are decoded and inspected. Length-prefixed bodies remain separate
|
|
107
108
|
* so binary bytes do not force adjacent text through the embed's base64 path.
|
|
108
109
|
*/
|
|
109
|
-
function normalizeReactFlightPreloadHints(stream) {
|
|
110
|
+
function normalizeReactFlightPreloadHints(stream, onCancel) {
|
|
110
111
|
let carry = null;
|
|
111
112
|
let rawBytesRemaining = 0;
|
|
112
113
|
let passThrough = false;
|
|
@@ -194,11 +195,28 @@ function normalizeReactFlightPreloadHints(stream) {
|
|
|
194
195
|
},
|
|
195
196
|
flush(controller) {
|
|
196
197
|
if (carry !== null && carry.byteLength > 0) controller.enqueue(rawBytesRemaining > 0 ? carry : normalizeReactFlightHintLine(carry));
|
|
197
|
-
}
|
|
198
|
+
},
|
|
199
|
+
cancel: onCancel
|
|
198
200
|
}));
|
|
199
201
|
}
|
|
200
202
|
function createRscRenderer(render) {
|
|
201
|
-
return (model, options) =>
|
|
203
|
+
return (model, options) => {
|
|
204
|
+
const cancellation = createRenderStreamCancellation();
|
|
205
|
+
return normalizeReactFlightPreloadHints(render(model, ignoreCancellationErrors(options, cancellation)), cancellation.record);
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
/** A consumer cancelling the payload is not a render failure. */
|
|
209
|
+
function ignoreCancellationErrors(options, cancellation) {
|
|
210
|
+
if (!options || typeof options !== "object") return options;
|
|
211
|
+
const onError = Reflect.get(options, "onError");
|
|
212
|
+
if (typeof onError !== "function") return options;
|
|
213
|
+
return {
|
|
214
|
+
...options,
|
|
215
|
+
onError(error, ...rest) {
|
|
216
|
+
if (cancellation.isReason(error)) return void 0;
|
|
217
|
+
return Reflect.apply(onError, options, [error, ...rest]);
|
|
218
|
+
}
|
|
219
|
+
};
|
|
202
220
|
}
|
|
203
221
|
function createRscPrerenderer(prerender) {
|
|
204
222
|
return async (model, options) => {
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { isNextStaticPath } from "../utils/asset-prefix.js";
|
|
2
|
-
import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
|
|
3
1
|
import { VINEXT_PRERENDER_SPECIAL_ERROR_HEADER } from "./headers.js";
|
|
4
|
-
import { normalizePath } from "./normalize-path.js";
|
|
5
2
|
import { readStaticFileSignal, readStaticFileSignalRequestHeaders } from "./static-file-signal.js";
|
|
6
3
|
import { attachRequestCfMetadata, cloneRequestWithUrl } from "./request-pipeline.js";
|
|
4
|
+
import { isNextStaticPath } from "../utils/asset-prefix.js";
|
|
7
5
|
import { handleConfiguredImageOptimization, invalidImageSourceResponse, isImageSourceBodyStatus } from "./image-optimization.js";
|
|
8
6
|
import { createStaticAssetRequest, mergeHeaders } from "./worker-utils.js";
|
|
9
7
|
import { resolveClientBuildFile } from "./client-build-files.js";
|
|
@@ -28,19 +26,34 @@ function cancelResponseBody(response) {
|
|
|
28
26
|
body.cancel().catch(() => {});
|
|
29
27
|
}
|
|
30
28
|
/**
|
|
29
|
+
* Return the pathname of the `_next/static` file a source's decoded pathname
|
|
30
|
+
* names, or null. Next.js matches the decoded pathname against its
|
|
31
|
+
* `.next/static` files literally, so a `.`, `..` or empty segment names no
|
|
32
|
+
* file. The asset binding decodes each segment once, so each segment is
|
|
33
|
+
* encoded once from the name checked here. Parsing the decoded pathname as a
|
|
34
|
+
* URL again would resolve a segment that decoded to `%2E%2E` as `..`, outside
|
|
35
|
+
* `_next/static`.
|
|
36
|
+
*/
|
|
37
|
+
function resolveNextStaticFile(decodedPathname, options) {
|
|
38
|
+
if (!isNextStaticPath(decodedPathname, options.basePath, options.assetPathPrefix)) return null;
|
|
39
|
+
const segments = decodedPathname.split("/").slice(1);
|
|
40
|
+
if (segments.some((segment) => segment === "" || segment === "." || segment === "..")) return null;
|
|
41
|
+
return "/" + segments.map(encodeURIComponent).join("/");
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
31
44
|
* Fetch a local image source. Build output is fetched from the asset binding,
|
|
32
45
|
* which serves it before the Worker and its middleware. Any other source is
|
|
33
46
|
* served only when the application pipeline selects a public file for it.
|
|
34
47
|
*/
|
|
35
48
|
async function fetchWorkerImageSource(imageUrl, request, options) {
|
|
36
49
|
const sourceUrl = new URL(imageUrl, request.url);
|
|
37
|
-
let
|
|
50
|
+
let decodedPathname;
|
|
38
51
|
try {
|
|
39
|
-
|
|
52
|
+
decodedPathname = decodeURIComponent(sourceUrl.pathname);
|
|
40
53
|
} catch {
|
|
41
54
|
return invalidImageSourceResponse();
|
|
42
55
|
}
|
|
43
|
-
const buildAssetPath =
|
|
56
|
+
const buildAssetPath = resolveNextStaticFile(decodedPathname, options) ?? resolveClientBuildFile(sourceUrl.pathname, options.basePath, options.clientBuildFiles);
|
|
44
57
|
if (buildAssetPath !== null) return options.assets.fetch(new Request(new URL(buildAssetPath, request.url)));
|
|
45
58
|
const sourceResponse = await options.fetchPublicFile(attachRequestCfMetadata(new Request(sourceUrl, { signal: request.signal }), request));
|
|
46
59
|
if (sourceResponse && isImageSourceBodyStatus(sourceResponse.status)) return sourceResponse;
|
package/dist/shims/head.js
CHANGED
|
@@ -183,7 +183,7 @@ function reduceHeadChildren(headChildren) {
|
|
|
183
183
|
const SAFE_ATTR_NAME_RE = /^[a-zA-Z][a-zA-Z0-9\-:.]*$/;
|
|
184
184
|
function isSafeAttrName(name) {
|
|
185
185
|
if (!SAFE_ATTR_NAME_RE.test(name)) return false;
|
|
186
|
-
if (name.length > 2 && name[0] === "o"
|
|
186
|
+
if (name.length > 2 && (name[0] === "o" || name[0] === "O") && (name[1] === "n" || name[1] === "N")) return false;
|
|
187
187
|
return true;
|
|
188
188
|
}
|
|
189
189
|
/**
|
package/dist/shims/headers.js
CHANGED
|
@@ -749,8 +749,8 @@ async function draftMode() {
|
|
|
749
749
|
}
|
|
750
750
|
};
|
|
751
751
|
}
|
|
752
|
-
const APPLY_RESPONSE_COOKIE = Symbol("vinext.apply-response-cookie");
|
|
753
|
-
const SYNCHRONIZE_REQUEST_COOKIES = Symbol("vinext.synchronize-request-cookies");
|
|
752
|
+
const APPLY_RESPONSE_COOKIE = Symbol.for("vinext.apply-response-cookie");
|
|
753
|
+
const SYNCHRONIZE_REQUEST_COOKIES = Symbol.for("vinext.synchronize-request-cookies");
|
|
754
754
|
var RequestCookies = class {
|
|
755
755
|
_cookies;
|
|
756
756
|
_responseCookies;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { compareHybridRoutePatterns } from "../../routing/utils.js";
|
|
2
1
|
import { stripBasePath } from "../../utils/base-path.js";
|
|
2
|
+
import { compareHybridRoutePatterns } from "../../routing/utils.js";
|
|
3
3
|
import { createRouteTrieCache, matchRouteWithTrie } from "../../routing/route-matching.js";
|
|
4
4
|
import { getLocalePathPrefix } from "../../utils/domain-locale.js";
|
|
5
5
|
//#region src/shims/internal/hybrid-client-route-owner-direct.ts
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { parseCookies } from "../../config/request-context.js";
|
|
2
|
+
import "../../config/config-matchers.js";
|
|
2
3
|
import { matchDirectHybridClientRoutes, resolveMatchedHybridClientRouteOwner, resolveSameOriginAppPathname } from "./hybrid-client-route-owner-direct.js";
|
|
3
4
|
import { mergeRewriteQuery } from "../../utils/query.js";
|
|
4
5
|
import { matchClientRewrite } from "../../client/client-rewrite-matcher.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { hasBasePath, stripBasePath } from "../utils/base-path.js";
|
|
2
|
-
import { isAbsoluteOrProtocolRelativeUrl } from "./url-utils.js";
|
|
2
|
+
import { collapseLeadingSlashes, isAbsoluteOrProtocolRelativeUrl } from "./url-utils.js";
|
|
3
3
|
//#region src/shims/link-prefetch.ts
|
|
4
4
|
function canLinkPrefetch(input) {
|
|
5
5
|
return input.nodeEnv === "production" && input.prefetch !== false && !input.isDangerous;
|
|
@@ -32,9 +32,10 @@ function getLinkPrefetchHref(input) {
|
|
|
32
32
|
const current = new URL(currentOrigin);
|
|
33
33
|
const parsed = href.startsWith("//") ? new URL(href, current.origin) : new URL(href);
|
|
34
34
|
if (parsed.origin !== current.origin) return null;
|
|
35
|
-
|
|
36
|
-
if (!
|
|
37
|
-
|
|
35
|
+
const pathname = collapseLeadingSlashes(parsed.pathname);
|
|
36
|
+
if (!basePath) return pathname + parsed.search + parsed.hash;
|
|
37
|
+
if (!hasBasePath(pathname, basePath)) return null;
|
|
38
|
+
return collapseLeadingSlashes(stripBasePath(pathname, basePath)) + parsed.search + parsed.hash;
|
|
38
39
|
} catch {
|
|
39
40
|
return null;
|
|
40
41
|
}
|
package/dist/shims/link.js
CHANGED
|
@@ -317,7 +317,7 @@ function prefetchUrl(href, mode, priority = "low", pagesRouteHref, locale) {
|
|
|
317
317
|
async function promotePrefetchEntriesForNavigation(href) {
|
|
318
318
|
if (typeof window === "undefined") return;
|
|
319
319
|
if (!hasAppNavigationRuntime()) return;
|
|
320
|
-
const [{ getPrefetchCache }, { stripRscCacheBustingSearchParam, stripRscSuffix }] = await Promise.all([loadNavigationModule(), import("../server/app-rsc-cache-busting.js")]);
|
|
320
|
+
const [{ getPrefetchCache }, { parseRscRequestPath, stripRscCacheBustingSearchParam, stripRscSuffix }] = await Promise.all([loadNavigationModule(), import("../server/app-rsc-cache-busting.js")]);
|
|
321
321
|
let target;
|
|
322
322
|
try {
|
|
323
323
|
target = new URL(toCanonicalBrowserNavigationHref(href, window.location.href, __basePath, __trailingSlash), window.location.href);
|
|
@@ -330,7 +330,7 @@ async function promotePrefetchEntriesForNavigation(href) {
|
|
|
330
330
|
const [rscUrl] = cacheKey.split("\0", 1);
|
|
331
331
|
let cached;
|
|
332
332
|
try {
|
|
333
|
-
cached =
|
|
333
|
+
cached = parseRscRequestPath(rscUrl);
|
|
334
334
|
} catch {
|
|
335
335
|
continue;
|
|
336
336
|
}
|
package/dist/shims/navigation.js
CHANGED
|
@@ -17,7 +17,7 @@ import { GLOBAL_ACCESSORS_KEY, ServerInsertedHTMLContext, _registerStateAccessor
|
|
|
17
17
|
import { BailoutToCSRError, DynamicServerError, HTTP_ERROR_FALLBACK_ERROR_CODE, RedirectType, decodeRedirectError, forbidden, getAccessFallbackHTTPStatus, isBailoutToCSRError, isDynamicServerError, isHTTPAccessFallbackError, isNextRouterError, isRedirectError, notFound, permanentRedirect, redirect, unauthorized, unstable_rethrow } from "./navigation-errors.js";
|
|
18
18
|
import { clearAppNavigationFailureTarget, stageAppNavigationFailureTarget } from "../client/app-nav-failure-handler.js";
|
|
19
19
|
import { beginAppRouterScrollIntent, clearAppRouterScrollIntent, consumeAppRouterScrollIntent, getPendingAppRouterScrollIntent, isLatestAppRouterScrollIntent } from "./app-router-scroll-state.js";
|
|
20
|
-
import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, createRscRequestHeaders, createRscRequestUrl, stripRscCacheBustingSearchParam, stripRscSuffix } from "../server/app-rsc-cache-busting.js";
|
|
20
|
+
import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, createRscRequestHeaders, createRscRequestUrl, formatRscRequestPath, parseRscRequestPath, stripRscCacheBustingSearchParam, stripRscSuffix } from "../server/app-rsc-cache-busting.js";
|
|
21
21
|
import { notifyAppRouterTransitionStart } from "../client/instrumentation-client-state.js";
|
|
22
22
|
import { getNavigationRuntime, hasAppNavigationRuntime } from "../client/navigation-runtime.js";
|
|
23
23
|
import { UnrecognizedActionError, unstable_isUnrecognizedActionError } from "./unrecognized-action-error.js";
|
|
@@ -236,7 +236,7 @@ function resolvePrefetchCacheEntryMountedSlotsHeader(entry) {
|
|
|
236
236
|
}
|
|
237
237
|
function normalizeRscCacheLookupUrl(rscUrl) {
|
|
238
238
|
try {
|
|
239
|
-
const url =
|
|
239
|
+
const url = parseRscRequestPath(rscUrl);
|
|
240
240
|
stripRscCacheBustingSearchParam(url);
|
|
241
241
|
return `${url.pathname}${url.search}`;
|
|
242
242
|
} catch {
|
|
@@ -245,7 +245,7 @@ function normalizeRscCacheLookupUrl(rscUrl) {
|
|
|
245
245
|
}
|
|
246
246
|
function normalizeRscCacheLookupPathname(rscUrl) {
|
|
247
247
|
try {
|
|
248
|
-
const url =
|
|
248
|
+
const url = parseRscRequestPath(rscUrl);
|
|
249
249
|
return stripRscSuffix(url.pathname);
|
|
250
250
|
} catch {
|
|
251
251
|
return null;
|
|
@@ -435,8 +435,7 @@ function toAppPrefetchDestination(href) {
|
|
|
435
435
|
}
|
|
436
436
|
const browserHref = toCanonicalBrowserNavigationHref(localHref, window.location.href, __basePath, __trailingSlash);
|
|
437
437
|
try {
|
|
438
|
-
|
|
439
|
-
return `${url.pathname}${url.search}`;
|
|
438
|
+
return formatRscRequestPath(new URL(browserHref, window.location.href));
|
|
440
439
|
} catch {
|
|
441
440
|
return browserHref.split("#", 1)[0];
|
|
442
441
|
}
|