vinext 0.0.41 → 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 +0 -1
- 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 +2 -2
- package/dist/check.js.map +1 -1
- package/dist/cli.js +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 +287 -95
- package/dist/entries/app-rsc-entry.js.map +1 -1
- package/dist/index.d.ts +1 -169
- package/dist/index.js +112 -432
- package/dist/index.js.map +1 -1
- package/dist/plugins/fonts.d.ts +49 -1
- package/dist/plugins/fonts.js +96 -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 +2 -1
- package/dist/server/app-page-boundary-render.js +40 -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 +7 -4
- package/dist/server/app-page-render.js +13 -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 +1 -0
- package/dist/server/app-page-response.js +1 -0
- 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 -83
- package/dist/server/app-page-route-wiring.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-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.js +6 -2
- package/dist/server/app-ssr-entry.js.map +1 -1
- package/dist/server/dev-server.js +2 -4
- package/dist/server/dev-server.js.map +1 -1
- package/dist/server/middleware.js +1 -5
- package/dist/server/middleware.js.map +1 -1
- package/dist/server/prod-server.d.ts +3 -3
- package/dist/server/prod-server.js +1 -1
- package/dist/server/prod-server.js.map +1 -1
- package/dist/server/request-pipeline.d.ts +2 -1
- package/dist/server/request-pipeline.js +34 -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/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/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 +3 -3
- 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,6 +25,7 @@ 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);
|
|
@@ -69,7 +71,7 @@ function generateRscEntry(appDir, routes, middlewarePath, metadataRoutes, global
|
|
|
69
71
|
if (route.pagePath) getImportVar(route.pagePath);
|
|
70
72
|
if (route.routePath) getImportVar(route.routePath);
|
|
71
73
|
for (const layout of route.layouts) getImportVar(layout);
|
|
72
|
-
for (const tmpl of route.templates)
|
|
74
|
+
for (const tmpl of route.templates) getImportVar(tmpl);
|
|
73
75
|
if (route.loadingPath) getImportVar(route.loadingPath);
|
|
74
76
|
if (route.errorPath) getImportVar(route.errorPath);
|
|
75
77
|
if (route.layoutErrorPaths) {
|
|
@@ -88,9 +90,9 @@ function generateRscEntry(appDir, routes, middlewarePath, metadataRoutes, global
|
|
|
88
90
|
for (const ir of slot.interceptingRoutes) getImportVar(ir.pagePath);
|
|
89
91
|
}
|
|
90
92
|
}
|
|
91
|
-
const routeEntries = routes.map((route) => {
|
|
93
|
+
const routeEntries = routes.map((route, routeIdx) => {
|
|
92
94
|
const layoutVars = route.layouts.map((l) => getImportVar(l));
|
|
93
|
-
const templateVars = route.templates.map((t) =>
|
|
95
|
+
const templateVars = route.templates.map((t) => getImportVar(t));
|
|
94
96
|
const notFoundVars = (route.notFoundPaths || []).map((nf) => nf ? getImportVar(nf) : "null");
|
|
95
97
|
const slotEntries = route.parallelSlots.map((slot) => {
|
|
96
98
|
const interceptEntries = slot.interceptingRoutes.map((ir) => ` {
|
|
@@ -99,7 +101,8 @@ function generateRscEntry(appDir, routes, middlewarePath, metadataRoutes, global
|
|
|
99
101
|
page: ${getImportVar(ir.pagePath)},
|
|
100
102
|
params: ${JSON.stringify(ir.params)},
|
|
101
103
|
}`);
|
|
102
|
-
return ` ${JSON.stringify(slot.
|
|
104
|
+
return ` ${JSON.stringify(slot.key)}: {
|
|
105
|
+
name: ${JSON.stringify(slot.name)},
|
|
103
106
|
page: ${slot.pagePath ? getImportVar(slot.pagePath) : "null"},
|
|
104
107
|
default: ${slot.defaultPath ? getImportVar(slot.defaultPath) : "null"},
|
|
105
108
|
layout: ${slot.layoutPath ? getImportVar(slot.layoutPath) : "null"},
|
|
@@ -114,6 +117,8 @@ ${interceptEntries.join(",\n")}
|
|
|
114
117
|
});
|
|
115
118
|
const layoutErrorVars = (route.layoutErrorPaths || []).map((ep) => ep ? getImportVar(ep) : "null");
|
|
116
119
|
return ` {
|
|
120
|
+
__buildTimeClassifications: __VINEXT_CLASS(${routeIdx}), // evaluated once at module load
|
|
121
|
+
__buildTimeReasons: __classDebug ? __VINEXT_CLASS_REASONS(${routeIdx}) : null,
|
|
117
122
|
pattern: ${JSON.stringify(route.pattern)},
|
|
118
123
|
patternParts: ${JSON.stringify(route.patternParts)},
|
|
119
124
|
isDynamic: ${route.isDynamic},
|
|
@@ -122,6 +127,7 @@ ${interceptEntries.join(",\n")}
|
|
|
122
127
|
routeHandler: ${route.routePath ? getImportVar(route.routePath) : "null"},
|
|
123
128
|
layouts: [${layoutVars.join(", ")}],
|
|
124
129
|
routeSegments: ${JSON.stringify(route.routeSegments)},
|
|
130
|
+
templateTreePositions: ${JSON.stringify(route.templateTreePositions)},
|
|
125
131
|
layoutTreePositions: ${JSON.stringify(route.layoutTreePositions)},
|
|
126
132
|
templates: [${templateVars.join(", ")}],
|
|
127
133
|
errors: [${layoutErrorVars.join(", ")}],
|
|
@@ -219,6 +225,7 @@ ${instrumentationPath ? `import * as _instrumentation from ${JSON.stringify(inst
|
|
|
219
225
|
${effectiveMetaRoutes.length > 0 ? `import { sitemapToXml, robotsToText, manifestToJson } from ${JSON.stringify(metadataRoutesPath)};` : ""}
|
|
220
226
|
import { requestContextFromRequest, normalizeHost, matchRedirect, matchRewrite, matchHeaders, isExternalUrl, proxyExternalRequest, sanitizeDestination } from ${JSON.stringify(configMatchersPath)};
|
|
221
227
|
import { decodePathParams as __decodePathParams } from ${JSON.stringify(normalizePathModulePath)};
|
|
228
|
+
import { buildRequestHeadersFromMiddlewareResponse as __buildRequestHeadersFromMiddlewareResponse } from ${JSON.stringify(middlewareRequestHeadersPath)};
|
|
222
229
|
import { validateCsrfOrigin, validateServerActionPayload, validateImageUrl, guardProtocolRelativeUrl, hasBasePath, stripBasePath, normalizeTrailingSlash, processMiddlewareHeaders } from ${JSON.stringify(requestPipelinePath)};
|
|
223
230
|
import {
|
|
224
231
|
isKnownDynamicAppRoute as __isKnownDynamicAppRoute,
|
|
@@ -246,7 +253,12 @@ import {
|
|
|
246
253
|
renderAppPageHttpAccessFallback as __renderAppPageHttpAccessFallback,
|
|
247
254
|
} from ${JSON.stringify(appPageBoundaryRenderPath)};
|
|
248
255
|
import {
|
|
249
|
-
|
|
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,
|
|
250
262
|
resolveAppPageChildSegments as __resolveAppPageChildSegments,
|
|
251
263
|
} from ${JSON.stringify(appPageRouteWiringPath)};
|
|
252
264
|
import {
|
|
@@ -257,6 +269,7 @@ import {
|
|
|
257
269
|
} from ${JSON.stringify(appPageResponsePath)};
|
|
258
270
|
import { getScriptNonceFromHeaderSources as __getScriptNonceFromHeaderSources } from ${JSON.stringify(cspPath)};
|
|
259
271
|
import {
|
|
272
|
+
resolveAppPageActionRerenderTarget as __resolveAppPageActionRerenderTarget,
|
|
260
273
|
buildAppPageElement as __buildAppPageElement,
|
|
261
274
|
resolveAppPageIntercept as __resolveAppPageIntercept,
|
|
262
275
|
validateAppPageDynamicParams as __validateAppPageDynamicParams,
|
|
@@ -397,7 +410,21 @@ function __isrCacheKey(pathname, suffix) {
|
|
|
397
410
|
return prefix + ":__hash:" + __isrFnv1a64(normalized) + ":" + suffix;
|
|
398
411
|
}
|
|
399
412
|
function __isrHtmlKey(pathname) { return __isrCacheKey(pathname, "html"); }
|
|
400
|
-
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
|
+
}
|
|
401
428
|
function __isrRouteKey(pathname) { return __isrCacheKey(pathname, "route"); }
|
|
402
429
|
// Verbose cache logging — opt in with NEXT_PRIVATE_DEBUG_CACHE=1.
|
|
403
430
|
// Matches the env var Next.js uses for its own cache debug output so operators
|
|
@@ -406,6 +433,16 @@ const __isrDebug = process.env.NEXT_PRIVATE_DEBUG_CACHE
|
|
|
406
433
|
? console.debug.bind(console, "[vinext] ISR:")
|
|
407
434
|
: undefined;
|
|
408
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
|
+
|
|
409
446
|
// Normalize null-prototype objects from matchPattern() into thenable objects
|
|
410
447
|
// that work both as Promises (for Next.js 15+ async params) and as plain
|
|
411
448
|
// objects with synchronous property access (for pre-15 code like params.id).
|
|
@@ -574,6 +611,24 @@ async function __ensureInstrumentation() {
|
|
|
574
611
|
return __instrumentationInitPromise;
|
|
575
612
|
}` : ""}
|
|
576
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
|
+
|
|
577
632
|
const routes = [
|
|
578
633
|
${routeEntries.join(",\n")}
|
|
579
634
|
];
|
|
@@ -731,17 +786,17 @@ function matchPattern(urlParts, patternParts) {
|
|
|
731
786
|
}
|
|
732
787
|
|
|
733
788
|
// Build a global intercepting route lookup for RSC navigation.
|
|
734
|
-
// Maps target URL patterns to { sourceRouteIndex,
|
|
789
|
+
// Maps target URL patterns to { sourceRouteIndex, slotKey, interceptPage, params }.
|
|
735
790
|
const interceptLookup = [];
|
|
736
791
|
for (let ri = 0; ri < routes.length; ri++) {
|
|
737
792
|
const r = routes[ri];
|
|
738
793
|
if (!r.slots) continue;
|
|
739
|
-
for (const [
|
|
794
|
+
for (const [slotKey, slotMod] of Object.entries(r.slots)) {
|
|
740
795
|
if (!slotMod.intercepts) continue;
|
|
741
796
|
for (const intercept of slotMod.intercepts) {
|
|
742
797
|
interceptLookup.push({
|
|
743
798
|
sourceRouteIndex: ri,
|
|
744
|
-
|
|
799
|
+
slotKey,
|
|
745
800
|
targetPattern: intercept.targetPattern,
|
|
746
801
|
targetPatternParts: intercept.targetPattern.split("/").filter(Boolean),
|
|
747
802
|
page: intercept.page,
|
|
@@ -766,10 +821,31 @@ function findIntercept(pathname) {
|
|
|
766
821
|
return null;
|
|
767
822
|
}
|
|
768
823
|
|
|
769
|
-
async function
|
|
824
|
+
async function buildPageElements(route, params, routePath, pageRequest) {
|
|
825
|
+
const {
|
|
826
|
+
opts,
|
|
827
|
+
searchParams,
|
|
828
|
+
isRscRequest,
|
|
829
|
+
request,
|
|
830
|
+
mountedSlotsHeader,
|
|
831
|
+
} = pageRequest;
|
|
770
832
|
const PageComponent = route.page?.default;
|
|
771
833
|
if (!PageComponent) {
|
|
772
|
-
|
|
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
|
+
};
|
|
773
849
|
}
|
|
774
850
|
|
|
775
851
|
// Resolve metadata and viewport from layouts and page.
|
|
@@ -798,6 +874,24 @@ async function buildPageElement(route, params, opts, searchParams) {
|
|
|
798
874
|
// route it to the nearest error.tsx boundary (or global-error.tsx).
|
|
799
875
|
const layoutMods = route.layouts.filter(Boolean);
|
|
800
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
|
+
|
|
801
895
|
// Build the parent promise chain and kick off metadata resolution in one pass.
|
|
802
896
|
// Each layout module is called exactly once. layoutMetaPromises[i] is the
|
|
803
897
|
// promise for layout[i]'s own metadata result.
|
|
@@ -820,22 +914,6 @@ async function buildPageElement(route, params, opts, searchParams) {
|
|
|
820
914
|
// Page's parent is the fully-accumulated layout metadata.
|
|
821
915
|
const pageParentPromise = accumulatedMetaPromise;
|
|
822
916
|
|
|
823
|
-
// Convert URLSearchParams → plain object so we can pass it to
|
|
824
|
-
// resolveModuleMetadata (which expects Record<string, string | string[]>).
|
|
825
|
-
// This same object is reused for pageProps.searchParams below.
|
|
826
|
-
const spObj = {};
|
|
827
|
-
let hasSearchParams = false;
|
|
828
|
-
if (searchParams && searchParams.forEach) {
|
|
829
|
-
searchParams.forEach(function(v, k) {
|
|
830
|
-
hasSearchParams = true;
|
|
831
|
-
if (k in spObj) {
|
|
832
|
-
spObj[k] = Array.isArray(spObj[k]) ? spObj[k].concat(v) : [spObj[k], v];
|
|
833
|
-
} else {
|
|
834
|
-
spObj[k] = v;
|
|
835
|
-
}
|
|
836
|
-
});
|
|
837
|
-
}
|
|
838
|
-
|
|
839
917
|
const [layoutMetaResults, layoutVpResults, pageMeta, pageVp] = await Promise.all([
|
|
840
918
|
Promise.all(layoutMetaPromises),
|
|
841
919
|
Promise.all(layoutMods.map((mod) => resolveModuleViewport(mod, params).catch((err) => { console.error("[vinext] Layout generateViewport() failed:", err); return null; }))),
|
|
@@ -867,19 +945,31 @@ async function buildPageElement(route, params, opts, searchParams) {
|
|
|
867
945
|
// dynamic, and this avoids false positives from React internals.
|
|
868
946
|
if (hasSearchParams) markDynamicUsage();
|
|
869
947
|
}
|
|
870
|
-
|
|
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({
|
|
871
957
|
element: createElement(PageComponent, pageProps),
|
|
872
958
|
globalErrorModule: ${globalErrorVar ? globalErrorVar : "null"},
|
|
959
|
+
isRscRequest,
|
|
960
|
+
mountedSlotIds,
|
|
873
961
|
makeThenableParams,
|
|
874
962
|
matchedParams: params,
|
|
875
963
|
resolvedMetadata,
|
|
876
964
|
resolvedViewport,
|
|
965
|
+
interceptionContext: opts?.interceptionContext ?? null,
|
|
966
|
+
routePath,
|
|
877
967
|
rootNotFoundModule: ${rootNotFoundVar ? rootNotFoundVar : "null"},
|
|
878
968
|
route,
|
|
879
969
|
slotOverrides:
|
|
880
|
-
opts && opts.
|
|
970
|
+
opts && opts.interceptSlotKey && opts.interceptPage
|
|
881
971
|
? {
|
|
882
|
-
[opts.
|
|
972
|
+
[opts.interceptSlotKey]: {
|
|
883
973
|
pageModule: opts.interceptPage,
|
|
884
974
|
params: opts.interceptParams || params,
|
|
885
975
|
},
|
|
@@ -1034,7 +1124,7 @@ export default async function handler(request, ctx) {
|
|
|
1034
1124
|
// Per-request container for middleware state. Passed into
|
|
1035
1125
|
// _handleRequest which fills in .headers and .status;
|
|
1036
1126
|
// avoids module-level variables that race on Workers.
|
|
1037
|
-
const _mwCtx = { headers: null, status: null };
|
|
1127
|
+
const _mwCtx = { headers: null, requestHeaders: null, status: null };
|
|
1038
1128
|
const response = await _handleRequest(request, __reqCtx, _mwCtx);
|
|
1039
1129
|
// Apply custom headers from next.config.js to non-redirect responses.
|
|
1040
1130
|
// Skip redirects (3xx) because Response.redirect() creates immutable headers,
|
|
@@ -1198,6 +1288,14 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
1198
1288
|
}
|
|
1199
1289
|
|
|
1200
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;
|
|
1201
1299
|
let cleanPathname = pathname.replace(/\\.rsc$/, "");
|
|
1202
1300
|
|
|
1203
1301
|
// Middleware response headers and custom rewrite status are stored in
|
|
@@ -1336,6 +1434,9 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
1336
1434
|
// be merged into the outgoing HTTP response — this prefix is reserved for
|
|
1337
1435
|
// internal routing signals and must never reach clients.
|
|
1338
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);
|
|
1339
1440
|
applyMiddlewareRequestHeaders(_mwCtx.headers);
|
|
1340
1441
|
processMiddlewareHeaders(_mwCtx.headers);
|
|
1341
1442
|
}
|
|
@@ -1520,10 +1621,7 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
1520
1621
|
returnValue = { ok: true, data };
|
|
1521
1622
|
} catch (e) {
|
|
1522
1623
|
// Detect redirect() / permanentRedirect() called inside the action.
|
|
1523
|
-
// These throw errors with digest "NEXT_REDIRECT
|
|
1524
|
-
// The type field is empty when redirect() was called without an explicit
|
|
1525
|
-
// type argument. In Server Action context, Next.js defaults to "push" so
|
|
1526
|
-
// the Back button works after form submissions.
|
|
1624
|
+
// These throw errors with digest "NEXT_REDIRECT;replace;url[;status]".
|
|
1527
1625
|
// The URL is encodeURIComponent-encoded to prevent semicolons in the URL
|
|
1528
1626
|
// from corrupting the delimiter-based digest format.
|
|
1529
1627
|
if (e && typeof e === "object" && "digest" in e) {
|
|
@@ -1532,7 +1630,7 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
1532
1630
|
const parts = digest.split(";");
|
|
1533
1631
|
actionRedirect = {
|
|
1534
1632
|
url: decodeURIComponent(parts[2]),
|
|
1535
|
-
type: parts[1] || "push", //
|
|
1633
|
+
type: parts[1] || "push", // "push" or "replace"
|
|
1536
1634
|
status: parts[3] ? parseInt(parts[3], 10) : 307,
|
|
1537
1635
|
};
|
|
1538
1636
|
returnValue = { ok: true, data: undefined };
|
|
@@ -1569,9 +1667,6 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
1569
1667
|
"Content-Type": "text/x-component; charset=utf-8",
|
|
1570
1668
|
"Vary": "RSC, Accept",
|
|
1571
1669
|
});
|
|
1572
|
-
// Merge middleware headers first so the framework's own redirect control
|
|
1573
|
-
// headers below are always authoritative and cannot be clobbered by
|
|
1574
|
-
// middleware that happens to set x-action-redirect* keys.
|
|
1575
1670
|
__mergeMiddlewareResponseHeaders(redirectHeaders, _mwCtx.headers);
|
|
1576
1671
|
redirectHeaders.set("x-action-redirect", actionRedirect.url);
|
|
1577
1672
|
redirectHeaders.set("x-action-redirect-type", actionRedirect.type);
|
|
@@ -1586,24 +1681,71 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
1586
1681
|
|
|
1587
1682
|
// After the action, re-render the current page so the client
|
|
1588
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.
|
|
1589
1690
|
const match = matchRoute(cleanPathname);
|
|
1590
1691
|
let element;
|
|
1692
|
+
let errorPattern = match ? match.route.pattern : cleanPathname;
|
|
1591
1693
|
if (match) {
|
|
1592
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
|
+
|
|
1593
1717
|
setNavigationContext({
|
|
1594
1718
|
pathname: cleanPathname,
|
|
1595
1719
|
searchParams: url.searchParams,
|
|
1596
|
-
params:
|
|
1720
|
+
params: __actionRerenderTarget.navigationParams,
|
|
1597
1721
|
});
|
|
1598
|
-
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;
|
|
1599
1735
|
} else {
|
|
1600
|
-
|
|
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
|
+
};
|
|
1601
1743
|
}
|
|
1602
1744
|
|
|
1603
1745
|
const onRenderError = createRscOnErrorHandler(
|
|
1604
1746
|
request,
|
|
1605
1747
|
cleanPathname,
|
|
1606
|
-
|
|
1748
|
+
errorPattern,
|
|
1607
1749
|
);
|
|
1608
1750
|
const rscStream = renderToReadableStream(
|
|
1609
1751
|
{ root: element, returnValue },
|
|
@@ -1618,15 +1760,22 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
1618
1760
|
const actionPendingCookies = getAndClearPendingCookies();
|
|
1619
1761
|
const actionDraftCookie = getDraftModeCookieHeader();
|
|
1620
1762
|
|
|
1621
|
-
const actionHeaders = new Headers({
|
|
1763
|
+
const actionHeaders = new Headers({
|
|
1764
|
+
"Content-Type": "text/x-component; charset=utf-8",
|
|
1765
|
+
"Vary": "RSC, Accept",
|
|
1766
|
+
});
|
|
1622
1767
|
__mergeMiddlewareResponseHeaders(actionHeaders, _mwCtx.headers);
|
|
1768
|
+
const actionResponse = new Response(rscStream, {
|
|
1769
|
+
status: _mwCtx.status ?? 200,
|
|
1770
|
+
headers: actionHeaders,
|
|
1771
|
+
});
|
|
1623
1772
|
if (actionPendingCookies.length > 0 || actionDraftCookie) {
|
|
1624
1773
|
for (const cookie of actionPendingCookies) {
|
|
1625
|
-
|
|
1774
|
+
actionResponse.headers.append("Set-Cookie", cookie);
|
|
1626
1775
|
}
|
|
1627
|
-
if (actionDraftCookie)
|
|
1776
|
+
if (actionDraftCookie) actionResponse.headers.append("Set-Cookie", actionDraftCookie);
|
|
1628
1777
|
}
|
|
1629
|
-
return
|
|
1778
|
+
return actionResponse;
|
|
1630
1779
|
} catch (err) {
|
|
1631
1780
|
getAndClearPendingCookies(); // Clear pending cookies on error
|
|
1632
1781
|
console.error("[vinext] Server action error:", err);
|
|
@@ -1686,12 +1835,24 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
1686
1835
|
if (!isRscRequest) {
|
|
1687
1836
|
const __pagesEntry = await import.meta.viteRsc.loadModule("ssr", "index");
|
|
1688
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;
|
|
1689
1844
|
// Use segment-wise decoding to preserve encoded path delimiters (%2F).
|
|
1690
1845
|
// decodeURIComponent would turn /admin%2Fpanel into /admin/panel,
|
|
1691
1846
|
// changing the path structure and bypassing middleware matchers.
|
|
1692
1847
|
// Ported from Next.js: packages/next/src/server/lib/router-utils/decode-path-params.ts
|
|
1693
1848
|
// https://github.com/vercel/next.js/blob/canary/packages/next/src/server/lib/router-utils/decode-path-params.ts
|
|
1694
|
-
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
|
+
);
|
|
1695
1856
|
// Only return the Pages Router response if it matched a route
|
|
1696
1857
|
// (non-404). A 404 means the path isn't a Pages route either,
|
|
1697
1858
|
// so fall through to the App Router not-found page below.
|
|
@@ -1834,6 +1995,7 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
1834
1995
|
markDynamicUsage,
|
|
1835
1996
|
method,
|
|
1836
1997
|
middlewareContext: _mwCtx,
|
|
1998
|
+
middlewareRequestHeaders: _mwCtx.requestHeaders,
|
|
1837
1999
|
params: makeThenableParams(params),
|
|
1838
2000
|
reportRequestError: _reportRequestError,
|
|
1839
2001
|
request,
|
|
@@ -1932,6 +2094,7 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
1932
2094
|
isrHtmlKey: __isrHtmlKey,
|
|
1933
2095
|
isrRscKey: __isrRscKey,
|
|
1934
2096
|
isrSet: __isrSet,
|
|
2097
|
+
mountedSlotsHeader: __mountedSlotsHeader,
|
|
1935
2098
|
revalidateSeconds,
|
|
1936
2099
|
renderFreshPageForCache: async function() {
|
|
1937
2100
|
// Re-render the page to produce fresh HTML + RSC data for the cache
|
|
@@ -1946,7 +2109,21 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
1946
2109
|
return _runWithUnifiedCtx(__revalUCtx, async () => {
|
|
1947
2110
|
_ensureFetchPatch();
|
|
1948
2111
|
setNavigationContext({ pathname: cleanPathname, searchParams: new URLSearchParams(), params });
|
|
1949
|
-
|
|
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
|
+
);
|
|
1950
2127
|
const __revalOnError = createRscOnErrorHandler(request, cleanPathname, route.pattern);
|
|
1951
2128
|
const __revalRscStream = renderToReadableStream(__revalElement, { onError: __revalOnError });
|
|
1952
2129
|
const __revalRscCapture = __teeAppPageRscStreamForCapture(__revalRscStream, true);
|
|
@@ -1995,44 +2172,30 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
1995
2172
|
// If the target URL matches an intercepting route in a parallel slot,
|
|
1996
2173
|
// render the source route with the intercepting page in the slot.
|
|
1997
2174
|
const __interceptResult = await __resolveAppPageIntercept({
|
|
1998
|
-
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
|
+
},
|
|
1999
2189
|
cleanPathname,
|
|
2000
2190
|
currentRoute: route,
|
|
2001
2191
|
findIntercept,
|
|
2002
|
-
|
|
2003
|
-
return sourceRoute.
|
|
2192
|
+
getRouteParamNames(sourceRoute) {
|
|
2193
|
+
return sourceRoute.params;
|
|
2004
2194
|
},
|
|
2005
2195
|
getSourceRoute(sourceRouteIndex) {
|
|
2006
2196
|
return routes[sourceRouteIndex];
|
|
2007
2197
|
},
|
|
2008
2198
|
isRscRequest,
|
|
2009
|
-
matchSourceRouteParams(pattern) {
|
|
2010
|
-
// Extract actual URL param values by prefix-matching the request pathname
|
|
2011
|
-
// against the source route's pattern. This handles all interception conventions:
|
|
2012
|
-
// (.) same-level, (..) one-level-up, and (...) root — the source pattern's
|
|
2013
|
-
// dynamic segments that align with the URL get their real values extracted.
|
|
2014
|
-
// We must NOT use matchRoute(pattern) here: the trie would match the literal
|
|
2015
|
-
// ":param" strings as dynamic segment values, returning e.g. {id: ":id"}.
|
|
2016
|
-
const patternParts = pattern.split("/").filter(Boolean);
|
|
2017
|
-
const urlParts = cleanPathname.split("/").filter(Boolean);
|
|
2018
|
-
const params = Object.create(null);
|
|
2019
|
-
for (let i = 0; i < patternParts.length; i++) {
|
|
2020
|
-
const pp = patternParts[i];
|
|
2021
|
-
if (pp.endsWith("+") || pp.endsWith("*")) {
|
|
2022
|
-
// urlParts.slice(i) safely returns [] when i >= urlParts.length,
|
|
2023
|
-
// which is the correct value for optional catch-all with zero segments.
|
|
2024
|
-
params[pp.slice(1, -1)] = urlParts.slice(i);
|
|
2025
|
-
break;
|
|
2026
|
-
}
|
|
2027
|
-
if (i >= urlParts.length) break;
|
|
2028
|
-
if (pp.startsWith(":")) {
|
|
2029
|
-
params[pp.slice(1)] = urlParts[i];
|
|
2030
|
-
} else if (pp !== urlParts[i]) {
|
|
2031
|
-
break;
|
|
2032
|
-
}
|
|
2033
|
-
}
|
|
2034
|
-
return params;
|
|
2035
|
-
},
|
|
2036
2199
|
renderInterceptResponse(sourceRoute, interceptElement) {
|
|
2037
2200
|
const interceptOnError = createRscOnErrorHandler(
|
|
2038
2201
|
request,
|
|
@@ -2046,7 +2209,10 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
2046
2209
|
// by the client, and async server components that run during consumption need the
|
|
2047
2210
|
// context to still be live. The AsyncLocalStorage scope from runWithRequestContext
|
|
2048
2211
|
// handles cleanup naturally when all async continuations complete.
|
|
2049
|
-
const interceptHeaders = new Headers({
|
|
2212
|
+
const interceptHeaders = new Headers({
|
|
2213
|
+
"Content-Type": "text/x-component; charset=utf-8",
|
|
2214
|
+
"Vary": "RSC, Accept",
|
|
2215
|
+
});
|
|
2050
2216
|
__mergeMiddlewareResponseHeaders(interceptHeaders, _mwCtx.headers);
|
|
2051
2217
|
return new Response(interceptStream, {
|
|
2052
2218
|
status: _mwCtx.status ?? 200,
|
|
@@ -2057,7 +2223,8 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
2057
2223
|
setNavigationContext,
|
|
2058
2224
|
toInterceptOpts(intercept) {
|
|
2059
2225
|
return {
|
|
2060
|
-
|
|
2226
|
+
interceptionContext: interceptionContextHeader,
|
|
2227
|
+
interceptSlotKey: intercept.slotKey,
|
|
2061
2228
|
interceptPage: intercept.page,
|
|
2062
2229
|
interceptParams: intercept.matchedParams,
|
|
2063
2230
|
};
|
|
@@ -2070,7 +2237,13 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
2070
2237
|
|
|
2071
2238
|
const __pageBuildResult = await __buildAppPageElement({
|
|
2072
2239
|
buildPageElement() {
|
|
2073
|
-
return
|
|
2240
|
+
return buildPageElements(route, params, cleanPathname, {
|
|
2241
|
+
opts: interceptOpts,
|
|
2242
|
+
searchParams: url.searchParams,
|
|
2243
|
+
isRscRequest,
|
|
2244
|
+
request,
|
|
2245
|
+
mountedSlotsHeader: __mountedSlotsHeader,
|
|
2246
|
+
});
|
|
2074
2247
|
},
|
|
2075
2248
|
renderErrorBoundaryPage(buildErr) {
|
|
2076
2249
|
return renderErrorBoundaryPage(route, buildErr, isRscRequest, request, params, _scriptNonce);
|
|
@@ -2108,19 +2281,6 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
2108
2281
|
// rscCssTransform — no manual loadCss() call needed.
|
|
2109
2282
|
const _hasLoadingBoundary = !!(route.loading && route.loading.default);
|
|
2110
2283
|
const _asyncLayoutParams = makeThenableParams(params);
|
|
2111
|
-
// Convert URLSearchParams to a plain object then wrap in makeThenableParams()
|
|
2112
|
-
// so probePage() passes the same shape that buildPageElement() gives to the
|
|
2113
|
-
// real render. Without this, pages that destructure await-ed searchParams
|
|
2114
|
-
// throw TypeError during probe.
|
|
2115
|
-
const _probeSearchObj = {};
|
|
2116
|
-
url.searchParams.forEach(function(v, k) {
|
|
2117
|
-
if (k in _probeSearchObj) {
|
|
2118
|
-
_probeSearchObj[k] = Array.isArray(_probeSearchObj[k]) ? _probeSearchObj[k].concat(v) : [_probeSearchObj[k], v];
|
|
2119
|
-
} else {
|
|
2120
|
-
_probeSearchObj[k] = v;
|
|
2121
|
-
}
|
|
2122
|
-
});
|
|
2123
|
-
const _asyncSearchParams = makeThenableParams(_probeSearchObj);
|
|
2124
2284
|
return __renderAppPageLifecycle({
|
|
2125
2285
|
cleanPathname,
|
|
2126
2286
|
clearRequestContext() {
|
|
@@ -2166,9 +2326,41 @@ async function _handleRequest(request, __reqCtx, _mwCtx) {
|
|
|
2166
2326
|
return LayoutComp({ params: _asyncLayoutParams, children: null });
|
|
2167
2327
|
},
|
|
2168
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);
|
|
2169
2340
|
return PageComponent({ params: _asyncLayoutParams, searchParams: _asyncSearchParams });
|
|
2170
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
|
+
},
|
|
2171
2362
|
revalidateSeconds,
|
|
2363
|
+
mountedSlotsHeader: __mountedSlotsHeader,
|
|
2172
2364
|
renderErrorBoundaryResponse(renderErr) {
|
|
2173
2365
|
return renderErrorBoundaryPage(route, renderErr, isRscRequest, request, params, _scriptNonce);
|
|
2174
2366
|
},
|