vinext 1.3.1 → 1.4.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 +25 -22
- package/THIRD_PARTY_LICENSES.md +47 -0
- package/dist/_virtual/_rolldown/runtime.js +3 -2
- package/dist/build/prerender.js +4 -3
- package/dist/build/report.d.ts +0 -14
- package/dist/build/report.js +1 -51
- package/dist/check.js +4 -7
- package/dist/cli.js +3 -0
- package/dist/client/dev-error-overlay-store.d.ts +1 -0
- package/dist/client/dev-error-overlay.d.ts +2 -0
- package/dist/client/dev-error-overlay.js +20 -4
- package/dist/client/navigation-runtime.d.ts +13 -1
- package/dist/client/navigation-runtime.js +1 -1
- package/dist/config/config-matchers.js +2 -0
- package/dist/config/destination-params.d.ts +2 -1
- package/dist/config/destination-params.js +52 -2
- package/dist/config/next-config.d.ts +25 -0
- package/dist/config/next-config.js +82 -4
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/dbcs-codec.js +327 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/dbcs-data.js +123 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/index.js +29 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/internal.js +134 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-codec.js +50 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-data-generated.js +455 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-data.js +147 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/big5-added.json.js +169 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp936.json.js +2584 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp949.json.js +2220 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp950.json.js +227 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/eucjp.json.js +425 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/gb18030-ranges.json.js +427 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/gbk-added.json.js +229 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/shiftjis.json.js +292 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/utf16.js +106 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/utf7.js +182 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/bom-handling.js +42 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/extend-node.js +147 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/index.js +94 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/streams.js +95 -0
- package/dist/deps/.pnpm/safer-buffer@2.1.2/deps/safer-buffer/safer.js +45 -0
- package/dist/entries/app-rsc-entry.js +17 -49
- package/dist/entries/app-rsc-manifest.js +3 -4
- package/dist/entries/app-ssr-entry.js +1 -0
- package/dist/entries/pages-server-entry.js +36 -9
- package/dist/index.js +112 -90
- package/dist/init-cloudflare.d.ts +1 -3
- package/dist/init-cloudflare.js +10 -48
- package/dist/init-platform.d.ts +2 -0
- package/dist/init-platform.js +4 -0
- package/dist/plugins/extensionless-dynamic-import.js +6 -2
- package/dist/plugins/next-intl-catalog.d.ts +12 -0
- package/dist/plugins/next-intl-catalog.js +85 -0
- package/dist/plugins/pages-node-externals.d.ts +1 -0
- package/dist/plugins/pages-node-externals.js +1 -1
- package/dist/plugins/strip-server-exports.js +2 -1
- package/dist/plugins/use-cache-callable.d.ts +1 -1
- package/dist/plugins/use-cache-callable.js +136 -94
- package/dist/routing/app-route-graph.d.ts +6 -0
- package/dist/routing/app-route-graph.js +9 -1
- package/dist/server/api-handler.js +21 -5
- package/dist/server/app-bfcache-identity.js +1 -1
- package/dist/server/app-browser-entry.js +86 -66
- package/dist/server/app-browser-history-controller.d.ts +5 -4
- package/dist/server/app-browser-history-controller.js +93 -15
- package/dist/server/app-browser-navigation-controller.d.ts +2 -2
- package/dist/server/app-browser-navigation-controller.js +1 -2
- package/dist/server/app-browser-rsc-redirect.js +7 -7
- package/dist/server/app-browser-server-action-client.d.ts +2 -0
- package/dist/server/app-browser-server-action-client.js +5 -4
- package/dist/server/app-browser-state.d.ts +2 -4
- package/dist/server/app-browser-state.js +9 -4
- package/dist/server/app-browser-supplemental-refresh.js +16 -1
- package/dist/server/app-browser-visible-commit.d.ts +1 -1
- package/dist/server/app-browser-visible-commit.js +4 -14
- package/dist/server/app-elements-wire.d.ts +6 -38
- package/dist/server/app-elements-wire.js +4 -41
- package/dist/server/app-elements.d.ts +2 -2
- package/dist/server/app-elements.js +2 -2
- package/dist/server/app-history-state.d.ts +2 -2
- package/dist/server/app-history-state.js +5 -2
- package/dist/server/app-mounted-layouts.d.ts +21 -0
- package/dist/server/app-mounted-layouts.js +67 -0
- package/dist/server/app-optimistic-routing.d.ts +19 -1
- package/dist/server/app-optimistic-routing.js +43 -4
- package/dist/server/app-page-boundary-render.js +10 -14
- package/dist/server/app-page-boundary.js +2 -2
- package/dist/server/app-page-cache-finalizer.d.ts +12 -1
- package/dist/server/app-page-cache-finalizer.js +70 -29
- package/dist/server/app-page-cache.d.ts +13 -1
- package/dist/server/app-page-cache.js +31 -9
- package/dist/server/app-page-dispatch.d.ts +5 -11
- package/dist/server/app-page-dispatch.js +84 -155
- package/dist/server/app-page-element-builder.d.ts +2 -2
- package/dist/server/app-page-element-builder.js +13 -12
- package/dist/server/app-page-execution.d.ts +17 -52
- package/dist/server/app-page-execution.js +102 -95
- package/dist/server/app-page-head.d.ts +13 -0
- package/dist/server/app-page-head.js +44 -16
- package/dist/server/app-page-http-access-fallback-metadata.d.ts +1 -0
- package/dist/server/app-page-http-access-fallback-metadata.js +2 -2
- package/dist/server/app-page-layout-gate.d.ts +35 -0
- package/dist/server/app-page-layout-gate.js +50 -0
- package/dist/server/app-page-params.d.ts +0 -1
- package/dist/server/app-page-params.js +1 -14
- package/dist/server/app-page-probe.d.ts +3 -21
- package/dist/server/app-page-probe.js +4 -37
- package/dist/server/app-page-render.d.ts +2 -13
- package/dist/server/app-page-render.js +103 -234
- package/dist/server/app-page-request.d.ts +1 -3
- package/dist/server/app-page-request.js +1 -1
- package/dist/server/app-page-response.js +3 -3
- package/dist/server/app-page-route-wiring.d.ts +13 -6
- package/dist/server/app-page-route-wiring.js +86 -63
- package/dist/server/app-page-rsc-render-status.d.ts +27 -1
- package/dist/server/app-page-rsc-render-status.js +121 -13
- package/dist/server/app-page-stream.d.ts +12 -8
- package/dist/server/app-page-stream.js +4 -3
- package/dist/server/app-pages-bridge.d.ts +4 -0
- package/dist/server/app-pages-bridge.js +7 -3
- package/dist/server/app-render-dependency.d.ts +11 -4
- package/dist/server/app-render-dependency.js +86 -38
- package/dist/server/app-request-stage-dispatch.js +1 -1
- package/dist/server/app-request-stage-independent-entry.js +1 -1
- package/dist/server/app-route-handler-cache.js +2 -2
- package/dist/server/app-route-handler-dispatch.js +14 -9
- package/dist/server/app-route-handler-execution.js +11 -5
- package/dist/server/app-route-handler-policy.d.ts +1 -1
- package/dist/server/app-route-handler-policy.js +3 -3
- package/dist/server/app-route-handler-response.js +1 -1
- package/dist/server/app-route-handler-runtime.d.ts +1 -1
- package/dist/server/app-route-handler-runtime.js +28 -11
- package/dist/server/app-router-entry.js +1 -1
- package/dist/server/app-rsc-cache-busting.d.ts +12 -12
- package/dist/server/app-rsc-cache-busting.js +31 -72
- package/dist/server/app-rsc-error-handler.d.ts +2 -1
- package/dist/server/app-rsc-error-handler.js +10 -2
- package/dist/server/app-rsc-errors.d.ts +8 -0
- package/dist/server/app-rsc-errors.js +11 -1
- package/dist/server/app-rsc-handler.d.ts +5 -5
- package/dist/server/app-rsc-handler.js +80 -83
- package/dist/server/app-rsc-request-normalization.d.ts +10 -16
- package/dist/server/app-rsc-request-normalization.js +12 -18
- package/dist/server/app-rsc-response-finalizer.js +2 -2
- package/dist/server/app-rsc-response-stage.js +9 -15
- package/dist/server/app-server-action-execution.d.ts +3 -1
- package/dist/server/app-server-action-execution.js +15 -8
- package/dist/server/app-ssr-entry.d.ts +8 -0
- package/dist/server/app-ssr-entry.js +22 -16
- package/dist/server/app-ssr-stream.js +1 -1
- package/dist/server/app-visited-response-cache.d.ts +36 -1
- package/dist/server/app-visited-response-cache.js +46 -5
- package/dist/server/app-worker-stages.d.ts +37 -6
- package/dist/server/app-worker-stages.js +81 -9
- package/dist/server/artifact-compatibility.d.ts +0 -1
- package/dist/server/artifact-compatibility.js +1 -10
- package/dist/server/bfcache-identity.d.ts +7 -0
- package/dist/server/bfcache-identity.js +10 -1
- package/dist/server/cache-proof.d.ts +1 -115
- package/dist/server/cache-proof.js +1 -544
- package/dist/server/cacheability-manifest.js +1 -2
- package/dist/server/cacheability-request.js +13 -8
- package/dist/server/dev-origin-check.d.ts +2 -1
- package/dist/server/dev-origin-check.js +2 -1
- package/dist/server/dev-server.js +6 -4
- package/dist/server/headers.d.ts +6 -3
- package/dist/server/headers.js +9 -5
- package/dist/server/image-optimization.d.ts +5 -0
- package/dist/server/image-optimization.js +6 -1
- package/dist/server/isr-cache.d.ts +8 -2
- package/dist/server/isr-cache.js +30 -2
- package/dist/server/metadata-route-response.js +32 -15
- package/dist/server/middleware-matcher.js +19 -6
- package/dist/server/middleware-runtime.js +6 -2
- package/dist/server/multi-stage.d.ts +57 -12
- package/dist/server/multi-stage.js +13 -1
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/pages-api-route.js +28 -19
- package/dist/server/pages-media-type.d.ts +21 -1
- package/dist/server/pages-media-type.js +69 -5
- package/dist/server/pages-node-compat.d.ts +1 -1
- package/dist/server/pages-node-compat.js +54 -27
- package/dist/server/pages-page-data.js +2 -1
- package/dist/server/pages-page-handler.js +28 -26
- package/dist/server/pages-page-response.d.ts +9 -0
- package/dist/server/pages-page-response.js +18 -4
- package/dist/server/pages-request-pipeline.d.ts +8 -0
- package/dist/server/pages-request-pipeline.js +2 -2
- package/dist/server/pages-request-stage-entry.js +36 -14
- package/dist/server/pages-response-stage-entry.js +9 -3
- package/dist/server/pages-router-entry.js +3 -2
- package/dist/server/prod-server.d.ts +2 -2
- package/dist/server/prod-server.js +47 -9
- package/dist/server/request-error-log.d.ts +9 -0
- package/dist/server/request-error-log.js +13 -0
- package/dist/server/request-pipeline.d.ts +15 -4
- package/dist/server/request-pipeline.js +43 -15
- package/dist/server/rsc-completion-metadata.js +3 -0
- package/dist/server/shared-cache-identity.d.ts +23 -0
- package/dist/server/shared-cache-identity.js +36 -0
- package/dist/server/static-file-cache.d.ts +9 -0
- package/dist/server/static-file-cache.js +13 -2
- package/dist/server/worker-stages.d.ts +16 -3
- package/dist/server/worker-stages.js +23 -4
- package/dist/shims/cache-handler.js +2 -2
- package/dist/shims/cache-request-state.d.ts +23 -26
- package/dist/shims/cache-request-state.js +22 -57
- package/dist/shims/cache-runtime.d.ts +3 -1
- package/dist/shims/cache-runtime.js +94 -48
- package/dist/shims/cache.d.ts +16 -10
- package/dist/shims/cache.js +47 -36
- package/dist/shims/cacheability-classification.d.ts +2 -0
- package/dist/shims/cdn-cache.d.ts +22 -5
- package/dist/shims/client-hook-error.d.ts +2 -0
- package/dist/shims/client-hook-error.js +16 -1
- package/dist/shims/client-page-root.js +2 -2
- package/dist/shims/dynamic.js +9 -6
- package/dist/shims/error-boundary.js +2 -2
- package/dist/shims/fetch-cache-state.d.ts +5 -1
- package/dist/shims/fetch-cache-state.js +1 -3
- package/dist/shims/fetch-cache.d.ts +2 -1
- package/dist/shims/fetch-cache.js +39 -25
- package/dist/shims/form.js +2 -2
- package/dist/shims/headers.d.ts +10 -24
- package/dist/shims/headers.js +22 -70
- package/dist/shims/internal/cache-context-accessor.d.ts +1 -1
- package/dist/shims/internal/navigation-untracked.js +1 -1
- package/dist/shims/link.js +8 -11
- package/dist/shims/metadata.d.ts +23 -21
- package/dist/shims/metadata.js +62 -24
- package/dist/shims/navigation-server.js +1 -1
- package/dist/shims/navigation.d.ts +74 -7
- package/dist/shims/navigation.js +184 -31
- package/dist/shims/navigation.react-server.js +2 -2
- package/dist/shims/request-state-types.d.ts +3 -2
- package/dist/shims/slot.d.ts +16 -0
- package/dist/shims/slot.js +44 -9
- package/dist/shims/unified-request-context.d.ts +7 -1
- package/dist/shims/unified-request-context.js +3 -3
- package/dist/utils/cache-control-metadata.d.ts +5 -0
- package/dist/utils/cache-control-metadata.js +9 -1
- package/dist/utils/cache-life-profiles.d.ts +33 -0
- package/dist/utils/cache-life-profiles.js +111 -0
- package/dist/utils/middleware-request-headers.d.ts +14 -3
- package/dist/utils/middleware-request-headers.js +54 -7
- package/dist/utils/project.d.ts +2 -2
- package/dist/utils/project.js +3 -16
- package/dist/utils/regex.d.ts +5 -0
- package/dist/utils/regex.js +11 -1
- package/dist/utils/text-stream.d.ts +10 -5
- package/dist/utils/text-stream.js +6 -6
- package/package.json +2 -1
- package/dist/build/layout-classification-types.d.ts +0 -60
- package/dist/build/layout-classification-types.js +0 -1
- package/dist/build/layout-classification.d.ts +0 -62
- package/dist/build/layout-classification.js +0 -98
- package/dist/build/route-classification-injector.d.ts +0 -33
- package/dist/build/route-classification-injector.js +0 -59
- package/dist/build/route-classification-manifest.d.ts +0 -54
- package/dist/build/route-classification-manifest.js +0 -143
- package/dist/server/app-browser-client-reuse-manifest.d.ts +0 -11
- package/dist/server/app-browser-client-reuse-manifest.js +0 -101
- package/dist/server/app-layout-param-observation.d.ts +0 -42
- package/dist/server/app-layout-param-observation.js +0 -168
- package/dist/server/client-reuse-manifest.d.ts +0 -103
- package/dist/server/client-reuse-manifest.js +0 -209
- package/dist/server/skip-cache-proof.d.ts +0 -60
- package/dist/server/skip-cache-proof.js +0 -168
- package/dist/server/static-layout-client-reuse-proof.d.ts +0 -14
- package/dist/server/static-layout-client-reuse-proof.js +0 -33
- package/dist/utils/sorted-array.d.ts +0 -8
- package/dist/utils/sorted-array.js +0 -20
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { preserveFullyBufferedBodyMetadata } from "./fully-buffered-response.js";
|
|
2
2
|
import { closeAfterResponse, closeAfterResponseWithBody, createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
|
|
3
|
-
import { VINEXT_REVALIDATE_HOST_HEADER } from "../utils/protocol-headers.js";
|
|
3
|
+
import { PRERENDER_REVALIDATE_HEADER, VINEXT_REVALIDATE_HOST_HEADER } from "../utils/protocol-headers.js";
|
|
4
4
|
import "./headers.js";
|
|
5
5
|
import { cloneRequestWithHeaders, cloneRequestWithUrl, filterInternalHeaders } from "./request-pipeline.js";
|
|
6
6
|
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
7
7
|
import { runOutsideWorkStoreScope } from "../shims/internal/work-store-scope.js";
|
|
8
|
+
import { isOnDemandRevalidateRequest } from "./revalidation-request.js";
|
|
8
9
|
import { applyEffectiveRequestCookieHeader, getDraftModeCookieHeader, headersContextFromRequest, restoreDraftModeTransition } from "../shims/headers.js";
|
|
9
10
|
import { ensureFetchPatch, setCurrentFetchSoftTags } from "../shims/fetch-cache.js";
|
|
10
11
|
import { traceFindPageComponents } from "./pages-execution-tracing.js";
|
|
11
12
|
import { getRenderedConcreteUrlPathsForRoute } from "./pregenerated-concrete-paths.js";
|
|
12
|
-
import { VINEXT_RSC_CACHE_BUSTING_SEARCH_PARAM, hasRscCacheBustingSearchParam, stripRscCacheBustingSearchParam
|
|
13
|
+
import { VINEXT_RSC_CACHE_BUSTING_SEARCH_PARAM, hasRscCacheBustingSearchParam, stripRscCacheBustingSearchParam } from "./app-rsc-cache-busting.js";
|
|
13
14
|
import { traceAppPageRender } from "./app-page-tracing.js";
|
|
14
15
|
import { buildPageCacheTags } from "./implicit-tags.js";
|
|
15
16
|
import { pickRootParams, setRootParams } from "../shims/root-params.js";
|
|
@@ -47,13 +48,6 @@ function requestWithoutRscCacheBustingSearchParam(request) {
|
|
|
47
48
|
stripRscCacheBustingSearchParam(url);
|
|
48
49
|
return cloneRequestWithUrl(request, url.toString());
|
|
49
50
|
}
|
|
50
|
-
function requestWithoutRscSuffix(request) {
|
|
51
|
-
const url = new URL(request.url);
|
|
52
|
-
const pathname = stripRscSuffix(url.pathname);
|
|
53
|
-
if (pathname === url.pathname) return request;
|
|
54
|
-
url.pathname = pathname;
|
|
55
|
-
return cloneRequestWithUrl(request, url.toString());
|
|
56
|
-
}
|
|
57
51
|
function pathnameForResolvedUrl(resolvedUrl) {
|
|
58
52
|
return resolvedUrl.split("#", 1)[0].split("?", 1)[0];
|
|
59
53
|
}
|
|
@@ -69,7 +63,7 @@ function rematchAppWorkerResponseStageRoute(options, normalized, props) {
|
|
|
69
63
|
return match;
|
|
70
64
|
}
|
|
71
65
|
async function renderAppWorkerResponseStage(options, rawRequest, ctx, props, stageOptions) {
|
|
72
|
-
if (props.protocolVersion !==
|
|
66
|
+
if (props.protocolVersion !== 13 || props.buildId !== options.buildId) return new Response("Incompatible vinext App response stage", { status: 409 });
|
|
73
67
|
if (props.kind === "app-full-request") return new Response("Invalid vinext App response stage", { status: 400 });
|
|
74
68
|
const rawRequestSignal = rawRequest.signal;
|
|
75
69
|
options.registerCacheAdapters();
|
|
@@ -104,6 +98,7 @@ async function renderAppWorkerResponseStage(options, rawRequest, ctx, props, sta
|
|
|
104
98
|
const requestContext = createRequestContext({
|
|
105
99
|
headersContext,
|
|
106
100
|
executionContext,
|
|
101
|
+
isOnDemandRevalidate: isOnDemandRevalidateRequest(request.headers.get(PRERENDER_REVALIDATE_HEADER)),
|
|
107
102
|
requestSignal: executionContext?.requestSignal ?? rawRequestSignal,
|
|
108
103
|
unstableCacheRevalidation: "background"
|
|
109
104
|
});
|
|
@@ -171,6 +166,7 @@ async function renderAppWorkerResponseStage(options, rawRequest, ctx, props, sta
|
|
|
171
166
|
pathname: props.resolvedUrl,
|
|
172
167
|
pagesDataRequest: props.isDataRequest ? request : null,
|
|
173
168
|
request: pageRequest,
|
|
169
|
+
sharedAcrossHosts: props.sharedAcrossHosts,
|
|
174
170
|
url: new URL(props.requestUrl)
|
|
175
171
|
}));
|
|
176
172
|
if (!pagesResponse) return new Response("Invalid vinext App response stage", { status: 404 });
|
|
@@ -189,9 +185,8 @@ async function renderAppWorkerResponseStage(options, rawRequest, ctx, props, sta
|
|
|
189
185
|
setRootParams(rootParams);
|
|
190
186
|
if (props.kind === "app-route-handler") {
|
|
191
187
|
setCurrentFetchSoftTags(buildPageCacheTags(props.cleanPathname, [], [...route.routeSegments], "route"));
|
|
192
|
-
const
|
|
193
|
-
const
|
|
194
|
-
const routeHandlerRequest = isEdgeRouteHandler(route.routeHandler) ? userlandRequest : normalizedUserlandRequest;
|
|
188
|
+
const userlandRequest = requestWithoutRscCacheBustingSearchParam(request);
|
|
189
|
+
const routeHandlerRequest = isEdgeRouteHandler(route.routeHandler) ? userlandRequest : request;
|
|
195
190
|
const routeHandlerUrl = new URL(routeHandlerRequest.url);
|
|
196
191
|
const internalRscValues = isEdgeRouteHandler(route.routeHandler) ? [] : routeHandlerUrl.searchParams.getAll(VINEXT_RSC_CACHE_BUSTING_SEARCH_PARAM);
|
|
197
192
|
routeHandlerUrl.search = searchParams.toString();
|
|
@@ -216,14 +211,13 @@ async function renderAppWorkerResponseStage(options, rawRequest, ctx, props, sta
|
|
|
216
211
|
return options.dispatchMatchedPage({
|
|
217
212
|
bypassInterceptionContextCache: props.bypassInterceptionContextCache,
|
|
218
213
|
cachePathname: props.cachePathname,
|
|
219
|
-
clientReuseManifest: normalized.clientReuseManifest,
|
|
220
214
|
cleanPathname: props.cleanPathname,
|
|
221
215
|
displayPathname: props.canonicalPathname,
|
|
222
216
|
formState: null,
|
|
223
217
|
handlerStart: process.env.NODE_ENV !== "production" ? performance.now() : 0,
|
|
224
218
|
interceptionContext: normalized.interceptionContextHeader,
|
|
225
219
|
interceptionId: normalized.interceptionIdHeader,
|
|
226
|
-
interceptionPathname: props.matchKind === "resolved" ? props.cleanPathname : normalized.
|
|
220
|
+
interceptionPathname: props.matchKind === "resolved" ? props.cleanPathname : normalized.requestPathname,
|
|
227
221
|
isProgressiveActionRender: false,
|
|
228
222
|
isRscRequest: normalized.isRscRequest,
|
|
229
223
|
middlewareContext,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { AppRscRenderMode } from "./app-rsc-render-mode.js";
|
|
2
|
-
import { ActionRevalidationKind } from "../shims/cache-request-state.js";
|
|
3
2
|
import { AppRenderErrorContextOverrides } from "./app-rsc-error-handler.js";
|
|
4
3
|
import { FetchCacheMode } from "../shims/fetch-cache-state.js";
|
|
5
4
|
import "../shims/fetch-cache.js";
|
|
6
5
|
import { HeadersAccessPhase } from "../shims/internal/headers-state.js";
|
|
7
6
|
import "../shims/headers.js";
|
|
7
|
+
import { ActionRevalidationKind } from "../shims/cache-request-state.js";
|
|
8
8
|
import { ReactFormState } from "react-dom/client";
|
|
9
9
|
//#region src/server/app-server-action-execution.d.ts
|
|
10
10
|
type AppPageParams = Record<string, string | string[]>;
|
|
@@ -156,6 +156,8 @@ export type HandleProgressiveServerActionRequestOptions = {
|
|
|
156
156
|
* routes fall through. See issue #1340.
|
|
157
157
|
*/
|
|
158
158
|
hasPageRoute: boolean;
|
|
159
|
+
/** The App Router route the form posted to, whose implicit tags the action runs with. */
|
|
160
|
+
currentRoute?: AppServerActionRoute | null;
|
|
159
161
|
maxActionBodySize: number;
|
|
160
162
|
middlewareHeaders: Headers | null;
|
|
161
163
|
readFormDataWithLimit: ReadFormDataWithLimit;
|
|
@@ -6,24 +6,25 @@ import { parseEdgeRequestCookieHeader } from "../utils/parse-cookie.js";
|
|
|
6
6
|
import { isExternalUrl } from "../utils/external-url.js";
|
|
7
7
|
import { addBasePathToPathname, hasBasePath, stripBasePath } from "../utils/base-path.js";
|
|
8
8
|
import { NEXT_ROUTER_STATE_TREE_HEADER, VINEXT_RSC_VARY_HEADER } from "./app-rsc-vary.js";
|
|
9
|
-
import { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER } from "./headers.js";
|
|
9
|
+
import { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, VINEXT_MOUNTED_LAYOUTS_HEADER, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER } from "./headers.js";
|
|
10
10
|
import { internalServerErrorResponse, payloadTooLargeResponse } from "./http-error-responses.js";
|
|
11
11
|
import { attachRequestCfMetadata, validateCsrfOrigin, validateServerActionPayload } from "./request-pipeline.js";
|
|
12
12
|
import { splitPathSegments } from "../routing/utils.js";
|
|
13
13
|
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
14
|
+
import { logRequestError } from "./request-error-log.js";
|
|
14
15
|
import { shareIsolatePromise } from "./isolate-shared-promise.js";
|
|
15
16
|
import { APP_RSC_RENDER_MODE_NAVIGATION } from "./app-rsc-render-mode.js";
|
|
16
17
|
import { isDraftModeRequest, setHeadersContext } from "../shims/headers.js";
|
|
17
18
|
import { _drainPendingRevalidations, getAndClearActionRevalidationKind } from "../shims/cache-request-state.js";
|
|
18
19
|
import { setCurrentFetchCacheMode, setCurrentFetchRevalidate, setCurrentFetchSoftTags, setCurrentForceDynamicFetchDefault } from "../shims/fetch-cache.js";
|
|
19
20
|
import { readStreamAsTextWithLimit } from "../utils/text-stream.js";
|
|
20
|
-
import { VINEXT_RSC_CONTENT_TYPE, applyRscCompatibilityIdHeader, createRscRequestUrl, stripRscCacheBustingSearchParam } from "./app-rsc-cache-busting.js";
|
|
21
21
|
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
22
|
+
import { VINEXT_RSC_CONTENT_TYPE, applyRscCompatibilityIdHeader, createRscRequestUrl, stripRscCacheBustingSearchParam } from "./app-rsc-cache-busting.js";
|
|
23
|
+
import { getSetCookieName } from "./cookie-utils.js";
|
|
24
|
+
import { createServerActionNotFoundResponse, getServerActionNotFoundMessage, isServerActionNotFoundError } from "./server-action-not-found.js";
|
|
22
25
|
import { applyEdgeRuntimeHeader } from "./app-page-response.js";
|
|
23
26
|
import { getNextErrorDigest, parseNextHttpErrorDigest, parseNextRedirectDigest } from "./next-error-digest.js";
|
|
24
27
|
import { hasDigest } from "./app-rsc-errors.js";
|
|
25
|
-
import { getSetCookieName } from "./cookie-utils.js";
|
|
26
|
-
import { createServerActionNotFoundResponse, getServerActionNotFoundMessage, isServerActionNotFoundError } from "./server-action-not-found.js";
|
|
27
28
|
import { resolveAppPageNavigationParams } from "./app-page-element-builder.js";
|
|
28
29
|
import "./app-page-stream.js";
|
|
29
30
|
import { buildAppPageTags } from "./implicit-tags.js";
|
|
@@ -211,6 +212,7 @@ async function createActionRedirectTargetRequest(options) {
|
|
|
211
212
|
headers.set("cookie", cookieHeader ?? "");
|
|
212
213
|
headers.set("RSC", "1");
|
|
213
214
|
headers.delete(NEXT_ROUTER_STATE_TREE_HEADER);
|
|
215
|
+
headers.delete(VINEXT_MOUNTED_LAYOUTS_HEADER);
|
|
214
216
|
stripRscCacheBustingSearchParam(options.url);
|
|
215
217
|
const requestPath = await createRscRequestUrl(`${options.url.pathname}${options.url.search}`, headers);
|
|
216
218
|
const requestUrl = new URL(requestPath, options.url.origin);
|
|
@@ -508,7 +510,10 @@ function createRejectedActionResult(error) {
|
|
|
508
510
|
* Next.js, a thrown string is not logged in development.
|
|
509
511
|
*/
|
|
510
512
|
function logRejectedActionResult(error) {
|
|
511
|
-
if (process.env.NODE_ENV === "production" || hasDigest(error))
|
|
513
|
+
if (process.env.NODE_ENV === "production" || hasDigest(error)) {
|
|
514
|
+
if (typeof error === "string") console.error("[vinext] Server action error:", error);
|
|
515
|
+
else logRequestError("[vinext] Server action error:", error);
|
|
516
|
+
}
|
|
512
517
|
}
|
|
513
518
|
function getActionHttpFallbackStatus(error) {
|
|
514
519
|
const digest = getNextErrorDigest(error);
|
|
@@ -519,7 +524,7 @@ function getActionHttpFallbackStatus(error) {
|
|
|
519
524
|
}
|
|
520
525
|
function createServerActionErrorResponse(error, options) {
|
|
521
526
|
options.getAndClearPendingCookies();
|
|
522
|
-
|
|
527
|
+
logRequestError("[vinext] Server action error:", error);
|
|
523
528
|
options.reportRequestError(error, {
|
|
524
529
|
path: options.cleanPathname,
|
|
525
530
|
method: options.request.method,
|
|
@@ -614,6 +619,7 @@ async function handleProgressiveServerActionRequest(options) {
|
|
|
614
619
|
let actionThrew = false;
|
|
615
620
|
let actionResult;
|
|
616
621
|
const rootParamsUsage = createRootParamsUsageController();
|
|
622
|
+
if (options.currentRoute) setCurrentFetchSoftTags(buildServerActionPageTags(options.currentRoute, options.cleanPathname));
|
|
617
623
|
const previousHeadersPhase = options.setHeadersAccessPhase("action");
|
|
618
624
|
try {
|
|
619
625
|
actionResult = await runWithRootParamsUsage({ kind: "server-action" }, action, rootParamsUsage);
|
|
@@ -625,7 +631,7 @@ async function handleProgressiveServerActionRequest(options) {
|
|
|
625
631
|
actionFailed = true;
|
|
626
632
|
actionFailedWithError = getActionHttpFallbackStatus(error) === null && !isServerActionNotFoundError(error, null);
|
|
627
633
|
if (actionFailedWithError) {
|
|
628
|
-
|
|
634
|
+
logRequestError("[vinext] Server action error:", error);
|
|
629
635
|
options.reportRequestError(error, {
|
|
630
636
|
path: options.cleanPathname,
|
|
631
637
|
method: options.request.method,
|
|
@@ -697,7 +703,7 @@ async function handleProgressiveServerActionRequest(options) {
|
|
|
697
703
|
});
|
|
698
704
|
getAndClearActionRevalidationKind();
|
|
699
705
|
options.getAndClearPendingCookies();
|
|
700
|
-
|
|
706
|
+
logRequestError("[vinext] Server action payload parsing error:", error);
|
|
701
707
|
options.reportRequestError(error, {
|
|
702
708
|
path: options.cleanPathname,
|
|
703
709
|
method: options.request.method,
|
|
@@ -823,6 +829,7 @@ async function handleServerActionRscRequest(options) {
|
|
|
823
829
|
let actionThrew = false;
|
|
824
830
|
const actionWasForwarded = Boolean(options.request.headers.get(ACTION_FORWARDED_HEADER));
|
|
825
831
|
const rootParamsUsage = createRootParamsUsageController();
|
|
832
|
+
if (options.currentRouteMatch) setCurrentFetchSoftTags(buildServerActionPageTags(options.currentRouteMatch.route, options.cleanPathname));
|
|
826
833
|
const previousHeadersPhase = options.setHeadersAccessPhase("action");
|
|
827
834
|
try {
|
|
828
835
|
try {
|
|
@@ -25,6 +25,8 @@ export declare function handleSsr(rscStream: ReadableStream<Uint8Array>, navCont
|
|
|
25
25
|
value: Promise<ArrayBuffer> | null;
|
|
26
26
|
};
|
|
27
27
|
pprFallbackShellSignal?: AbortSignal;
|
|
28
|
+
/** Aborts a streaming render whose document is given up. */
|
|
29
|
+
signal?: AbortSignal;
|
|
28
30
|
/**
|
|
29
31
|
* Pattern of the route this render shows, whose client references load
|
|
30
32
|
* before it starts, or null for a render without a route (a route-miss
|
|
@@ -70,6 +72,12 @@ export declare function handleSsr(rscStream: ReadableStream<Uint8Array>, navCont
|
|
|
70
72
|
*/
|
|
71
73
|
isCacheCandidate?: boolean;
|
|
72
74
|
fallbackToErrorDocumentOnShellError?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Whether the RSC render threw the given shell error. As in Next.js, in
|
|
77
|
+
* dev the error document carries only an error that the HTML render alone
|
|
78
|
+
* threw, for the overlay: the browser reports the others itself.
|
|
79
|
+
*/
|
|
80
|
+
isServerComponentError?: (error: unknown) => boolean;
|
|
73
81
|
/**
|
|
74
82
|
* The parallel slot not-found boundaries that catch the error that
|
|
75
83
|
* rejected the shell, or null when none catches it. The document then
|
|
@@ -2,6 +2,7 @@ import { deferUntilStreamConsumed } from "./defer-until-stream-consumed.js";
|
|
|
2
2
|
import { notFoundResponse } from "./http-error-responses.js";
|
|
3
3
|
import { isOpenRedirectShaped, repeatedSlashRedirectResponse } from "./open-redirect.js";
|
|
4
4
|
import "./server-globals.js";
|
|
5
|
+
import { isNavigationSignalError } from "../utils/navigation-signal.js";
|
|
5
6
|
import { isPprFallbackShellAbortError } from "../shims/ppr-fallback-shell.js";
|
|
6
7
|
import { onRenderDynamicLatched } from "../shims/internal/headers-state.js";
|
|
7
8
|
import { AppRouterContext } from "../shims/internal/app-router-context.js";
|
|
@@ -10,23 +11,24 @@ import { withScriptNonce } from "../shims/script-nonce-context.js";
|
|
|
10
11
|
import { createInlineScriptTag, createNonceAttribute, escapeHtmlAttr, safeJsonStringify } from "./html.js";
|
|
11
12
|
import { getClientTraceMetadataHTML, markClientTraceMetadataBlock } from "./client-trace-metadata.js";
|
|
12
13
|
import { setPagesClientAssets } from "./pages-client-assets.js";
|
|
14
|
+
import { RSC_FORM_STATE_GLOBAL } from "../client/browser-globals.js";
|
|
15
|
+
import { createNavigationRuntimeRenderedSearchScript, createNavigationRuntimeRscCompatibilityScript, createNavigationRuntimeRscMetadataScript, createRscEmbedTransform, createTickBufferedTransform, rewriteInlineCssStylesheetLinks, waitAtLeastOneReactRenderTask } from "./app-ssr-stream.js";
|
|
13
16
|
import { AppElementsWire } from "./app-elements-wire.js";
|
|
14
17
|
import "./app-elements.js";
|
|
18
|
+
import { createInitialBfcacheMaps } from "./app-bfcache-identity.js";
|
|
19
|
+
import { isBailoutToCSRError, isDynamicServerError } from "../shims/navigation-errors.js";
|
|
15
20
|
import { ServerInsertedHTMLContext, clearServerInsertedHTML, getBfcacheIdMapContext, registerServerInsertedHTMLCallback, renderServerInsertedHTML, setNavigationContext } from "../shims/navigation-context-state.js";
|
|
16
21
|
import "../shims/navigation-server.js";
|
|
17
|
-
import DefaultGlobalError from "../shims/default-global-error.js";
|
|
18
|
-
import { CAUGHT_NOT_FOUND_BOUNDARIES_GLOBAL, withCaughtNotFoundBoundaries } from "../shims/caught-not-found-boundaries.js";
|
|
19
22
|
import { BfcacheIdentityMapContext } from "../shims/slot.js";
|
|
20
|
-
import { getNextErrorDigest } from "./next-error-digest.js";
|
|
21
|
-
import { createSsrErrorMetaRenderer } from "./app-ssr-error-meta.js";
|
|
22
|
-
import { createRenderStreamCancellation, isAppRenderAbortError } from "./app-render-abort-error.js";
|
|
23
|
-
import { RSC_FORM_STATE_GLOBAL } from "../client/browser-globals.js";
|
|
24
|
-
import { createNavigationRuntimeRenderedSearchScript, createNavigationRuntimeRscCompatibilityScript, createNavigationRuntimeRscMetadataScript, createRscEmbedTransform, createTickBufferedTransform, rewriteInlineCssStylesheetLinks, waitAtLeastOneReactRenderTask } from "./app-ssr-stream.js";
|
|
25
|
-
import { createInitialBfcacheMaps } from "./app-bfcache-identity.js";
|
|
26
23
|
import { createAppRouteTree } from "./app-route-tree.js";
|
|
24
|
+
import DefaultGlobalError from "../shims/default-global-error.js";
|
|
25
|
+
import { CAUGHT_NOT_FOUND_BOUNDARIES_GLOBAL, withCaughtNotFoundBoundaries } from "../shims/caught-not-found-boundaries.js";
|
|
27
26
|
import { ssrServerConsumerManifest } from "./app-client-reference-manifest.js";
|
|
28
27
|
import { createClientReferencePreloader, resolveRouteClientReferences } from "./app-client-reference-preloader.js";
|
|
28
|
+
import { getNextErrorDigest } from "./next-error-digest.js";
|
|
29
|
+
import { createSsrErrorMetaRenderer } from "./app-ssr-error-meta.js";
|
|
29
30
|
import { createClientPageSsrSearchParamsSource } from "./app-page-search-params-observation.js";
|
|
31
|
+
import { createRenderStreamCancellation, isAppRenderAbortError } from "./app-render-abort-error.js";
|
|
30
32
|
import { runWithRootParamsScope } from "../shims/root-params.js";
|
|
31
33
|
import { runWithNavigationContext } from "../shims/navigation-state.js";
|
|
32
34
|
import { startCandidateSearchParamsGate } from "./app-ssr-search-params-gate.js";
|
|
@@ -71,13 +73,14 @@ function createUtf8Stream(html) {
|
|
|
71
73
|
controller.close();
|
|
72
74
|
} });
|
|
73
75
|
}
|
|
74
|
-
function buildBootstrapModuleScript(bootstrapModuleUrl, nonce) {
|
|
76
|
+
function buildBootstrapModuleScript(bootstrapModuleUrl, nonce, crossOrigin) {
|
|
75
77
|
if (!bootstrapModuleUrl) return "";
|
|
76
|
-
|
|
78
|
+
const crossOriginAttribute = crossOrigin === void 0 ? "" : ` crossorigin="${crossOrigin === "use-credentials" ? "use-credentials" : ""}"`;
|
|
79
|
+
return `<script type="module"${createNonceAttribute(nonce)} src="` + escapeHtmlAttr(bootstrapModuleUrl) + `"${crossOriginAttribute} id="_R_" async="" fetchPriority="low"><\/script>`;
|
|
77
80
|
}
|
|
78
|
-
function renderSsrErrorDocumentShell(bootstrapModuleUrl, nonce) {
|
|
79
|
-
const html = renderToStaticMarkup(createElement(DefaultGlobalError, { error: null })).replace("<style>", "<style data-vinext-error-shell-style=\"\">");
|
|
80
|
-
const bootstrapScript = buildBootstrapModuleScript(bootstrapModuleUrl, nonce);
|
|
81
|
+
function renderSsrErrorDocumentShell(bootstrapModuleUrl, nonce, crossOrigin) {
|
|
82
|
+
const html = renderToStaticMarkup(createElement(DefaultGlobalError, { error: null })).replace("<head>", "<head><meta name=\"robots\" content=\"noindex\"/>").replace("<style>", "<style data-vinext-error-shell-style=\"\">");
|
|
83
|
+
const bootstrapScript = buildBootstrapModuleScript(bootstrapModuleUrl, nonce, crossOrigin);
|
|
81
84
|
if (!bootstrapScript) return createUtf8Stream(`<!DOCTYPE html>${html}`);
|
|
82
85
|
const documentClose = "</body></html>";
|
|
83
86
|
if (!html.endsWith(documentClose)) return createUtf8Stream(`<!DOCTYPE html>${html}${bootstrapScript}`);
|
|
@@ -277,6 +280,7 @@ async function handleSsr(rscStream, navContext, fontData, options) {
|
|
|
277
280
|
if (link) reactLinkHeader = link;
|
|
278
281
|
} : void 0,
|
|
279
282
|
maxHeadersLength: captureHeaders ? maxHeadersLength : void 0,
|
|
283
|
+
signal: options?.signal,
|
|
280
284
|
onError(error) {
|
|
281
285
|
if (pprFallbackShellSignal && isPprFallbackShellAbortError(error)) return;
|
|
282
286
|
if (isAppRenderAbortError(error) || htmlCancellation.isReason(error)) return;
|
|
@@ -291,6 +295,7 @@ async function handleSsr(rscStream, navContext, fontData, options) {
|
|
|
291
295
|
let htmlStream;
|
|
292
296
|
let renderComplete = Promise.resolve();
|
|
293
297
|
let shellErrorRecovered = false;
|
|
298
|
+
let ssrOnlyShellError;
|
|
294
299
|
let caughtShellError;
|
|
295
300
|
let caughtBoundaries = null;
|
|
296
301
|
let shouldDelayInitialHtmlPull = false;
|
|
@@ -354,10 +359,11 @@ async function handleSsr(rscStream, navContext, fontData, options) {
|
|
|
354
359
|
shouldDelayInitialHtmlPull = options?.waitForAllReady !== true;
|
|
355
360
|
caughtShellError = error;
|
|
356
361
|
htmlStream = caughtHtmlStream;
|
|
357
|
-
} else if (options?.fallbackToErrorDocumentOnShellError !== true ||
|
|
362
|
+
} else if (options?.fallbackToErrorDocumentOnShellError !== true || isNavigationSignalError(error) || isBailoutToCSRError(error) || isDynamicServerError(error)) throw error;
|
|
358
363
|
else {
|
|
359
364
|
shellErrorRecovered = true;
|
|
360
|
-
|
|
365
|
+
if (options?.isServerComponentError?.(error) !== true) ssrOnlyShellError = error;
|
|
366
|
+
htmlStream = renderSsrErrorDocumentShell(bootstrapModuleUrl, options?.scriptNonce, assetCrossOrigin);
|
|
361
367
|
}
|
|
362
368
|
}
|
|
363
369
|
}
|
|
@@ -384,7 +390,7 @@ async function handleSsr(rscStream, navContext, fontData, options) {
|
|
|
384
390
|
const getInsertedHTML = () => {
|
|
385
391
|
const insertedHTML = renderInsertedHtml(renderServerInsertedHTML());
|
|
386
392
|
const errorMetaHTML = errorMetaRenderer.flush();
|
|
387
|
-
const initialDevServerErrorHTML = createInitialDevServerErrorScript(options?.initialDevServerError, options?.scriptNonce);
|
|
393
|
+
const initialDevServerErrorHTML = createInitialDevServerErrorScript(options?.initialDevServerError ?? ssrOnlyShellError, options?.scriptNonce);
|
|
388
394
|
if (didInjectHeadHTML) return insertedHTML + errorMetaHTML + getRenderedSearchHTML();
|
|
389
395
|
didInjectHeadHTML = true;
|
|
390
396
|
const hidesQuery = searchParamsGate !== null && searchParamsGate.gate.decision !== "real";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createNonceAttribute, escapeHtmlAttr, htmlTokenListContains, safeJsonStringify, scriptSafeJsonStringify } from "./html.js";
|
|
2
|
-
import { getVinextRscCompatibilityId } from "./app-rsc-cache-busting.js";
|
|
3
2
|
import { bytesToBase64, concatUint8Arrays } from "./app-rsc-embedded-chunks.js";
|
|
4
3
|
import { NAVIGATION_RUNTIME_SYMBOL_DESCRIPTION } from "../client/browser-globals.js";
|
|
4
|
+
import { getVinextRscCompatibilityId } from "./app-rsc-cache-busting.js";
|
|
5
5
|
import { Buffer, isUtf8 } from "node:buffer";
|
|
6
6
|
//#region src/server/app-ssr-stream.ts
|
|
7
7
|
const RSC_EMBED_TEXT_BATCH_MAX_BYTES = 65536;
|
|
@@ -7,7 +7,17 @@ export type VisitedResponseCacheEntry = {
|
|
|
7
7
|
createdAt: number;
|
|
8
8
|
elements?: AppElements;
|
|
9
9
|
expiresAt: number;
|
|
10
|
+
/**
|
|
11
|
+
* Stored by initial hydration, which Next.js keeps out of its route cache
|
|
12
|
+
* (outside Cache Components), so a visible Link still prefetches the URL.
|
|
13
|
+
*/
|
|
14
|
+
fromHydration?: true;
|
|
10
15
|
mountedSlotsHeader: string | null;
|
|
16
|
+
/**
|
|
17
|
+
* A history restore revoked navigation reuse. The entry stays only as the
|
|
18
|
+
* BFCache that a full prefetch reads (see `findVisitedResponseForFullPrefetch`).
|
|
19
|
+
*/
|
|
20
|
+
navigationReuseRevoked?: true;
|
|
11
21
|
params: Record<string, string | string[]>;
|
|
12
22
|
response: CachedRscResponse;
|
|
13
23
|
reuseAfterHistoryRestore: boolean;
|
|
@@ -18,6 +28,7 @@ export declare function hasNavigationResponseHistoryLifetime(snapshot: CachedRsc
|
|
|
18
28
|
export declare function createVisitedResponseCacheEntry(options: {
|
|
19
29
|
elements?: AppElements;
|
|
20
30
|
fallbackTtlMs?: number;
|
|
31
|
+
fromHydration?: boolean;
|
|
21
32
|
now: number;
|
|
22
33
|
mountedSlotsHeader?: string | null;
|
|
23
34
|
params: Record<string, string | string[]>;
|
|
@@ -34,6 +45,30 @@ export declare function findVisitedResponseCacheEntry(cache: Map<string, Visited
|
|
|
34
45
|
} | null;
|
|
35
46
|
export declare function deleteVisitedResponseCacheEntry(cache: Map<string, VisitedResponseCacheEntry>, rscUrl: string, interceptionContext: string | null): boolean;
|
|
36
47
|
export declare function deleteAllVisitedResponseCacheEntries(cache: Map<string, VisitedResponseCacheEntry>, rscUrl: string, interceptionContext: string | null): number;
|
|
37
|
-
export declare function
|
|
48
|
+
export declare function revokeHistoryRestoreNavigationReuse(cache: Map<string, VisitedResponseCacheEntry>): void;
|
|
49
|
+
/**
|
|
50
|
+
* Next.js fulfills a full prefetch from the BFCache, which holds the data of
|
|
51
|
+
* every navigation, while it is within the static stale time of that
|
|
52
|
+
* navigation (`attemptToFulfillDynamicSegmentFromBFCache`). Navigation reuse
|
|
53
|
+
* that a history restore revoked does not matter here.
|
|
54
|
+
*
|
|
55
|
+
* Next.js dates a BFCache entry from its navigation, even one that committed an
|
|
56
|
+
* older prefetched payload. Its re-prefetch of an expired route still waits for
|
|
57
|
+
* a fresh route tree first, so a navigation made then fetches fresh data
|
|
58
|
+
* (`client-cache.experimental.test.ts`, "re-use the cache for 5 minutes").
|
|
59
|
+
* vinext seeds the full prefetch synchronously, so dating it from the
|
|
60
|
+
* navigation would replay that expired payload. It dates from when the payload
|
|
61
|
+
* arrived instead, which only costs a request Next.js might have saved.
|
|
62
|
+
*
|
|
63
|
+
* The match follows direct visited reuse: an entry with committed elements
|
|
64
|
+
* replays them, because its raw response may be skip-pruned against the tree
|
|
65
|
+
* it was requested from; otherwise the request-time or response-declared slot
|
|
66
|
+
* context must match.
|
|
67
|
+
*/
|
|
68
|
+
export declare function findVisitedResponseForFullPrefetch(cache: Map<string, VisitedResponseCacheEntry>, rscUrls: readonly string[], interceptionContext: string | null, mountedSlotsHeader: string | null): {
|
|
69
|
+
navigatedAt: number;
|
|
70
|
+
navigationFreshUntil: number | null;
|
|
71
|
+
response: CachedRscResponse;
|
|
72
|
+
} | null;
|
|
38
73
|
//#endregion
|
|
39
74
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { parseRscRequestPath, stripRscCacheBustingSearchParam } from "./app-rsc-cache-busting.js";
|
|
1
2
|
import { AppElementsWire } from "./app-elements-wire.js";
|
|
2
3
|
import "./app-elements.js";
|
|
3
|
-
import { parseRscRequestPath, stripRscCacheBustingSearchParam } from "./app-rsc-cache-busting.js";
|
|
4
4
|
import { resolveCachedRscResponseExpiresAt } from "../shims/navigation.js";
|
|
5
5
|
//#region src/server/app-visited-response-cache.ts
|
|
6
6
|
const VISITED_RESPONSE_CACHE_TTL = 3e5;
|
|
@@ -14,6 +14,7 @@ function createVisitedResponseCacheEntry(options) {
|
|
|
14
14
|
createdAt: options.now,
|
|
15
15
|
...options.elements ? { elements: options.elements } : {},
|
|
16
16
|
expiresAt: resolveCachedRscResponseExpiresAt(options.now, options.response, options.fallbackTtlMs ?? 3e5),
|
|
17
|
+
...options.fromHydration === true ? { fromHydration: true } : {},
|
|
17
18
|
mountedSlotsHeader: options.mountedSlotsHeader ?? null,
|
|
18
19
|
params: options.params,
|
|
19
20
|
response: options.response,
|
|
@@ -75,11 +76,51 @@ function deleteAllVisitedResponseCacheEntries(cache, rscUrl, interceptionContext
|
|
|
75
76
|
while (deleteVisitedResponseCacheEntry(cache, rscUrl, interceptionContext)) deleted++;
|
|
76
77
|
return deleted;
|
|
77
78
|
}
|
|
78
|
-
function
|
|
79
|
-
for (const
|
|
79
|
+
function revokeHistoryRestoreNavigationReuse(cache) {
|
|
80
|
+
for (const entry of cache.values()) {
|
|
80
81
|
if (entry.reuseAfterHistoryRestore) continue;
|
|
81
|
-
|
|
82
|
+
entry.navigationReuseRevoked = true;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Next.js fulfills a full prefetch from the BFCache, which holds the data of
|
|
87
|
+
* every navigation, while it is within the static stale time of that
|
|
88
|
+
* navigation (`attemptToFulfillDynamicSegmentFromBFCache`). Navigation reuse
|
|
89
|
+
* that a history restore revoked does not matter here.
|
|
90
|
+
*
|
|
91
|
+
* Next.js dates a BFCache entry from its navigation, even one that committed an
|
|
92
|
+
* older prefetched payload. Its re-prefetch of an expired route still waits for
|
|
93
|
+
* a fresh route tree first, so a navigation made then fetches fresh data
|
|
94
|
+
* (`client-cache.experimental.test.ts`, "re-use the cache for 5 minutes").
|
|
95
|
+
* vinext seeds the full prefetch synchronously, so dating it from the
|
|
96
|
+
* navigation would replay that expired payload. It dates from when the payload
|
|
97
|
+
* arrived instead, which only costs a request Next.js might have saved.
|
|
98
|
+
*
|
|
99
|
+
* The match follows direct visited reuse: an entry with committed elements
|
|
100
|
+
* replays them, because its raw response may be skip-pruned against the tree
|
|
101
|
+
* it was requested from; otherwise the request-time or response-declared slot
|
|
102
|
+
* context must match.
|
|
103
|
+
*/
|
|
104
|
+
function findVisitedResponseForFullPrefetch(cache, rscUrls, interceptionContext, mountedSlotsHeader) {
|
|
105
|
+
for (const rscUrl of rscUrls) {
|
|
106
|
+
const match = findVisitedResponseCacheEntry(cache, rscUrl, interceptionContext);
|
|
107
|
+
if (match === null) continue;
|
|
108
|
+
const { entry } = match;
|
|
109
|
+
if (entry.elements === void 0 && entry.mountedSlotsHeader !== mountedSlotsHeader && (entry.response.mountedSlotsHeader ?? null) !== mountedSlotsHeader) continue;
|
|
110
|
+
const navigationFresh = entry.fromHydration !== true && entry.navigationReuseRevoked !== true && (entry.elements !== void 0 || entry.mountedSlotsHeader === mountedSlotsHeader) && isVisitedResponseCacheEntryFresh(entry, {
|
|
111
|
+
navigationKind: "navigate",
|
|
112
|
+
now: Date.now()
|
|
113
|
+
});
|
|
114
|
+
return {
|
|
115
|
+
navigatedAt: entry.response.receivedAt ?? entry.createdAt,
|
|
116
|
+
navigationFreshUntil: navigationFresh ? entry.expiresAt : null,
|
|
117
|
+
response: entry.elements === void 0 ? entry.response : {
|
|
118
|
+
...entry.response,
|
|
119
|
+
preparedElements: entry.elements
|
|
120
|
+
}
|
|
121
|
+
};
|
|
82
122
|
}
|
|
123
|
+
return null;
|
|
83
124
|
}
|
|
84
125
|
//#endregion
|
|
85
|
-
export { MAX_TRAVERSAL_CACHE_TTL, VISITED_RESPONSE_CACHE_TTL, createVisitedResponseCacheEntry, deleteAllVisitedResponseCacheEntries,
|
|
126
|
+
export { MAX_TRAVERSAL_CACHE_TTL, VISITED_RESPONSE_CACHE_TTL, createVisitedResponseCacheEntry, deleteAllVisitedResponseCacheEntries, deleteVisitedResponseCacheEntry, findVisitedResponseCacheEntry, findVisitedResponseForFullPrefetch, hasNavigationResponseHistoryLifetime, isVisitedResponseCacheEntryFresh, revokeHistoryRestoreNavigationReuse };
|
|
@@ -3,7 +3,7 @@ import { VinextResponseStageCacheability, VinextResponseStageDispatchOptions, Vi
|
|
|
3
3
|
import { AppRscRenderMode } from "./app-rsc-render-mode.js";
|
|
4
4
|
import { TrustedPrerenderState } from "./prerender-route-params.js";
|
|
5
5
|
//#region src/server/app-worker-stages.d.ts
|
|
6
|
-
export declare const APP_WORKER_RESPONSE_STAGE_PROTOCOL_VERSION =
|
|
6
|
+
export declare const APP_WORKER_RESPONSE_STAGE_PROTOCOL_VERSION = 13;
|
|
7
7
|
export declare const APP_METADATA_RESPONSE_STAGE_NO_MATCH_HEADER = "x-vinext-app-metadata-stage-no-match";
|
|
8
8
|
type AppPageParams = Record<string, string | string[]>;
|
|
9
9
|
type AppWorkerResponseStageEnvelope = {
|
|
@@ -66,7 +66,7 @@ type AppMetadataWorkerResponseStageProps = AppWorkerResponseStageEnvelope & {
|
|
|
66
66
|
resolvedUrl: string;
|
|
67
67
|
routePathname: string;
|
|
68
68
|
};
|
|
69
|
-
type HybridPagesWorkerResponseStageProps = AppWorkerResponseStageEnvelope & {
|
|
69
|
+
export type HybridPagesWorkerResponseStageProps = AppWorkerResponseStageEnvelope & {
|
|
70
70
|
kind: "hybrid-pages";
|
|
71
71
|
allowRscDocumentFallback: boolean;
|
|
72
72
|
appRouteMatch: {
|
|
@@ -83,19 +83,50 @@ type HybridPagesWorkerResponseStageProps = AppWorkerResponseStageEnvelope & {
|
|
|
83
83
|
resourceKind: "api" | "page";
|
|
84
84
|
requestUrl: string;
|
|
85
85
|
resolvedUrl: string;
|
|
86
|
+
/**
|
|
87
|
+
* The shared cache entry answers every host, as Next.js keys a static page
|
|
88
|
+
* by its path, so a getInitialProps render of a page without
|
|
89
|
+
* getStaticProps, which reads the request, is not stored.
|
|
90
|
+
*/
|
|
91
|
+
sharedAcrossHosts: boolean;
|
|
86
92
|
};
|
|
87
93
|
export type AppWorkerResponseStageProps = AppFullRequestWorkerResponseStageProps | AppMatchedWorkerResponseStageProps | AppMetadataWorkerResponseStageProps | AppNotFoundWorkerResponseStageProps | HybridPagesWorkerResponseStageProps;
|
|
88
94
|
export type DispatchAppWorkerResponseStage = VinextResponseStageTransport<AppWorkerResponseStageProps>;
|
|
89
95
|
export type RenderAppWorkerResponseStageLocally = (request: Request, props: AppWorkerResponseStageProps) => Promise<Response>;
|
|
90
96
|
/** Normalize a shared App page HEAD request onto its method-invariant GET representation. */
|
|
91
97
|
export declare function prepareSharedAppPageDispatch(request: Request, cache: VinextResponseStageDispatchOptions["cache"]): Request;
|
|
98
|
+
type SharedAppCacheIdentity = NonNullable<VinextResponseStageDispatchOptions["cacheIdentity"]>;
|
|
99
|
+
/** App Router dispatches whose shared cache entry every host can reuse. */
|
|
100
|
+
export type SharedAppCacheIdentityProps = Exclude<AppWorkerResponseStageProps, {
|
|
101
|
+
kind: "app-full-request" | "hybrid-pages";
|
|
102
|
+
}>;
|
|
103
|
+
/**
|
|
104
|
+
* Build the cache identity of a shared App Router dispatch: the dispatched
|
|
105
|
+
* request and props under the cache identity origin.
|
|
106
|
+
*/
|
|
107
|
+
export declare function createSharedAppCacheIdentity(request: Request, props: SharedAppCacheIdentityProps): SharedAppCacheIdentity;
|
|
92
108
|
/**
|
|
93
109
|
* Build the query-free cache identity of a shared App page dispatch. The user
|
|
94
|
-
* query leaves both the URL and `resolvedUrl`;
|
|
95
|
-
*
|
|
96
|
-
|
|
110
|
+
* query leaves both the URL and `resolvedUrl`; an RSC request's validated
|
|
111
|
+
* `_rsc` and the render mode stay because they select the representation. HTML identities also drop the RSC selector headers.
|
|
112
|
+
*/
|
|
113
|
+
export declare function createSharedAppPageCacheIdentity(request: Request, props: AppMatchedWorkerResponseStageProps): SharedAppCacheIdentity;
|
|
114
|
+
/**
|
|
115
|
+
* Build the query-free cache identity of a shared Route Handler or metadata
|
|
116
|
+
* route dispatch. Next.js keys a route handler by its pathname: the query and
|
|
117
|
+
* the RSC selectors pick no representation of a handler's response, and a
|
|
118
|
+
* handler that reads the request's URL or headers is dynamic, so admission
|
|
119
|
+
* refuses its response. Keeping them in the identity would only let a client
|
|
120
|
+
* store one entry per query or selector value. The method, path and route
|
|
121
|
+
* props stay; the selector headers and the props derived from them leave.
|
|
122
|
+
*/
|
|
123
|
+
export declare function createSharedAppRouteCacheIdentity(request: Request, props: AppMatchedWorkerResponseStageProps | AppMetadataWorkerResponseStageProps): SharedAppCacheIdentity;
|
|
124
|
+
/**
|
|
125
|
+
* Build the cache identity of a shared hybrid Pages page dispatch: the
|
|
126
|
+
* dispatched request and props under `origin`, so every host that names it
|
|
127
|
+
* shares one entry.
|
|
97
128
|
*/
|
|
98
|
-
export declare function
|
|
129
|
+
export declare function createSharedHybridPagesCacheIdentity(request: Request, props: HybridPagesWorkerResponseStageProps, origin: string): SharedAppCacheIdentity;
|
|
99
130
|
/**
|
|
100
131
|
* Drop the user query from an App page dispatch URL and its `resolvedUrl`,
|
|
101
132
|
* keeping an RSC request's validated `_rsc`, the rule the query-free cache
|