vinext 1.0.1 → 1.2.0

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 (334) hide show
  1. package/README.md +93 -10
  2. package/dist/build/app-page-static-eligibility.d.ts +15 -0
  3. package/dist/build/app-page-static-eligibility.js +82 -0
  4. package/dist/build/client-build-config.d.ts +10 -0
  5. package/dist/build/client-build-config.js +18 -2
  6. package/dist/build/pages-client-assets-module.d.ts +8 -0
  7. package/dist/build/pages-client-assets-module.js +21 -1
  8. package/dist/build/prerender-paths.js +8 -81
  9. package/dist/build/prerender.js +33 -8
  10. package/dist/build/run-prerender.js +1 -1
  11. package/dist/build/server-manifest.d.ts +7 -0
  12. package/dist/build/server-manifest.js +11 -1
  13. package/dist/build/ssr-manifest.d.ts +2 -0
  14. package/dist/build/ssr-manifest.js +6 -2
  15. package/dist/cache/cache-adapters-virtual.d.ts +7 -1
  16. package/dist/cache/cache-adapters-virtual.js +3 -3
  17. package/dist/check.js +7 -6
  18. package/dist/cli.js +2 -1
  19. package/dist/client/client-redirect-matcher.d.ts +14 -0
  20. package/dist/client/client-redirect-matcher.js +37 -0
  21. package/dist/client/client-redirects.d.ts +27 -0
  22. package/dist/client/client-redirects.js +28 -0
  23. package/dist/client/client-rewrites.d.ts +2 -1
  24. package/dist/client/client-rewrites.js +1 -1
  25. package/dist/client/navigation-runtime.d.ts +11 -0
  26. package/dist/client/navigation-runtime.js +1 -1
  27. package/dist/config/config-matchers.d.ts +26 -11
  28. package/dist/config/config-matchers.js +81 -82
  29. package/dist/config/destination-params.d.ts +47 -0
  30. package/dist/config/destination-params.js +116 -0
  31. package/dist/config/next-config.d.ts +14 -0
  32. package/dist/config/next-config.js +21 -3
  33. package/dist/entries/app-rsc-entry.d.ts +6 -0
  34. package/dist/entries/app-rsc-entry.js +84 -49
  35. package/dist/entries/pages-client-entry.js +3 -1
  36. package/dist/entries/pages-server-entry.js +13 -37
  37. package/dist/index.d.ts +7 -2
  38. package/dist/index.js +193 -73
  39. package/dist/init-cloudflare.d.ts +9 -0
  40. package/dist/init-cloudflare.js +107 -31
  41. package/dist/init-platform.d.ts +4 -0
  42. package/dist/init-platform.js +27 -2
  43. package/dist/init.d.ts +1 -0
  44. package/dist/init.js +67 -3
  45. package/dist/plugins/ast-scope.d.ts +7 -0
  46. package/dist/plugins/ast-scope.js +59 -3
  47. package/dist/plugins/cache-flight-codec.d.ts +19 -0
  48. package/dist/plugins/cache-flight-codec.js +68 -0
  49. package/dist/plugins/commonjs-esm-facade.d.ts +35 -0
  50. package/dist/plugins/commonjs-esm-facade.js +80 -0
  51. package/dist/plugins/dynamic-preload-metadata.d.ts +1 -1
  52. package/dist/plugins/dynamic-preload-metadata.js +9 -8
  53. package/dist/plugins/fonts.d.ts +8 -11
  54. package/dist/plugins/fonts.js +71 -34
  55. package/dist/plugins/ignore-dynamic-requests.d.ts +1 -1
  56. package/dist/plugins/ignore-dynamic-requests.js +3 -4
  57. package/dist/plugins/middleware-server-only.d.ts +5 -4
  58. package/dist/plugins/middleware-server-only.js +8 -5
  59. package/dist/plugins/pages-node-externals.js +1 -1
  60. package/dist/plugins/rsc-scan-glob-imports.d.ts +19 -0
  61. package/dist/plugins/rsc-scan-glob-imports.js +50 -0
  62. package/dist/plugins/strip-server-exports.js +262 -98
  63. package/dist/plugins/transform-result.d.ts +9 -5
  64. package/dist/plugins/transitive-externals.js +1 -1
  65. package/dist/plugins/typeof-window.d.ts +2 -2
  66. package/dist/plugins/use-cache-callable.js +8 -2
  67. package/dist/plugins/worker-server-only-imports.d.ts +20 -0
  68. package/dist/plugins/worker-server-only-imports.js +31 -0
  69. package/dist/plugins/worker-use-server.d.ts +25 -0
  70. package/dist/plugins/worker-use-server.js +129 -0
  71. package/dist/routing/file-matcher.d.ts +1 -0
  72. package/dist/routing/file-matcher.js +1 -1
  73. package/dist/server/api-handler.d.ts +1 -0
  74. package/dist/server/api-handler.js +19 -8
  75. package/dist/server/app-browser-action-result.d.ts +1 -1
  76. package/dist/server/app-browser-action-result.js +9 -2
  77. package/dist/server/app-browser-entry.js +11 -7
  78. package/dist/server/app-browser-history-controller.d.ts +2 -0
  79. package/dist/server/app-browser-history-controller.js +8 -0
  80. package/dist/server/app-browser-interception-context.js +26 -2
  81. package/dist/server/app-browser-navigation-controller.d.ts +7 -1
  82. package/dist/server/app-browser-navigation-controller.js +94 -11
  83. package/dist/server/app-browser-server-action-client.js +1 -1
  84. package/dist/server/app-fallback-renderer.d.ts +2 -0
  85. package/dist/server/app-fallback-renderer.js +1 -0
  86. package/dist/server/app-history-state.d.ts +3 -0
  87. package/dist/server/app-history-state.js +7 -0
  88. package/dist/server/app-middleware.d.ts +11 -0
  89. package/dist/server/app-middleware.js +19 -3
  90. package/dist/server/app-optimistic-routing.js +1 -1
  91. package/dist/server/app-page-boundary-render.d.ts +5 -0
  92. package/dist/server/app-page-boundary-render.js +6 -4
  93. package/dist/server/app-page-cache-finalizer.d.ts +11 -0
  94. package/dist/server/app-page-cache-finalizer.js +41 -7
  95. package/dist/server/app-page-cache-render.d.ts +18 -0
  96. package/dist/server/app-page-cache-render.js +63 -43
  97. package/dist/server/app-page-cache.d.ts +6 -1
  98. package/dist/server/app-page-cache.js +28 -8
  99. package/dist/server/app-page-dispatch.d.ts +12 -2
  100. package/dist/server/app-page-dispatch.js +51 -33
  101. package/dist/server/app-page-element-builder.d.ts +7 -0
  102. package/dist/server/app-page-element-builder.js +27 -42
  103. package/dist/server/app-page-execution.d.ts +15 -12
  104. package/dist/server/app-page-execution.js +30 -40
  105. package/dist/server/app-page-head.d.ts +5 -0
  106. package/dist/server/app-page-head.js +9 -3
  107. package/dist/server/app-page-ppr-runtime.js +1 -1
  108. package/dist/server/app-page-probe.d.ts +0 -109
  109. package/dist/server/app-page-probe.js +3 -136
  110. package/dist/server/app-page-render-identity.d.ts +0 -1
  111. package/dist/server/app-page-render-identity.js +1 -1
  112. package/dist/server/app-page-render-observation.js +3 -3
  113. package/dist/server/app-page-render.d.ts +13 -5
  114. package/dist/server/app-page-render.js +219 -119
  115. package/dist/server/app-page-request.d.ts +0 -1
  116. package/dist/server/app-page-request.js +54 -17
  117. package/dist/server/app-page-response.d.ts +4 -3
  118. package/dist/server/app-page-response.js +4 -3
  119. package/dist/server/app-page-route-wiring.d.ts +17 -5
  120. package/dist/server/app-page-route-wiring.js +57 -35
  121. package/dist/server/app-page-rsc-render-status.d.ts +48 -0
  122. package/dist/server/app-page-rsc-render-status.js +54 -0
  123. package/dist/server/app-page-stream.d.ts +15 -8
  124. package/dist/server/app-page-stream.js +6 -0
  125. package/dist/server/app-pages-bridge.d.ts +1 -1
  126. package/dist/server/app-pages-bridge.js +2 -3
  127. package/dist/server/app-prerender-endpoints.js +9 -6
  128. package/dist/server/app-request-stage-dispatch.js +7 -3
  129. package/dist/server/app-request-stage-independent-entry.js +29 -9
  130. package/dist/server/app-response-header-provenance.d.ts +2 -0
  131. package/dist/server/app-response-header-provenance.js +10 -4
  132. package/dist/server/app-response-stage-entry.js +10 -2
  133. package/dist/server/app-route-handler-cache.d.ts +1 -0
  134. package/dist/server/app-route-handler-cache.js +1 -0
  135. package/dist/server/app-route-handler-dispatch.d.ts +1 -0
  136. package/dist/server/app-route-handler-dispatch.js +6 -3
  137. package/dist/server/app-route-handler-execution.d.ts +1 -0
  138. package/dist/server/app-route-handler-execution.js +1 -0
  139. package/dist/server/app-route-handler-runtime.d.ts +4 -1
  140. package/dist/server/app-route-handler-runtime.js +45 -24
  141. package/dist/server/app-router-entry.js +27 -8
  142. package/dist/server/app-rsc-cache-busting.js +1 -1
  143. package/dist/server/app-rsc-errors.js +20 -16
  144. package/dist/server/app-rsc-handler.d.ts +11 -0
  145. package/dist/server/app-rsc-handler.js +291 -125
  146. package/dist/server/app-rsc-request-normalization.d.ts +3 -1
  147. package/dist/server/app-rsc-request-normalization.js +4 -2
  148. package/dist/server/app-rsc-response-stage.d.ts +1 -1
  149. package/dist/server/app-rsc-response-stage.js +10 -6
  150. package/dist/server/app-rsc-route-matching.d.ts +9 -1
  151. package/dist/server/app-rsc-route-matching.js +36 -19
  152. package/dist/server/app-segment-config.d.ts +2 -1
  153. package/dist/server/app-server-action-execution.d.ts +2 -1
  154. package/dist/server/app-server-action-execution.js +62 -23
  155. package/dist/server/app-ssr-entry.d.ts +3 -2
  156. package/dist/server/app-ssr-entry.js +8 -5
  157. package/dist/server/app-ssr-stream.d.ts +6 -1
  158. package/dist/server/app-ssr-stream.js +34 -15
  159. package/dist/server/app-worker-stages.d.ts +7 -2
  160. package/dist/server/app-worker-stages.js +4 -4
  161. package/dist/server/cacheability-request.js +11 -7
  162. package/dist/server/client-build-files.d.ts +16 -0
  163. package/dist/server/client-build-files.js +36 -0
  164. package/dist/server/client-reuse-manifest.js +1 -1
  165. package/dist/server/config-headers.js +2 -0
  166. package/dist/server/dev-server.js +50 -29
  167. package/dist/server/dev-stack-sourcemap.js +18 -23
  168. package/dist/server/document-initial-head.d.ts +0 -11
  169. package/dist/server/document-initial-head.js +1 -1
  170. package/dist/server/forwarded-middleware-context.d.ts +5 -0
  171. package/dist/server/forwarded-middleware-context.js +22 -0
  172. package/dist/server/headers.d.ts +18 -1
  173. package/dist/server/headers.js +19 -2
  174. package/dist/server/http-conditional.d.ts +11 -0
  175. package/dist/server/http-conditional.js +10 -1
  176. package/dist/server/http-error-responses.d.ts +1 -1
  177. package/dist/server/image-optimization.d.ts +54 -0
  178. package/dist/server/image-optimization.js +118 -9
  179. package/dist/server/isr-cache.d.ts +10 -0
  180. package/dist/server/isr-cache.js +43 -8
  181. package/dist/server/metadata-route-response.js +9 -8
  182. package/dist/server/middleware-matcher-pattern.js +8 -4
  183. package/dist/server/middleware-matcher.d.ts +2 -0
  184. package/dist/server/middleware-matcher.js +23 -2
  185. package/dist/server/middleware-response-headers.js +2 -0
  186. package/dist/server/middleware-runtime.d.ts +13 -0
  187. package/dist/server/middleware-runtime.js +33 -20
  188. package/dist/server/middleware.d.ts +1 -1
  189. package/dist/server/middleware.js +3 -1
  190. package/dist/server/multi-stage.d.ts +19 -0
  191. package/dist/server/navigation-planner.js +1 -1
  192. package/dist/server/node-response-signal.d.ts +16 -0
  193. package/dist/server/node-response-signal.js +26 -0
  194. package/dist/server/normalize-path.d.ts +0 -13
  195. package/dist/server/normalize-path.js +1 -34
  196. package/dist/server/open-redirect.d.ts +47 -0
  197. package/dist/server/open-redirect.js +74 -1
  198. package/dist/server/pages-api-route.d.ts +3 -2
  199. package/dist/server/pages-api-route.js +4 -3
  200. package/dist/server/pages-cache-tag.d.ts +12 -0
  201. package/dist/server/pages-cache-tag.js +19 -0
  202. package/dist/server/pages-client-assets.d.ts +2 -0
  203. package/dist/server/pages-data-route.d.ts +10 -0
  204. package/dist/server/pages-data-route.js +19 -2
  205. package/dist/server/pages-document-asset-props.d.ts +5 -1
  206. package/dist/server/pages-document-asset-props.js +13 -5
  207. package/dist/server/pages-document-splice.d.ts +19 -0
  208. package/dist/server/pages-document-splice.js +55 -0
  209. package/dist/server/pages-i18n.d.ts +12 -1
  210. package/dist/server/pages-i18n.js +18 -4
  211. package/dist/server/pages-node-compat.d.ts +16 -5
  212. package/dist/server/pages-node-compat.js +20 -12
  213. package/dist/server/pages-page-data.d.ts +32 -24
  214. package/dist/server/pages-page-data.js +50 -120
  215. package/dist/server/pages-page-handler.d.ts +0 -6
  216. package/dist/server/pages-page-handler.js +209 -130
  217. package/dist/server/pages-page-response.d.ts +12 -6
  218. package/dist/server/pages-page-response.js +41 -34
  219. package/dist/server/pages-request-pipeline.d.ts +10 -2
  220. package/dist/server/pages-request-pipeline.js +37 -18
  221. package/dist/server/pages-request-stage-entry.d.ts +6 -0
  222. package/dist/server/pages-request-stage-entry.js +79 -16
  223. package/dist/server/pages-response-stage-entry.js +4 -0
  224. package/dist/server/pages-revalidate.js +1 -1
  225. package/dist/server/pages-router-entry.js +4 -3
  226. package/dist/server/prerender-manifest.d.ts +3 -3
  227. package/dist/server/prerender-manifest.js +4 -3
  228. package/dist/server/prerender-work-unit-setup.js +4 -0
  229. package/dist/server/prod-server.d.ts +20 -7
  230. package/dist/server/prod-server.js +343 -129
  231. package/dist/server/proper-error.d.ts +4 -0
  232. package/dist/server/proper-error.js +31 -0
  233. package/dist/server/request-pipeline.d.ts +24 -9
  234. package/dist/server/request-pipeline.js +24 -9
  235. package/dist/server/response-compression.d.ts +43 -0
  236. package/dist/server/response-compression.js +111 -0
  237. package/dist/server/revalidation-request.d.ts +1 -0
  238. package/dist/server/revalidation-request.js +1 -1
  239. package/dist/server/rsc-stream-hints.js +31 -2
  240. package/dist/server/seed-cache.d.ts +1 -0
  241. package/dist/server/seed-cache.js +15 -11
  242. package/dist/server/server-reference-loader.d.ts +4 -0
  243. package/dist/server/server-reference-loader.js +29 -0
  244. package/dist/server/socket-error-backstop.d.ts +23 -1
  245. package/dist/server/socket-error-backstop.js +69 -17
  246. package/dist/server/static-file-signal.d.ts +15 -4
  247. package/dist/server/static-file-signal.js +46 -12
  248. package/dist/server/worker-image-optimization.d.ts +34 -0
  249. package/dist/server/worker-image-optimization.js +86 -0
  250. package/dist/server/worker-stages.d.ts +1 -1
  251. package/dist/server/worker-stages.js +2 -2
  252. package/dist/server/worker-utils.d.ts +8 -3
  253. package/dist/server/worker-utils.js +12 -7
  254. package/dist/shims/app-router-scroll.js +4 -1
  255. package/dist/shims/app-router-tree-context.d.ts +5 -0
  256. package/dist/shims/app-router-tree-context.js +27 -0
  257. package/dist/shims/cache-adapter-instantiate.d.ts +50 -0
  258. package/dist/shims/cache-adapter-instantiate.js +118 -0
  259. package/dist/shims/cache-callable-runtime.d.ts +6 -42
  260. package/dist/shims/cache-callable-runtime.js +65 -174
  261. package/dist/shims/cache-flight-arguments.d.ts +22 -0
  262. package/dist/shims/cache-flight-arguments.js +56 -0
  263. package/dist/shims/cache-handler.js +1 -9
  264. package/dist/shims/cache-request-state.d.ts +15 -0
  265. package/dist/shims/cache-request-state.js +31 -8
  266. package/dist/shims/cache-runtime.d.ts +12 -20
  267. package/dist/shims/cache-runtime.js +166 -225
  268. package/dist/shims/cache.d.ts +4 -4
  269. package/dist/shims/cache.js +44 -16
  270. package/dist/shims/cacheability-classification.d.ts +7 -0
  271. package/dist/shims/cdn-cache.d.ts +8 -0
  272. package/dist/shims/cdn-cache.js +17 -1
  273. package/dist/shims/disable-smooth-scroll.d.ts +3 -0
  274. package/dist/shims/disable-smooth-scroll.js +36 -0
  275. package/dist/shims/document-placeholders.d.ts +19 -0
  276. package/dist/shims/document-placeholders.js +45 -0
  277. package/dist/shims/document.js +21 -5
  278. package/dist/shims/dynamic-preload-chunks.d.ts +1 -0
  279. package/dist/shims/dynamic-preload-chunks.js +13 -9
  280. package/dist/shims/dynamic.d.ts +1 -1
  281. package/dist/shims/dynamic.js +60 -8
  282. package/dist/shims/error-boundary-navigation.d.ts +7 -0
  283. package/dist/shims/error-boundary-navigation.js +19 -1
  284. package/dist/shims/error-boundary.d.ts +10 -10
  285. package/dist/shims/error-boundary.js +26 -7
  286. package/dist/shims/fetch-cache-state.d.ts +66 -0
  287. package/dist/shims/fetch-cache-state.js +92 -0
  288. package/dist/shims/fetch-cache.d.ts +3 -61
  289. package/dist/shims/fetch-cache.js +161 -108
  290. package/dist/shims/form.js +1 -1
  291. package/dist/shims/head.d.ts +10 -6
  292. package/dist/shims/head.js +15 -13
  293. package/dist/shims/headers.d.ts +13 -0
  294. package/dist/shims/headers.js +47 -4
  295. package/dist/shims/image.js +2 -1
  296. package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -2
  297. package/dist/shims/internal/app-page-props-cache-key.js +24 -15
  298. package/dist/shims/internal/headers-state.d.ts +0 -1
  299. package/dist/shims/internal/work-store-scope.d.ts +5 -0
  300. package/dist/shims/internal/work-store-scope.js +24 -0
  301. package/dist/shims/metadata.js +3 -3
  302. package/dist/shims/navigation-errors.d.ts +6 -0
  303. package/dist/shims/navigation-errors.js +11 -1
  304. package/dist/shims/navigation.d.ts +7 -0
  305. package/dist/shims/navigation.js +45 -9
  306. package/dist/shims/request-context.d.ts +11 -0
  307. package/dist/shims/request-state-types.d.ts +2 -1
  308. package/dist/shims/router.js +12 -20
  309. package/dist/shims/server.d.ts +16 -0
  310. package/dist/shims/server.js +24 -4
  311. package/dist/shims/thenable-params.d.ts +4 -0
  312. package/dist/shims/thenable-params.js +25 -3
  313. package/dist/shims/unified-request-context.d.ts +1 -1
  314. package/dist/shims/unified-request-context.js +1 -0
  315. package/dist/shims/url-utils.d.ts +2 -0
  316. package/dist/shims/url-utils.js +3 -1
  317. package/dist/utils/client-runtime-metadata.js +1 -1
  318. package/dist/utils/hash.d.ts +7 -0
  319. package/dist/utils/hash.js +11 -1
  320. package/dist/utils/mdx-scan.d.ts +5 -0
  321. package/dist/utils/mdx-scan.js +8 -1
  322. package/dist/utils/package-name.d.ts +6 -0
  323. package/dist/utils/package-name.js +12 -1
  324. package/dist/utils/plugin-rsc-version.d.ts +4 -0
  325. package/dist/utils/plugin-rsc-version.js +15 -0
  326. package/dist/utils/prerender-output-paths.js +15 -4
  327. package/dist/utils/public-file-path.d.ts +10 -2
  328. package/dist/utils/public-file-path.js +13 -9
  329. package/dist/utils/public-routes.js +2 -2
  330. package/dist/utils/react-version.d.ts +3 -0
  331. package/dist/utils/react-version.js +1 -1
  332. package/dist/utils/regex-safety.d.ts +10 -0
  333. package/dist/utils/regex-safety.js +70 -18
  334. package/package.json +9 -5
