vinext 0.0.40 → 0.0.42
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 -2
- package/dist/build/client-build-config.d.ts +119 -0
- package/dist/build/client-build-config.js +149 -0
- package/dist/build/client-build-config.js.map +1 -0
- package/dist/build/layout-classification-types.d.ts +62 -0
- package/dist/build/layout-classification-types.js +1 -0
- package/dist/build/layout-classification.d.ts +60 -0
- package/dist/build/layout-classification.js +98 -0
- package/dist/build/layout-classification.js.map +1 -0
- package/dist/build/report.d.ts +15 -1
- package/dist/build/report.js +50 -1
- package/dist/build/report.js.map +1 -1
- package/dist/build/route-classification-manifest.d.ts +53 -0
- package/dist/build/route-classification-manifest.js +145 -0
- package/dist/build/route-classification-manifest.js.map +1 -0
- package/dist/build/run-prerender.js +1 -1
- package/dist/build/ssr-manifest.d.ts +19 -0
- package/dist/build/ssr-manifest.js +71 -0
- package/dist/build/ssr-manifest.js.map +1 -0
- package/dist/check.js +4 -4
- package/dist/check.js.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/client/entry.js +1 -1
- package/dist/config/config-matchers.js +1 -0
- package/dist/config/config-matchers.js.map +1 -1
- package/dist/entries/app-rsc-entry.js +341 -114
- package/dist/entries/app-rsc-entry.js.map +1 -1
- package/dist/entries/pages-server-entry.js +205 -199
- package/dist/entries/pages-server-entry.js.map +1 -1
- package/dist/index.d.ts +1 -169
- package/dist/index.js +113 -432
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +1 -1
- package/dist/init.js +2 -2
- package/dist/init.js.map +1 -1
- package/dist/plugins/fonts.d.ts +49 -1
- package/dist/plugins/fonts.js +97 -3
- package/dist/plugins/fonts.js.map +1 -1
- package/dist/plugins/postcss.d.ts +27 -0
- package/dist/plugins/postcss.js +94 -0
- package/dist/plugins/postcss.js.map +1 -0
- package/dist/plugins/strip-server-exports.d.ts +14 -0
- package/dist/plugins/strip-server-exports.js +73 -0
- package/dist/plugins/strip-server-exports.js.map +1 -0
- package/dist/routing/app-router.d.ts +6 -4
- package/dist/routing/app-router.js +21 -22
- package/dist/routing/app-router.js.map +1 -1
- package/dist/server/app-browser-entry.js +235 -97
- package/dist/server/app-browser-entry.js.map +1 -1
- package/dist/server/app-browser-error.d.ts +8 -0
- package/dist/server/app-browser-error.js +9 -0
- package/dist/server/app-browser-error.js.map +1 -0
- package/dist/server/app-browser-state.d.ts +93 -0
- package/dist/server/app-browser-state.js +132 -0
- package/dist/server/app-browser-state.js.map +1 -0
- package/dist/server/app-elements.d.ts +92 -0
- package/dist/server/app-elements.js +122 -0
- package/dist/server/app-elements.js.map +1 -0
- package/dist/server/app-page-boundary-render.d.ts +3 -1
- package/dist/server/app-page-boundary-render.js +41 -1
- package/dist/server/app-page-boundary-render.js.map +1 -1
- package/dist/server/app-page-cache.d.ts +6 -3
- package/dist/server/app-page-cache.js +14 -8
- package/dist/server/app-page-cache.js.map +1 -1
- package/dist/server/app-page-execution.d.ts +36 -3
- package/dist/server/app-page-execution.js +50 -10
- package/dist/server/app-page-execution.js.map +1 -1
- package/dist/server/app-page-probe.d.ts +10 -4
- package/dist/server/app-page-probe.js +24 -15
- package/dist/server/app-page-probe.js.map +1 -1
- package/dist/server/app-page-render.d.ts +8 -4
- package/dist/server/app-page-render.js +15 -4
- package/dist/server/app-page-render.js.map +1 -1
- package/dist/server/app-page-request.d.ts +52 -4
- package/dist/server/app-page-request.js +86 -16
- package/dist/server/app-page-request.js.map +1 -1
- package/dist/server/app-page-response.d.ts +4 -11
- package/dist/server/app-page-response.js +7 -19
- package/dist/server/app-page-response.js.map +1 -1
- package/dist/server/app-page-route-wiring.d.ts +22 -8
- package/dist/server/app-page-route-wiring.js +219 -81
- package/dist/server/app-page-route-wiring.js.map +1 -1
- package/dist/server/app-page-stream.d.ts +4 -1
- package/dist/server/app-page-stream.js +2 -1
- package/dist/server/app-page-stream.js.map +1 -1
- package/dist/server/app-render-dependency.d.ts +13 -0
- package/dist/server/app-render-dependency.js +35 -0
- package/dist/server/app-render-dependency.js.map +1 -0
- package/dist/server/app-route-handler-execution.d.ts +1 -0
- package/dist/server/app-route-handler-execution.js +1 -0
- package/dist/server/app-route-handler-execution.js.map +1 -1
- package/dist/server/app-route-handler-response.js +2 -1
- package/dist/server/app-route-handler-response.js.map +1 -1
- package/dist/server/app-route-handler-runtime.d.ts +1 -0
- package/dist/server/app-route-handler-runtime.js +26 -1
- package/dist/server/app-route-handler-runtime.js.map +1 -1
- package/dist/server/app-ssr-entry.d.ts +3 -1
- package/dist/server/app-ssr-entry.js +23 -19
- package/dist/server/app-ssr-entry.js.map +1 -1
- package/dist/server/app-ssr-stream.d.ts +1 -1
- package/dist/server/app-ssr-stream.js +4 -4
- package/dist/server/app-ssr-stream.js.map +1 -1
- package/dist/server/csp.d.ts +12 -0
- package/dist/server/csp.js +46 -0
- package/dist/server/csp.js.map +1 -0
- package/dist/server/dev-server.js +22 -18
- package/dist/server/dev-server.js.map +1 -1
- package/dist/server/html.d.ts +4 -1
- package/dist/server/html.js +11 -1
- package/dist/server/html.js.map +1 -1
- package/dist/server/middleware-response-headers.d.ts +12 -0
- package/dist/server/middleware-response-headers.js +23 -0
- package/dist/server/middleware-response-headers.js.map +1 -0
- package/dist/server/middleware.js +1 -5
- package/dist/server/middleware.js.map +1 -1
- package/dist/server/pages-page-data.d.ts +1 -0
- package/dist/server/pages-page-data.js +2 -2
- package/dist/server/pages-page-data.js.map +1 -1
- package/dist/server/pages-page-response.d.ts +2 -1
- package/dist/server/pages-page-response.js +16 -14
- package/dist/server/pages-page-response.js.map +1 -1
- package/dist/server/prod-server.d.ts +3 -3
- package/dist/server/prod-server.js +5 -4
- package/dist/server/prod-server.js.map +1 -1
- package/dist/server/request-pipeline.d.ts +15 -1
- package/dist/server/request-pipeline.js +88 -5
- package/dist/server/request-pipeline.js.map +1 -1
- package/dist/shims/cache-runtime.d.ts +1 -0
- package/dist/shims/cache-runtime.js +0 -5
- package/dist/shims/cache-runtime.js.map +1 -1
- package/dist/shims/cache.d.ts +1 -0
- package/dist/shims/cache.js +1 -8
- package/dist/shims/cache.js.map +1 -1
- package/dist/shims/client-hook-error.d.ts +14 -0
- package/dist/shims/client-hook-error.js +19 -0
- package/dist/shims/client-hook-error.js.map +1 -0
- package/dist/shims/constants.d.ts +3 -3
- package/dist/shims/constants.js +3 -3
- package/dist/shims/constants.js.map +1 -1
- package/dist/shims/document.d.ts +6 -6
- package/dist/shims/error-boundary.d.ts +4 -4
- package/dist/shims/error-boundary.js +1 -1
- package/dist/shims/error-boundary.js.map +1 -1
- package/dist/shims/form.d.ts +3 -3
- package/dist/shims/head-state.d.ts +1 -0
- package/dist/shims/head-state.js +0 -5
- package/dist/shims/head-state.js.map +1 -1
- package/dist/shims/headers.d.ts +11 -0
- package/dist/shims/headers.js +13 -10
- package/dist/shims/headers.js.map +1 -1
- package/dist/shims/i18n-state.d.ts +1 -0
- package/dist/shims/i18n-state.js +0 -4
- package/dist/shims/i18n-state.js.map +1 -1
- package/dist/shims/internal/app-router-context.d.ts +6 -6
- package/dist/shims/internal/router-context.d.ts +2 -2
- package/dist/shims/layout-segment-context.d.ts +2 -2
- package/dist/shims/link.js +19 -11
- package/dist/shims/link.js.map +1 -1
- package/dist/shims/metadata.d.ts +3 -3
- package/dist/shims/navigation-state.d.ts +2 -0
- package/dist/shims/navigation-state.js +0 -13
- package/dist/shims/navigation-state.js.map +1 -1
- package/dist/shims/navigation.d.ts +55 -8
- package/dist/shims/navigation.js +97 -23
- package/dist/shims/navigation.js.map +1 -1
- package/dist/shims/navigation.react-server.d.ts +14 -0
- package/dist/shims/navigation.react-server.js +29 -0
- package/dist/shims/navigation.react-server.js.map +1 -0
- package/dist/shims/request-context.d.ts +1 -0
- package/dist/shims/request-context.js +0 -9
- package/dist/shims/request-context.js.map +1 -1
- package/dist/shims/request-state-types.d.ts +1 -1
- package/dist/shims/router-state.d.ts +1 -0
- package/dist/shims/router-state.js +0 -5
- package/dist/shims/router-state.js.map +1 -1
- package/dist/shims/script-nonce-context.d.ts +12 -0
- package/dist/shims/script-nonce-context.js +17 -0
- package/dist/shims/script-nonce-context.js.map +1 -0
- package/dist/shims/script.js +41 -10
- package/dist/shims/script.js.map +1 -1
- package/dist/shims/server.js +6 -1
- package/dist/shims/server.js.map +1 -1
- package/dist/shims/slot.d.ts +11 -7
- package/dist/shims/slot.js +28 -19
- package/dist/shims/slot.js.map +1 -1
- package/dist/shims/unified-request-context.d.ts +2 -0
- package/dist/shims/unified-request-context.js +0 -14
- package/dist/shims/unified-request-context.js.map +1 -1
- package/dist/shims/url-safety.js +25 -4
- package/dist/shims/url-safety.js.map +1 -1
- package/dist/utils/mdx-scan.d.ts +10 -0
- package/dist/utils/mdx-scan.js +36 -0
- package/dist/utils/mdx-scan.js.map +1 -0
- package/dist/utils/public-routes.d.ts +5 -0
- package/dist/utils/public-routes.js +50 -0
- package/dist/utils/public-routes.js.map +1 -0
- package/package.json +9 -9
- package/dist/plugins/fix-use-server-closure-collision.d.ts +0 -29
- package/dist/plugins/fix-use-server-closure-collision.js +0 -204
- package/dist/plugins/fix-use-server-closure-collision.js.map +0 -1
|
@@ -15,6 +15,7 @@ import fs from "node:fs";
|
|
|
15
15
|
*/
|
|
16
16
|
const configMatchersPath = resolveEntryPath("../config/config-matchers.js", import.meta.url);
|
|
17
17
|
const requestPipelinePath = resolveEntryPath("../server/request-pipeline.js", import.meta.url);
|
|
18
|
+
const middlewareRequestHeadersPath = resolveEntryPath("../server/middleware-request-headers.js", import.meta.url);
|
|
18
19
|
const requestContextShimPath = resolveEntryPath("../shims/request-context.js", import.meta.url);
|
|
19
20
|
const normalizePathModulePath = resolveEntryPath("../server/normalize-path.js", import.meta.url);
|
|
20
21
|
const appRouteHandlerRuntimePath = resolveEntryPath("../server/app-route-handler-runtime.js", import.meta.url);
|
|
@@ -24,9 +25,11 @@ const appRouteHandlerCachePath = resolveEntryPath("../server/app-route-handler-c
|
|
|
24
25
|
const appPageCachePath = resolveEntryPath("../server/app-page-cache.js", import.meta.url);
|
|
25
26
|
const appPageExecutionPath = resolveEntryPath("../server/app-page-execution.js", import.meta.url);
|
|
26
27
|
const appPageBoundaryRenderPath = resolveEntryPath("../server/app-page-boundary-render.js", import.meta.url);
|
|
28
|
+
const appElementsPath = resolveEntryPath("../server/app-elements.js", import.meta.url);
|
|
27
29
|
const appPageRouteWiringPath = resolveEntryPath("../server/app-page-route-wiring.js", import.meta.url);
|
|
28
30
|
const appPageRenderPath = resolveEntryPath("../server/app-page-render.js", import.meta.url);
|
|
29
31
|
const appPageResponsePath = resolveEntryPath("../server/app-page-response.js", import.meta.url);
|
|
32
|
+
const cspPath = resolveEntryPath("../server/csp.js", import.meta.url);
|
|
30
33
|
const appPageRequestPath = resolveEntryPath("../server/app-page-request.js", import.meta.url);
|
|
31
34
|
const appRouteHandlerResponsePath = resolveEntryPath("../server/app-route-handler-response.js", import.meta.url);
|
|
32
35
|
const routeTriePath = resolveEntryPath("../routing/route-trie.js", import.meta.url);
|
|
@@ -68,7 +71,7 @@ function generateRscEntry(appDir, routes, middlewarePath, metadataRoutes, global
|
|
|
68
71
|
if (route.pagePath) getImportVar(route.pagePath);
|
|
69
72
|
if (route.routePath) getImportVar(route.routePath);
|
|
70
73
|
for (const layout of route.layouts) getImportVar(layout);
|
|
71
|
-
for (const tmpl of route.templates)
|
|
74
|
+
for (const tmpl of route.templates) getImportVar(tmpl);
|
|
72
75
|
if (route.loadingPath) getImportVar(route.loadingPath);
|
|
73
76
|
if (route.errorPath) getImportVar(route.errorPath);
|
|
74
77
|
if (route.layoutErrorPaths) {
|
|
@@ -87,9 +90,9 @@ function generateRscEntry(appDir, routes, middlewarePath, metadataRoutes, global
|
|
|
87
90
|
for (const ir of slot.interceptingRoutes) getImportVar(ir.pagePath);
|
|
88
91
|
}
|
|
89
92
|
}
|
|
90
|
-
const routeEntries = routes.map((route) => {
|
|
93
|
+
const routeEntries = routes.map((route, routeIdx) => {
|
|
91
94
|
const layoutVars = route.layouts.map((l) => getImportVar(l));
|
|
92
|
-
const templateVars = route.templates.map((t) =>
|
|
95
|
+
const templateVars = route.templates.map((t) => getImportVar(t));
|
|
93
96
|
const notFoundVars = (route.notFoundPaths || []).map((nf) => nf ? getImportVar(nf) : "null");
|
|
94
97
|
const slotEntries = route.parallelSlots.map((slot) => {
|
|
95
98
|
const interceptEntries = slot.interceptingRoutes.map((ir) => ` {
|
|
@@ -98,7 +101,8 @@ function generateRscEntry(appDir, routes, middlewarePath, metadataRoutes, global
|
|
|
98
101
|
page: ${getImportVar(ir.pagePath)},
|
|
99
102
|
params: ${JSON.stringify(ir.params)},
|
|
100
103
|
}`);
|
|
101
|
-
return ` ${JSON.stringify(slot.
|
|
104
|
+
return ` ${JSON.stringify(slot.key)}: {
|
|
105
|
+
name: ${JSON.stringify(slot.name)},
|
|
102
106
|
page: ${slot.pagePath ? getImportVar(slot.pagePath) : "null"},
|
|
103
107
|
default: ${slot.defaultPath ? getImportVar(slot.defaultPath) : "null"},
|
|
104
108
|
layout: ${slot.layoutPath ? getImportVar(slot.layoutPath) : "null"},
|
|
@@ -113,6 +117,8 @@ ${interceptEntries.join(",\n")}
|
|
|
113
117
|
});
|
|
114
118
|
const layoutErrorVars = (route.layoutErrorPaths || []).map((ep) => ep ? getImportVar(ep) : "null");
|
|
115
119
|
return ` {
|
|
120
|
+
__buildTimeClassifications: __VINEXT_CLASS(${routeIdx}), // evaluated once at module load
|
|
121
|
+
__buildTimeReasons: __classDebug ? __VINEXT_CLASS_REASONS(${routeIdx}) : null,
|
|
116
122
|
pattern: ${JSON.stringify(route.pattern)},
|
|
117
123
|
patternParts: ${JSON.stringify(route.patternParts)},
|
|
118
124
|
isDynamic: ${route.isDynamic},
|
|
@@ -121,6 +127,7 @@ ${interceptEntries.join(",\n")}
|
|
|
121
127
|
routeHandler: ${route.routePath ? getImportVar(route.routePath) : "null"},
|
|
122
128
|
layouts: [${layoutVars.join(", ")}],
|
|
123
129
|
routeSegments: ${JSON.stringify(route.routeSegments)},
|
|
130
|
+
templateTreePositions: ${JSON.stringify(route.templateTreePositions)},
|
|
124
131
|
layoutTreePositions: ${JSON.stringify(route.layoutTreePositions)},
|
|
125
132
|
templates: [${templateVars.join(", ")}],
|
|
126
133
|
errors: [${layoutErrorVars.join(", ")}],
|
|
@@ -218,7 +225,8 @@ ${instrumentationPath ? `import * as _instrumentation from ${JSON.stringify(inst
|
|
|
218
225
|
${effectiveMetaRoutes.length > 0 ? `import { sitemapToXml, robotsToText, manifestToJson } from ${JSON.stringify(metadataRoutesPath)};` : ""}
|
|
219
226
|
import { requestContextFromRequest, normalizeHost, matchRedirect, matchRewrite, matchHeaders, isExternalUrl, proxyExternalRequest, sanitizeDestination } from ${JSON.stringify(configMatchersPath)};
|
|
220
227
|
import { decodePathParams as __decodePathParams } from ${JSON.stringify(normalizePathModulePath)};
|
|
221
|
-
import {
|
|
228
|
+
import { buildRequestHeadersFromMiddlewareResponse as __buildRequestHeadersFromMiddlewareResponse } from ${JSON.stringify(middlewareRequestHeadersPath)};
|
|
229
|
+
import { validateCsrfOrigin, validateServerActionPayload, validateImageUrl, guardProtocolRelativeUrl, hasBasePath, stripBasePath, normalizeTrailingSlash, processMiddlewareHeaders } from ${JSON.stringify(requestPipelinePath)};
|
|
222
230
|
import {
|
|
223
231
|
isKnownDynamicAppRoute as __isKnownDynamicAppRoute,
|
|
224
232
|
} from ${JSON.stringify(appRouteHandlerRuntimePath)};
|
|
@@ -245,7 +253,12 @@ import {
|
|
|
245
253
|
renderAppPageHttpAccessFallback as __renderAppPageHttpAccessFallback,
|
|
246
254
|
} from ${JSON.stringify(appPageBoundaryRenderPath)};
|
|
247
255
|
import {
|
|
248
|
-
|
|
256
|
+
APP_INTERCEPTION_CONTEXT_KEY as __APP_INTERCEPTION_CONTEXT_KEY,
|
|
257
|
+
createAppPayloadRouteId as __createAppPayloadRouteId,
|
|
258
|
+
} from ${JSON.stringify(appElementsPath)};
|
|
259
|
+
import {
|
|
260
|
+
buildAppPageElements as __buildAppPageElements,
|
|
261
|
+
createAppPageTreePath as __createAppPageTreePath,
|
|
249
262
|
resolveAppPageChildSegments as __resolveAppPageChildSegments,
|
|
250
263
|
} from ${JSON.stringify(appPageRouteWiringPath)};
|
|
251
264
|
import {
|
|
@@ -254,7 +267,9 @@ import {
|
|
|
254
267
|
import {
|
|
255
268
|
mergeMiddlewareResponseHeaders as __mergeMiddlewareResponseHeaders,
|
|
256
269
|
} from ${JSON.stringify(appPageResponsePath)};
|
|
270
|
+
import { getScriptNonceFromHeaderSources as __getScriptNonceFromHeaderSources } from ${JSON.stringify(cspPath)};
|
|
257
271
|
import {
|
|
272
|
+
resolveAppPageActionRerenderTarget as __resolveAppPageActionRerenderTarget,
|
|
258
273
|
buildAppPageElement as __buildAppPageElement,
|
|
259
274
|
resolveAppPageIntercept as __resolveAppPageIntercept,
|
|
260
275
|
validateAppPageDynamicParams as __validateAppPageDynamicParams,
|
|
@@ -395,7 +410,21 @@ function __isrCacheKey(pathname, suffix) {
|
|
|
395
410
|
return prefix + ":__hash:" + __isrFnv1a64(normalized) + ":" + suffix;
|
|
396
411
|
}
|
|
397
412
|
function __isrHtmlKey(pathname) { return __isrCacheKey(pathname, "html"); }
|
|
398
|
-
function __isrRscKey(pathname
|
|
413
|
+
function __isrRscKey(pathname, mountedSlotsHeader) {
|
|
414
|
+
if (!mountedSlotsHeader) return __isrCacheKey(pathname, "rsc");
|
|
415
|
+
return __isrCacheKey(pathname, "rsc:" + __isrFnv1a64(mountedSlotsHeader));
|
|
416
|
+
}
|
|
417
|
+
function __normalizeMountedSlotsHeader(raw) {
|
|
418
|
+
if (!raw) return null;
|
|
419
|
+
const normalized = Array.from(
|
|
420
|
+
new Set(
|
|
421
|
+
raw
|
|
422
|
+
.split(/\\s+/)
|
|
423
|
+
.filter(Boolean),
|
|
424
|
+
),
|
|
425
|
+
).sort().join(" ");
|
|
426
|
+
return normalized || null;
|
|
427
|
+
}
|
|
399
428
|
function __isrRouteKey(pathname) { return __isrCacheKey(pathname, "route"); }
|
|
400
429
|
// Verbose cache logging — opt in with NEXT_PRIVATE_DEBUG_CACHE=1.
|
|
401
430
|
// Matches the env var Next.js uses for its own cache debug output so operators
|
|
@@ -404,6 +433,16 @@ const __isrDebug = process.env.NEXT_PRIVATE_DEBUG_CACHE
|
|
|
404
433
|
? console.debug.bind(console, "[vinext] ISR:")
|
|
405
434
|
: undefined;
|
|
406
435
|
|
|
436
|
+
// Classification debug — opt in with VINEXT_DEBUG_CLASSIFICATION=1. Gated on
|
|
437
|
+
// the env var so the hot path pays no overhead unless an operator is actively
|
|
438
|
+
// tracing why a layout was flagged static or dynamic. The reason payload is
|
|
439
|
+
// carried by __VINEXT_CLASS_REASONS and consumed inside probeAppPageLayouts.
|
|
440
|
+
const __classDebug = process.env.VINEXT_DEBUG_CLASSIFICATION
|
|
441
|
+
? function(layoutId, reason) {
|
|
442
|
+
console.debug("[vinext] CLS:", layoutId, reason);
|
|
443
|
+
}
|
|
444
|
+
: undefined;
|
|
445
|
+
|
|
407
446
|
// Normalize null-prototype objects from matchPattern() into thenable objects
|
|
408
447
|
// that work both as Promises (for Next.js 15+ async params) and as plain
|
|
409
448
|
// objects with synchronous property access (for pre-15 code like params.id).
|
|
@@ -572,6 +611,24 @@ async function __ensureInstrumentation() {
|
|
|
572
611
|
return __instrumentationInitPromise;
|
|
573
612
|
}` : ""}
|
|
574
613
|
|
|
614
|
+
// Build-time layout classification dispatch. Replaced in generateBundle
|
|
615
|
+
// with a switch statement that returns a pre-computed per-layout
|
|
616
|
+
// Map<layoutIndex, "static" | "dynamic"> for each route. Until the
|
|
617
|
+
// plugin patches this stub, every route falls back to the Layer 3
|
|
618
|
+
// runtime probe, which is the current (slow) behaviour.
|
|
619
|
+
function __VINEXT_CLASS(routeIdx) {
|
|
620
|
+
return null;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
// Build-time layout classification reasons dispatch. Sibling of
|
|
624
|
+
// __VINEXT_CLASS, returning a per-route Map<layoutIndex, ClassificationReason>
|
|
625
|
+
// that feeds the debug channel when VINEXT_DEBUG_CLASSIFICATION is active.
|
|
626
|
+
// Replaced in generateBundle with a real dispatch table; the stub returns
|
|
627
|
+
// null so the hot path never allocates reason maps when debug is off.
|
|
628
|
+
function __VINEXT_CLASS_REASONS(routeIdx) {
|
|
629
|
+
return null;
|
|
630
|
+
}
|
|
631
|
+
|
|
575
632
|
const routes = [
|
|
576
633
|
${routeEntries.join(",\n")}
|
|
577
634
|
];
|
|
@@ -593,7 +650,7 @@ const rootLayouts = [${rootLayoutVars.join(", ")}];
|
|
|
593
650
|
* @param opts.boundaryComponent - Override the boundary component (for layout-level notFound)
|
|
594
651
|
* @param opts.layouts - Override the layouts to wrap with (for layout-level notFound, excludes the throwing layout)
|
|
595
652
|
*/
|
|
596
|
-
async function renderHTTPAccessFallbackPage(route, statusCode, isRscRequest, request, opts) {
|
|
653
|
+
async function renderHTTPAccessFallbackPage(route, statusCode, isRscRequest, request, opts, scriptNonce) {
|
|
597
654
|
return __renderAppPageHttpAccessFallback({
|
|
598
655
|
boundaryComponent: opts?.boundaryComponent ?? null,
|
|
599
656
|
buildFontLinkHeader: __buildAppPageFontLinkHeader,
|
|
@@ -624,13 +681,14 @@ async function renderHTTPAccessFallbackPage(route, statusCode, isRscRequest, req
|
|
|
624
681
|
rootUnauthorizedModule: rootUnauthorizedModule,
|
|
625
682
|
route,
|
|
626
683
|
renderToReadableStream,
|
|
684
|
+
scriptNonce,
|
|
627
685
|
statusCode,
|
|
628
686
|
});
|
|
629
687
|
}
|
|
630
688
|
|
|
631
689
|
/** Convenience: render a not-found page (404) */
|
|
632
|
-
async function renderNotFoundPage(route, isRscRequest, request, matchedParams) {
|
|
633
|
-
return renderHTTPAccessFallbackPage(route, 404, isRscRequest, request, { matchedParams });
|
|
690
|
+
async function renderNotFoundPage(route, isRscRequest, request, matchedParams, scriptNonce) {
|
|
691
|
+
return renderHTTPAccessFallbackPage(route, 404, isRscRequest, request, { matchedParams }, scriptNonce);
|
|
634
692
|
}
|
|
635
693
|
|
|
636
694
|
/**
|
|
@@ -640,7 +698,7 @@ async function renderNotFoundPage(route, isRscRequest, request, matchedParams) {
|
|
|
640
698
|
* Next.js returns HTTP 200 when error.tsx catches an error (the error is "handled"
|
|
641
699
|
* by the boundary). This matches that behavior intentionally.
|
|
642
700
|
*/
|
|
643
|
-
async function renderErrorBoundaryPage(route, error, isRscRequest, request, matchedParams) {
|
|
701
|
+
async function renderErrorBoundaryPage(route, error, isRscRequest, request, matchedParams, scriptNonce) {
|
|
644
702
|
return __renderAppPageErrorBoundary({
|
|
645
703
|
buildFontLinkHeader: __buildAppPageFontLinkHeader,
|
|
646
704
|
clearRequestContext() {
|
|
@@ -668,6 +726,7 @@ async function renderErrorBoundaryPage(route, error, isRscRequest, request, matc
|
|
|
668
726
|
route,
|
|
669
727
|
renderToReadableStream,
|
|
670
728
|
sanitizeErrorForClient: __sanitizeErrorForClient,
|
|
729
|
+
scriptNonce,
|
|
671
730
|
});
|
|
672
731
|
}
|
|
673
732
|
|
|
@@ -727,17 +786,17 @@ function matchPattern(urlParts, patternParts) {
|
|
|
727
786
|
}
|
|
728
787
|
|
|
729
788
|
// Build a global intercepting route lookup for RSC navigation.
|
|
730
|
-
// Maps target URL patterns to { sourceRouteIndex,
|
|
789
|
+
// Maps target URL patterns to { sourceRouteIndex, slotKey, interceptPage, params }.
|
|
731
790
|
const interceptLookup = [];
|
|
732
791
|
for (let ri = 0; ri < routes.length; ri++) {
|
|
733
792
|
const r = routes[ri];
|
|
734
793
|
if (!r.slots) continue;
|
|
735
|
-
for (const [
|
|
794
|
+
for (const [slotKey, slotMod] of Object.entries(r.slots)) {
|
|
736
795
|
if (!slotMod.intercepts) continue;
|
|
737
796
|
for (const intercept of slotMod.intercepts) {
|
|
738
797
|
interceptLookup.push({
|
|
739
798
|
sourceRouteIndex: ri,
|
|
740
|
-
|
|
799
|
+
slotKey,
|
|
741
800
|
targetPattern: intercept.targetPattern,
|
|
742
801
|
targetPatternParts: intercept.targetPattern.split("/").filter(Boolean),
|
|
743
802
|
page: intercept.page,
|
|
@@ -762,10 +821,31 @@ function findIntercept(pathname) {
|
|
|
762
821
|
return null;
|
|
763
822
|
}
|
|
764
823
|
|
|
765
|
-
async function
|
|
824
|
+
async function buildPageElements(route, params, routePath, pageRequest) {
|
|
825
|
+
const {
|
|
826
|
+
opts,
|
|
827
|
+
searchParams,
|
|
828
|
+
isRscRequest,
|
|
829
|
+
request,
|
|
830
|
+
mountedSlotsHeader,
|
|
831
|
+
} = pageRequest;
|
|
766
832
|
const PageComponent = route.page?.default;
|
|
767
833
|
if (!PageComponent) {
|
|
768
|
-
|
|
834
|
+
const _interceptionContext = opts?.interceptionContext ?? null;
|
|
835
|
+
const _noExportRouteId = __createAppPayloadRouteId(routePath, _interceptionContext);
|
|
836
|
+
let _noExportRootLayout = null;
|
|
837
|
+
if (route.layouts?.length > 0) {
|
|
838
|
+
// Compute the root layout tree path for this error payload using the
|
|
839
|
+
// canonical helper so it stays aligned with buildAppPageElements().
|
|
840
|
+
const _tp = route.layoutTreePositions?.[0] ?? 0;
|
|
841
|
+
_noExportRootLayout = __createAppPageTreePath(route.routeSegments, _tp);
|
|
842
|
+
}
|
|
843
|
+
return {
|
|
844
|
+
[__APP_INTERCEPTION_CONTEXT_KEY]: _interceptionContext,
|
|
845
|
+
__route: _noExportRouteId,
|
|
846
|
+
__rootLayout: _noExportRootLayout,
|
|
847
|
+
[_noExportRouteId]: createElement("div", null, "Page has no default export"),
|
|
848
|
+
};
|
|
769
849
|
}
|
|
770
850
|
|
|
771
851
|
// Resolve metadata and viewport from layouts and page.
|
|
@@ -794,6 +874,24 @@ async function buildPageElement(route, params, opts, searchParams) {
|
|
|
794
874
|
// route it to the nearest error.tsx boundary (or global-error.tsx).
|
|
795
875
|
const layoutMods = route.layouts.filter(Boolean);
|
|
796
876
|
|
|
877
|
+
// Convert URLSearchParams → plain object for page generateMetadata() and
|
|
878
|
+
// pageProps.searchParams. Built before the layout loop so the page metadata
|
|
879
|
+
// call (below) and pageProps can reference the same object.
|
|
880
|
+
// NOTE: Layouts do NOT receive searchParams in generateMetadata() — only
|
|
881
|
+
// pages do. This matches Next.js behavior (resolve-metadata.ts:777).
|
|
882
|
+
const spObj = Object.create(null);
|
|
883
|
+
let hasSearchParams = false;
|
|
884
|
+
if (searchParams && searchParams.forEach) {
|
|
885
|
+
searchParams.forEach(function(v, k) {
|
|
886
|
+
hasSearchParams = true;
|
|
887
|
+
if (k in spObj) {
|
|
888
|
+
spObj[k] = Array.isArray(spObj[k]) ? spObj[k].concat(v) : [spObj[k], v];
|
|
889
|
+
} else {
|
|
890
|
+
spObj[k] = v;
|
|
891
|
+
}
|
|
892
|
+
});
|
|
893
|
+
}
|
|
894
|
+
|
|
797
895
|
// Build the parent promise chain and kick off metadata resolution in one pass.
|
|
798
896
|
// Each layout module is called exactly once. layoutMetaPromises[i] is the
|
|
799
897
|
// promise for layout[i]'s own metadata result.
|
|
@@ -816,22 +914,6 @@ async function buildPageElement(route, params, opts, searchParams) {
|
|
|
816
914
|
// Page's parent is the fully-accumulated layout metadata.
|
|
817
915
|
const pageParentPromise = accumulatedMetaPromise;
|
|
818
916
|
|
|
819
|
-
// Convert URLSearchParams → plain object so we can pass it to
|
|
820
|
-
// resolveModuleMetadata (which expects Record<string, string | string[]>).
|
|
821
|
-
// This same object is reused for pageProps.searchParams below.
|
|
822
|
-
const spObj = {};
|
|
823
|
-
let hasSearchParams = false;
|
|
824
|
-
if (searchParams && searchParams.forEach) {
|
|
825
|
-
searchParams.forEach(function(v, k) {
|
|
826
|
-
hasSearchParams = true;
|
|
827
|
-
if (k in spObj) {
|
|
828
|
-
spObj[k] = Array.isArray(spObj[k]) ? spObj[k].concat(v) : [spObj[k], v];
|
|
829
|
-
} else {
|
|
830
|
-
spObj[k] = v;
|
|
831
|
-
}
|
|
832
|
-
});
|
|
833
|
-
}
|
|
834
|
-
|
|
835
917
|
const [layoutMetaResults, layoutVpResults, pageMeta, pageVp] = await Promise.all([
|
|
836
918
|
Promise.all(layoutMetaPromises),
|
|
837
919
|
Promise.all(layoutMods.map((mod) => resolveModuleViewport(mod, params).catch((err) => { console.error("[vinext] Layout generateViewport() failed:", err); return null; }))),
|
|
@@ -863,19 +945,31 @@ async function buildPageElement(route, params, opts, searchParams) {
|
|
|
863
945
|
// dynamic, and this avoids false positives from React internals.
|
|
864
946
|
if (hasSearchParams) markDynamicUsage();
|
|
865
947
|
}
|
|
866
|
-
|
|
948
|
+
// mountedSlotsHeader is threaded through from the handler scope so every
|
|
949
|
+
// call site shares one source of truth for request-derived values. Reading
|
|
950
|
+
// the same header in two places invites silent drift when a future refactor
|
|
951
|
+
// changes only one of them.
|
|
952
|
+
const mountedSlotIds = mountedSlotsHeader
|
|
953
|
+
? new Set(mountedSlotsHeader.split(" "))
|
|
954
|
+
: null;
|
|
955
|
+
|
|
956
|
+
return __buildAppPageElements({
|
|
867
957
|
element: createElement(PageComponent, pageProps),
|
|
868
958
|
globalErrorModule: ${globalErrorVar ? globalErrorVar : "null"},
|
|
959
|
+
isRscRequest,
|
|
960
|
+
mountedSlotIds,
|
|
869
961
|
makeThenableParams,
|
|
870
962
|
matchedParams: params,
|
|
871
963
|
resolvedMetadata,
|
|
872
964
|
resolvedViewport,
|
|
965
|
+
interceptionContext: opts?.interceptionContext ?? null,
|
|
966
|
+
routePath,
|
|
873
967
|
rootNotFoundModule: ${rootNotFoundVar ? rootNotFoundVar : "null"},
|
|
874
968
|
route,
|
|
875
969
|
slotOverrides:
|
|
876
|
-
opts && opts.
|
|
970
|
+
opts && opts.interceptSlotKey && opts.interceptPage
|
|
877
971
|
? {
|
|
878
|
-
[opts.
|
|
972
|
+
[opts.interceptSlotKey]: {
|
|
879
973
|
pageModule: opts.interceptPage,
|
|
880
974
|
params: opts.interceptParams || params,
|
|
881
975
|
},
|
|
@@ -1030,7 +1124,7 @@ export default async function handler(request, ctx) {
|
|
|
1030
1124
|
// Per-request container for middleware state. Passed into
|
|
1031
1125
|
// _handleRequest which fills in .headers and .status;
|
|
1032
1126
|
// avoids module-level variables that race on Workers.
|
|
1033
|
-
const _mwCtx = { headers: null, status: null };
|
|
1127
|
+
const _mwCtx = { headers: null, requestHeaders: null, status: null };
|
|
1034
1128
|
const response = await _handleRequest(request, __reqCtx, _mwCtx);
|
|
1035
1129
|
// Apply custom headers from next.config.js to non-redirect responses.
|
|
1036
1130
|
// Skip redirects (3xx) because Response.redirect() creates immutable headers,
|
|
@@ -1194,6 +1288,14 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
1194
1288
|
}
|
|
1195
1289
|
|
|
1196
1290
|
const isRscRequest = pathname.endsWith(".rsc") || request.headers.get("accept")?.includes("text/x-component");
|
|
1291
|
+
// Read mounted-slots header once at the handler scope and thread it through
|
|
1292
|
+
// every buildPageElements call site. Previously both the handler and
|
|
1293
|
+
// buildPageElements read and normalized it independently, which invited
|
|
1294
|
+
// silent drift if a future refactor changed only one path.
|
|
1295
|
+
const __mountedSlotsHeader = __normalizeMountedSlotsHeader(
|
|
1296
|
+
request.headers.get("x-vinext-mounted-slots"),
|
|
1297
|
+
);
|
|
1298
|
+
const interceptionContextHeader = request.headers.get("X-Vinext-Interception-Context")?.replaceAll("\0", "") || null;
|
|
1197
1299
|
let cleanPathname = pathname.replace(/\\.rsc$/, "");
|
|
1198
1300
|
|
|
1199
1301
|
// Middleware response headers and custom rewrite status are stored in
|
|
@@ -1332,11 +1434,16 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
1332
1434
|
// be merged into the outgoing HTTP response — this prefix is reserved for
|
|
1333
1435
|
// internal routing signals and must never reach clients.
|
|
1334
1436
|
if (_mwCtx.headers) {
|
|
1437
|
+
// Preserve the pre-strip header set so route handlers can reconstruct
|
|
1438
|
+
// a request object with middleware header overrides applied.
|
|
1439
|
+
_mwCtx.requestHeaders = new Headers(_mwCtx.headers);
|
|
1335
1440
|
applyMiddlewareRequestHeaders(_mwCtx.headers);
|
|
1336
1441
|
processMiddlewareHeaders(_mwCtx.headers);
|
|
1337
1442
|
}
|
|
1338
1443
|
` : ""}
|
|
1339
1444
|
|
|
1445
|
+
const _scriptNonce = __getScriptNonceFromHeaderSources(request.headers, _mwCtx.headers);
|
|
1446
|
+
|
|
1340
1447
|
// Build post-middleware request context for afterFiles/fallback rewrites.
|
|
1341
1448
|
// These run after middleware in the App Router execution order and should
|
|
1342
1449
|
// evaluate has/missing conditions against middleware-modified headers.
|
|
@@ -1496,6 +1603,12 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
1496
1603
|
}
|
|
1497
1604
|
throw sizeErr;
|
|
1498
1605
|
}
|
|
1606
|
+
const payloadResponse = await validateServerActionPayload(body);
|
|
1607
|
+
if (payloadResponse) {
|
|
1608
|
+
setHeadersContext(null);
|
|
1609
|
+
setNavigationContext(null);
|
|
1610
|
+
return payloadResponse;
|
|
1611
|
+
}
|
|
1499
1612
|
const temporaryReferences = createTemporaryReferenceSet();
|
|
1500
1613
|
const args = await decodeReply(body, { temporaryReferences });
|
|
1501
1614
|
const action = await loadServerAction(actionId);
|
|
@@ -1508,10 +1621,7 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
1508
1621
|
returnValue = { ok: true, data };
|
|
1509
1622
|
} catch (e) {
|
|
1510
1623
|
// Detect redirect() / permanentRedirect() called inside the action.
|
|
1511
|
-
// These throw errors with digest "NEXT_REDIRECT
|
|
1512
|
-
// The type field is empty when redirect() was called without an explicit
|
|
1513
|
-
// type argument. In Server Action context, Next.js defaults to "push" so
|
|
1514
|
-
// the Back button works after form submissions.
|
|
1624
|
+
// These throw errors with digest "NEXT_REDIRECT;replace;url[;status]".
|
|
1515
1625
|
// The URL is encodeURIComponent-encoded to prevent semicolons in the URL
|
|
1516
1626
|
// from corrupting the delimiter-based digest format.
|
|
1517
1627
|
if (e && typeof e === "object" && "digest" in e) {
|
|
@@ -1520,7 +1630,7 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
1520
1630
|
const parts = digest.split(";");
|
|
1521
1631
|
actionRedirect = {
|
|
1522
1632
|
url: decodeURIComponent(parts[2]),
|
|
1523
|
-
type: parts[1] || "push", //
|
|
1633
|
+
type: parts[1] || "push", // "push" or "replace"
|
|
1524
1634
|
status: parts[3] ? parseInt(parts[3], 10) : 307,
|
|
1525
1635
|
};
|
|
1526
1636
|
returnValue = { ok: true, data: undefined };
|
|
@@ -1557,9 +1667,6 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
1557
1667
|
"Content-Type": "text/x-component; charset=utf-8",
|
|
1558
1668
|
"Vary": "RSC, Accept",
|
|
1559
1669
|
});
|
|
1560
|
-
// Merge middleware headers first so the framework's own redirect control
|
|
1561
|
-
// headers below are always authoritative and cannot be clobbered by
|
|
1562
|
-
// middleware that happens to set x-action-redirect* keys.
|
|
1563
1670
|
__mergeMiddlewareResponseHeaders(redirectHeaders, _mwCtx.headers);
|
|
1564
1671
|
redirectHeaders.set("x-action-redirect", actionRedirect.url);
|
|
1565
1672
|
redirectHeaders.set("x-action-redirect-type", actionRedirect.type);
|
|
@@ -1574,24 +1681,71 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
1574
1681
|
|
|
1575
1682
|
// After the action, re-render the current page so the client
|
|
1576
1683
|
// gets an updated React tree reflecting any mutations.
|
|
1684
|
+
//
|
|
1685
|
+
// When the original request came from inside an intercepted modal
|
|
1686
|
+
// (X-Vinext-Interception-Context present + source route still
|
|
1687
|
+
// matches), rebuild the intercepted tree — otherwise the modal would
|
|
1688
|
+
// unmount and the direct route would render in its place. Mirrors
|
|
1689
|
+
// the interception resolution used by the GET path.
|
|
1577
1690
|
const match = matchRoute(cleanPathname);
|
|
1578
1691
|
let element;
|
|
1692
|
+
let errorPattern = match ? match.route.pattern : cleanPathname;
|
|
1579
1693
|
if (match) {
|
|
1580
1694
|
const { route: actionRoute, params: actionParams } = match;
|
|
1695
|
+
const __actionRerenderTarget = __resolveAppPageActionRerenderTarget({
|
|
1696
|
+
cleanPathname,
|
|
1697
|
+
currentParams: actionParams,
|
|
1698
|
+
currentRoute: actionRoute,
|
|
1699
|
+
findIntercept,
|
|
1700
|
+
getRouteParamNames(sourceRoute) {
|
|
1701
|
+
return sourceRoute.params;
|
|
1702
|
+
},
|
|
1703
|
+
getSourceRoute(sourceRouteIndex) {
|
|
1704
|
+
return routes[sourceRouteIndex];
|
|
1705
|
+
},
|
|
1706
|
+
isRscRequest,
|
|
1707
|
+
toInterceptOpts(intercept) {
|
|
1708
|
+
return {
|
|
1709
|
+
interceptionContext: interceptionContextHeader,
|
|
1710
|
+
interceptSlotKey: intercept.slotKey,
|
|
1711
|
+
interceptPage: intercept.page,
|
|
1712
|
+
interceptParams: intercept.matchedParams,
|
|
1713
|
+
};
|
|
1714
|
+
},
|
|
1715
|
+
});
|
|
1716
|
+
|
|
1581
1717
|
setNavigationContext({
|
|
1582
1718
|
pathname: cleanPathname,
|
|
1583
1719
|
searchParams: url.searchParams,
|
|
1584
|
-
params:
|
|
1720
|
+
params: __actionRerenderTarget.navigationParams,
|
|
1585
1721
|
});
|
|
1586
|
-
element =
|
|
1722
|
+
element = buildPageElements(
|
|
1723
|
+
__actionRerenderTarget.route,
|
|
1724
|
+
__actionRerenderTarget.params,
|
|
1725
|
+
cleanPathname,
|
|
1726
|
+
{
|
|
1727
|
+
opts: __actionRerenderTarget.interceptOpts,
|
|
1728
|
+
searchParams: url.searchParams,
|
|
1729
|
+
isRscRequest,
|
|
1730
|
+
request,
|
|
1731
|
+
mountedSlotsHeader: __mountedSlotsHeader,
|
|
1732
|
+
},
|
|
1733
|
+
);
|
|
1734
|
+
errorPattern = __actionRerenderTarget.route.pattern;
|
|
1587
1735
|
} else {
|
|
1588
|
-
|
|
1736
|
+
const _actionRouteId = __createAppPayloadRouteId(cleanPathname, null);
|
|
1737
|
+
element = {
|
|
1738
|
+
[__APP_INTERCEPTION_CONTEXT_KEY]: null,
|
|
1739
|
+
__route: _actionRouteId,
|
|
1740
|
+
__rootLayout: null,
|
|
1741
|
+
[_actionRouteId]: createElement("div", null, "Page not found"),
|
|
1742
|
+
};
|
|
1589
1743
|
}
|
|
1590
1744
|
|
|
1591
1745
|
const onRenderError = createRscOnErrorHandler(
|
|
1592
1746
|
request,
|
|
1593
1747
|
cleanPathname,
|
|
1594
|
-
|
|
1748
|
+
errorPattern,
|
|
1595
1749
|
);
|
|
1596
1750
|
const rscStream = renderToReadableStream(
|
|
1597
1751
|
{ root: element, returnValue },
|
|
@@ -1606,15 +1760,22 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
1606
1760
|
const actionPendingCookies = getAndClearPendingCookies();
|
|
1607
1761
|
const actionDraftCookie = getDraftModeCookieHeader();
|
|
1608
1762
|
|
|
1609
|
-
const actionHeaders = new Headers({
|
|
1763
|
+
const actionHeaders = new Headers({
|
|
1764
|
+
"Content-Type": "text/x-component; charset=utf-8",
|
|
1765
|
+
"Vary": "RSC, Accept",
|
|
1766
|
+
});
|
|
1610
1767
|
__mergeMiddlewareResponseHeaders(actionHeaders, _mwCtx.headers);
|
|
1768
|
+
const actionResponse = new Response(rscStream, {
|
|
1769
|
+
status: _mwCtx.status ?? 200,
|
|
1770
|
+
headers: actionHeaders,
|
|
1771
|
+
});
|
|
1611
1772
|
if (actionPendingCookies.length > 0 || actionDraftCookie) {
|
|
1612
1773
|
for (const cookie of actionPendingCookies) {
|
|
1613
|
-
|
|
1774
|
+
actionResponse.headers.append("Set-Cookie", cookie);
|
|
1614
1775
|
}
|
|
1615
|
-
if (actionDraftCookie)
|
|
1776
|
+
if (actionDraftCookie) actionResponse.headers.append("Set-Cookie", actionDraftCookie);
|
|
1616
1777
|
}
|
|
1617
|
-
return
|
|
1778
|
+
return actionResponse;
|
|
1618
1779
|
} catch (err) {
|
|
1619
1780
|
getAndClearPendingCookies(); // Clear pending cookies on error
|
|
1620
1781
|
console.error("[vinext] Server action error:", err);
|
|
@@ -1674,12 +1835,24 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
1674
1835
|
if (!isRscRequest) {
|
|
1675
1836
|
const __pagesEntry = await import.meta.viteRsc.loadModule("ssr", "index");
|
|
1676
1837
|
if (typeof __pagesEntry.renderPage === "function") {
|
|
1838
|
+
const __pagesRequestHeaders = _mwCtx.requestHeaders
|
|
1839
|
+
? __buildRequestHeadersFromMiddlewareResponse(request.headers, _mwCtx.requestHeaders)
|
|
1840
|
+
: null;
|
|
1841
|
+
const __pagesRequest = __pagesRequestHeaders
|
|
1842
|
+
? new Request(request.url, { method: request.method, headers: __pagesRequestHeaders })
|
|
1843
|
+
: request;
|
|
1677
1844
|
// Use segment-wise decoding to preserve encoded path delimiters (%2F).
|
|
1678
1845
|
// decodeURIComponent would turn /admin%2Fpanel into /admin/panel,
|
|
1679
1846
|
// changing the path structure and bypassing middleware matchers.
|
|
1680
1847
|
// Ported from Next.js: packages/next/src/server/lib/router-utils/decode-path-params.ts
|
|
1681
1848
|
// https://github.com/vercel/next.js/blob/canary/packages/next/src/server/lib/router-utils/decode-path-params.ts
|
|
1682
|
-
const __pagesRes = await __pagesEntry.renderPage(
|
|
1849
|
+
const __pagesRes = await __pagesEntry.renderPage(
|
|
1850
|
+
__pagesRequest,
|
|
1851
|
+
__decodePathParams(url.pathname) + (url.search || ""),
|
|
1852
|
+
{},
|
|
1853
|
+
undefined,
|
|
1854
|
+
_mwCtx.requestHeaders,
|
|
1855
|
+
);
|
|
1683
1856
|
// Only return the Pages Router response if it matched a route
|
|
1684
1857
|
// (non-404). A 404 means the path isn't a Pages route either,
|
|
1685
1858
|
// so fall through to the App Router not-found page below.
|
|
@@ -1692,7 +1865,7 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
1692
1865
|
}
|
|
1693
1866
|
` : ""}
|
|
1694
1867
|
// Render custom not-found page if available, otherwise plain 404
|
|
1695
|
-
const notFoundResponse = await renderNotFoundPage(null, isRscRequest, request);
|
|
1868
|
+
const notFoundResponse = await renderNotFoundPage(null, isRscRequest, request, undefined, _scriptNonce);
|
|
1696
1869
|
if (notFoundResponse) return notFoundResponse;
|
|
1697
1870
|
setHeadersContext(null);
|
|
1698
1871
|
setNavigationContext(null);
|
|
@@ -1822,6 +1995,7 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
1822
1995
|
markDynamicUsage,
|
|
1823
1996
|
method,
|
|
1824
1997
|
middlewareContext: _mwCtx,
|
|
1998
|
+
middlewareRequestHeaders: _mwCtx.requestHeaders,
|
|
1825
1999
|
params: makeThenableParams(params),
|
|
1826
2000
|
reportRequestError: _reportRequestError,
|
|
1827
2001
|
request,
|
|
@@ -1905,6 +2079,7 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
1905
2079
|
if (
|
|
1906
2080
|
process.env.NODE_ENV === "production" &&
|
|
1907
2081
|
!isForceDynamic &&
|
|
2082
|
+
(isRscRequest || !_scriptNonce) &&
|
|
1908
2083
|
revalidateSeconds !== null && revalidateSeconds > 0 && revalidateSeconds !== Infinity
|
|
1909
2084
|
) {
|
|
1910
2085
|
const __cachedPageResponse = await __readAppPageCacheResponse({
|
|
@@ -1919,6 +2094,7 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
1919
2094
|
isrHtmlKey: __isrHtmlKey,
|
|
1920
2095
|
isrRscKey: __isrRscKey,
|
|
1921
2096
|
isrSet: __isrSet,
|
|
2097
|
+
mountedSlotsHeader: __mountedSlotsHeader,
|
|
1922
2098
|
revalidateSeconds,
|
|
1923
2099
|
renderFreshPageForCache: async function() {
|
|
1924
2100
|
// Re-render the page to produce fresh HTML + RSC data for the cache
|
|
@@ -1933,7 +2109,21 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
1933
2109
|
return _runWithUnifiedCtx(__revalUCtx, async () => {
|
|
1934
2110
|
_ensureFetchPatch();
|
|
1935
2111
|
setNavigationContext({ pathname: cleanPathname, searchParams: new URLSearchParams(), params });
|
|
1936
|
-
|
|
2112
|
+
// Slot context (X-Vinext-Mounted-Slots) is inherited from the
|
|
2113
|
+
// triggering request so the regen result is cached under the
|
|
2114
|
+
// correct slot-variant key.
|
|
2115
|
+
const __revalElement = await buildPageElements(
|
|
2116
|
+
route,
|
|
2117
|
+
params,
|
|
2118
|
+
cleanPathname,
|
|
2119
|
+
{
|
|
2120
|
+
opts: undefined,
|
|
2121
|
+
searchParams: new URLSearchParams(),
|
|
2122
|
+
isRscRequest,
|
|
2123
|
+
request,
|
|
2124
|
+
mountedSlotsHeader: __mountedSlotsHeader,
|
|
2125
|
+
},
|
|
2126
|
+
);
|
|
1937
2127
|
const __revalOnError = createRscOnErrorHandler(request, cleanPathname, route.pattern);
|
|
1938
2128
|
const __revalRscStream = renderToReadableStream(__revalElement, { onError: __revalOnError });
|
|
1939
2129
|
const __revalRscCapture = __teeAppPageRscStreamForCapture(__revalRscStream, true);
|
|
@@ -1982,44 +2172,30 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
1982
2172
|
// If the target URL matches an intercepting route in a parallel slot,
|
|
1983
2173
|
// render the source route with the intercepting page in the slot.
|
|
1984
2174
|
const __interceptResult = await __resolveAppPageIntercept({
|
|
1985
|
-
buildPageElement,
|
|
2175
|
+
buildPageElement(interceptRoute, interceptParams, interceptOpts, interceptSearchParams) {
|
|
2176
|
+
return buildPageElements(
|
|
2177
|
+
interceptRoute,
|
|
2178
|
+
interceptParams,
|
|
2179
|
+
cleanPathname,
|
|
2180
|
+
{
|
|
2181
|
+
opts: interceptOpts,
|
|
2182
|
+
searchParams: interceptSearchParams,
|
|
2183
|
+
isRscRequest,
|
|
2184
|
+
request,
|
|
2185
|
+
mountedSlotsHeader: __mountedSlotsHeader,
|
|
2186
|
+
},
|
|
2187
|
+
);
|
|
2188
|
+
},
|
|
1986
2189
|
cleanPathname,
|
|
1987
2190
|
currentRoute: route,
|
|
1988
2191
|
findIntercept,
|
|
1989
|
-
|
|
1990
|
-
return sourceRoute.
|
|
2192
|
+
getRouteParamNames(sourceRoute) {
|
|
2193
|
+
return sourceRoute.params;
|
|
1991
2194
|
},
|
|
1992
2195
|
getSourceRoute(sourceRouteIndex) {
|
|
1993
2196
|
return routes[sourceRouteIndex];
|
|
1994
2197
|
},
|
|
1995
2198
|
isRscRequest,
|
|
1996
|
-
matchSourceRouteParams(pattern) {
|
|
1997
|
-
// Extract actual URL param values by prefix-matching the request pathname
|
|
1998
|
-
// against the source route's pattern. This handles all interception conventions:
|
|
1999
|
-
// (.) same-level, (..) one-level-up, and (...) root — the source pattern's
|
|
2000
|
-
// dynamic segments that align with the URL get their real values extracted.
|
|
2001
|
-
// We must NOT use matchRoute(pattern) here: the trie would match the literal
|
|
2002
|
-
// ":param" strings as dynamic segment values, returning e.g. {id: ":id"}.
|
|
2003
|
-
const patternParts = pattern.split("/").filter(Boolean);
|
|
2004
|
-
const urlParts = cleanPathname.split("/").filter(Boolean);
|
|
2005
|
-
const params = Object.create(null);
|
|
2006
|
-
for (let i = 0; i < patternParts.length; i++) {
|
|
2007
|
-
const pp = patternParts[i];
|
|
2008
|
-
if (pp.endsWith("+") || pp.endsWith("*")) {
|
|
2009
|
-
// urlParts.slice(i) safely returns [] when i >= urlParts.length,
|
|
2010
|
-
// which is the correct value for optional catch-all with zero segments.
|
|
2011
|
-
params[pp.slice(1, -1)] = urlParts.slice(i);
|
|
2012
|
-
break;
|
|
2013
|
-
}
|
|
2014
|
-
if (i >= urlParts.length) break;
|
|
2015
|
-
if (pp.startsWith(":")) {
|
|
2016
|
-
params[pp.slice(1)] = urlParts[i];
|
|
2017
|
-
} else if (pp !== urlParts[i]) {
|
|
2018
|
-
break;
|
|
2019
|
-
}
|
|
2020
|
-
}
|
|
2021
|
-
return params;
|
|
2022
|
-
},
|
|
2023
2199
|
renderInterceptResponse(sourceRoute, interceptElement) {
|
|
2024
2200
|
const interceptOnError = createRscOnErrorHandler(
|
|
2025
2201
|
request,
|
|
@@ -2033,7 +2209,10 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
2033
2209
|
// by the client, and async server components that run during consumption need the
|
|
2034
2210
|
// context to still be live. The AsyncLocalStorage scope from runWithRequestContext
|
|
2035
2211
|
// handles cleanup naturally when all async continuations complete.
|
|
2036
|
-
const interceptHeaders = new Headers({
|
|
2212
|
+
const interceptHeaders = new Headers({
|
|
2213
|
+
"Content-Type": "text/x-component; charset=utf-8",
|
|
2214
|
+
"Vary": "RSC, Accept",
|
|
2215
|
+
});
|
|
2037
2216
|
__mergeMiddlewareResponseHeaders(interceptHeaders, _mwCtx.headers);
|
|
2038
2217
|
return new Response(interceptStream, {
|
|
2039
2218
|
status: _mwCtx.status ?? 200,
|
|
@@ -2044,7 +2223,8 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
2044
2223
|
setNavigationContext,
|
|
2045
2224
|
toInterceptOpts(intercept) {
|
|
2046
2225
|
return {
|
|
2047
|
-
|
|
2226
|
+
interceptionContext: interceptionContextHeader,
|
|
2227
|
+
interceptSlotKey: intercept.slotKey,
|
|
2048
2228
|
interceptPage: intercept.page,
|
|
2049
2229
|
interceptParams: intercept.matchedParams,
|
|
2050
2230
|
};
|
|
@@ -2057,10 +2237,16 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
2057
2237
|
|
|
2058
2238
|
const __pageBuildResult = await __buildAppPageElement({
|
|
2059
2239
|
buildPageElement() {
|
|
2060
|
-
return
|
|
2240
|
+
return buildPageElements(route, params, cleanPathname, {
|
|
2241
|
+
opts: interceptOpts,
|
|
2242
|
+
searchParams: url.searchParams,
|
|
2243
|
+
isRscRequest,
|
|
2244
|
+
request,
|
|
2245
|
+
mountedSlotsHeader: __mountedSlotsHeader,
|
|
2246
|
+
});
|
|
2061
2247
|
},
|
|
2062
2248
|
renderErrorBoundaryPage(buildErr) {
|
|
2063
|
-
return renderErrorBoundaryPage(route, buildErr, isRscRequest, request, params);
|
|
2249
|
+
return renderErrorBoundaryPage(route, buildErr, isRscRequest, request, params, _scriptNonce);
|
|
2064
2250
|
},
|
|
2065
2251
|
renderSpecialError(__buildSpecialError) {
|
|
2066
2252
|
return __buildAppPageSpecialErrorResponse({
|
|
@@ -2069,9 +2255,16 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
2069
2255
|
setNavigationContext(null);
|
|
2070
2256
|
},
|
|
2071
2257
|
renderFallbackPage(statusCode) {
|
|
2072
|
-
return renderHTTPAccessFallbackPage(
|
|
2073
|
-
|
|
2074
|
-
|
|
2258
|
+
return renderHTTPAccessFallbackPage(
|
|
2259
|
+
route,
|
|
2260
|
+
statusCode,
|
|
2261
|
+
isRscRequest,
|
|
2262
|
+
request,
|
|
2263
|
+
{
|
|
2264
|
+
matchedParams: params,
|
|
2265
|
+
},
|
|
2266
|
+
_scriptNonce,
|
|
2267
|
+
);
|
|
2075
2268
|
},
|
|
2076
2269
|
requestUrl: request.url,
|
|
2077
2270
|
specialError: __buildSpecialError,
|
|
@@ -2088,19 +2281,6 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
2088
2281
|
// rscCssTransform — no manual loadCss() call needed.
|
|
2089
2282
|
const _hasLoadingBoundary = !!(route.loading && route.loading.default);
|
|
2090
2283
|
const _asyncLayoutParams = makeThenableParams(params);
|
|
2091
|
-
// Convert URLSearchParams to a plain object then wrap in makeThenableParams()
|
|
2092
|
-
// so probePage() passes the same shape that buildPageElement() gives to the
|
|
2093
|
-
// real render. Without this, pages that destructure await-ed searchParams
|
|
2094
|
-
// throw TypeError during probe.
|
|
2095
|
-
const _probeSearchObj = {};
|
|
2096
|
-
url.searchParams.forEach(function(v, k) {
|
|
2097
|
-
if (k in _probeSearchObj) {
|
|
2098
|
-
_probeSearchObj[k] = Array.isArray(_probeSearchObj[k]) ? _probeSearchObj[k].concat(v) : [_probeSearchObj[k], v];
|
|
2099
|
-
} else {
|
|
2100
|
-
_probeSearchObj[k] = v;
|
|
2101
|
-
}
|
|
2102
|
-
});
|
|
2103
|
-
const _asyncSearchParams = makeThenableParams(_probeSearchObj);
|
|
2104
2284
|
return __renderAppPageLifecycle({
|
|
2105
2285
|
cleanPathname,
|
|
2106
2286
|
clearRequestContext() {
|
|
@@ -2146,11 +2326,43 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
2146
2326
|
return LayoutComp({ params: _asyncLayoutParams, children: null });
|
|
2147
2327
|
},
|
|
2148
2328
|
probePage() {
|
|
2329
|
+
const _probeSearchObj = {};
|
|
2330
|
+
url.searchParams.forEach(function(v, k) {
|
|
2331
|
+
if (k in _probeSearchObj) {
|
|
2332
|
+
_probeSearchObj[k] = Array.isArray(_probeSearchObj[k])
|
|
2333
|
+
? _probeSearchObj[k].concat(v)
|
|
2334
|
+
: [_probeSearchObj[k], v];
|
|
2335
|
+
} else {
|
|
2336
|
+
_probeSearchObj[k] = v;
|
|
2337
|
+
}
|
|
2338
|
+
});
|
|
2339
|
+
const _asyncSearchParams = makeThenableParams(_probeSearchObj);
|
|
2149
2340
|
return PageComponent({ params: _asyncLayoutParams, searchParams: _asyncSearchParams });
|
|
2150
2341
|
},
|
|
2342
|
+
classification: {
|
|
2343
|
+
getLayoutId(index) {
|
|
2344
|
+
const tp = route.layoutTreePositions?.[index] ?? 0;
|
|
2345
|
+
return "layout:" + __createAppPageTreePath(route.routeSegments, tp);
|
|
2346
|
+
},
|
|
2347
|
+
buildTimeClassifications: route.__buildTimeClassifications,
|
|
2348
|
+
buildTimeReasons: route.__buildTimeReasons,
|
|
2349
|
+
debugClassification: __classDebug,
|
|
2350
|
+
async runWithIsolatedDynamicScope(fn) {
|
|
2351
|
+
const priorDynamic = consumeDynamicUsage();
|
|
2352
|
+
try {
|
|
2353
|
+
const result = await fn();
|
|
2354
|
+
const dynamicDetected = consumeDynamicUsage();
|
|
2355
|
+
return { result, dynamicDetected };
|
|
2356
|
+
} finally {
|
|
2357
|
+
consumeDynamicUsage();
|
|
2358
|
+
if (priorDynamic) markDynamicUsage();
|
|
2359
|
+
}
|
|
2360
|
+
},
|
|
2361
|
+
},
|
|
2151
2362
|
revalidateSeconds,
|
|
2363
|
+
mountedSlotsHeader: __mountedSlotsHeader,
|
|
2152
2364
|
renderErrorBoundaryResponse(renderErr) {
|
|
2153
|
-
return renderErrorBoundaryPage(route, renderErr, isRscRequest, request, params);
|
|
2365
|
+
return renderErrorBoundaryPage(route, renderErr, isRscRequest, request, params, _scriptNonce);
|
|
2154
2366
|
},
|
|
2155
2367
|
async renderLayoutSpecialError(__layoutSpecialError, li) {
|
|
2156
2368
|
return __buildAppPageSpecialErrorResponse({
|
|
@@ -2173,11 +2385,18 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
2173
2385
|
}
|
|
2174
2386
|
if (!parentNotFound) parentNotFound = ${rootNotFoundVar ? `${rootNotFoundVar}?.default` : "null"};
|
|
2175
2387
|
const parentLayouts = route.layouts.slice(0, li);
|
|
2176
|
-
return renderHTTPAccessFallbackPage(
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2388
|
+
return renderHTTPAccessFallbackPage(
|
|
2389
|
+
route,
|
|
2390
|
+
statusCode,
|
|
2391
|
+
isRscRequest,
|
|
2392
|
+
request,
|
|
2393
|
+
{
|
|
2394
|
+
boundaryComponent: parentNotFound,
|
|
2395
|
+
layouts: parentLayouts,
|
|
2396
|
+
matchedParams: params,
|
|
2397
|
+
},
|
|
2398
|
+
_scriptNonce,
|
|
2399
|
+
);
|
|
2181
2400
|
},
|
|
2182
2401
|
requestUrl: request.url,
|
|
2183
2402
|
specialError: __layoutSpecialError,
|
|
@@ -2190,9 +2409,16 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
2190
2409
|
setNavigationContext(null);
|
|
2191
2410
|
},
|
|
2192
2411
|
renderFallbackPage(statusCode) {
|
|
2193
|
-
return renderHTTPAccessFallbackPage(
|
|
2194
|
-
|
|
2195
|
-
|
|
2412
|
+
return renderHTTPAccessFallbackPage(
|
|
2413
|
+
route,
|
|
2414
|
+
statusCode,
|
|
2415
|
+
isRscRequest,
|
|
2416
|
+
request,
|
|
2417
|
+
{
|
|
2418
|
+
matchedParams: params,
|
|
2419
|
+
},
|
|
2420
|
+
_scriptNonce,
|
|
2421
|
+
);
|
|
2196
2422
|
},
|
|
2197
2423
|
requestUrl: request.url,
|
|
2198
2424
|
specialError,
|
|
@@ -2207,6 +2433,7 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
2207
2433
|
// each have their own ALS store and are unaffected.
|
|
2208
2434
|
return _suppressHookWarningAls.run(true, probe);
|
|
2209
2435
|
},
|
|
2436
|
+
scriptNonce: _scriptNonce,
|
|
2210
2437
|
waitUntil(__cachePromise) {
|
|
2211
2438
|
_getRequestExecutionContext()?.waitUntil(__cachePromise);
|
|
2212
2439
|
},
|