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.
Files changed (201) hide show
  1. package/README.md +1 -2
  2. package/dist/build/client-build-config.d.ts +119 -0
  3. package/dist/build/client-build-config.js +149 -0
  4. package/dist/build/client-build-config.js.map +1 -0
  5. package/dist/build/layout-classification-types.d.ts +62 -0
  6. package/dist/build/layout-classification-types.js +1 -0
  7. package/dist/build/layout-classification.d.ts +60 -0
  8. package/dist/build/layout-classification.js +98 -0
  9. package/dist/build/layout-classification.js.map +1 -0
  10. package/dist/build/report.d.ts +15 -1
  11. package/dist/build/report.js +50 -1
  12. package/dist/build/report.js.map +1 -1
  13. package/dist/build/route-classification-manifest.d.ts +53 -0
  14. package/dist/build/route-classification-manifest.js +145 -0
  15. package/dist/build/route-classification-manifest.js.map +1 -0
  16. package/dist/build/run-prerender.js +1 -1
  17. package/dist/build/ssr-manifest.d.ts +19 -0
  18. package/dist/build/ssr-manifest.js +71 -0
  19. package/dist/build/ssr-manifest.js.map +1 -0
  20. package/dist/check.js +4 -4
  21. package/dist/check.js.map +1 -1
  22. package/dist/cli.js +1 -1
  23. package/dist/cli.js.map +1 -1
  24. package/dist/client/entry.js +1 -1
  25. package/dist/config/config-matchers.js +1 -0
  26. package/dist/config/config-matchers.js.map +1 -1
  27. package/dist/entries/app-rsc-entry.js +341 -114
  28. package/dist/entries/app-rsc-entry.js.map +1 -1
  29. package/dist/entries/pages-server-entry.js +205 -199
  30. package/dist/entries/pages-server-entry.js.map +1 -1
  31. package/dist/index.d.ts +1 -169
  32. package/dist/index.js +113 -432
  33. package/dist/index.js.map +1 -1
  34. package/dist/init.d.ts +1 -1
  35. package/dist/init.js +2 -2
  36. package/dist/init.js.map +1 -1
  37. package/dist/plugins/fonts.d.ts +49 -1
  38. package/dist/plugins/fonts.js +97 -3
  39. package/dist/plugins/fonts.js.map +1 -1
  40. package/dist/plugins/postcss.d.ts +27 -0
  41. package/dist/plugins/postcss.js +94 -0
  42. package/dist/plugins/postcss.js.map +1 -0
  43. package/dist/plugins/strip-server-exports.d.ts +14 -0
  44. package/dist/plugins/strip-server-exports.js +73 -0
  45. package/dist/plugins/strip-server-exports.js.map +1 -0
  46. package/dist/routing/app-router.d.ts +6 -4
  47. package/dist/routing/app-router.js +21 -22
  48. package/dist/routing/app-router.js.map +1 -1
  49. package/dist/server/app-browser-entry.js +235 -97
  50. package/dist/server/app-browser-entry.js.map +1 -1
  51. package/dist/server/app-browser-error.d.ts +8 -0
  52. package/dist/server/app-browser-error.js +9 -0
  53. package/dist/server/app-browser-error.js.map +1 -0
  54. package/dist/server/app-browser-state.d.ts +93 -0
  55. package/dist/server/app-browser-state.js +132 -0
  56. package/dist/server/app-browser-state.js.map +1 -0
  57. package/dist/server/app-elements.d.ts +92 -0
  58. package/dist/server/app-elements.js +122 -0
  59. package/dist/server/app-elements.js.map +1 -0
  60. package/dist/server/app-page-boundary-render.d.ts +3 -1
  61. package/dist/server/app-page-boundary-render.js +41 -1
  62. package/dist/server/app-page-boundary-render.js.map +1 -1
  63. package/dist/server/app-page-cache.d.ts +6 -3
  64. package/dist/server/app-page-cache.js +14 -8
  65. package/dist/server/app-page-cache.js.map +1 -1
  66. package/dist/server/app-page-execution.d.ts +36 -3
  67. package/dist/server/app-page-execution.js +50 -10
  68. package/dist/server/app-page-execution.js.map +1 -1
  69. package/dist/server/app-page-probe.d.ts +10 -4
  70. package/dist/server/app-page-probe.js +24 -15
  71. package/dist/server/app-page-probe.js.map +1 -1
  72. package/dist/server/app-page-render.d.ts +8 -4
  73. package/dist/server/app-page-render.js +15 -4
  74. package/dist/server/app-page-render.js.map +1 -1
  75. package/dist/server/app-page-request.d.ts +52 -4
  76. package/dist/server/app-page-request.js +86 -16
  77. package/dist/server/app-page-request.js.map +1 -1
  78. package/dist/server/app-page-response.d.ts +4 -11
  79. package/dist/server/app-page-response.js +7 -19
  80. package/dist/server/app-page-response.js.map +1 -1
  81. package/dist/server/app-page-route-wiring.d.ts +22 -8
  82. package/dist/server/app-page-route-wiring.js +219 -81
  83. package/dist/server/app-page-route-wiring.js.map +1 -1
  84. package/dist/server/app-page-stream.d.ts +4 -1
  85. package/dist/server/app-page-stream.js +2 -1
  86. package/dist/server/app-page-stream.js.map +1 -1
  87. package/dist/server/app-render-dependency.d.ts +13 -0
  88. package/dist/server/app-render-dependency.js +35 -0
  89. package/dist/server/app-render-dependency.js.map +1 -0
  90. package/dist/server/app-route-handler-execution.d.ts +1 -0
  91. package/dist/server/app-route-handler-execution.js +1 -0
  92. package/dist/server/app-route-handler-execution.js.map +1 -1
  93. package/dist/server/app-route-handler-response.js +2 -1
  94. package/dist/server/app-route-handler-response.js.map +1 -1
  95. package/dist/server/app-route-handler-runtime.d.ts +1 -0
  96. package/dist/server/app-route-handler-runtime.js +26 -1
  97. package/dist/server/app-route-handler-runtime.js.map +1 -1
  98. package/dist/server/app-ssr-entry.d.ts +3 -1
  99. package/dist/server/app-ssr-entry.js +23 -19
  100. package/dist/server/app-ssr-entry.js.map +1 -1
  101. package/dist/server/app-ssr-stream.d.ts +1 -1
  102. package/dist/server/app-ssr-stream.js +4 -4
  103. package/dist/server/app-ssr-stream.js.map +1 -1
  104. package/dist/server/csp.d.ts +12 -0
  105. package/dist/server/csp.js +46 -0
  106. package/dist/server/csp.js.map +1 -0
  107. package/dist/server/dev-server.js +22 -18
  108. package/dist/server/dev-server.js.map +1 -1
  109. package/dist/server/html.d.ts +4 -1
  110. package/dist/server/html.js +11 -1
  111. package/dist/server/html.js.map +1 -1
  112. package/dist/server/middleware-response-headers.d.ts +12 -0
  113. package/dist/server/middleware-response-headers.js +23 -0
  114. package/dist/server/middleware-response-headers.js.map +1 -0
  115. package/dist/server/middleware.js +1 -5
  116. package/dist/server/middleware.js.map +1 -1
  117. package/dist/server/pages-page-data.d.ts +1 -0
  118. package/dist/server/pages-page-data.js +2 -2
  119. package/dist/server/pages-page-data.js.map +1 -1
  120. package/dist/server/pages-page-response.d.ts +2 -1
  121. package/dist/server/pages-page-response.js +16 -14
  122. package/dist/server/pages-page-response.js.map +1 -1
  123. package/dist/server/prod-server.d.ts +3 -3
  124. package/dist/server/prod-server.js +5 -4
  125. package/dist/server/prod-server.js.map +1 -1
  126. package/dist/server/request-pipeline.d.ts +15 -1
  127. package/dist/server/request-pipeline.js +88 -5
  128. package/dist/server/request-pipeline.js.map +1 -1
  129. package/dist/shims/cache-runtime.d.ts +1 -0
  130. package/dist/shims/cache-runtime.js +0 -5
  131. package/dist/shims/cache-runtime.js.map +1 -1
  132. package/dist/shims/cache.d.ts +1 -0
  133. package/dist/shims/cache.js +1 -8
  134. package/dist/shims/cache.js.map +1 -1
  135. package/dist/shims/client-hook-error.d.ts +14 -0
  136. package/dist/shims/client-hook-error.js +19 -0
  137. package/dist/shims/client-hook-error.js.map +1 -0
  138. package/dist/shims/constants.d.ts +3 -3
  139. package/dist/shims/constants.js +3 -3
  140. package/dist/shims/constants.js.map +1 -1
  141. package/dist/shims/document.d.ts +6 -6
  142. package/dist/shims/error-boundary.d.ts +4 -4
  143. package/dist/shims/error-boundary.js +1 -1
  144. package/dist/shims/error-boundary.js.map +1 -1
  145. package/dist/shims/form.d.ts +3 -3
  146. package/dist/shims/head-state.d.ts +1 -0
  147. package/dist/shims/head-state.js +0 -5
  148. package/dist/shims/head-state.js.map +1 -1
  149. package/dist/shims/headers.d.ts +11 -0
  150. package/dist/shims/headers.js +13 -10
  151. package/dist/shims/headers.js.map +1 -1
  152. package/dist/shims/i18n-state.d.ts +1 -0
  153. package/dist/shims/i18n-state.js +0 -4
  154. package/dist/shims/i18n-state.js.map +1 -1
  155. package/dist/shims/internal/app-router-context.d.ts +6 -6
  156. package/dist/shims/internal/router-context.d.ts +2 -2
  157. package/dist/shims/layout-segment-context.d.ts +2 -2
  158. package/dist/shims/link.js +19 -11
  159. package/dist/shims/link.js.map +1 -1
  160. package/dist/shims/metadata.d.ts +3 -3
  161. package/dist/shims/navigation-state.d.ts +2 -0
  162. package/dist/shims/navigation-state.js +0 -13
  163. package/dist/shims/navigation-state.js.map +1 -1
  164. package/dist/shims/navigation.d.ts +55 -8
  165. package/dist/shims/navigation.js +97 -23
  166. package/dist/shims/navigation.js.map +1 -1
  167. package/dist/shims/navigation.react-server.d.ts +14 -0
  168. package/dist/shims/navigation.react-server.js +29 -0
  169. package/dist/shims/navigation.react-server.js.map +1 -0
  170. package/dist/shims/request-context.d.ts +1 -0
  171. package/dist/shims/request-context.js +0 -9
  172. package/dist/shims/request-context.js.map +1 -1
  173. package/dist/shims/request-state-types.d.ts +1 -1
  174. package/dist/shims/router-state.d.ts +1 -0
  175. package/dist/shims/router-state.js +0 -5
  176. package/dist/shims/router-state.js.map +1 -1
  177. package/dist/shims/script-nonce-context.d.ts +12 -0
  178. package/dist/shims/script-nonce-context.js +17 -0
  179. package/dist/shims/script-nonce-context.js.map +1 -0
  180. package/dist/shims/script.js +41 -10
  181. package/dist/shims/script.js.map +1 -1
  182. package/dist/shims/server.js +6 -1
  183. package/dist/shims/server.js.map +1 -1
  184. package/dist/shims/slot.d.ts +11 -7
  185. package/dist/shims/slot.js +28 -19
  186. package/dist/shims/slot.js.map +1 -1
  187. package/dist/shims/unified-request-context.d.ts +2 -0
  188. package/dist/shims/unified-request-context.js +0 -14
  189. package/dist/shims/unified-request-context.js.map +1 -1
  190. package/dist/shims/url-safety.js +25 -4
  191. package/dist/shims/url-safety.js.map +1 -1
  192. package/dist/utils/mdx-scan.d.ts +10 -0
  193. package/dist/utils/mdx-scan.js +36 -0
  194. package/dist/utils/mdx-scan.js.map +1 -0
  195. package/dist/utils/public-routes.d.ts +5 -0
  196. package/dist/utils/public-routes.js +50 -0
  197. package/dist/utils/public-routes.js.map +1 -0
  198. package/package.json +9 -9
  199. package/dist/plugins/fix-use-server-closure-collision.d.ts +0 -29
  200. package/dist/plugins/fix-use-server-closure-collision.js +0 -204
  201. 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) if (tmpl) getImportVar(tmpl);
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) => t ? getImportVar(t) : "null");
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.name)}: {
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 { validateCsrfOrigin, validateImageUrl, guardProtocolRelativeUrl, hasBasePath, stripBasePath, normalizeTrailingSlash, processMiddlewareHeaders } from ${JSON.stringify(requestPipelinePath)};
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
- buildAppPageRouteElement as __buildAppPageRouteElement,
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) { return __isrCacheKey(pathname, "rsc"); }
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, slotName, interceptPage, params }.
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 [slotName, slotMod] of Object.entries(r.slots)) {
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
- slotName,
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 buildPageElement(route, params, opts, searchParams) {
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
- return createElement("div", null, "Page has no default export");
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
- return __buildAppPageRouteElement({
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.interceptSlot && opts.interceptPage
970
+ opts && opts.interceptSlotKey && opts.interceptPage
877
971
  ? {
878
- [opts.interceptSlot]: {
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;<type>;<url>[;<status>]".
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", // Server Action → default "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: actionParams,
1720
+ params: __actionRerenderTarget.navigationParams,
1585
1721
  });
1586
- element = await buildPageElement(actionRoute, actionParams, undefined, url.searchParams);
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
- element = createElement("div", null, "Page not found");
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
- match ? match.route.pattern : cleanPathname,
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({ "Content-Type": "text/x-component; charset=utf-8", "Vary": "RSC, Accept" });
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
- actionHeaders.append("Set-Cookie", cookie);
1774
+ actionResponse.headers.append("Set-Cookie", cookie);
1614
1775
  }
1615
- if (actionDraftCookie) actionHeaders.append("Set-Cookie", actionDraftCookie);
1776
+ if (actionDraftCookie) actionResponse.headers.append("Set-Cookie", actionDraftCookie);
1616
1777
  }
1617
- return new Response(rscStream, { status: _mwCtx.status ?? 200, headers: actionHeaders });
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(request, __decodePathParams(url.pathname) + (url.search || ""), {});
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
- const __revalElement = await buildPageElement(route, params, undefined, new URLSearchParams());
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
- getRoutePattern(sourceRoute) {
1990
- return sourceRoute.pattern;
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({ "Content-Type": "text/x-component; charset=utf-8", "Vary": "RSC, Accept" });
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
- interceptSlot: intercept.slotName,
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 buildPageElement(route, params, interceptOpts, url.searchParams);
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(route, statusCode, isRscRequest, request, {
2073
- matchedParams: params,
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(route, statusCode, isRscRequest, request, {
2177
- boundaryComponent: parentNotFound,
2178
- layouts: parentLayouts,
2179
- matchedParams: params,
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(route, statusCode, isRscRequest, request, {
2194
- matchedParams: params,
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
  },