@@ -26,34 +26,49 @@ async function renderAppPageCacheArtifactsImpl(options, renderSpan) {
26
26
  const rscCapture = teeAppPageRscStreamForCapture(rscStream, options.captureRscData);
27
27
  const capturedRscDataRef = { value: null };
28
28
  const fontPreloads = options.getFontPreloads();
29
- const htmlResult = await (await options.loadSsrHandler()).handleSsr(rscCapture.ssrStream, options.getNavigationContext(), {
30
- links: options.getFontLinks(),
31
- styles: options.getFontStyles(),
32
- preloads: fontPreloads
33
- }, {
34
- basePath: options.basePath,
35
- clientTraceMetadata: options.clientTraceMetadata,
36
- reactMaxHeadersLength: options.reactMaxHeadersLength,
37
- rootParams: options.rootParams,
38
- waitForAllReady: options.waitForAllReady,
39
- isStaticGeneration: true,
40
- isForceStatic: options.isForceStatic,
41
- onSsrError: options.onSsrError && options.isCapturedRscError ? createAppPageSsrErrorHandler((error) => {
42
- recordAppPageRenderError(renderSpan, error);
43
- return options.onSsrError?.(error);
44
- }, options.isCapturedRscError) : options.onSsrError ? (error) => {
45
- recordAppPageRenderError(renderSpan, error);
46
- return options.onSsrError?.(error);
47
- } : void 0,
48
- ...rscCapture.sideStream ? {
49
- sideStream: rscCapture.sideStream,
50
- capturedRscDataRef
51
- } : {}
52
- });
53
- const htmlStream = isAppSsrRenderResult(htmlResult) ? htmlResult.htmlStream : htmlResult;
54
- const reactLinkHeader = isAppSsrRenderResult(htmlResult) ? htmlResult.linkHeader : void 0;
55
- const linkHeader = buildAppPageLinkHeader(reactLinkHeader, buildAppPageFontLinkHeader(fontPreloads), options.reactMaxHeadersLength);
56
- const html = await readStreamAsText(htmlStream);
29
+ const ssrHandler = await options.loadSsrHandler();
30
+ let htmlResult = null;
31
+ let specialErrorDocument = null;
32
+ try {
33
+ htmlResult = await ssrHandler.handleSsr(rscCapture.ssrStream, options.getNavigationContext(), {
34
+ links: options.getFontLinks(),
35
+ styles: options.getFontStyles(),
36
+ preloads: fontPreloads
37
+ }, {
38
+ basePath: options.basePath,
39
+ clientTraceMetadata: options.clientTraceMetadata,
40
+ reactMaxHeadersLength: options.reactMaxHeadersLength,
41
+ rootParams: options.rootParams,
42
+ waitForAllReady: options.waitForAllReady,
43
+ mirrorNextFlight: options.mirrorNextFlight,
44
+ isStaticGeneration: true,
45
+ isForceStatic: options.isForceStatic,
46
+ onSsrError: options.onSsrError && options.isCapturedRscError ? createAppPageSsrErrorHandler((error) => {
47
+ recordAppPageRenderError(renderSpan, error);
48
+ return options.onSsrError?.(error);
49
+ }, options.isCapturedRscError) : options.onSsrError ? (error) => {
50
+ recordAppPageRenderError(renderSpan, error);
51
+ return options.onSsrError?.(error);
52
+ } : void 0,
53
+ ...rscCapture.sideStream ? {
54
+ sideStream: rscCapture.sideStream,
55
+ capturedRscDataRef
56
+ } : {}
57
+ });
58
+ } catch (error) {
59
+ if (!options.renderShellSpecialError) throw error;
60
+ await capturedRscDataRef.value?.catch(() => {});
61
+ specialErrorDocument = await options.renderShellSpecialError(error);
62
+ if (!specialErrorDocument) throw error;
63
+ }
64
+ let html = specialErrorDocument?.html ?? "";
65
+ let linkHeader = specialErrorDocument?.linkHeader;
66
+ if (htmlResult) {
67
+ const htmlStream = isAppSsrRenderResult(htmlResult) ? htmlResult.htmlStream : htmlResult;
68
+ const reactLinkHeader = isAppSsrRenderResult(htmlResult) ? htmlResult.linkHeader : void 0;
69
+ linkHeader = buildAppPageLinkHeader(reactLinkHeader, buildAppPageFontLinkHeader(fontPreloads), options.reactMaxHeadersLength);
70
+ html = await readStreamAsText(htmlStream);
71
+ }
57
72
  let rscData;
58
73
  if (options.captureRscData) {
59
74
  const capturedPromise = capturedRscDataRef.value;
@@ -65,24 +80,29 @@ async function renderAppPageCacheArtifactsImpl(options, renderSpan) {
65
80
  const observationState = consumeAppPageRenderObservationState();
66
81
  consumeInvalidDynamicUsageError();
67
82
  const usedDynamicApi = consumeDynamicUsage() || isRenderDynamicLatched();
83
+ const htmlRenderObservation = createAppPageRenderObservation({
84
+ boundaryOutcome: { kind: "success" },
85
+ cacheability: "public",
86
+ cacheTags: tags,
87
+ cleanPathname: options.cleanPathname,
88
+ completeness: "complete",
89
+ output: createAppPageHtmlOutputScope({
90
+ element: options.element,
91
+ renderEpoch: null,
92
+ rootBoundaryId: null,
93
+ routePattern: options.route.pattern
94
+ }),
95
+ params: options.navigationParams,
96
+ state: observationState
97
+ });
68
98
  const result = {
69
99
  html,
70
- htmlRenderObservation: createAppPageRenderObservation({
71
- boundaryOutcome: { kind: "success" },
72
- cacheability: "public",
73
- cacheTags: tags,
74
- cleanPathname: options.cleanPathname,
75
- completeness: "complete",
76
- output: createAppPageHtmlOutputScope({
77
- element: options.element,
78
- renderEpoch: null,
79
- rootBoundaryId: null,
80
- routePattern: options.route.pattern
81
- }),
82
- params: options.navigationParams,
83
- state: observationState
84
- }),
100
+ htmlRenderObservation,
85
101
  ...linkHeader ? { linkHeader } : {},
102
+ ...specialErrorDocument ? {
103
+ headers: specialErrorDocument.headers,
104
+ status: specialErrorDocument.status
105
+ } : {},
86
106
  tags,
87
107
  usedDynamicApi,
88
108
  cacheControl: typeof cacheLife?.revalidate === "number" ? {
@@ -21,11 +21,15 @@ export type AppPageCacheOutcomeMetric = Readonly<{
21
21
  type AppPageCacheOutcomeRecorder = (metric: AppPageCacheOutcomeMetric) => void;
22
22
  type AppPageCacheRenderResult = {
23
23
  cacheControl?: CacheControlMetadata;
24
+ /** Response headers stored with both entries, such as a redirect's `location`. */
25
+ headers?: Record<string, string>;
24
26
  html: string;
25
27
  htmlRenderObservation: RenderObservation;
26
28
  linkHeader?: string;
27
29
  rscData: ArrayBuffer;
28
30
  rscRenderObservation: RenderObservation;
31
+ /** The status of a render whose shell ended in a special error. */
32
+ status?: number;
29
33
  /**
30
34
  * The route-level revalidate of the route this render regenerated, or null
31
35
  * when it has none and the render's cacheLife sets it. Undefined keeps the
@@ -40,6 +44,7 @@ type BuildAppPageCachedResponseOptions = {
40
44
  cacheState: "HIT" | "STALE";
41
45
  expireSeconds?: number;
42
46
  isEdgeRuntime?: boolean;
47
+ isRoutePPREnabled?: boolean;
43
48
  isRscRequest: boolean;
44
49
  middlewareHeaders?: Headers | null;
45
50
  middlewareStatus?: number | null;
@@ -88,7 +93,7 @@ type ReadAppPageFallbackShellCacheResponseOptions = {
88
93
  isEdgeRuntime?: boolean;
89
94
  isrDebug?: AppPageDebugLogger;
90
95
  isrGet: AppPageCacheGetter;
91
- isrHtmlKey: (pathname: string) => string;
96
+ isrFallbackShellHtmlKey: (pathname: string) => string;
92
97
  middlewareHeaders?: Headers | null;
93
98
  middlewareStatus?: number | null;
94
99
  revalidateSeconds: number;
@@ -1,5 +1,5 @@
1
1
  import { VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_RSC_VARY_HEADER } from "./app-rsc-vary.js";
2
- import { VINEXT_PARAMS_HEADER, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER } from "./headers.js";
2
+ import { VINEXT_PARAMS_HEADER, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, VINEXT_SPECIAL_ERROR_STATUS_HEADER } from "./headers.js";
3
3
  import { applyCdnResponseHeaders } from "./cache-control.js";
4
4
  import { decideIsr } from "./isr-decision.js";
5
5
  import { buildAppPageCacheValue, isrCacheControl, resolveRouteExpireSeconds } from "./isr-cache.js";
@@ -53,6 +53,10 @@ function buildAppPageCachedHeaders(options) {
53
53
  if (options.params && Object.keys(options.params).length > 0) headers.set(VINEXT_PARAMS_HEADER, encodeURIComponent(JSON.stringify(options.params)));
54
54
  if (options.mountedSlotsHeader) headers.set(VINEXT_MOUNTED_SLOTS_HEADER, options.mountedSlotsHeader);
55
55
  applyClientStaleTimeHeader(headers, options.staleTimeSeconds);
56
+ for (const [name, value] of Object.entries(options.storedHeaders ?? {})) {
57
+ if (name.toLowerCase() === "link") continue;
58
+ for (const item of Array.isArray(value) ? value : [value]) headers.append(name, item);
59
+ }
56
60
  mergeMiddlewareResponseHeaders(headers, options.middlewareHeaders ?? null);
57
61
  if (options.linkHeader) {
58
62
  if (Array.isArray(options.linkHeader)) for (const value of options.linkHeader) headers.append("Link", value);
@@ -88,8 +92,15 @@ function resolveRegenerationFailureCacheControl(previous) {
88
92
  ...previous.stale === void 0 ? {} : { stale: previous.stale }
89
93
  };
90
94
  }
95
+ function isRedirectStatus(status) {
96
+ return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;
97
+ }
91
98
  function buildAppPageCachedResponse(cachedValue, options) {
92
- const status = options.middlewareStatus ?? (cachedValue.status || 200);
99
+ const storedStatus = cachedValue.status || 200;
100
+ const isRedirect = isRedirectStatus(storedStatus);
101
+ const isHttpErrorFallbackStatus = storedStatus === 401 || storedStatus === 403 || storedStatus === 404;
102
+ const replayStatus = options.isRscRequest && (isRedirect || options.isRoutePPREnabled === true) ? 200 : storedStatus;
103
+ const status = isRedirect || isHttpErrorFallbackStatus ? replayStatus : options.middlewareStatus ?? replayStatus;
93
104
  const { cacheControl } = decideIsr({
94
105
  cacheState: options.cacheState,
95
106
  kind: "app-page",
@@ -108,17 +119,19 @@ function buildAppPageCachedResponse(cachedValue, options) {
108
119
  middlewareHeaders: options.middlewareHeaders,
109
120
  mountedSlotsHeader: options.mountedSlotsHeader,
110
121
  params: options.params,
111
- staleTimeSeconds
122
+ staleTimeSeconds,
123
+ storedHeaders: cachedValue.headers
112
124
  });
113
125
  if (options.renderedPathAndSearch) rscHeaders.set(VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, encodeURIComponent(options.renderedPathAndSearch));
114
126
  applyRscCompatibilityIdHeader(rscHeaders);
115
127
  applyRscDeploymentIdHeader(rscHeaders);
128
+ if (isHttpErrorFallbackStatus && status === storedStatus) rscHeaders.set(VINEXT_SPECIAL_ERROR_STATUS_HEADER, String(storedStatus));
116
129
  return new Response(cachedValue.rscData, {
117
130
  status,
118
131
  headers: rscHeaders
119
132
  });
120
133
  }
121
- if (typeof cachedValue.html !== "string" || cachedValue.html.length === 0) return null;
134
+ if (typeof cachedValue.html !== "string" || cachedValue.html.length === 0 && !isRedirect) return null;
122
135
  const htmlHeaders = buildAppPageCachedHeaders({
123
136
  cacheControl,
124
137
  cacheState: options.cacheState,
@@ -126,7 +139,8 @@ function buildAppPageCachedResponse(cachedValue, options) {
126
139
  isEdgeRuntime: options.isEdgeRuntime,
127
140
  linkHeader: cachedValue.headers?.link,
128
141
  middlewareHeaders: options.middlewareHeaders,
129
- staleTimeSeconds
142
+ staleTimeSeconds,
143
+ storedHeaders: cachedValue.headers
130
144
  });
131
145
  const response = new Response(cachedValue.html, {
132
146
  status,
@@ -218,6 +232,7 @@ async function readAppPageCacheResponse(options) {
218
232
  cacheControl: cached?.value.cacheControl,
219
233
  expireSeconds: options.expireSeconds,
220
234
  isEdgeRuntime: options.isEdgeRuntime,
235
+ isRoutePPREnabled: options.isRoutePPREnabled,
221
236
  isRscRequest: options.isRscRequest,
222
237
  middlewareHeaders: options.middlewareHeaders,
223
238
  middlewareStatus: options.middlewareStatus,
@@ -287,9 +302,13 @@ see more here https://nextjs.org/docs/messages/app-static-to-dynamic-error`);
287
302
  return false;
288
303
  }
289
304
  };
290
- if (!await store(rscKey, buildAppPageCacheValue("", revalidatedPage.rscData, 200, revalidatedPage.rscRenderObservation))) return;
305
+ const status = revalidatedPage.status ?? 200;
306
+ if (!await store(rscKey, buildAppPageCacheValue("", revalidatedPage.rscData, status, revalidatedPage.rscRenderObservation, revalidatedPage.headers))) return;
291
307
  if (!options.isRscRequest) {
292
- if (!await store(isrKey, buildAppPageCacheValue(revalidatedPage.html, void 0, 200, revalidatedPage.htmlRenderObservation, revalidatedPage.linkHeader ? { link: revalidatedPage.linkHeader } : void 0))) return;
308
+ if (!await store(isrKey, buildAppPageCacheValue(revalidatedPage.html, void 0, status, revalidatedPage.htmlRenderObservation, revalidatedPage.linkHeader ? {
309
+ ...revalidatedPage.headers,
310
+ link: revalidatedPage.linkHeader
311
+ } : revalidatedPage.headers))) return;
293
312
  }
294
313
  options.isrDebug?.("regen complete", options.cleanPathname);
295
314
  };
@@ -306,6 +325,7 @@ see more here https://nextjs.org/docs/messages/app-static-to-dynamic-error`);
306
325
  cacheControl: cached.value.cacheControl,
307
326
  expireSeconds: options.expireSeconds,
308
327
  isEdgeRuntime: options.isEdgeRuntime,
328
+ isRoutePPREnabled: options.isRoutePPREnabled,
309
329
  isRscRequest: options.isRscRequest,
310
330
  middlewareHeaders: options.middlewareHeaders,
311
331
  middlewareStatus: options.middlewareStatus,
@@ -355,7 +375,7 @@ see more here https://nextjs.org/docs/messages/app-static-to-dynamic-error`);
355
375
  return null;
356
376
  }
357
377
  async function readAppPageFallbackShellCacheResponse(options) {
358
- const isrKey = options.isrHtmlKey(options.fallbackPathname);
378
+ const isrKey = options.isrFallbackShellHtmlKey(options.fallbackPathname);
359
379
  try {
360
380
  const cached = await options.isrGet(isrKey);
361
381
  const cachedValue = getCachedAppPageValue(cached);
@@ -13,7 +13,8 @@ import { AppPageSsrHandler } from "./app-page-stream.js";
13
13
  import { AppRenderErrorContextOverrides } from "./app-rsc-error-handler.js";
14
14
  import { AppPageCacheSetter, ISRCacheEntry } from "./isr-cache.js";
15
15
  import { PprFallbackShellState } from "../shims/ppr-fallback-shell.js";
16
- import { FetchCacheMode } from "../shims/fetch-cache.js";
16
+ import { FetchCacheMode } from "../shims/fetch-cache-state.js";
17
+ import "../shims/fetch-cache.js";
17
18
  import { AppPagePprFallbackCacheShell } from "./app-ppr-fallback-shell.js";
18
19
  import { WarmPprFallbackShellCachesOptions } from "./app-ppr-fallback-shell-render.js";
19
20
  import { ValidateAppPageDynamicParamsOptions } from "./app-page-request.js";
@@ -142,6 +143,7 @@ export type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
142
143
  observeMetadataSearchParamsAccess?: boolean;
143
144
  observePageSearchParamsAccess?: boolean;
144
145
  serveStreamingMetadata?: boolean;
146
+ placeStreamedMetadataInHead?: boolean;
145
147
  }) => Promise<AppPageElement>;
146
148
  clientReuseManifest?: ClientReuseManifestParseResult;
147
149
  cleanPathname: string;
@@ -196,6 +198,7 @@ export type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
196
198
  isRscRequest: boolean;
197
199
  isrDebug?: AppPageDebugLogger;
198
200
  isrGet: AppPageCacheGetter;
201
+ isrFallbackShellHtmlKey: (pathname: string) => string;
199
202
  isrHtmlKey: (pathname: string) => string;
200
203
  isrRscKey: (pathname: string, mountedSlotsHeader?: string | null, renderMode?: AppRscRenderMode, interceptionContext?: string | null, interceptionId?: string | null) => string;
201
204
  isrSet: AppPageCacheSetter;
@@ -221,13 +224,14 @@ export type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
221
224
  staticParamsValidationParams?: AppPageParams;
222
225
  rootParams?: RootParams;
223
226
  probeLayoutAt: (layoutIndex: number, layoutParamAccess?: AppLayoutParamAccessTracker) => unknown;
224
- probePage: (searchParams?: URLSearchParams) => unknown;
225
227
  expireSeconds?: number;
226
228
  renderErrorBoundaryPage: (error: unknown, errorOrigin?: "rsc" | "ssr") => Promise<Response | null>;
227
229
  renderHttpAccessFallbackPage: (statusCode: number, opts: {
228
230
  boundaryComponent?: unknown;
229
231
  boundaryModule?: AppPageModule | null;
230
232
  intercept?: AppPageDispatchInterceptOptions | null;
233
+ /** The document may be stored, so it must not carry the request's query. */
234
+ isCacheCandidate?: boolean;
231
235
  layouts?: readonly AppPageModule[];
232
236
  matchedParams: AppPageParams;
233
237
  }, middlewareContext: AppPageMiddlewareContext | null) => Promise<Response | null>;
@@ -268,6 +272,12 @@ export type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
268
272
  searchParams: URLSearchParams;
269
273
  }) => void;
270
274
  renderMode?: AppRscRenderMode;
275
+ /**
276
+ * Render the document whole before its first byte, with streamed metadata in
277
+ * `<head>`, as a background regeneration does. The adapter sets this for a
278
+ * render no client is waiting on, such as its regeneration or a warm-up.
279
+ */
280
+ renderWholeDocument?: boolean;
271
281
  };
272
282
  export declare function shouldReadAppPageCache(options: {
273
283
  isProgressiveActionRender: boolean;
@@ -3,29 +3,31 @@ import "../utils/protocol-headers.js";
3
3
  import { getRequestExecutionContext } from "../shims/request-context.js";
4
4
  import { VINEXT_INTERCEPTION_ID_HEADER, VINEXT_RSC_VARY_HEADER } from "./app-rsc-vary.js";
5
5
  import "./headers.js";
6
+ import { runInWorkStoreScope } from "../shims/internal/work-store-scope.js";
6
7
  import { beginRouteCacheability, isRouteCacheabilityIdentityProbe, isRouteCacheabilityProbe, markRouteCacheabilityPatternDynamic, readRouteCacheabilityState } from "../shims/cacheability-classification.js";
7
8
  import { APP_RSC_RENDER_MODE_PREFETCH_DYNAMIC_SHELL } from "./app-rsc-render-mode.js";
8
- import { AppElementsWire } from "./app-elements-wire.js";
9
- import "./app-elements.js";
10
9
  import { consumeDynamicUsage, consumeInvalidDynamicUsageError, getAndClearPendingCookies, getDraftModeCookieHeader, getHeadersContext, isDraftModeRequest, peekDynamicUsage, peekRenderRequestApiUsage, runWithIsolatedDynamicUsage, setHeadersContext } from "../shims/headers.js";
11
10
  import { _captureRequestScopedCacheLifeAccessors } from "../shims/cache-request-state.js";
12
11
  import { ensureFetchPatch, getCollectedFetchTags, peekDynamicFetchObservations, runWithFetchDedupe, setCurrentFetchCacheMode, setCurrentFetchRevalidate, setCurrentFetchSoftTags, setCurrentForceDynamicFetchDefault, setRefreshStaleFetchesInForeground } from "../shims/fetch-cache.js";
13
12
  import { cacheabilityManifestPageState } from "./cacheability-manifest.js";
13
+ import { isAppPageStaticEligible } from "./app-segment-config.js";
14
+ import { AppElementsWire } from "./app-elements-wire.js";
15
+ import "./app-elements.js";
14
16
  import { VINEXT_RSC_CONTENT_TYPE, applyRscCompatibilityIdHeader, applyRscDeploymentIdHeader } from "./app-rsc-cache-busting.js";
15
17
  import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
18
+ import { getFrameworkLinkHeader } from "./app-response-header-provenance.js";
16
19
  import { resolveUncacheableCacheControl } from "./app-page-response.js";
17
20
  import { buildRscRedirectFlightStream } from "./app-rsc-redirect-flight.js";
18
- import { buildAppPageSpecialErrorResponse, probeAppPageThrownError, resolveAppPageSpecialError } from "./app-page-execution.js";
21
+ import { buildAppPageSpecialErrorResponse, resolveAppPageShellSpecialError, resolveAppPageSpecialError, resolveAppPageSpecialErrorStoredHeaders } from "./app-page-execution.js";
19
22
  import { resolveAppPageTraceOperation } from "./app-page-tracing.js";
20
23
  import { createAppPageTreePath } from "./app-page-route-wiring.js";
21
24
  import { traceResponseStart } from "./response-start-tracing.js";
22
25
  import { buildAppPageTags } from "./implicit-tags.js";
23
26
  import { consumeAppPageRenderObservationState, discardAppPageRenderState } from "./app-page-render-observation.js";
24
- import { isAppPageStaticEligible } from "./app-segment-config.js";
27
+ import { createAppPageRscErrorTracker } from "./app-page-stream.js";
25
28
  import { resolveAppPageParentHttpAccessBoundary, resolveAppPageParentHttpAccessBoundaryModule } from "./app-page-boundary.js";
26
29
  import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
27
30
  import { resolveAppPageNavigationParams } from "./app-page-element-builder.js";
28
- import { createAppPageRscErrorTracker } from "./app-page-stream.js";
29
31
  import { createAppLayoutParamAccessTracker, isAppLayoutObservationUnsafeForStaticReuse } from "./app-layout-param-observation.js";
30
32
  import { resolveAppPageMethodResponse } from "./app-page-method.js";
31
33
  import { buildAppPageElement, resolveAppPageIntercept, resolveAppPageInterceptionRerenderTarget, validateAppPageDynamicParams } from "./app-page-request.js";
@@ -149,7 +151,7 @@ async function runAppPageRevalidationContext(options, renderFn) {
149
151
  executionContext: getRequestExecutionContext(),
150
152
  unstableCacheRevalidation: "foreground"
151
153
  });
152
- const revalidation = runWithRequestContext(requestContext, async () => {
154
+ const revalidation = runWithRequestContext(requestContext, () => runInWorkStoreScope(async () => {
153
155
  ensureFetchPatch();
154
156
  setRefreshStaleFetchesInForeground(process.env.VINEXT_PRERENDER === "1");
155
157
  setCurrentFetchSoftTags(buildAppPageTags(options.cleanPathname, [], options.routeSegments));
@@ -159,7 +161,7 @@ async function runAppPageRevalidationContext(options, renderFn) {
159
161
  params: options.params
160
162
  });
161
163
  return await runWithFetchDedupe(renderFn);
162
- });
164
+ }));
163
165
  try {
164
166
  return await revalidation;
165
167
  } finally {
@@ -255,7 +257,6 @@ async function dispatchAppPageInner(options) {
255
257
  const pageSearchParams = shouldUseEmptySearchParams ? new URLSearchParams() : options.searchParams;
256
258
  const layoutParamAccess = createAppLayoutParamAccessTracker();
257
259
  const activeLoadingTreePositions = getActiveLoadingTreePositions(route);
258
- const hasActiveLoadingBoundary = activeLoadingTreePositions.length > 0;
259
260
  setCurrentFetchSoftTags(buildAppPageTags(options.cleanPathname, [], route.routeSegments));
260
261
  setCurrentFetchCacheMode(options.fetchCache ?? null);
261
262
  setCurrentFetchRevalidate(currentRevalidateSeconds);
@@ -313,7 +314,7 @@ async function dispatchAppPageInner(options) {
313
314
  });
314
315
  const isNeverStoredPath = options.pprRuntime === void 0 && hasNoManifestAdmissionState(route.pattern);
315
316
  const shouldReadCache = !isRouteCacheabilityProbe() && isCacheEligibleRender && !isNeverStoredPath;
316
- const isCacheCandidate = isCacheEligibleRender && isStaticEligible && options.pprRuntime === void 0 && !isNeverStoredPath;
317
+ const isCacheCandidate = isCacheEligibleRender && isStaticEligible && options.pprFallbackShell === void 0 && !isNeverStoredPath;
317
318
  if (shouldReadCache && isStaticEligible) {
318
319
  traceOperation = resolveAppPageTraceOperation({
319
320
  hasRequestSearchParams,
@@ -396,14 +397,16 @@ async function dispatchAppPageInner(options) {
396
397
  isForceStatic: revalidationDynamicConfig === "force-static",
397
398
  observeMetadataSearchParamsAccess: revalidationDynamicConfig !== "force-static",
398
399
  observePageSearchParamsAccess: revalidationDynamicConfig !== "force-static",
399
- serveStreamingMetadata: false
400
+ serveStreamingMetadata: placeGeneratedMetadataInBody,
401
+ placeStreamedMetadataInHead: true
400
402
  });
401
403
  const baseRevalidatedOnError = options.createRscOnErrorHandler(options.cleanPathname, revalidationTarget.route.pattern, { revalidateReason: "stale" });
402
404
  const baseRevalidatedOnSsrError = options.createRscOnErrorHandler(options.cleanPathname, revalidationTarget.route.pattern, {
403
405
  renderSource: "server-rendering",
404
406
  revalidateReason: "stale"
405
407
  });
406
- revalidationRscErrorTracker = createAppPageRscErrorTracker(baseRevalidatedOnError);
408
+ const rscErrorTracker = createAppPageRscErrorTracker(baseRevalidatedOnError);
409
+ revalidationRscErrorTracker = rscErrorTracker;
407
410
  const rendered = await renderAppPageCacheArtifacts({
408
411
  basePath: options.basePath,
409
412
  captureRscData: true,
@@ -416,14 +419,36 @@ async function dispatchAppPageInner(options) {
416
419
  getNavigationContext: options.getNavigationContext,
417
420
  loadSsrHandler: options.loadSsrHandler,
418
421
  mountedSlotsHeader: options.mountedSlotsHeader,
422
+ mirrorNextFlight: () => rscErrorTracker.getCapturedSpecialError() !== null,
419
423
  navigationParams: revalidationTarget.navigationParams,
420
- isCapturedRscError: revalidationRscErrorTracker.isCapturedError,
421
- onError: revalidationRscErrorTracker.onRenderError,
424
+ isCapturedRscError: rscErrorTracker.isCapturedError,
425
+ onError: rscErrorTracker.onRenderError,
422
426
  onSsrError(error) {
423
427
  reportedSsrRevalidationErrors.add(error);
424
428
  return baseRevalidatedOnSsrError(error, void 0, void 0);
425
429
  },
426
430
  reactMaxHeadersLength: options.reactMaxHeadersLength,
431
+ async renderShellSpecialError(error) {
432
+ const specialError = resolveAppPageShellSpecialError(error, rscErrorTracker.getCapturedSpecialErrors(error));
433
+ if (!specialError) return null;
434
+ if (options.isRscRequest) {
435
+ if (specialError.fromMetadata === true) return null;
436
+ return {
437
+ headers: resolveAppPageSpecialErrorStoredHeaders(specialError, options.basePath),
438
+ html: "",
439
+ status: specialError.statusCode
440
+ };
441
+ }
442
+ if (revalidationTarget.route !== route) return null;
443
+ const document = await renderPageSpecialError(options, specialError, false, revalidationTarget.interceptOpts, true);
444
+ if (document.status !== specialError.statusCode) return null;
445
+ return {
446
+ headers: resolveAppPageSpecialErrorStoredHeaders(specialError, options.basePath),
447
+ html: await document.text(),
448
+ linkHeader: getFrameworkLinkHeader(document.headers) ?? void 0,
449
+ status: specialError.statusCode
450
+ };
451
+ },
427
452
  renderToReadableStream: options.renderToReadableStream,
428
453
  rootParams: options.rootParams,
429
454
  route: revalidationTarget.route,
@@ -432,6 +457,7 @@ async function dispatchAppPageInner(options) {
432
457
  });
433
458
  options.clearRequestContext();
434
459
  return {
460
+ headers: rendered.headers,
435
461
  html: rendered.html,
436
462
  htmlRenderObservation: rendered.htmlRenderObservation,
437
463
  linkHeader: rendered.linkHeader,
@@ -440,6 +466,7 @@ async function dispatchAppPageInner(options) {
440
466
  tags: rendered.tags,
441
467
  cacheControl: rendered.cacheControl,
442
468
  revalidateSeconds: revalidationRouteRevalidateSeconds,
469
+ status: rendered.status,
443
470
  usedDynamicApi: rendered.usedDynamicApi
444
471
  };
445
472
  });
@@ -465,6 +492,7 @@ async function dispatchAppPageInner(options) {
465
492
  if (dynamicParamsResponse) {
466
493
  const renderedNotFound = await options.renderHttpAccessFallbackPage(404, { matchedParams: options.params }, options.middlewareContext);
467
494
  const cachePolicy = {
495
+ dynamicStaleTimeSeconds: options.dynamicStaleTimeSeconds,
468
496
  isDraftMode,
469
497
  isDynamicError,
470
498
  isForceDynamic,
@@ -510,7 +538,8 @@ async function dispatchAppPageInner(options) {
510
538
  isForceStatic: sourceDynamicConfig === "force-static",
511
539
  observeMetadataSearchParamsAccess: sourceDynamicConfig !== "force-static",
512
540
  observePageSearchParamsAccess: sourceDynamicConfig !== "force-static",
513
- serveStreamingMetadata: placeGeneratedMetadataInBody
541
+ serveStreamingMetadata: placeGeneratedMetadataInBody,
542
+ placeStreamedMetadataInHead: options.renderWholeDocument === true
514
543
  });
515
544
  },
516
545
  cleanPathname: options.cleanPathname,
@@ -565,19 +594,10 @@ async function dispatchAppPageInner(options) {
565
594
  isForceStatic,
566
595
  observeMetadataSearchParamsAccess: !isForceStatic,
567
596
  observePageSearchParamsAccess: !isForceStatic,
568
- serveStreamingMetadata: placeGeneratedMetadataInBody
597
+ serveStreamingMetadata: placeGeneratedMetadataInBody,
598
+ placeStreamedMetadataInHead: options.renderWholeDocument === true
569
599
  });
570
600
  },
571
- async probePageSpecialError() {
572
- if (hasActiveLoadingBoundary) return null;
573
- const pageError = await probeAppPageThrownError({
574
- probePage: () => options.probePage(pageSearchParams),
575
- runWithSuppressedHookWarning(probe) {
576
- return options.runWithSuppressedHookWarning(probe);
577
- }
578
- });
579
- return resolveAppPageSpecialError(pageError);
580
- },
581
601
  renderErrorBoundaryPage(buildError) {
582
602
  return options.renderErrorBoundaryPage(buildError);
583
603
  },
@@ -645,7 +665,6 @@ async function dispatchAppPageInner(options) {
645
665
  return requestCacheLife.peek();
646
666
  },
647
667
  handlerStart: options.handlerStart,
648
- hasLoadingBoundary: hasActiveLoadingBoundary,
649
668
  omitPendingDynamicCacheState: hasRequestSearchParams && !(isCacheCandidate && !options.isRscRequest),
650
669
  formState: options.formState ?? null,
651
670
  isProgressiveActionRender: options.isProgressiveActionRender === true,
@@ -657,7 +676,9 @@ async function dispatchAppPageInner(options) {
657
676
  isStaticEligible,
658
677
  isCacheCandidate,
659
678
  isPrerender,
679
+ isRoutePPREnabled: options.pprRuntime !== void 0,
660
680
  isSpeculativePrerender,
681
+ renderWholeDocument: options.renderWholeDocument === true && !options.isRscRequest,
661
682
  isProduction: options.isProduction,
662
683
  isRscRequest: options.isRscRequest,
663
684
  traceOperation,
@@ -690,10 +711,6 @@ async function dispatchAppPageInner(options) {
690
711
  probeLayoutAt(layoutIndex) {
691
712
  return options.probeLayoutAt(layoutIndex, layoutParamAccess);
692
713
  },
693
- probePage() {
694
- return options.probePage(pageSearchParams);
695
- },
696
- probePageBeforeRender: options.isRscRequest,
697
714
  classification: {
698
715
  getLayoutId(index) {
699
716
  const treePosition = route.layoutTreePositions?.[index] ?? 0;
@@ -719,8 +736,8 @@ async function dispatchAppPageInner(options) {
719
736
  renderLayoutSpecialError(specialError, layoutIndex) {
720
737
  return renderLayoutSpecialError(options, specialError, layoutIndex, serveStreamingMetadata);
721
738
  },
722
- renderPageSpecialError(specialError) {
723
- return renderPageSpecialError(options, specialError, serveStreamingMetadata, interceptResult.interceptOpts);
739
+ renderPageSpecialError(specialError, renderOptions) {
740
+ return renderPageSpecialError(options, specialError, serveStreamingMetadata, interceptResult.interceptOpts, renderOptions?.isCacheCandidate === true);
724
741
  },
725
742
  renderToReadableStream: options.renderToReadableStream,
726
743
  hasCustomGlobalError: options.hasCustomGlobalError,
@@ -773,7 +790,7 @@ async function renderLayoutSpecialError(options, specialError, layoutIndex, serv
773
790
  specialError
774
791
  });
775
792
  }
776
- async function renderPageSpecialError(options, specialError, serveStreamingMetadata, intercept) {
793
+ async function renderPageSpecialError(options, specialError, serveStreamingMetadata, intercept, isCacheCandidate = false) {
777
794
  return buildAppPageSpecialErrorResponse({
778
795
  basePath: options.basePath,
779
796
  buildRscRedirectFlightStream: (rscOptions) => buildRscRedirectFlightStream({
@@ -802,6 +819,7 @@ async function renderPageSpecialError(options, specialError, serveStreamingMetad
802
819
  const useLayoutAlignedBoundary = boundaryLayoutIndex !== null && (routeBoundaryModule === null || routeBoundaryModule === parentBoundaryModule);
803
820
  const fallbackOptions = {
804
821
  intercept,
822
+ ...isCacheCandidate ? { isCacheCandidate } : {},
805
823
  matchedParams: options.params
806
824
  };
807
825
  if (useLayoutAlignedBoundary && boundaryLayoutIndex !== null) {
@@ -61,6 +61,13 @@ export type AppPagePageRequest<TModule extends AppPageModule = AppPageModule> =
61
61
  observeMetadataSearchParamsAccess?: boolean;
62
62
  /** Whether generated metadata may stream into the response body. */
63
63
  serveStreamingMetadata?: boolean;
64
+ /**
65
+ * Wait for streamed metadata in `<head>`, for a document rendered whole
66
+ * before it's written, such as a background regeneration. Next.js does this
67
+ * for every static or ISR render. Its errors still reach the route's
68
+ * boundaries through the outlet.
69
+ */
70
+ placeStreamedMetadataInHead?: boolean;
64
71
  /** Whether streamed render errors must be sanitized for client transport. */
65
72
  isProduction?: boolean;
66
73
  };