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
@@ -1,10 +1,10 @@
1
- import { fnv1a64 } from "../utils/hash.js";
2
1
  import { normalizeMountedSlotsHeader } from "./app-mounted-slots-header.js";
3
- import { AppElementsWire, isAppElementsRecord } from "./app-elements-wire.js";
4
- import "./app-elements.js";
2
+ import { fnv1a64 } from "../utils/hash.js";
5
3
  import { consumeDynamicUsage, consumeInvalidDynamicUsageError, consumeRenderRequestApiUsage } from "../shims/headers.js";
6
4
  import { _consumeRequestScopedCacheLife } from "../shims/cache-request-state.js";
7
5
  import { consumeDynamicFetchObservations } from "../shims/fetch-cache.js";
6
+ import { AppElementsWire, isAppElementsRecord } from "./app-elements-wire.js";
7
+ import "./app-elements.js";
8
8
  import { buildRenderObservation, buildRenderRequestApiObservations } from "./cache-proof.js";
9
9
  //#region src/server/app-page-render-observation.ts
10
10
  function readRootBoundaryId(element) {
@@ -23,6 +23,13 @@ type AppPageRequestCacheLife = {
23
23
  stale?: number;
24
24
  };
25
25
  type AppPageRenderableElement = ReactNode | Readonly<Record<string, ReactNode>>;
26
+ type AppPageSpecialErrorRenderOptions = {
27
+ /**
28
+ * The document may be stored in place of the page's, so like a cache
29
+ * candidate's render it must not carry the request's query.
30
+ */
31
+ isCacheCandidate?: boolean;
32
+ };
26
33
  type PreparedAppPageElement = {
27
34
  element: AppPageRenderableElement;
28
35
  response?: never;
@@ -63,7 +70,6 @@ type RenderAppPageLifecycleOptionsBase = {
63
70
  getDraftModeCookieHeader: () => string | null | undefined;
64
71
  handlerStart: number;
65
72
  hasCustomGlobalError?: boolean;
66
- hasLoadingBoundary: boolean;
67
73
  dynamicStaleTimeSeconds?: number;
68
74
  isDynamicError: boolean;
69
75
  isDraftMode: boolean;
@@ -83,9 +89,12 @@ type RenderAppPageLifecycleOptionsBase = {
83
89
  isCacheCandidate?: boolean;
84
90
  isProgressiveActionRender?: boolean;
85
91
  isPrerender?: boolean;
92
+ /** PPR routes send every RSC response as a 200. */
93
+ isRoutePPREnabled?: boolean;
86
94
  isSpeculativePrerender?: boolean;
95
+ /** Wait for the whole document before its first byte, as a prerender does. */
96
+ renderWholeDocument?: boolean;
87
97
  isProduction: boolean;
88
- probePageBeforeRender?: boolean;
89
98
  omitPendingDynamicCacheState?: boolean;
90
99
  isRscRequest: boolean;
91
100
  traceOperation?: "prerender" | "render";
@@ -107,13 +116,12 @@ type RenderAppPageLifecycleOptionsBase = {
107
116
  rootParams?: RootParams;
108
117
  peekRenderObservationState?: () => AppPageRenderObservationState;
109
118
  probeLayoutAt: (layoutIndex: number) => unknown;
110
- probePage: () => unknown;
111
119
  expireSeconds?: number;
112
120
  formState?: ReactFormState | null;
113
121
  revalidateSeconds: number | null;
114
122
  renderErrorBoundaryResponse: (error: unknown, errorOrigin: "rsc" | "ssr") => Promise<Response | null>;
115
123
  renderLayoutSpecialError: (specialError: AppPageSpecialError, layoutIndex: number) => Promise<Response>;
116
- renderPageSpecialError: (specialError: AppPageSpecialError) => Promise<Response>;
124
+ renderPageSpecialError: (specialError: AppPageSpecialError, renderOptions?: AppPageSpecialErrorRenderOptions) => Promise<Response>;
117
125
  renderToReadableStream: (element: ReactNode | AppOutgoingElements, options: {
118
126
  onError: AppPageBoundaryOnError;
119
127
  signal?: AbortSignal;
@@ -150,6 +158,6 @@ type RenderAppPageLifecycleOptions = RenderAppPageLifecycleOptionsBase & ({
150
158
  * its response policy, such as error boundaries and special errors, get the
151
159
  * same header as the normal render.
152
160
  */
153
- export declare function applyIneligibleRouteCachePolicy(response: Response, options: Pick<RenderAppPageLifecycleOptions, "isDraftMode" | "isDynamicError" | "isForceDynamic" | "isForceStatic" | "isProduction" | "isProgressiveActionRender" | "isRscRequest" | "isStaticEligible" | "middlewareContext" | "peekDynamicUsage" | "revalidateSeconds" | "scriptNonce">): Response;
161
+ export declare function applyIneligibleRouteCachePolicy(response: Response, options: Pick<RenderAppPageLifecycleOptions, "dynamicStaleTimeSeconds" | "isDraftMode" | "isDynamicError" | "isForceDynamic" | "isForceStatic" | "isProduction" | "isProgressiveActionRender" | "isRscRequest" | "isStaticEligible" | "middlewareContext" | "peekDynamicUsage" | "revalidateSeconds" | "scriptNonce">, probeCacheLife?: AppPageRequestCacheLife | null): Response;
154
162
  export declare function renderAppPageLifecycle(options: RenderAppPageLifecycleOptions): Promise<Response>;
155
163
  //#endregion
@@ -1,32 +1,36 @@
1
1
  import { preserveFullyBufferedBodyMetadata } from "./fully-buffered-response.js";
2
2
  import { bindRequestContext } from "../shims/unified-request-context.js";
3
- import { VINEXT_RSC_COMPLETION_METADATA_HEADER } from "./headers.js";
3
+ import { getRequestExecutionContext } from "../shims/request-context.js";
4
+ import { VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_RSC_COMPLETION_METADATA_HEADER } from "./headers.js";
4
5
  import { internalServerErrorResponse } from "./http-error-responses.js";
5
6
  import { isRouteCacheabilityEvaluation, recordRouteCacheabilityClientTraceMetadataMarker } from "../shims/cacheability-classification.js";
6
7
  import { NEVER_CACHE_CONTROL, NO_STORE_CACHE_CONTROL, applyCdnResponseHeaders, isCdnResponsePolicyHeader } from "./cache-control.js";
7
- import { createArtifactCompatibilityEnvelope, createArtifactCompatibilityGraphVersion } from "./artifact-compatibility.js";
8
- import { AppElementsWire, isAppElementsRecord } from "./app-elements-wire.js";
9
- import "./app-elements.js";
10
8
  import { resolveClientStaleTimeSeconds } from "../utils/cache-control-metadata.js";
11
- import { isRenderDynamicLatched } from "../shims/internal/headers-state.js";
12
- import { peekDynamicUsage } from "../shims/headers.js";
9
+ import { isRenderDynamicLatched, markDynamicUsage } from "../shims/internal/headers-state.js";
10
+ import { peekDynamicUsage, runWithDetachedDynamicUsage } from "../shims/headers.js";
13
11
  import { runWithFetchDedupe } from "../shims/fetch-cache.js";
12
+ import { setCacheStateHeaders } from "./cache-headers.js";
14
13
  import { deferUntilStreamConsumed } from "./defer-until-stream-consumed.js";
14
+ import { createArtifactCompatibilityEnvelope, createArtifactCompatibilityGraphVersion } from "./artifact-compatibility.js";
15
+ import { AppElementsWire, isAppElementsRecord } from "./app-elements-wire.js";
16
+ import "./app-elements.js";
15
17
  import { isBailoutToCSRError } from "../shims/navigation-errors.js";
16
18
  import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
17
- import { copyLinkHeaderProvenance } from "./app-response-header-provenance.js";
18
- import { applyEdgeRuntimeHeader, buildAppPageHtmlResponse, buildAppPageRscResponse, resolveAppPageHtmlResponsePolicy, resolveAppPageRscResponsePolicy, resolveUncacheableCacheControl } from "./app-page-response.js";
19
- import { buildAppPageFontLinkHeader, readAppPageBinaryStream, resolveAppPageSpecialError, teeAppPageRscStreamForCapture } from "./app-page-execution.js";
19
+ import { applyPrerenderCacheLifeHeader, applyPrerenderCacheTagsHeader } from "./prerender-cache-life-header.js";
20
+ import { copyLinkHeaderProvenance, getFrameworkLinkHeader } from "./app-response-header-provenance.js";
21
+ import { applyClientStaleTimeHeader, applyEdgeRuntimeHeader, buildAppPageHtmlResponse, buildAppPageRscResponse, resolveAppPageHtmlResponsePolicy, resolveAppPageRscResponsePolicy, resolveUncacheableCacheControl } from "./app-page-response.js";
22
+ import { buildAppPageFontLinkHeader, readAppPageBinaryStream, resolveAppPageShellSpecialError, resolveAppPageSpecialError, resolveAppPageSpecialErrorStoredHeaders, teeAppPageRscStreamForCapture } from "./app-page-execution.js";
20
23
  import { probeAppPageBeforeRender } from "./app-page-probe.js";
21
24
  import { hasDigest } from "./app-rsc-errors.js";
22
25
  import { recordAppPageRenderError, traceAppPageRender } from "./app-page-tracing.js";
23
26
  import { traceResponseStartWithCompletion } from "./response-start-tracing.js";
24
27
  import { DEFAULT_CACHE_VARIANT_BUDGET, buildCacheVariantWithRouteBudget, buildRenderObservation, buildRenderRequestApiObservations, createStaticLayoutArtifactReuseDecision } from "./cache-proof.js";
25
28
  import { createAppPageHtmlOutputScope, createAppPageRenderObservation, createAppPageRscOutputScope } from "./app-page-render-observation.js";
29
+ import { buildAppPageLinkHeader, createAppPageFontData, createAppPageRscErrorTracker, createAppPageSsrErrorHandler, renderAppPageHtmlStream, renderAppPageHtmlStreamWithRecovery } from "./app-page-stream.js";
30
+ import { createAppPageRscRenderStatusResolver } from "./app-page-rsc-render-status.js";
26
31
  import { finalizeAppPageCacheabilityEvaluationResponse, finalizeAppPageHtmlCacheResponse, finalizeAppPageRscCacheResponse } from "./app-page-cache-finalizer.js";
27
32
  import { createStaticLayoutClientReuseArtifactCompatibility, createStaticLayoutClientReusePayloadHash, createStaticLayoutClientReuseRouteId } from "./static-layout-client-reuse-proof.js";
28
33
  import { appendRscCompletionMetadata } from "./rsc-completion-metadata.js";
29
- import { buildAppPageLinkHeader, createAppPageFontData, createAppPageRscErrorTracker, createAppPageSsrErrorHandler, renderAppPageHtmlStream, renderAppPageHtmlStreamWithRecovery } from "./app-page-stream.js";
30
34
  import { getStaticLayoutObservationSkipRejection } from "./app-layout-param-observation.js";
31
35
  import { createClientReuseSkipTransportPlan, crossCheckClientReuseManifestEntryWithCache } from "./skip-cache-proof.js";
32
36
  //#region src/server/app-page-render.ts
@@ -70,15 +74,32 @@ function applyRequestCacheLife(options) {
70
74
  * its response policy, such as error boundaries and special errors, get the
71
75
  * same header as the normal render.
72
76
  */
73
- function applyIneligibleRouteCachePolicy(response, options) {
77
+ function applyIneligibleRouteCachePolicy(response, options, probeCacheLife = null) {
74
78
  const cacheControl = resolveEarlyResponseCacheControl(options);
75
- if (!cacheControl) return response;
79
+ const isRscRedirect = options.isRscRequest && response.headers.has("X-Vinext-Rsc-Redirect");
80
+ if (!cacheControl) {
81
+ const staleTimeSeconds = isRscRedirect ? resolveClientStaleTimeSeconds(probeCacheLife) : void 0;
82
+ if (staleTimeSeconds === void 0) return response;
83
+ const stamped = cloneForStamping(response);
84
+ applyClientStaleTimeHeader(stamped.headers, staleTimeSeconds);
85
+ return stamped;
86
+ }
87
+ const dynamicStaleTimeSeconds = isRscRedirect ? options.dynamicStaleTimeSeconds ?? resolveConfiguredDynamicStaleTimeSeconds() : void 0;
76
88
  const middlewarePolicy = [...options.middlewareContext.headers ?? []].filter(([name, value]) => isCdnResponsePolicyHeader(name) && response.headers.get(name) === value);
77
- if (middlewarePolicy.some(([name]) => name === "cache-control")) return response;
89
+ const keepsMiddlewareCacheControl = middlewarePolicy.some(([name]) => name === "cache-control");
90
+ if (keepsMiddlewareCacheControl && dynamicStaleTimeSeconds === void 0) return response;
91
+ const stamped = cloneForStamping(response);
92
+ if (!keepsMiddlewareCacheControl) {
93
+ applyCdnResponseHeaders(stamped.headers, { cacheControl });
94
+ for (const [name, value] of middlewarePolicy) stamped.headers.set(name, value);
95
+ }
96
+ if (dynamicStaleTimeSeconds !== void 0) stamped.headers.set(VINEXT_DYNAMIC_STALE_TIME_HEADER, String(dynamicStaleTimeSeconds));
97
+ return stamped;
98
+ }
99
+ /** Some early responses have immutable headers, so stamp a copy. */
100
+ function cloneForStamping(response) {
78
101
  const stamped = preserveFullyBufferedBodyMetadata(response, new Response(response.body, response));
79
102
  copyLinkHeaderProvenance(response.headers, stamped.headers);
80
- applyCdnResponseHeaders(stamped.headers, { cacheControl });
81
- for (const [name, value] of middlewarePolicy) stamped.headers.set(name, value);
82
103
  return stamped;
83
104
  }
84
105
  /** The known-dynamic branches of the RSC and HTML response policies, in their order. */
@@ -368,32 +389,26 @@ async function renderAppPageLifecycleImpl(options, renderSpan) {
368
389
  }
369
390
  return dynamicUsageObserved;
370
391
  };
371
- const configuredProbePageBeforeRender = options.probePageBeforeRender ?? options.isRscRequest;
372
- const probePageBeforeRender = options.isRscRequest || configuredProbePageBeforeRender && !(options.peekDynamicUsage?.() ?? false);
373
- const preRenderResult = await probeAppPageBeforeRender({
374
- hasLoadingBoundary: options.hasLoadingBoundary,
375
- probePageBeforeRender,
392
+ const probeOutcome = await runWithDetachedDynamicUsage(() => probeAppPageBeforeRender({
376
393
  skipProbes: options.pprFallbackShellSignal !== void 0,
377
394
  layoutCount: options.layoutCount,
378
395
  probeLayoutAt(layoutIndex) {
379
396
  return options.probeLayoutAt(layoutIndex);
380
397
  },
381
- probePage() {
382
- return options.probePage();
383
- },
384
398
  renderLayoutSpecialError(specialError, layoutIndex) {
385
399
  return options.renderLayoutSpecialError(specialError, layoutIndex);
386
400
  },
387
- renderPageSpecialError(specialError) {
388
- return options.renderPageSpecialError(specialError);
389
- },
390
401
  resolveSpecialError: resolveAppPageSpecialError,
391
402
  runWithSuppressedHookWarning(probe) {
392
403
  return options.runWithSuppressedHookWarning(probe);
393
404
  },
394
405
  classification: options.classification
395
- });
396
- if (preRenderResult.response) return applyIneligibleRouteCachePolicy(preRenderResult.response, options);
406
+ }));
407
+ const preRenderResult = probeOutcome.result;
408
+ if (preRenderResult.response) {
409
+ if (probeOutcome.dynamicDetected) markDynamicUsage();
410
+ return applyIneligibleRouteCachePolicy(preRenderResult.response, options, probeOutcome.cacheLife);
411
+ }
397
412
  const layoutFlags = preRenderResult.layoutFlags;
398
413
  const artifactCompatibility = createAppPageArtifactCompatibility(options.element, options.routePattern);
399
414
  const rootBoundaryId = artifactCompatibility?.rootBoundaryId ?? null;
@@ -458,7 +473,7 @@ async function renderAppPageLifecycleImpl(options, renderSpan) {
458
473
  if (options.pprFallbackShellSignal) pprFallbackShellRsc = new Uint8Array(await readAppPageBinaryStream(rscStream));
459
474
  let revalidateSeconds = options.revalidateSeconds;
460
475
  let expireSeconds = options.expireSeconds;
461
- const shouldWaitForAllReady = options.isPrerender === true && options.isSpeculativePrerender !== true;
476
+ const shouldWaitForAllReady = options.isPrerender === true && options.isSpeculativePrerender !== true || options.renderWholeDocument === true;
462
477
  const shouldReadRequestCacheLifeForPrerender = options.isPrerender === true;
463
478
  const mayResolveCacheLifeAfterHeaders = options.isProgressiveActionRender !== true && (revalidateSeconds === null || revalidateSeconds > 0) && !options.isDraftMode && !options.isForceDynamic && !shouldBypassRscCache;
464
479
  const shouldCaptureRscForCacheMetadata = (options.isProduction || options.isPrerender === true) && mayResolveCacheLifeAfterHeaders && options.isStaticEligible;
@@ -474,6 +489,16 @@ async function renderAppPageLifecycleImpl(options, renderSpan) {
474
489
  const capturedRscDataRef = { value: null };
475
490
  if (rscCapture.sideStream && options.isRscRequest) capturedRscDataRef.value = readAppPageBinaryStream(rscCapture.sideStream);
476
491
  if (options.isRscRequest) {
492
+ const resolveRscRenderStatus = options.isProduction && shouldCaptureRscForCacheMetadata && capturedRscDataRef.value !== null && options.isPrerender !== true && options.isRoutePPREnabled !== true ? createAppPageRscRenderStatusResolver({
493
+ basePath: options.basePath,
494
+ capturedRscData: capturedRscDataRef.value,
495
+ getCapturedSpecialError: rscErrorTracker.getCapturedSpecialError,
496
+ getCapturedSpecialErrors: rscErrorTracker.getCapturedSpecialErrors,
497
+ isForceStatic: options.isForceStatic,
498
+ loadSsrHandler: options.loadSsrHandler,
499
+ navigationContext: options.getNavigationContext(),
500
+ rootParams: options.rootParams
501
+ }) : void 0;
477
502
  let requestCacheLifeForPrerender = null;
478
503
  if (shouldWaitForAllReady) await settleCapturedRscRenderForCacheMetadata(capturedRscDataRef.value);
479
504
  if (shouldReadRequestCacheLifeForPrerender) {
@@ -566,6 +591,7 @@ async function renderAppPageLifecycleImpl(options, renderSpan) {
566
591
  mountedSlotsHeader: options.mountedSlotsHeader,
567
592
  omitPendingDynamicCacheState: options.omitPendingDynamicCacheState,
568
593
  renderMode: options.renderMode,
594
+ resolveRscRenderStatus,
569
595
  preserveClientResponseHeaders: rscResponsePolicy.cacheState !== "MISS",
570
596
  expireSeconds,
571
597
  isStaticEligible: options.isStaticEligible,
@@ -591,6 +617,145 @@ async function renderAppPageLifecycleImpl(options, renderSpan) {
591
617
  let requestCacheLifeForPrerender = null;
592
618
  let dynamicUsedDuringHtmlRender = false;
593
619
  let renderEnd;
620
+ let shellSpecialError = null;
621
+ const resolveHtmlCacheWrite = (dynamicUsedDuringRender) => {
622
+ const htmlResponsePolicy = resolveAppPageHtmlResponsePolicy({
623
+ dynamicUsedDuringRender,
624
+ isProgressiveActionRender: options.isProgressiveActionRender === true,
625
+ hasScriptNonce: Boolean(options.scriptNonce),
626
+ isDraftMode: options.isDraftMode,
627
+ isDynamicError: options.isDynamicError,
628
+ isForceDynamic: options.isForceDynamic,
629
+ isForceStatic: options.isForceStatic,
630
+ isProduction: options.isProduction,
631
+ isStaticEligible: options.isStaticEligible,
632
+ expireSeconds,
633
+ revalidateSeconds
634
+ });
635
+ const shouldSpeculativelyWriteCache = options.isProduction && shouldCaptureRscForCacheMetadata && !options.isEdgeRuntime && revalidateSeconds === null && !options.isDynamicError && !options.isForceStatic && !options.scriptNonce && options.isProgressiveActionRender !== true && !dynamicUsedDuringRender;
636
+ return {
637
+ htmlResponsePolicy,
638
+ shouldWriteHtmlCache: htmlResponsePolicy.shouldWriteToCache || shouldSpeculativelyWriteCache
639
+ };
640
+ };
641
+ const finalizeHtmlCacheWrite = (response, write) => finalizeAppPageHtmlCacheResponse(response, {
642
+ bypassInterceptionContextCache: options.bypassInterceptionContextCache,
643
+ capturedDynamicUsageBeforeContextCleanup: write.capturedDynamicUsageBeforeContextCleanup,
644
+ capturedRscDataPromise: capturedRscDataRef.value,
645
+ cleanPathname: options.cleanPathname,
646
+ clientTraceMetadataMarker,
647
+ consumeDynamicUsage: consumeRenderDynamicUsage,
648
+ consumeRenderObservationState,
649
+ createHtmlRenderObservation(input) {
650
+ return createAppPageRenderObservation({
651
+ boundaryOutcome: { kind: "success" },
652
+ cacheability: "public",
653
+ cacheTags: input.cacheTags,
654
+ cleanPathname: options.cleanPathname,
655
+ completeness: "complete",
656
+ output: htmlOutputScope,
657
+ params: options.navigationParams,
658
+ state: input.state
659
+ });
660
+ },
661
+ createRscRenderObservation(input) {
662
+ return createAppPageRenderObservation({
663
+ boundaryOutcome: { kind: "success" },
664
+ cacheability: "public",
665
+ cacheTags: input.cacheTags,
666
+ cleanPathname: options.cleanPathname,
667
+ completeness: "complete",
668
+ output: rscOutputScope,
669
+ params: options.navigationParams,
670
+ state: input.state
671
+ });
672
+ },
673
+ getPageTags() {
674
+ return options.getPageTags();
675
+ },
676
+ getRequestCacheLife() {
677
+ return readRequestCacheLifeForCachePolicy(options);
678
+ },
679
+ headers: write.headers,
680
+ isrDebug: options.isrDebug,
681
+ isrHtmlKey: options.isrHtmlKey,
682
+ isrRscKey: options.isrRscKey,
683
+ isrSet: options.isrSet,
684
+ interceptionContext: options.interceptionContext,
685
+ interceptionId: options.interceptionId,
686
+ omitPendingDynamicCacheState: options.omitPendingDynamicCacheState,
687
+ preserveClientResponseHeaders: !write.htmlResponsePolicy.shouldWriteToCache,
688
+ expireSeconds,
689
+ isStaticEligible: options.isStaticEligible,
690
+ revalidateSeconds: resolveAppPageCacheWriteRevalidateSeconds({
691
+ isDynamicError: options.isDynamicError,
692
+ isForceStatic: options.isForceStatic,
693
+ isStaticEligible: options.isStaticEligible,
694
+ revalidateSeconds
695
+ }),
696
+ linkHeader: write.linkHeader,
697
+ status: write.status,
698
+ waitUntil(cachePromise) {
699
+ options.waitUntil?.(cachePromise);
700
+ }
701
+ });
702
+ const mayStoreShellSpecialError = () => options.isProduction && shouldCaptureRscForCacheMetadata && options.isPrerender !== true && capturedRscDataRef.value !== null && resolveEarlyResponseCacheControl(options) === null;
703
+ const mayPrerenderShellSpecialError = () => options.isPrerender === true && options.isSpeculativePrerender !== true && options.pprFallbackShellSignal === void 0 && shouldCaptureRscForCacheMetadata && capturedRscDataRef.value !== null && resolveEarlyResponseCacheControl(options) === null;
704
+ const readPrerenderCacheMetadata = () => ({
705
+ cacheTags: options.getPageTags(),
706
+ requestCacheLife: readRequestCacheLifeForPrerender(options)
707
+ });
708
+ let prerenderedSpecialError = null;
709
+ const finalizePrerenderedShellSpecialErrorResponse = async (response, specialError, prerendered) => {
710
+ if (response.status !== specialError.statusCode) return applyIneligibleRouteCachePolicy(response, options);
711
+ const body = await response.arrayBuffer();
712
+ const { cacheTags, requestCacheLife } = prerendered.redirectMetadata ?? readPrerenderCacheMetadata();
713
+ ({expireSeconds, revalidateSeconds} = applyRequestCacheLife({
714
+ expireSeconds,
715
+ requestCacheLife,
716
+ revalidateSeconds
717
+ }));
718
+ const { htmlResponsePolicy } = resolveHtmlCacheWrite(prerendered.dynamicUsed || consumeRenderDynamicUsage());
719
+ const headers = new Headers(response.headers);
720
+ if (htmlResponsePolicy.cacheControl && !headers.has("cache-control")) headers.set("Cache-Control", htmlResponsePolicy.cacheControl);
721
+ applyPrerenderCacheLifeHeader(headers, requestCacheLife);
722
+ applyPrerenderCacheTagsHeader(headers, cacheTags);
723
+ getRequestExecutionContext()?.recordPrerenderSpecialError?.({
724
+ headers: resolveAppPageSpecialErrorStoredHeaders(specialError, options.basePath) ?? {},
725
+ status: response.status
726
+ });
727
+ const prerenderResponse = new Response(body, {
728
+ headers,
729
+ status: response.status,
730
+ statusText: response.statusText
731
+ });
732
+ copyLinkHeaderProvenance(response.headers, prerenderResponse.headers);
733
+ return prerenderResponse;
734
+ };
735
+ const finalizeShellSpecialErrorResponse = (response, specialError) => {
736
+ if (response.status !== specialError.statusCode) return applyIneligibleRouteCachePolicy(response, options);
737
+ const dynamicUsedDuringRender = consumeRenderDynamicUsage();
738
+ const { htmlResponsePolicy, shouldWriteHtmlCache } = resolveHtmlCacheWrite(dynamicUsedDuringRender);
739
+ const headers = new Headers(response.headers);
740
+ if (htmlResponsePolicy.cacheControl && !headers.has("cache-control")) headers.set("Cache-Control", htmlResponsePolicy.cacheControl);
741
+ if (htmlResponsePolicy.cacheState) setCacheStateHeaders(headers, htmlResponsePolicy.cacheState);
742
+ const policyResponse = new Response(response.body, {
743
+ headers,
744
+ status: response.status,
745
+ statusText: response.statusText
746
+ });
747
+ copyLinkHeaderProvenance(response.headers, policyResponse.headers);
748
+ if (!shouldWriteHtmlCache) return policyResponse;
749
+ const clientResponse = finalizeHtmlCacheWrite(policyResponse, {
750
+ capturedDynamicUsageBeforeContextCleanup: () => dynamicUsedDuringRender,
751
+ headers: resolveAppPageSpecialErrorStoredHeaders(specialError, options.basePath),
752
+ htmlResponsePolicy,
753
+ linkHeader: getFrameworkLinkHeader(response.headers),
754
+ status: response.status
755
+ });
756
+ copyLinkHeaderProvenance(response.headers, clientResponse.headers);
757
+ return clientResponse;
758
+ };
594
759
  const htmlRender = await renderAppPageHtmlStreamWithRecovery({
595
760
  onShellRendered() {
596
761
  if (!options.isProduction) renderEnd = performance.now();
@@ -657,30 +822,34 @@ async function renderAppPageLifecycleImpl(options, renderSpan) {
657
822
  isStaticGeneration: options.isPrerender === true,
658
823
  isForceStatic: options.isForceStatic,
659
824
  isCacheCandidate: isCacheCandidateHtmlRender,
660
- onSsrError: createAppPageSsrErrorHandler(onSsrError, rscErrorTracker.isCapturedError)
825
+ onSsrError: createAppPageSsrErrorHandler(onSsrError, rscErrorTracker.isCapturedError),
826
+ mirrorNextFlight: () => rscErrorTracker.getCapturedSpecialError() !== null
661
827
  });
662
828
  },
663
- renderSpecialErrorResponse(specialError) {
664
- return options.renderPageSpecialError(specialError);
829
+ async renderSpecialErrorResponse(specialError) {
830
+ shellSpecialError = specialError;
831
+ const mayPrerender = mayPrerenderShellSpecialError();
832
+ if (mayStoreShellSpecialError() || mayPrerender) await settleCapturedRscRenderForCacheMetadata(capturedRscDataRef.value, peekRenderDynamicUsage);
833
+ if (mayPrerender) prerenderedSpecialError = {
834
+ dynamicUsed: consumeRenderDynamicUsage(),
835
+ redirectMetadata: specialError.kind === "redirect" ? readPrerenderCacheMetadata() : null
836
+ };
837
+ return options.renderPageSpecialError(specialError, { isCacheCandidate: isCacheCandidateHtmlRender });
665
838
  },
666
- resolveSpecialError: resolveAppPageSpecialError
839
+ resolveSpecialError(error) {
840
+ return resolveAppPageShellSpecialError(error, rscErrorTracker.getCapturedSpecialErrors(error));
841
+ }
667
842
  });
668
843
  options.onRenderComplete?.(htmlRender.renderComplete);
669
- if (htmlRender.response) return applyIneligibleRouteCachePolicy(htmlRender.response, options);
844
+ if (htmlRender.response) {
845
+ if (shellSpecialError && options.isProduction && options.isPrerender !== true && resolveEarlyResponseCacheControl(options) === null) return finalizeShellSpecialErrorResponse(htmlRender.response, shellSpecialError);
846
+ if (shellSpecialError && prerenderedSpecialError) return finalizePrerenderedShellSpecialErrorResponse(htmlRender.response, shellSpecialError, prerenderedSpecialError);
847
+ return applyIneligibleRouteCachePolicy(htmlRender.response, options);
848
+ }
670
849
  let htmlStream = htmlRender.htmlStream;
671
850
  if (!htmlStream) throw new Error("[vinext] Expected an HTML stream when no fallback response was returned");
672
851
  const linkHeader = buildAppPageLinkHeader(htmlRender.linkHeader, fontLinkHeader, options.reactMaxHeadersLength);
673
852
  if (options.isPrerender === true) await htmlRender.metadataReady;
674
- if (options.hasLoadingBoundary || !probePageBeforeRender) {
675
- const captured = rscErrorTracker.getCapturedSpecialError();
676
- if (captured) {
677
- const specialError = resolveAppPageSpecialError(captured);
678
- if (specialError) {
679
- htmlStream.cancel().catch(() => {});
680
- return applyIneligibleRouteCachePolicy(await options.renderPageSpecialError(specialError), options);
681
- }
682
- }
683
- }
684
853
  let dynamicUsedDuringRender = consumeRenderDynamicUsage();
685
854
  dynamicUsedDuringHtmlRender = dynamicUsedDuringRender;
686
855
  const stopSpeculativeMetadataWaitOnDynamicUsage = options.isSpeculativePrerender === true && shouldReadRequestCacheLifeForPrerender ? () => {
@@ -710,19 +879,7 @@ async function renderAppPageLifecycleImpl(options, renderSpan) {
710
879
  dynamicUsedDuringHtmlRender = dynamicUsedBeforeContextCleanup;
711
880
  options.clearRequestContext();
712
881
  });
713
- const htmlResponsePolicy = resolveAppPageHtmlResponsePolicy({
714
- dynamicUsedDuringRender,
715
- isProgressiveActionRender: options.isProgressiveActionRender === true,
716
- hasScriptNonce: Boolean(options.scriptNonce),
717
- isDraftMode: options.isDraftMode,
718
- isDynamicError: options.isDynamicError,
719
- isForceDynamic: options.isForceDynamic,
720
- isForceStatic: options.isForceStatic,
721
- isProduction: options.isProduction,
722
- isStaticEligible: options.isStaticEligible,
723
- expireSeconds,
724
- revalidateSeconds
725
- });
882
+ const { htmlResponsePolicy, shouldWriteHtmlCache } = resolveHtmlCacheWrite(dynamicUsedDuringRender);
726
883
  const htmlResponseTiming = buildResponseTiming({
727
884
  compileEnd,
728
885
  handlerStart: options.handlerStart,
@@ -747,8 +904,7 @@ async function renderAppPageLifecycleImpl(options, renderSpan) {
747
904
  applyCdnResponseHeaders(response.headers, { cacheControl: NEVER_CACHE_CONTROL });
748
905
  return response;
749
906
  }
750
- const shouldSpeculativelyWriteCache = options.isProduction && shouldCaptureRscForCacheMetadata && !options.isEdgeRuntime && revalidateSeconds === null && !options.isDynamicError && !options.isForceStatic && !options.scriptNonce && options.isProgressiveActionRender !== true && !dynamicUsedDuringRender;
751
- if (htmlResponsePolicy.shouldWriteToCache || shouldSpeculativelyWriteCache) {
907
+ if (shouldWriteHtmlCache) {
752
908
  const isrResponse = buildAppPageHtmlResponse(safeHtmlStream, {
753
909
  cacheTags: options.isPrerender === true ? options.getPageTags() : void 0,
754
910
  draftCookie,
@@ -760,66 +916,10 @@ async function renderAppPageLifecycleImpl(options, renderSpan) {
760
916
  timing: htmlResponseTiming
761
917
  });
762
918
  if (options.isPrerender === true) return isrResponse;
763
- return finalizeAppPageHtmlCacheResponse(isrResponse, {
764
- bypassInterceptionContextCache: options.bypassInterceptionContextCache,
765
- capturedDynamicUsageBeforeContextCleanup() {
766
- return dynamicUsedBeforeContextCleanup;
767
- },
768
- capturedRscDataPromise: capturedRscDataRef.value,
769
- cleanPathname: options.cleanPathname,
770
- clientTraceMetadataMarker,
771
- consumeDynamicUsage: consumeRenderDynamicUsage,
772
- consumeRenderObservationState,
773
- createHtmlRenderObservation(input) {
774
- return createAppPageRenderObservation({
775
- boundaryOutcome: { kind: "success" },
776
- cacheability: "public",
777
- cacheTags: input.cacheTags,
778
- cleanPathname: options.cleanPathname,
779
- completeness: "complete",
780
- output: htmlOutputScope,
781
- params: options.navigationParams,
782
- state: input.state
783
- });
784
- },
785
- createRscRenderObservation(input) {
786
- return createAppPageRenderObservation({
787
- boundaryOutcome: { kind: "success" },
788
- cacheability: "public",
789
- cacheTags: input.cacheTags,
790
- cleanPathname: options.cleanPathname,
791
- completeness: "complete",
792
- output: rscOutputScope,
793
- params: options.navigationParams,
794
- state: input.state
795
- });
796
- },
797
- getPageTags() {
798
- return options.getPageTags();
799
- },
800
- getRequestCacheLife() {
801
- return readRequestCacheLifeForCachePolicy(options);
802
- },
803
- isrDebug: options.isrDebug,
804
- isrHtmlKey: options.isrHtmlKey,
805
- isrRscKey: options.isrRscKey,
806
- isrSet: options.isrSet,
807
- interceptionContext: options.interceptionContext,
808
- interceptionId: options.interceptionId,
809
- omitPendingDynamicCacheState: options.omitPendingDynamicCacheState,
810
- preserveClientResponseHeaders: !htmlResponsePolicy.shouldWriteToCache,
811
- expireSeconds,
812
- isStaticEligible: options.isStaticEligible,
813
- revalidateSeconds: resolveAppPageCacheWriteRevalidateSeconds({
814
- isDynamicError: options.isDynamicError,
815
- isForceStatic: options.isForceStatic,
816
- isStaticEligible: options.isStaticEligible,
817
- revalidateSeconds
818
- }),
819
- linkHeader: linkHeader ?? null,
820
- waitUntil(cachePromise) {
821
- options.waitUntil?.(cachePromise);
822
- }
919
+ return finalizeHtmlCacheWrite(isrResponse, {
920
+ capturedDynamicUsageBeforeContextCleanup: () => dynamicUsedBeforeContextCleanup,
921
+ htmlResponsePolicy,
922
+ linkHeader: linkHeader ?? null
823
923
  });
824
924
  }
825
925
  const response = buildAppPageHtmlResponse(safeHtmlStream, {
@@ -49,7 +49,6 @@ type ResolveAppPageGenerateStaticParamsSourcesOptions = {
49
49
  };
50
50
  type BuildAppPageElementOptions<TElement> = {
51
51
  buildPageElement: () => Promise<TElement>;
52
- probePageSpecialError?: () => Promise<AppPageSpecialError | null>;
53
52
  renderErrorBoundaryPage: (error: unknown) => Promise<Response | null>;
54
53
  renderSpecialError: (specialError: AppPageSpecialError) => Promise<Response>;
55
54
  resolveSpecialError: (error: unknown) => AppPageSpecialError | null;
@@ -183,24 +183,62 @@ async function generateIndependentStaticParams(sources, primaryParams, requestPa
183
183
  validated
184
184
  };
185
185
  }
186
- async function generateChainedStaticParams(sources) {
187
- let generatedParams = [];
186
+ function isStaticParamsRowConsistentWithRequest(row, requestParams) {
187
+ const sharedKeys = Object.keys(row).filter((key) => requestParams[key] !== void 0);
188
+ return areStaticParamsAllowed(requestParams, [row], false, sharedKeys);
189
+ }
190
+ function rewritesParentParams(parentParams, item) {
191
+ return Object.keys(item).some((key) => Object.hasOwn(parentParams, key) && JSON.stringify(item[key]) !== JSON.stringify(parentParams[key]));
192
+ }
193
+ async function generateChainedStaticParams(sources, requestParams, results = /* @__PURE__ */ new Map()) {
194
+ let generatedRows = [];
195
+ let skippedParents = false;
196
+ let needsEveryCombination = false;
188
197
  for (const source of sources) {
189
- const hasParentParams = generatedParams.length > 0;
190
- const parents = hasParentParams ? generatedParams : [{}];
191
- const nextParams = [];
192
- for (const parentParams of parents) {
193
- const result = await runWithFetchDedupe(() => source.generateStaticParams({ params: parentParams }));
194
- if (Array.isArray(result) && result.length > 0) {
195
- for (const item of result) if (item !== null && typeof item === "object" && !Array.isArray(item)) nextParams.push({
196
- ...parentParams,
197
- ...item
198
+ let sourceResults = results.get(source);
199
+ if (!sourceResults) {
200
+ sourceResults = /* @__PURE__ */ new Map();
201
+ results.set(source, sourceResults);
202
+ }
203
+ const hasParentParams = generatedRows.length > 0;
204
+ let parents = hasParentParams ? generatedRows : [{
205
+ params: {},
206
+ lineage: ""
207
+ }];
208
+ const nextRows = [];
209
+ if (requestParams) {
210
+ const consistent = parents.filter((row) => isStaticParamsRowConsistentWithRequest(row.params, requestParams));
211
+ parents = consistent.length > 0 ? consistent : parents.slice(0, 1);
212
+ }
213
+ if (hasParentParams && parents.length < generatedRows.length) skippedParents = true;
214
+ for (const parent of parents) {
215
+ let result = sourceResults.get(parent.lineage);
216
+ if (!sourceResults.has(parent.lineage)) {
217
+ result = await runWithFetchDedupe(() => source.generateStaticParams({ params: parent.params }));
218
+ sourceResults.set(parent.lineage, result);
219
+ }
220
+ if (Array.isArray(result) && result.length > 0) result.forEach((item, index) => {
221
+ if (item === null || typeof item !== "object" || Array.isArray(item)) return;
222
+ const row = item;
223
+ if (skippedParents && rewritesParentParams(parent.params, row)) needsEveryCombination = true;
224
+ nextRows.push({
225
+ params: {
226
+ ...parent.params,
227
+ ...row
228
+ },
229
+ lineage: `${parent.lineage}/${index}`
198
230
  });
199
- } else if (hasParentParams) nextParams.push(parentParams);
231
+ });
232
+ else if (hasParentParams) nextRows.push({
233
+ params: parent.params,
234
+ lineage: `${parent.lineage}/-`
235
+ });
200
236
  }
201
- generatedParams = nextParams;
237
+ if (skippedParents && nextRows.length === 0) needsEveryCombination = true;
238
+ generatedRows = nextRows;
202
239
  }
203
- return generatedParams;
240
+ if (needsEveryCombination) return generateChainedStaticParams(sources, null, results);
241
+ return generatedRows.map((row) => row.params);
204
242
  }
205
243
  function normalizeGenerateStaticParams(generateStaticParams) {
206
244
  return (Array.isArray(generateStaticParams) ? generateStaticParams : [generateStaticParams]).flatMap((source) => {
@@ -218,7 +256,7 @@ async function validateAppPageDynamicParams(options) {
218
256
  if (generateStaticParamsSources.length === 0) return notFoundResponse();
219
257
  const chainedSources = generateStaticParamsSources.filter((source) => source.chained);
220
258
  let chainedStaticParams = null;
221
- if (chainedSources.length > 0) chainedStaticParams = await generateChainedStaticParams(chainedSources);
259
+ if (chainedSources.length > 0) chainedStaticParams = await generateChainedStaticParams(chainedSources, generateStaticParamsSources.some((source) => !source.chained) ? null : options.params);
222
260
  const independentChains = /* @__PURE__ */ new Map();
223
261
  for (const source of generateStaticParamsSources.filter((source) => !source.chained)) {
224
262
  const chain = independentChains.get(source.independentChain ?? source) ?? [];
@@ -333,8 +371,7 @@ async function buildAppPageElement(options) {
333
371
  response: null
334
372
  };
335
373
  } catch (error) {
336
- const buildSpecialError = options.resolveSpecialError(error);
337
- const specialError = (buildSpecialError ? await options.probePageSpecialError?.() : null) ?? buildSpecialError;
374
+ const specialError = options.resolveSpecialError(error);
338
375
  if (specialError) return {
339
376
  element: null,
340
377
  response: await options.renderSpecialError(specialError)
@@ -71,9 +71,10 @@ type BuildAppPageHtmlResponseOptions = {
71
71
  timing?: AppPageResponseTiming;
72
72
  };
73
73
  /**
74
- * Only ever set from a *completed* render's cacheLife (cache replay or
75
- * prerender seed) — `use cache` scopes keep resolving after headers commit,
76
- * so a streaming response can never carry it.
74
+ * Only ever set from a *completed* render's cacheLife (cache replay,
75
+ * prerender seed, or a layout probe's early redirect) — `use cache` scopes
76
+ * keep resolving after headers commit, so a streaming response can never
77
+ * carry it.
77
78
  */
78
79
  export declare function applyClientStaleTimeHeader(headers: Headers, staleTimeSeconds: number | undefined): void;
79
80
  /**