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
@@ -3,7 +3,7 @@ import { cacheabilityManifestPageState, cacheabilityRequestIdentity, cacheabilit
3
3
  import { keepOnlyValidatedRscCacheBustingSearchParam } from "./app-rsc-cache-busting.js";
4
4
  import { isTrustedPrerenderState } from "./prerender-route-params.js";
5
5
  //#region src/server/app-worker-stages.ts
6
- const APP_WORKER_RESPONSE_STAGE_PROTOCOL_VERSION = 10;
6
+ const APP_WORKER_RESPONSE_STAGE_PROTOCOL_VERSION = 11;
7
7
  const APP_METADATA_RESPONSE_STAGE_NO_MATCH_HEADER = "x-vinext-app-metadata-stage-no-match";
8
8
  const STATIC_FILE_SIGNAL_TOKEN_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
9
9
  /** Normalize a shared App page HEAD request onto its method-invariant GET representation. */
@@ -80,8 +80,8 @@ function isCanonicalHttpOrigin(value) {
80
80
  function isAppWorkerResponseStageProps(value) {
81
81
  if (!value || typeof value !== "object") return false;
82
82
  const props = value;
83
- if (props.protocolVersion !== 10 || props.buildId !== null && typeof props.buildId !== "string" || !isResponseStageCacheability(props.cacheability) || props.draftModeCookie !== null && typeof props.draftModeCookie !== "string" || props.middlewareCookieOverlay !== null && typeof props.middlewareCookieOverlay !== "string" || !isCanonicalHttpOrigin(props.requestOrigin) || props.scriptNonce !== null && typeof props.scriptNonce !== "string") return false;
84
- if (props.kind === "app-full-request") return typeof props.prerenderDiscovery === "boolean" && typeof props.staticFileSignalToken === "string" && STATIC_FILE_SIGNAL_TOKEN_RE.test(props.staticFileSignalToken) && (props.trustedPrerenderState === null || isTrustedPrerenderState(props.trustedPrerenderState));
83
+ if (props.protocolVersion !== 11 || props.buildId !== null && typeof props.buildId !== "string" || !isResponseStageCacheability(props.cacheability) || props.draftModeCookie !== null && typeof props.draftModeCookie !== "string" || props.middlewareCookieOverlay !== null && typeof props.middlewareCookieOverlay !== "string" || !isCanonicalHttpOrigin(props.requestOrigin) || props.scriptNonce !== null && typeof props.scriptNonce !== "string") return false;
84
+ if (props.kind === "app-full-request") return typeof props.headRequest === "boolean" && typeof props.prerenderDiscovery === "boolean" && typeof props.staticFileSignalToken === "string" && STATIC_FILE_SIGNAL_TOKEN_RE.test(props.staticFileSignalToken) && (props.trustedPrerenderState === null || isTrustedPrerenderState(props.trustedPrerenderState));
85
85
  if (props.kind === "hybrid-pages") {
86
86
  const hybrid = props;
87
87
  const appRouteMatch = hybrid.appRouteMatch;
@@ -91,7 +91,7 @@ function isAppWorkerResponseStageProps(value) {
91
91
  const special = props;
92
92
  return typeof special.canonicalPathname === "string" && special.canonicalPathname.startsWith("/") && typeof special.cleanPathname === "string" && special.cleanPathname.startsWith("/") && typeof special.isRscRequest === "boolean" && (special.mountedSlotsHeader === null || typeof special.mountedSlotsHeader === "string") && typeof special.resolvedUrl === "string" && special.resolvedUrl.startsWith("/") && (props.kind !== "app-metadata" || typeof props.routePathname === "string" && props.routePathname.startsWith("/")) && (special.renderMode === "navigation" || special.renderMode === "prefetch-empty" || special.renderMode === "prefetch-dynamic-shell" || special.renderMode === "prefetch-loading-shell");
93
93
  }
94
- return (props.kind === "app-page" || props.kind === "app-route-handler") && typeof props.bypassInterceptionContextCache === "boolean" && typeof props.cachePathname === "string" && props.cachePathname.startsWith("/") && typeof props.canUseCanonicalLoadingShell === "boolean" && typeof props.canonicalPathname === "string" && props.canonicalPathname.startsWith("/") && typeof props.cleanPathname === "string" && props.cleanPathname.startsWith("/") && (props.forceDynamic === void 0 || typeof props.forceDynamic === "boolean") && (props.interceptionContext === null || typeof props.interceptionContext === "string") && (props.interceptionId === null || typeof props.interceptionId === "string") && typeof props.isRscRequest === "boolean" && (props.matchKind === "interception" || props.matchKind === "request" || props.matchKind === "resolved") && (props.mountedSlotsHeader === null || typeof props.mountedSlotsHeader === "string") && isAppPageParams(props.params) && typeof props.resolvedUrl === "string" && props.resolvedUrl.startsWith("/") && typeof props.routePattern === "string" && props.routePattern.startsWith("/") && typeof props.routePathname === "string" && props.routePathname.startsWith("/") && (props.renderMode === "navigation" || props.renderMode === "prefetch-empty" || props.renderMode === "prefetch-dynamic-shell" || props.renderMode === "prefetch-loading-shell");
94
+ return (props.kind === "app-page" || props.kind === "app-route-handler") && typeof props.bypassInterceptionContextCache === "boolean" && typeof props.cachePathname === "string" && props.cachePathname.startsWith("/") && typeof props.canUseCanonicalLoadingShell === "boolean" && typeof props.canonicalPathname === "string" && props.canonicalPathname.startsWith("/") && typeof props.cleanPathname === "string" && props.cleanPathname.startsWith("/") && (props.forceDynamic === void 0 || typeof props.forceDynamic === "boolean") && (props.interceptionContext === null || typeof props.interceptionContext === "string") && (props.interceptionId === null || typeof props.interceptionId === "string") && typeof props.isRscRequest === "boolean" && (props.matchKind === "interception" || props.matchKind === "raw-request" || props.matchKind === "request" || props.matchKind === "resolved") && (props.mountedSlotsHeader === null || typeof props.mountedSlotsHeader === "string") && isAppPageParams(props.params) && typeof props.resolvedUrl === "string" && props.resolvedUrl.startsWith("/") && typeof props.routePattern === "string" && props.routePattern.startsWith("/") && typeof props.routePathname === "string" && props.routePathname.startsWith("/") && (props.renderMode === "navigation" || props.renderMode === "prefetch-empty" || props.renderMode === "prefetch-dynamic-shell" || props.renderMode === "prefetch-loading-shell");
95
95
  }
96
96
  function isSerializedHeaders(value) {
97
97
  return Array.isArray(value) && value.every((entry) => Array.isArray(entry) && entry.length === 2 && typeof entry[0] === "string" && typeof entry[1] === "string");
@@ -1,7 +1,7 @@
1
1
  import "../utils/protocol-headers.js";
2
2
  import { isVinextRscVaryField } from "./app-rsc-vary.js";
3
- import { VINEXT_CACHEABILITY_PROBE_HEADER, VINEXT_CACHEABILITY_PROBE_ROUTE_HEADER } from "./headers.js";
4
- import { isNonCacheableCacheControl } from "../shims/cdn-cache.js";
3
+ import { VINEXT_CACHEABILITY_PROBE_HEADER, VINEXT_CACHEABILITY_PROBE_ROUTE_HEADER, VINEXT_SPECIAL_ERROR_STATUS_HEADER } from "./headers.js";
4
+ import { hasSharedCacheCredentials, isNonCacheableCacheControl } from "../shims/cdn-cache.js";
5
5
  import { CACHEABILITY_REQUEST_STATE, recordConfigCdnCachePolicyHeader } from "../shims/cacheability-classification.js";
6
6
  import { NO_STORE_CACHE_CONTROL, applyCdnResponseBuildIdentityHeaders, applyCdnResponseHeaders, hasExplicitNonCacheableResponsePolicy, isCdnResponsePolicyHeader, readCdnResponseCacheControl, readCdnResponsePolicyHeaderName } from "./cache-control.js";
7
7
  import { cacheabilityManifestPageState, cacheabilityManifestRouteState, cacheabilityRepresentationMatchesPageRoute, cacheabilityRequestIdentity, cacheabilityRoutePathname, findCacheabilityManifestRoute, parseCacheabilityManifest, resolveCacheabilityRepresentation } from "./cacheability-manifest.js";
@@ -70,7 +70,7 @@ function readBoundManifest(raw, buildId) {
70
70
  }
71
71
  function createWorkerCacheabilityAdmissionContext(base, request, rawManifest, buildId, requiresCompletedResponseAdmission = rawManifest != null, responseVary, resolvedRoutePathname, trustedRepresentation, options) {
72
72
  const identity = cacheabilityRequestIdentity(request, trustedRepresentation);
73
- const credentialedRequest = request.headers.has("authorization") || request.headers.has("cookie") || request.headers.has("proxy-authorization");
73
+ const credentialedRequest = hasSharedCacheCredentials(request.headers);
74
74
  const routePathname = identity ? cacheabilityRoutePathname(resolvedRoutePathname ?? new URL(request.url).pathname, identity.representation) : void 0;
75
75
  if (!rawManifest) {
76
76
  if (!requiresCompletedResponseAdmission) return base;
@@ -348,9 +348,10 @@ async function captureCacheabilityAdmissionBody(body, deadlineAt, limit = CACHEA
348
348
  throw error;
349
349
  }
350
350
  }
351
- function responseWithCachePolicy(response, body, outcome, browserCacheControl) {
351
+ function responseWithCachePolicy(response, body, outcome, browserCacheControl, completedStatus) {
352
352
  const headers = new Headers(response.headers);
353
353
  if (typeof body === "string") headers.delete("Content-Length");
354
+ for (const [name, value] of Object.entries(completedStatus?.headers ?? {})) if (!headers.has(name)) headers.set(name, value);
354
355
  applyCdnResponseHeaders(headers, outcome?.cacheable === true && outcome.cacheControl ? {
355
356
  cacheControl: outcome.cacheControl,
356
357
  tags: outcome.tags,
@@ -359,10 +360,13 @@ function responseWithCachePolicy(response, body, outcome, browserCacheControl) {
359
360
  cacheControl: NO_STORE_CACHE_CONTROL,
360
361
  browserCacheControl
361
362
  });
363
+ const status = completedStatus?.status ?? response.status;
364
+ const completed = completedStatus?.status;
365
+ if (completed === 401 || completed === 403 || completed === 404) headers.set(VINEXT_SPECIAL_ERROR_STATUS_HEADER, String(completed));
362
366
  return new Response(body, {
363
367
  headers,
364
- status: response.status,
365
- statusText: response.statusText
368
+ status,
369
+ statusText: status === response.status ? response.statusText : ""
366
370
  });
367
371
  }
368
372
  async function stripSharedHtmlClientTraceMetadata(body, marker) {
@@ -499,7 +503,7 @@ async function finalizeWorkerCacheabilityAdmission(response, state) {
499
503
  const effectivePolicyHeader = readCdnResponsePolicyHeaderName(response.headers);
500
504
  const replacesRendererPolicy = outcome !== rendererOutcome && effectivePolicyHeader !== null && state.configCdnCachePolicy?.get(effectivePolicyHeader) === response.headers.get(effectivePolicyHeader);
501
505
  if (state.route.kind === "app-page" && !replacesRendererPolicy && rendererOutcome?.searchParamsUnread !== true) return responseWithCachePolicy(response, captured.body, null, browserCacheControl);
502
- return responseWithCachePolicy(response, representation === "html" && state.clientTraceMetadataMarker ? await stripSharedHtmlClientTraceMetadata(captured.body, state.clientTraceMetadataMarker) : captured.body, outcome, browserCacheControl);
506
+ return responseWithCachePolicy(response, representation === "html" && state.clientTraceMetadataMarker ? await stripSharedHtmlClientTraceMetadata(captured.body, state.clientTraceMetadataMarker) : captured.body, outcome, browserCacheControl, rendererOutcome ?? void 0);
503
507
  }
504
508
  async function finalizeWorkerCacheabilityResponse(response, ctx) {
505
509
  const state = readState(ctx);
@@ -0,0 +1,16 @@
1
+ //#region src/server/client-build-files.d.ts
2
+ /**
3
+ * Return the URL pathname of the client build file a request pathname names,
4
+ * or null. Client build files are the files the client build emits outside
5
+ * `_next/static` (see `collectClientBuildFiles`). Workers Static Assets serves
6
+ * them before the Worker unless the Worker runs first, so servers handle them
7
+ * before middleware and routing.
8
+ *
9
+ * `pathname` is the raw request pathname. The list holds file names and
10
+ * `basePath` is the configured string, so each segment is decoded exactly once
11
+ * before matching; a segment that decodes to a `/` names no file. The result
12
+ * is the file's segment-encoded pathname below `basePath`, so a server that
13
+ * decodes it once gets the file name back.
14
+ */
15
+ export declare function resolveClientBuildFile(pathname: string, basePath: string, clientBuildFiles: ReadonlySet<string>): string | null;
16
+ //#endregion
@@ -0,0 +1,36 @@
1
+ //#region src/server/client-build-files.ts
2
+ /**
3
+ * Return the URL pathname of the client build file a request pathname names,
4
+ * or null. Client build files are the files the client build emits outside
5
+ * `_next/static` (see `collectClientBuildFiles`). Workers Static Assets serves
6
+ * them before the Worker unless the Worker runs first, so servers handle them
7
+ * before middleware and routing.
8
+ *
9
+ * `pathname` is the raw request pathname. The list holds file names and
10
+ * `basePath` is the configured string, so each segment is decoded exactly once
11
+ * before matching; a segment that decodes to a `/` names no file. The result
12
+ * is the file's segment-encoded pathname below `basePath`, so a server that
13
+ * decodes it once gets the file name back.
14
+ */
15
+ function resolveClientBuildFile(pathname, basePath, clientBuildFiles) {
16
+ if (clientBuildFiles.size === 0) return null;
17
+ let filePath = pathname;
18
+ if (filePath.includes("%")) {
19
+ let segments;
20
+ try {
21
+ segments = filePath.split("/").map(decodeURIComponent);
22
+ } catch {
23
+ return null;
24
+ }
25
+ if (segments.some((segment) => segment.includes("/"))) return null;
26
+ filePath = segments.join("/");
27
+ }
28
+ if (basePath) {
29
+ if (!filePath.startsWith(`${basePath}/`)) return null;
30
+ filePath = filePath.slice(basePath.length);
31
+ }
32
+ if (!clientBuildFiles.has(filePath)) return null;
33
+ return filePath.split("/").map(encodeURIComponent).join("/");
34
+ }
35
+ //#endregion
36
+ export { resolveClientBuildFile };
@@ -1,6 +1,6 @@
1
1
  import { isUnknownRecord } from "../utils/record.js";
2
- import { fnv1a64 } from "../utils/hash.js";
3
2
  import { parseAppElementsWireElementKey } from "./app-elements-wire-key.js";
3
+ import { fnv1a64 } from "../utils/hash.js";
4
4
  import { parseArtifactCompatibilityEnvelope } from "./artifact-compatibility.js";
5
5
  import { isNonNegativeSafeInteger } from "../utils/number.js";
6
6
  //#region src/server/client-reuse-manifest.ts
@@ -1,4 +1,5 @@
1
1
  import { matchHeaders } from "../config/config-matchers.js";
2
+ import "./headers.js";
2
3
  import { markRouteCacheabilityConfigCdnCachePolicy, markRouteCacheabilityDynamic, markRouteCacheabilityFinalResponseUncacheable } from "../shims/cacheability-classification.js";
3
4
  import { isCdnResponsePolicyHeader, isNonCacheableCdnResponsePolicy } from "./cache-control.js";
4
5
  import { mergeVaryHeader } from "./middleware-response-headers.js";
@@ -77,6 +78,7 @@ function applyConfigHeadersToResponse(responseHeaders, options) {
77
78
  if (options.recordCacheability !== false) markExplicitConfigResponseVeto(matched);
78
79
  for (const header of matched) {
79
80
  const lowerName = header.key.toLowerCase();
81
+ if (lowerName === "x-vinext-special-error-status") continue;
80
82
  if (lowerName === "link") {
81
83
  if (options.middlewareHeaders?.get(lowerName)) continue;
82
84
  const postConfigLink = options.appendToPostConfigLink ? responseHeaders.get(lowerName) : null;
@@ -18,9 +18,12 @@ import { mergeRouteParamsIntoQuery, parseQueryString } from "../utils/query.js";
18
18
  import "../shims/router-state.js";
19
19
  import { withScriptNonce } from "../shims/script-nonce-context.js";
20
20
  import { createInlineScriptTag, createNonceAttribute, safeJsonStringify } from "./html.js";
21
+ import { createDocumentPlaceholderToken, getDocumentHeadOpenMarker } from "../shims/document-placeholders.js";
21
22
  import { applyDocumentAssetProps, extractDocumentAssetProps, markDocumentAssetPropsProtectedTags, stripDocumentAssetPropsProtectionMarkers } from "./pages-document-asset-props.js";
23
+ import { spliceDocumentHeadClose, spliceDocumentHeadOpen, spliceDocumentScripts, splitDocumentAtMain } from "./pages-document-splice.js";
22
24
  import { getClientTraceMetadataHTML } from "./client-trace-metadata.js";
23
25
  import { getScriptNonceFromNodeHeaderSources } from "./csp.js";
26
+ import { stripViteModuleQuery } from "../utils/path.js";
24
27
  import { logRequest, now } from "./request-log.js";
25
28
  import { buildDefaultPagesNotFoundResponse } from "./pages-default-404.js";
26
29
  import { buildPagesReadinessNextData } from "./pages-readiness.js";
@@ -30,7 +33,7 @@ import { callDocumentGetInitialProps } from "./document-initial-head.js";
30
33
  import { hasPagesGetInitialProps, loadDevAppInitialProps, loadPagesGetInitialProps } from "./pages-get-initial-props.js";
31
34
  import { isSerializableProps } from "./pages-serializable-props.js";
32
35
  import { traceFindPageComponents, tracePagesData, tracePagesDocument, tracePagesDocumentStream } from "./pages-execution-tracing.js";
33
- import { assertPages404DoesNotReturnNotFound, buildPagesRedirectProps, getPagesRouteParams, matchesPagesStaticPath, mergePagesDataProps, resolvePagesRedirect, resolvePagesRedirectLocation, resolvePagesRevalidateSeconds } from "./pages-page-data.js";
36
+ import { assertPages404DoesNotReturnNotFound, buildPagesRedirectProps, getPagesRouteParams, matchesPagesStaticPath, mergePagesDataProps, resolvePagesRedirect, resolvePagesRedirectLocation, resolvePagesRevalidateSeconds, resolvePagesStatusPageRenderPath } from "./pages-page-data.js";
34
37
  import { createPagesDevModuleUrl } from "./pages-dev-module-url.js";
35
38
  import { collectPagesDevInitialStylesheetHeadHTML } from "./pages-dev-stylesheets.js";
36
39
  import { createPagesDevHydrationScript } from "./pages-dev-hydration.js";
@@ -141,13 +144,20 @@ function writeGsspRedirect(res, redirect, isDataReq, props, options) {
141
144
  });
142
145
  res.end(location);
143
146
  }
144
- /** Body placeholder used to split the document shell for streaming. */
145
- const STREAM_BODY_MARKER = "<!--VINEXT_STREAM_BODY-->";
146
147
  function stripDevPagesNotFoundFramingHeaders(res) {
147
148
  res.removeHeader("Content-Length");
148
149
  res.removeHeader("Transfer-Encoding");
149
150
  }
150
151
  /**
152
+ * Vite's `transformIndexHtml` treats its URL as the HTML document's path, so
153
+ * the request query carries no meaning there. Since Vite 8.3.3 it also maps
154
+ * `/?q` onto the project root directory and then watches the filesystem root
155
+ * for each inline `<style>` proxy module, so pass the bare path.
156
+ */
157
+ function toHtmlTransformPath(url) {
158
+ return stripViteModuleQuery(url);
159
+ }
160
+ /**
151
161
  * Stream a Pages Router page response using progressive SSR.
152
162
  *
153
163
  * Sends the HTML shell (head, layout, Suspense fallbacks) immediately
@@ -161,7 +171,7 @@ function stripDevPagesNotFoundFramingHeaders(res) {
161
171
  * shell sooner).
162
172
  */
163
173
  async function streamPageToResponseImpl(routePattern, res, element, options) {
164
- const { url, server, fontHeadHTML, assetHeadHTML = "", scripts, DocumentComponent, statusCode, extraHeaders, getHeadHTML, getTailHeadHTML, enhancePageElement, scriptNonce, documentContext, setDocumentInitialHead, crossOrigin, bufferBodyBeforeHeaders = false, preserveExistingContentType = false, onDocumentBody } = options;
174
+ const { url, server, runner, fontHeadHTML, assetHeadHTML = "", scripts, DocumentComponent, statusCode, extraHeaders, getHeadHTML, getTailHeadHTML, enhancePageElement, scriptNonce, documentContext, setDocumentInitialHead, crossOrigin, bufferBodyBeforeHeaders = false, preserveExistingContentType = false, onDocumentBody } = options;
165
175
  const renderDocument = async () => {
166
176
  const documentRenderPage = await runDocumentRenderPage({
167
177
  DocumentComponent,
@@ -201,6 +211,8 @@ async function streamPageToResponseImpl(routePattern, res, element, options) {
201
211
  const ssrHeadMarkerId = randomUUID();
202
212
  const ssrHeadStartMarker = `<!--VINEXT_SSR_HEAD_START:${ssrHeadMarkerId}-->`;
203
213
  const ssrHeadEndMarker = `<!--VINEXT_SSR_HEAD_END:${ssrHeadMarkerId}-->`;
214
+ const streamBodyMarker = `<!--VINEXT_STREAM_BODY:${ssrHeadMarkerId}-->`;
215
+ const documentToken = createDocumentPlaceholderToken();
204
216
  let tailHeadHTML = getTailHeadHTML?.() ?? "";
205
217
  if (documentRenderPage.status === "rendered" && documentRenderPage.stylesHTML) {
206
218
  if (tailHeadHTML) tailHeadHTML += "\n ";
@@ -217,34 +229,34 @@ async function streamPageToResponseImpl(routePattern, res, element, options) {
217
229
  if (DocumentComponent) {
218
230
  const docProps = documentRenderPage.status === "skipped" ? await loadUserDocumentInitialProps(DocumentComponent) : documentRenderPage.docProps;
219
231
  const docElement = docProps ? React.createElement(DocumentComponent, docProps) : React.createElement(DocumentComponent);
220
- const renderedDocument = extractDocumentAssetProps(await renderToStringAsync(docElement));
232
+ const { withDocumentPlaceholders } = await runner.import("vinext/document-placeholders");
233
+ const renderedDocument = extractDocumentAssetProps(await renderToStringAsync(withDocumentPlaceholders(docElement, documentToken)), documentToken);
221
234
  documentAssetProps = renderedDocument.props;
222
235
  let docHtml = protectAssetTags(renderedDocument.html);
223
236
  const generatedScripts = applyGeneratedAssetProps(scripts, renderedDocument.props, "next-script");
224
237
  const generatedAssetHeadHTML = applyGeneratedAssetProps(assetHeadHTML, renderedDocument.props, "next-script");
225
- docHtml = docHtml.replace("__NEXT_MAIN__", STREAM_BODY_MARKER);
226
- if (headHTML || fontHeadHTML || generatedAssetHeadHTML || tailHeadHTML) docHtml = docHtml.replace("</head>", `${ssrHeadStartMarker}${protectAssetTags(headHTML)}${ssrHeadEndMarker} ${protectAssetTags(fontHeadHTML)}\n ${generatedAssetHeadHTML}\n ${protectAssetTags(tailHeadHTML)}\n</head>`);
227
- docHtml = docHtml.replace("<!-- __NEXT_SCRIPTS__ -->", generatedScripts);
228
- if (!docHtml.includes("__NEXT_DATA__")) docHtml = docHtml.replace("</body>", ` ${generatedScripts}\n</body>`);
229
- shellTemplate = docHtml;
238
+ docHtml = spliceDocumentHeadClose(docHtml, documentToken, headHTML || fontHeadHTML || generatedAssetHeadHTML || tailHeadHTML ? `${ssrHeadStartMarker}${protectAssetTags(headHTML)}${ssrHeadEndMarker} ${protectAssetTags(fontHeadHTML)}\n ${generatedAssetHeadHTML}\n ${protectAssetTags(tailHeadHTML)}\n` : "");
239
+ docHtml = spliceDocumentScripts(docHtml, documentToken, generatedScripts);
240
+ const main = splitDocumentAtMain(docHtml, documentToken);
241
+ shellTemplate = main.prefix + streamBodyMarker + main.suffix;
230
242
  } else {
231
243
  const generatedScripts = applyGeneratedAssetProps(scripts, {}, "next-script");
232
244
  const generatedAssetHeadHTML = applyGeneratedAssetProps(assetHeadHTML, {}, "next-script");
233
245
  shellTemplate = `<!DOCTYPE html>
234
246
  <html>
235
- <head>
247
+ <head${getDocumentHeadOpenMarker(documentToken)}>
236
248
  ${ssrHeadStartMarker}${protectAssetTags(headHTML)}${ssrHeadEndMarker}
237
249
  ${protectAssetTags(fontHeadHTML)}
238
250
  ${generatedAssetHeadHTML}
239
251
  ${protectAssetTags(tailHeadHTML)}
240
252
  </head>
241
253
  <body>
242
- <div id="__next">${STREAM_BODY_MARKER}</div>
254
+ <div id="__next">${streamBodyMarker}</div>
243
255
  ${generatedScripts}
244
256
  </body>
245
257
  </html>`;
246
258
  }
247
- let transformedShell = await server.transformIndexHtml(url, shellTemplate);
259
+ let transformedShell = await server.transformIndexHtml(toHtmlTransformPath(url), shellTemplate);
248
260
  transformedShell = stripDocumentAssetPropsProtectionMarkers(applyDocumentAssetProps(transformedShell, documentAssetProps, {
249
261
  configuredCrossOrigin: crossOrigin,
250
262
  protectedAssetMarker,
@@ -252,14 +264,17 @@ async function streamPageToResponseImpl(routePattern, res, element, options) {
252
264
  }), protectedAssetMarker);
253
265
  const ssrHeadStart = transformedShell.indexOf(ssrHeadStartMarker);
254
266
  const ssrHeadEnd = transformedShell.indexOf(ssrHeadEndMarker);
267
+ let transformedHeadHTML = "";
255
268
  if (ssrHeadStart !== -1 && ssrHeadEnd > ssrHeadStart) {
256
- const transformedHeadHTML = transformedShell.slice(ssrHeadStart + ssrHeadStartMarker.length, ssrHeadEnd);
257
- transformedShell = transformedShell.slice(0, ssrHeadStart) + transformedShell.slice(ssrHeadEnd + ssrHeadEndMarker.length);
258
- transformedShell = transformedShell.replace(/<head(?:\s[^>]*)?>/i, (openingHead) => `${openingHead}${transformedHeadHTML}`);
269
+ const ssrHeadHTML = transformedShell.slice(ssrHeadStart + ssrHeadStartMarker.length, ssrHeadEnd);
270
+ const moveToHeadOpen = transformedShell.includes(getDocumentHeadOpenMarker(documentToken));
271
+ if (moveToHeadOpen) transformedHeadHTML = ssrHeadHTML;
272
+ transformedShell = transformedShell.slice(0, ssrHeadStart) + (moveToHeadOpen ? "" : ssrHeadHTML) + transformedShell.slice(ssrHeadEnd + ssrHeadEndMarker.length);
259
273
  }
260
- const markerIdx = transformedShell.indexOf(STREAM_BODY_MARKER);
274
+ transformedShell = spliceDocumentHeadOpen(transformedShell, documentToken, transformedHeadHTML);
275
+ const markerIdx = transformedShell.indexOf(streamBodyMarker);
261
276
  const prefix = transformedShell.slice(0, markerIdx);
262
- const suffix = transformedShell.slice(markerIdx + 25);
277
+ const suffix = transformedShell.slice(markerIdx + streamBodyMarker.length);
263
278
  const bufferedBody = bufferBodyBeforeHeaders ? await new Response(bodyStream).text() : null;
264
279
  const headers = { "Transfer-Encoding": "chunked" };
265
280
  if (!preserveExistingContentType || !res.hasHeader("Content-Type")) headers["Content-Type"] = "text/html; charset=utf-8";
@@ -374,7 +389,9 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
374
389
  locale: locale ?? currentDefaultLocale,
375
390
  locales: i18nConfig?.locales,
376
391
  defaultLocale: currentDefaultLocale,
377
- crossOrigin
392
+ crossOrigin,
393
+ trailingSlash,
394
+ requestPathname: new URL(originalUrl, "http://vinext.local").pathname
378
395
  };
379
396
  const match = matchRoute(localeStrippedUrl, routes);
380
397
  if (!match) {
@@ -442,7 +459,8 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
442
459
  isStaticPropsRender = typeof pageModule.getStaticProps === "function" && typeof pageModule.getServerSideProps !== "function";
443
460
  if (isStaticPropsRender) {
444
461
  query = mergeRouteParamsIntoQuery({}, params);
445
- requestAsPath = localeStrippedUrl.split("?")[0];
462
+ const routePattern = patternToNextFormat(route.pattern);
463
+ requestAsPath = routePattern === "/404" || routePattern === "/500" ? resolvePagesStatusPageRenderPath(routePattern, trailingSlash, errorPageContext.requestPathname) : localeStrippedUrl.split("?")[0];
446
464
  }
447
465
  const requestPreview = typeof pageModule.getStaticProps === "function" || typeof pageModule.getServerSideProps === "function" ? getPagesPreviewState(req.headers.cookie, { isOnDemandRevalidate: isOnDemandRevalidateRequest(req.headers[PRERENDER_REVALIDATE_HEADER]) }) : {
448
466
  data: false,
@@ -854,6 +872,7 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
854
872
  await streamPageToResponse(route.pattern, res, withScriptNonce(element, scriptNonce), {
855
873
  url,
856
874
  server,
875
+ runner,
857
876
  fontHeadHTML,
858
877
  assetHeadHTML,
859
878
  scripts: allScripts,
@@ -953,10 +972,11 @@ async function renderErrorPage(server, runner, req, res, url, pagesDir, statusCo
953
972
  if (!ErrorComponent) continue;
954
973
  const createElement = React.createElement;
955
974
  res.statusCode = statusCode;
975
+ const renderUrl = errorPage !== "/_error" && typeof errorModule.getStaticProps === "function" ? resolvePagesStatusPageRenderPath(errorPage, context.trailingSlash === true, context.requestPathname ?? url.split("?")[0]) : url;
956
976
  const errorRouter = {
957
977
  pathname: errorPage,
958
- query: parseQueryString(url),
959
- asPath: url
978
+ query: parseQueryString(renderUrl),
979
+ asPath: renderUrl
960
980
  };
961
981
  try {
962
982
  errorRouterShim = await importModule(runner, "next/router");
@@ -973,7 +993,7 @@ async function renderErrorPage(server, runner, req, res, url, pagesDir, statusCo
973
993
  err,
974
994
  pathname: errorPage,
975
995
  query: errorRouter.query,
976
- asPath: url
996
+ asPath: renderUrl
977
997
  });
978
998
  if (res.headersSent || res.writableEnded) return;
979
999
  let errorProps = {
@@ -994,7 +1014,7 @@ async function renderErrorPage(server, runner, req, res, url, pagesDir, statusCo
994
1014
  writeGsspRedirect(res, staticResult.redirect, false, { pageProps: errorProps }, {
995
1015
  basePath: context.basePath,
996
1016
  method: "getStaticProps",
997
- routeUrl: url
1017
+ routeUrl: renderUrl
998
1018
  });
999
1019
  return;
1000
1020
  }
@@ -1025,7 +1045,7 @@ async function renderErrorPage(server, runner, req, res, url, pagesDir, statusCo
1025
1045
  err,
1026
1046
  pathname: errorPage,
1027
1047
  query: errorRouter.query,
1028
- asPath: url
1048
+ asPath: renderUrl
1029
1049
  }
1030
1050
  });
1031
1051
  if (res.headersSent || res.writableEnded) return;
@@ -1058,7 +1078,7 @@ async function renderErrorPage(server, runner, req, res, url, pagesDir, statusCo
1058
1078
  const errorScripts = `${`<script id="__NEXT_DATA__" type="application/json"${nonceAttr}>${safeJsonStringify({
1059
1079
  props: renderProps,
1060
1080
  page: errorPage,
1061
- query: parseQueryString(url),
1081
+ query: parseQueryString(renderUrl),
1062
1082
  buildId: context.buildId ?? process.env.__VINEXT_BUILD_ID ?? "development",
1063
1083
  isFallback: false,
1064
1084
  locale: context.locale,
@@ -1085,6 +1105,7 @@ async function renderErrorPage(server, runner, req, res, url, pagesDir, statusCo
1085
1105
  if (DocumentComponent) await streamPageToResponse(errorPage, res, element, {
1086
1106
  url,
1087
1107
  server,
1108
+ runner,
1088
1109
  fontHeadHTML: "",
1089
1110
  assetHeadHTML,
1090
1111
  scripts: errorScripts,
@@ -1093,8 +1114,8 @@ async function renderErrorPage(server, runner, req, res, url, pagesDir, statusCo
1093
1114
  documentContext: {
1094
1115
  err,
1095
1116
  pathname: errorPage,
1096
- query: parseQueryString(url),
1097
- asPath: url,
1117
+ query: parseQueryString(renderUrl),
1118
+ asPath: renderUrl,
1098
1119
  req,
1099
1120
  res
1100
1121
  },
@@ -1130,7 +1151,7 @@ async function renderErrorPage(server, runner, req, res, url, pagesDir, statusCo
1130
1151
  ${protectedErrorScripts}
1131
1152
  </body>
1132
1153
  </html>`;
1133
- const transformedHtml = stripDocumentAssetPropsProtectionMarkers(applyDocumentAssetProps(await server.transformIndexHtml(url, html), {}, {
1154
+ const transformedHtml = stripDocumentAssetPropsProtectionMarkers(applyDocumentAssetProps(await server.transformIndexHtml(toHtmlTransformPath(url), html), {}, {
1134
1155
  configuredCrossOrigin: context.crossOrigin,
1135
1156
  protectedAssetMarker
1136
1157
  }), protectedAssetMarker);
@@ -1,7 +1,7 @@
1
- import { toSlash } from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
1
+ import path, { toSlash } from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
2
2
  import { VINEXT_ORIGINAL_STACK_TRACE_ENDPOINT } from "../utils/dev-stack-sourcemap-endpoint.js";
3
- import { readFile } from "node:fs/promises";
4
3
  import { fileURLToPath, pathToFileURL } from "node:url";
4
+ import { isFileLoadingAllowed } from "vite";
5
5
  //#region src/server/dev-stack-sourcemap.ts
6
6
  const MAX_ORIGINAL_STACK_TRACE_BODY_BYTES = 1048576;
7
7
  const V8_PAREN_STACK_LINE = /^(\s*at\s+.*?\()(.+):(\d+):(\d+)(\)\s*)$/;
@@ -162,7 +162,7 @@ async function mapGeneratedFrame(server, file, line, column, methodName, request
162
162
  const original = traceOriginalPositionFor(sourceMap, generatedLine, generatedColumn);
163
163
  if (!original) return null;
164
164
  const originalFile = resolveSourceFile(original.source, sourceMap, generatedFrame.sourceMapBaseUrl);
165
- const codeFrame = await createStackCodeFrame({
165
+ const codeFrame = createStackCodeFrame({
166
166
  file: originalFile,
167
167
  line: original.line,
168
168
  column: original.column,
@@ -224,11 +224,12 @@ function getLocalSourcePath(server, file) {
224
224
  }
225
225
  localPath = stripQuery(localPath);
226
226
  if (!isAbsolutePath(localPath)) return null;
227
+ localPath = path.resolve(localPath);
227
228
  const localPathForCompare = normalizeLocalPathForCompare(localPath);
228
229
  if (localPathForCompare.includes("/node_modules/")) return null;
229
230
  const root = server.config?.root;
230
231
  if (!root) return null;
231
- const rootForCompare = normalizeLocalPathForCompare(root);
232
+ const rootForCompare = normalizeLocalPathForCompare(path.resolve(root));
232
233
  return localPathForCompare === rootForCompare || localPathForCompare.startsWith(`${rootForCompare}/`) ? localPath : null;
233
234
  }
234
235
  function isAbsolutePath(value) {
@@ -242,18 +243,18 @@ function normalizeLocalPathForCompare(value) {
242
243
  return /^[A-Za-z]:\//.test(normalized) ? normalized.toLowerCase() : normalized;
243
244
  }
244
245
  function normalizeIgnoreListPath(value) {
245
- let path = devirtualizeReactServerFrame(value);
246
- if (path.startsWith("file://")) try {
247
- path = fileURLToPath(path);
246
+ let normalized = devirtualizeReactServerFrame(value);
247
+ if (normalized.startsWith("file://")) try {
248
+ normalized = fileURLToPath(normalized);
248
249
  } catch {}
249
250
  else try {
250
- const url = new URL(path);
251
- if (url.protocol === "http:" || url.protocol === "https:") path = `${url.pathname}${url.search}`;
251
+ const url = new URL(normalized);
252
+ if (url.protocol === "http:" || url.protocol === "https:") normalized = `${url.pathname}${url.search}`;
252
253
  } catch {}
253
254
  try {
254
- path = decodeURIComponent(path);
255
+ normalized = decodeURIComponent(normalized);
255
256
  } catch {}
256
- return toSlash(path).toLowerCase();
257
+ return toSlash(normalized).toLowerCase();
257
258
  }
258
259
  function isExternalHttpFrame(file, requestHost) {
259
260
  if (!/^https?:\/\//i.test(file) || !requestHost) return false;
@@ -274,10 +275,9 @@ function isIgnoreListedOriginalFrame(file) {
274
275
  function isSourceMapIgnored(sourceMap, sourceIndex) {
275
276
  return sourceMap.ignoreList?.includes(sourceIndex) ?? false;
276
277
  }
277
- async function createStackCodeFrame({ file, line, column, methodName, sourceContent }) {
278
- const source = sourceContent ?? await readSourceFileForCodeFrame(file);
279
- if (!source) return null;
280
- const sourceLines = source.split(/\r\n|\r|\n/);
278
+ function createStackCodeFrame({ file, line, column, methodName, sourceContent }) {
279
+ if (!sourceContent) return null;
280
+ const sourceLines = sourceContent.split(/\r\n|\r|\n/);
281
281
  if (line < 1 || line > sourceLines.length) return null;
282
282
  const start = Math.max(1, line - 2);
283
283
  const end = Math.min(sourceLines.length, line + 3);
@@ -295,14 +295,6 @@ async function createStackCodeFrame({ file, line, column, methodName, sourceCont
295
295
  lines
296
296
  };
297
297
  }
298
- async function readSourceFileForCodeFrame(file) {
299
- if (!file.startsWith("file://")) return null;
300
- try {
301
- return await readFile(fileURLToPath(file), "utf8");
302
- } catch {
303
- return null;
304
- }
305
- }
306
298
  function getMappableClientGeneratedUrl(file, requestHost) {
307
299
  const isAbsoluteHttpUrl = /^https?:\/\//i.test(file);
308
300
  let url;
@@ -335,6 +327,9 @@ async function loadServerSourceMapForLocalPath(server, localPath) {
335
327
  const environment = server.environments[environmentName];
336
328
  if (!environment) continue;
337
329
  try {
330
+ const resolved = await environment.pluginContainer.resolveId(localPath);
331
+ if (!resolved || resolved.external || resolved.id.startsWith("\0")) continue;
332
+ if (!isFileLoadingAllowed(server.config, stripQuery(resolved.id))) continue;
338
333
  const sourceMap = normalizeSourceMapPayload((await environment.transformRequest(localPath))?.map);
339
334
  if (sourceMap) return sourceMap;
340
335
  } catch {}
@@ -1,15 +1,4 @@
1
1
  import React from "react";
2
2
  //#region src/server/document-initial-head.d.ts
3
- /**
4
- * True when `_document` supplies its own `getInitialProps`, rather than
5
- * exposing none or inheriting the shim's default. Comparing against the
6
- * captured `DEFAULT_GET_INITIAL_PROPS` reference is what distinguishes a user
7
- * override from the default — extending the shim's `Document` without
8
- * overriding inherits the same static function.
9
- *
10
- * Callers use this to decide whether the render pipeline owes `_document` the
11
- * full `getInitialProps` contract, since only an override can observe it.
12
- */
13
- export declare function hasUserDocumentGetInitialProps(DocumentComponent: React.ComponentType | null | undefined): boolean;
14
3
  export declare function callDocumentGetInitialProps(DocumentComponent: React.ComponentType | null | undefined, setDocumentInitialHead: ((head: React.ReactNode[]) => void) | undefined): Promise<void>;
15
4
  //#endregion
@@ -45,4 +45,4 @@ async function callDocumentGetInitialProps(DocumentComponent, setDocumentInitial
45
45
  }
46
46
  }
47
47
  //#endregion
48
- export { callDocumentGetInitialProps, hasUserDocumentGetInitialProps };
48
+ export { callDocumentGetInitialProps };
@@ -0,0 +1,5 @@
1
+ //#region src/server/forwarded-middleware-context.d.ts
2
+ export declare function sealForwardedMiddlewareContext(key: string, context: string): string;
3
+ /** Returns the forwarded context JSON, or null unless it carries `key`. */
4
+ export declare function openForwardedMiddlewareContext(value: string | null, key: string | null | undefined): string | null;
5
+ //#endregion
@@ -0,0 +1,22 @@
1
+ import { safeEqual } from "./revalidation-request.js";
2
+ //#region src/server/forwarded-middleware-context.ts
3
+ /**
4
+ * Hybrid app+pages dev runs middleware once in the Pages connect handler and
5
+ * forwards the result to the App Router in x-vinext-mw-ctx. The value is
6
+ * prefixed with a per-dev-server key that only vinext's generated RSC entry
7
+ * knows, so a client-supplied copy can never stand in for running middleware,
8
+ * whichever plugin builds the App Router request first.
9
+ */
10
+ const KEY_SEPARATOR = ".";
11
+ function sealForwardedMiddlewareContext(key, context) {
12
+ return key + KEY_SEPARATOR + context;
13
+ }
14
+ /** Returns the forwarded context JSON, or null unless it carries `key`. */
15
+ function openForwardedMiddlewareContext(value, key) {
16
+ if (value === null || !key) return null;
17
+ const separatorIndex = value.indexOf(KEY_SEPARATOR);
18
+ if (separatorIndex === -1 || !safeEqual(value.slice(0, separatorIndex), key)) return null;
19
+ return value.slice(separatorIndex + 1);
20
+ }
21
+ //#endregion
22
+ export { openForwardedMiddlewareContext, sealForwardedMiddlewareContext };
@@ -48,7 +48,10 @@ export declare const VINEXT_PRERENDER_READINESS_PATH = "/__vinext/prerender/read
48
48
  export declare const VINEXT_PRERENDER_READINESS_HEADER = "X-Vinext-Prerender-Readiness";
49
49
  /** TPR (Tailored Per-Request) revalidation interval in seconds. */
50
50
  export declare const VINEXT_REVALIDATE_HEADER = "x-vinext-revalidate";
51
- /** Actual Pages cache tag regenerated by an authenticated on-demand request. */
51
+ /**
52
+ * Actual Pages cache tag regenerated by an authenticated on-demand request.
53
+ * URI-encoded, because a decoded path can end in whitespace that Headers trims.
54
+ */
52
55
  export declare const VINEXT_REVALIDATED_CACHE_TAG_HEADER = "x-vinext-revalidated-cache-tag";
53
56
  /** Marker on cached ISR entries indicating RSC payload (value "1"). */
54
57
  export declare const VINEXT_RSC_MARKER_HEADER = "x-vinext-rsc";
@@ -58,6 +61,12 @@ export declare const VINEXT_PARAMS_HEADER = "X-Vinext-Params";
58
61
  export declare const VINEXT_DYNAMIC_STALE_TIME_HEADER = "X-Vinext-Dynamic-Stale-Time";
59
62
  /** Marks an RSC body carrying completion metadata after the Flight payload. */
60
63
  export declare const VINEXT_RSC_COMPLETION_METADATA_HEADER = "X-Vinext-Rsc-Completion-Metadata";
64
+ /**
65
+ * Carries the stored status of an App page RSC response whose 401, 403 or 404
66
+ * is its page's notFound(), forbidden() or unauthorized(). Middleware and
67
+ * config headers can't set it, and the request stage strips it.
68
+ */
69
+ export declare const VINEXT_SPECIAL_ERROR_STATUS_HEADER = "x-vinext-special-error-status";
61
70
  /** URL-encoded rendered path and search after middleware/config rewrites. */
62
71
  export declare const VINEXT_RENDERED_PATH_AND_SEARCH_HEADER = "X-Vinext-Rendered-Path-And-Search";
63
72
  /** Prerender-only JSON side channel carrying request cacheLife metadata. */
@@ -66,6 +75,14 @@ export declare const VINEXT_PRERENDER_CACHE_LIFE_HEADER = "x-vinext-prerender-ca
66
75
  export declare const VINEXT_PRERENDER_REWRITTEN_HEADER = "x-vinext-prerender-rewritten";
67
76
  /** Marks a local prerender-server 500 that originated from a thrown render error. */
68
77
  export declare const VINEXT_PRERENDER_RENDER_ERROR_HEADER = "x-vinext-prerender-render-error";
78
+ /**
79
+ * Prerender-only marker: the response's 401, 403, 404 or redirect is its page's
80
+ * notFound(), forbidden(), unauthorized() or redirect(), which escaped the shell.
81
+ * Its value is the JSON of the headers to store: a redirect's own location, or
82
+ * `{}`. Only the prerender server sets it, from the special error the page
83
+ * recorded on its ctx, and it drops one that the response carries.
84
+ */
85
+ export declare const VINEXT_PRERENDER_SPECIAL_ERROR_HEADER = "x-vinext-prerender-special-error";
69
86
  /** Internal marker persisted only inside metadata-route APP_ROUTE cache values. */
70
87
  export declare const VINEXT_METADATA_ROUTE_CACHE_HEADER = "x-vinext-metadata-route-cache";
71
88
  /** Disabled-by-default client hint describing already-held App Router payload entries. */