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,9 +1,10 @@
1
1
  //#region src/server/socket-error-backstop.ts
2
2
  /**
3
- * Process-level backstop for peer-disconnect errors that escape
4
- * per-connection / per-request error guards.
3
+ * Process-level backstop for errors that escape per-connection /
4
+ * per-request error guards.
5
5
  *
6
- * Three real call sites in vinext that hit this:
6
+ * Three real call sites in vinext that hit this with peer-disconnect
7
+ * errors:
7
8
  * - `fromWeb(fetch().body).pipe(res)` in proxyExternalRewriteNode.
8
9
  * - Streaming surfaces inside `@vitejs/plugin-rsc` with their own
9
10
  * pipe topology (destinations aren't inbound connection sockets).
@@ -14,13 +15,25 @@
14
15
  * inside a `nextTick` callback. The throw escapes to
15
16
  * `uncaughtException`, where this listener filters it.
16
17
  *
17
- * Filters strictly on peer-disconnect codes (ECONNRESET / EPIPE /
18
- * ECONNABORTED) plus benign static-asset `import()` rejections (see
19
- * `isBenignAssetImportError`), and synchronously re-throws everything
20
- * else, preserving Node's default crash semantics for genuine bugs.
21
- * This is more conservative than Next.js's equivalent
22
- * (`router-server.ts`'s log-only handler), which silently swallows
23
- * every uncaught — vinext keeps real bugs surfacing.
18
+ * Always absorbs benign static-asset `import()` rejections (see
19
+ * `isBenignAssetImportError`). Outside prerender it also silently
20
+ * absorbs peer-disconnect codes (ECONNRESET / EPIPE / ECONNABORTED) and
21
+ * Node's cancelled-request-body enqueue race (see
22
+ * `isCancelledRequestBodyEnqueueError`). Everything else depends on the
23
+ * phase:
24
+ *
25
+ * - **Running server** (`vite dev`, `vinext start`, standalone
26
+ * `server.js`): logged and absorbed, matching the log-only
27
+ * `uncaughtException` / `unhandledRejection` handlers that Next.js's
28
+ * `router-server.ts` installs for both `next dev` and `next start`.
29
+ * App code may legitimately leave a rejection unhandled for a few
30
+ * ticks (Next.js's documented "Preloading data" pattern,
31
+ * fire-and-forget calls), and request input can often choose whether
32
+ * it rejects, so crashing would let one anonymous request take down
33
+ * the whole process. The dev server's `configureServer` hook and
34
+ * `startProdServer()` opt in via `{ runningServer: true }`.
35
+ * - **Build and prerender**: synchronously re-thrown, preserving
36
+ * Node's default crash semantics.
24
37
  *
25
38
  * **Installed at module load.** Earlier iterations tried to gate
26
39
  * install via Vite's `config()` hook (`command === "serve"`) so it
@@ -66,11 +79,12 @@
66
79
  * top of every user's `vite.config.ts`, so vinext's listener registers
67
80
  * before most user / tooling listeners (Sentry, OpenTelemetry,
68
81
  * structured logging). For peer-disconnect codes the early-return is
69
- * fine. For non-peer-disconnect errors the synchronous re-throw still
70
- * crashes the process with the original stack, but listeners
71
- * registered after vinext don't observe the event. Users who need
72
- * crash-reporter visibility for non-peer-disconnect errors must
73
- * register their handler before importing vinext.
82
+ * fine, and on a running production server every other error is
83
+ * logged without throwing, so later listeners still observe it. In
84
+ * the re-throw phases the synchronous re-throw still crashes the
85
+ * process with the original stack, but listeners registered after
86
+ * vinext don't observe the event. Users who need crash-reporter
87
+ * visibility there must register their handler before importing vinext.
74
88
  *
75
89
  * **Symbol.for caveat.** `Symbol.for("vinext.socketErrorBackstop")`
76
90
  * is process-global, so if two different vinext versions are loaded
@@ -81,6 +95,7 @@
81
95
  * time the listener absorbs an error.
82
96
  */
83
97
  const SOCKET_BACKSTOP_FLAG = Symbol.for("vinext.socketErrorBackstop");
98
+ const RUNNING_SERVER_FLAG = Symbol.for("vinext.socketErrorBackstop.runningServer");
84
99
  /**
85
100
  * Pure predicate: returns the peer-disconnect code when `err` carries
86
101
  * one of `ECONNRESET` / `EPIPE` / `ECONNABORTED`, otherwise `undefined`.
@@ -153,6 +168,24 @@ function isBenignAssetImportError(err) {
153
168
  return false;
154
169
  }
155
170
  /**
171
+ * Pure predicate: returns `true` when `err` is Node's
172
+ * `Readable.toWeb()` adapter enqueueing into a request body stream that was
173
+ * already cancelled. `pull()` calls `req.resume()`, which schedules `flow()`
174
+ * on `nextTick`; if the body is cancelled before that tick runs, `flow()`
175
+ * still emits the chunks already buffered in `req` and the adapter's
176
+ * `onData` throws inside the `nextTick` callback. srvx (used by
177
+ * `@vitejs/plugin-rsc` in dev) builds `request.body` this way, so any
178
+ * cancelled request body, e.g. an oversized Server Action, can crash the
179
+ * dev server. Node main drops that data instead (`if (wasCanceled) return;`
180
+ * in `onData`), so absorbing it matches upstream behaviour. Exported for
181
+ * unit testing in isolation.
182
+ */
183
+ function isCancelledRequestBodyEnqueueError(err) {
184
+ if (err === null || typeof err !== "object") return false;
185
+ const { code, message, stack } = err;
186
+ return code === "ERR_INVALID_STATE" && typeof message === "string" && message.includes("Controller is already closed") && typeof stack === "string" && /\.onData \(node:internal\/webstreams\/adapters:\d+/.test(stack);
187
+ }
188
+ /**
156
189
  * Test-only: returns whether the backstop has been installed in this
157
190
  * process. Used by the unit test to assert idempotent install via the
158
191
  * Symbol.for guard. Not part of the public API.
@@ -160,8 +193,15 @@ function isBenignAssetImportError(err) {
160
193
  function isSocketErrorBackstopInstalled() {
161
194
  return Boolean(process[SOCKET_BACKSTOP_FLAG]);
162
195
  }
163
- function installSocketErrorBackstop() {
196
+ /**
197
+ * Installs the backstop once per process. Pass `{ runningServer: true }`
198
+ * from a long-lived production server to log, rather than re-throw,
199
+ * errors outside the absorbed set. The flag is process-global and sticky,
200
+ * so it also applies when `index.ts` installed the listeners first.
201
+ */
202
+ function installSocketErrorBackstop(options = {}) {
164
203
  const proc = process;
204
+ if (options.runningServer) proc[RUNNING_SERVER_FLAG] = true;
165
205
  if (proc[SOCKET_BACKSTOP_FLAG]) return;
166
206
  if (process.env.VITEST === "true" || process.env.NODE_ENV === "test") return;
167
207
  proc[SOCKET_BACKSTOP_FLAG] = true;
@@ -183,6 +223,14 @@ function installSocketErrorBackstop() {
183
223
  if (debug) console.warn(`[vinext] absorbed uncaughtException ${code}`);
184
224
  return;
185
225
  }
226
+ if (isCancelledRequestBodyEnqueueError(err)) {
227
+ if (debug) console.warn("[vinext] absorbed uncaughtException ERR_INVALID_STATE (cancelled request body)");
228
+ return;
229
+ }
230
+ if (proc[RUNNING_SERVER_FLAG]) {
231
+ console.error("[vinext] uncaughtException:", err);
232
+ return;
233
+ }
186
234
  throw err;
187
235
  });
188
236
  process.on("unhandledRejection", (reason) => {
@@ -193,8 +241,12 @@ function installSocketErrorBackstop() {
193
241
  if (debug) console.warn(`[vinext] absorbed unhandledRejection ${code}`);
194
242
  return;
195
243
  }
244
+ if (proc[RUNNING_SERVER_FLAG]) {
245
+ console.error("[vinext] unhandledRejection:", reason);
246
+ return;
247
+ }
196
248
  throw reason;
197
249
  });
198
250
  }
199
251
  //#endregion
200
- export { installSocketErrorBackstop, isBenignAssetImportError, isSocketErrorBackstopInstalled, peerDisconnectCode };
252
+ export { installSocketErrorBackstop, isBenignAssetImportError, isCancelledRequestBodyEnqueueError, isSocketErrorBackstopInstalled, peerDisconnectCode };
@@ -3,14 +3,25 @@ export type StaticFileSignalContext = {
3
3
  headers: Headers | null;
4
4
  status: number | null;
5
5
  };
6
- /** Create the only response shape that host runtimes may resolve as an asset. */
7
- export declare function createStaticFileSignal(pathname: string, context: StaticFileSignalContext): Response;
6
+ /**
7
+ * Create the only response shape that host runtimes may resolve as an asset.
8
+ * `requestHeaders` are the request headers after middleware's overrides, which
9
+ * the asset fetch uses in place of the original request's headers.
10
+ */
11
+ export declare function createStaticFileSignal(pathname: string, context: StaticFileSignalContext, requestHeaders?: Headers | null): Response;
8
12
  /** Whether this response was created by vinext's public-file router. */
9
13
  export declare function isStaticFileSignal(response: Response): boolean;
10
14
  /** Return the encoded asset pathname only for a framework-created signal. */
11
15
  export declare function readStaticFileSignal(response: Response): string | null;
12
- /** Encode a framework-authenticated signal for a standards-only stage transport. */
16
+ /** Return the post-middleware request headers a framework-created signal carries. */
17
+ export declare function readStaticFileSignalRequestHeaders(response: Response): Headers | null;
18
+ /**
19
+ * Encode a framework-authenticated signal for a standards-only stage transport.
20
+ * Post-middleware request headers travel in the body, which has no platform
21
+ * size limit, rather than in a response header. Their marker header carries
22
+ * the real status, since the body needs a status that allows one.
23
+ */
13
24
  export declare function serializeStaticFileSignalForTransport(response: Response, token: string): Response;
14
25
  /** Restore and consume a signal returned by the trusted response-stage wrapper. */
15
- export declare function restoreStaticFileSignalFromTransport(response: Response, token: string): Response;
26
+ export declare function restoreStaticFileSignalFromTransport(response: Response, token: string): Promise<Response>;
16
27
  //#endregion
@@ -1,6 +1,8 @@
1
1
  //#region src/server/static-file-signal.ts
2
2
  const STATIC_FILE_SIGNAL = Symbol.for("vinext.static-file-signal");
3
+ const STATIC_FILE_REQUEST_HEADERS = Symbol.for("vinext.static-file-request-headers");
3
4
  const STATIC_FILE_SIGNAL_TRANSPORT_HEADER = "x-vinext-stage-static-file";
5
+ const STATIC_FILE_REQUEST_HEADERS_TRANSPORT_HEADER = "x-vinext-stage-static-file-request-headers";
4
6
  const STATIC_FILE_REPRESENTATION_HEADERS = [
5
7
  "content-encoding",
6
8
  "content-length",
@@ -14,17 +16,19 @@ const STATIC_FILE_REPRESENTATION_HEADERS = [
14
16
  * before the host runtime can fetch the asset. Application response headers
15
17
  * remain ordinary metadata and cannot alter framework control flow.
16
18
  */
17
- function markStaticFileSignal(response, pathname) {
18
- return markEncodedStaticFileSignal(response, encodeURIComponent(pathname));
19
+ function markStaticFileSignal(response, pathname, requestHeaders) {
20
+ return markEncodedStaticFileSignal(response, encodeURIComponent(pathname), requestHeaders);
19
21
  }
20
- function markEncodedStaticFileSignal(response, encodedPathname) {
22
+ function markEncodedStaticFileSignal(response, encodedPathname, requestHeaders) {
21
23
  Object.defineProperty(response, STATIC_FILE_SIGNAL, { value: encodedPathname });
24
+ if (requestHeaders) Object.defineProperty(response, STATIC_FILE_REQUEST_HEADERS, { value: requestHeaders });
22
25
  return response;
23
26
  }
24
27
  function withoutTransportHeader(response) {
25
- if (!response.headers.has(STATIC_FILE_SIGNAL_TRANSPORT_HEADER)) return response;
28
+ if (!response.headers.has(STATIC_FILE_SIGNAL_TRANSPORT_HEADER) && !response.headers.has(STATIC_FILE_REQUEST_HEADERS_TRANSPORT_HEADER)) return response;
26
29
  const headers = new Headers(response.headers);
27
30
  headers.delete(STATIC_FILE_SIGNAL_TRANSPORT_HEADER);
31
+ headers.delete(STATIC_FILE_REQUEST_HEADERS_TRANSPORT_HEADER);
28
32
  if (response.status < 200 || response.status > 599) return response;
29
33
  const body = response.status === 204 || response.status === 205 || response.status === 304 ? null : response.body;
30
34
  return new Response(body, {
@@ -33,14 +37,18 @@ function withoutTransportHeader(response) {
33
37
  statusText: response.statusText
34
38
  });
35
39
  }
36
- /** Create the only response shape that host runtimes may resolve as an asset. */
37
- function createStaticFileSignal(pathname, context) {
40
+ /**
41
+ * Create the only response shape that host runtimes may resolve as an asset.
42
+ * `requestHeaders` are the request headers after middleware's overrides, which
43
+ * the asset fetch uses in place of the original request's headers.
44
+ */
45
+ function createStaticFileSignal(pathname, context, requestHeaders = null) {
38
46
  const headers = new Headers();
39
47
  if (context.headers) for (const [key, value] of context.headers) headers.append(key, value);
40
48
  return markStaticFileSignal(new Response(null, {
41
49
  status: context.status ?? 200,
42
50
  headers
43
- }), pathname);
51
+ }), pathname, requestHeaders);
44
52
  }
45
53
  /** Whether this response was created by vinext's public-file router. */
46
54
  function isStaticFileSignal(response) {
@@ -51,22 +59,40 @@ function readStaticFileSignal(response) {
51
59
  const signal = Reflect.get(response, STATIC_FILE_SIGNAL);
52
60
  return typeof signal === "string" ? signal : null;
53
61
  }
54
- /** Encode a framework-authenticated signal for a standards-only stage transport. */
62
+ /** Return the post-middleware request headers a framework-created signal carries. */
63
+ function readStaticFileSignalRequestHeaders(response) {
64
+ const headers = Reflect.get(response, STATIC_FILE_REQUEST_HEADERS);
65
+ return headers instanceof Headers ? headers : null;
66
+ }
67
+ function isHeaderEntries(value) {
68
+ return Array.isArray(value) && value.every((entry) => Array.isArray(entry) && entry.length === 2 && typeof entry[0] === "string" && typeof entry[1] === "string");
69
+ }
70
+ /**
71
+ * Encode a framework-authenticated signal for a standards-only stage transport.
72
+ * Post-middleware request headers travel in the body, which has no platform
73
+ * size limit, rather than in a response header. Their marker header carries
74
+ * the real status, since the body needs a status that allows one.
75
+ */
55
76
  function serializeStaticFileSignalForTransport(response, token) {
56
77
  const signal = readStaticFileSignal(response);
57
78
  if (signal === null) return response;
58
79
  const headers = new Headers(response.headers);
59
80
  for (const name of STATIC_FILE_REPRESENTATION_HEADERS) headers.delete(name);
81
+ headers.delete(STATIC_FILE_REQUEST_HEADERS_TRANSPORT_HEADER);
60
82
  headers.set(STATIC_FILE_SIGNAL_TRANSPORT_HEADER, `${token}:${signal}`);
61
- return new Response(null, {
83
+ const requestHeaders = readStaticFileSignalRequestHeaders(response);
84
+ if (!requestHeaders) return new Response(null, {
62
85
  headers,
63
86
  status: response.status,
64
87
  statusText: response.statusText
65
88
  });
89
+ headers.set(STATIC_FILE_REQUEST_HEADERS_TRANSPORT_HEADER, `${token}:${response.status}`);
90
+ return new Response(JSON.stringify([...requestHeaders]), { headers });
66
91
  }
67
92
  /** Restore and consume a signal returned by the trusted response-stage wrapper. */
68
- function restoreStaticFileSignalFromTransport(response, token) {
93
+ async function restoreStaticFileSignalFromTransport(response, token) {
69
94
  const transported = response.headers.get(STATIC_FILE_SIGNAL_TRANSPORT_HEADER);
95
+ const requestHeadersMarker = response.headers.get(STATIC_FILE_REQUEST_HEADERS_TRANSPORT_HEADER);
70
96
  const cleaned = withoutTransportHeader(response);
71
97
  const prefix = `${token}:`;
72
98
  if (transported === null || !transported.startsWith(prefix)) return cleaned;
@@ -76,7 +102,15 @@ function restoreStaticFileSignalFromTransport(response, token) {
76
102
  } catch {
77
103
  return cleaned;
78
104
  }
79
- return markEncodedStaticFileSignal(cleaned, encodedPathname);
105
+ if (requestHeadersMarker === null) return markEncodedStaticFileSignal(cleaned, encodedPathname, null);
106
+ const status = Number(requestHeadersMarker.startsWith(prefix) ? requestHeadersMarker.slice(prefix.length) : NaN);
107
+ if (!Number.isInteger(status) || status < 200 || status > 599) return cleaned;
108
+ const entries = JSON.parse(await cleaned.text());
109
+ if (!isHeaderEntries(entries)) throw new Error("Invalid static-file request headers from the response stage");
110
+ return markEncodedStaticFileSignal(new Response(null, {
111
+ headers: cleaned.headers,
112
+ status
113
+ }), encodedPathname, new Headers(entries));
80
114
  }
81
115
  //#endregion
82
- export { createStaticFileSignal, isStaticFileSignal, readStaticFileSignal, restoreStaticFileSignalFromTransport, serializeStaticFileSignalForTransport };
116
+ export { createStaticFileSignal, isStaticFileSignal, readStaticFileSignal, readStaticFileSignalRequestHeaders, restoreStaticFileSignalFromTransport, serializeStaticFileSignalForTransport };
@@ -0,0 +1,34 @@
1
+ import { VinextAssetFetcher } from "./multi-stage.js";
2
+ import { ImageConfig, ImageOptimizationSignal } from "./image-optimization.js";
3
+ //#region src/server/worker-image-optimization.d.ts
4
+ export type WorkerImageSourceOptions = {
5
+ assets: VinextAssetFetcher;
6
+ basePath: string;
7
+ assetPathPrefix: string;
8
+ clientBuildFiles: ReadonlySet<string>;
9
+ /**
10
+ * Run `sourceRequest`, a GET without the caller's headers, through the
11
+ * application pipeline and return the public file it selects with a 2xx
12
+ * outcome, or null.
13
+ */
14
+ fetchPublicFile(sourceRequest: Request): Promise<Response | null>;
15
+ };
16
+ /**
17
+ * Fetch a local image source. Build output is fetched from the asset binding,
18
+ * which serves it before the Worker and its middleware. Any other source is
19
+ * served only when the application pipeline selects a public file for it.
20
+ */
21
+ export declare function fetchWorkerImageSource(imageUrl: string, request: Request, options: WorkerImageSourceOptions): Promise<Response>;
22
+ /**
23
+ * Return the public file a framework static-file signal selects, provided the
24
+ * pipeline answered with a body-bearing 2xx outcome. The file is fetched with middleware's
25
+ * request header overrides, as resolveStaticAssetSignal fetches it.
26
+ */
27
+ export declare function fetchSignalledPublicFile(response: Response, sourceRequest: Request, assets: VinextAssetFetcher): Promise<Response> | null;
28
+ /**
29
+ * Serve the App Router image endpoint once the request handler admitted it
30
+ * through middleware and rewrites. Middleware's response headers are sent with
31
+ * the image, as Next.js does.
32
+ */
33
+ export declare function serveWorkerImageOptimization(request: Request, signal: ImageOptimizationSignal, allowedWidths: number[] | undefined, imageConfig: ImageConfig | undefined, options: WorkerImageSourceOptions): Promise<Response>;
34
+ //#endregion
@@ -0,0 +1,86 @@
1
+ import { isNextStaticPath } from "../utils/asset-prefix.js";
2
+ import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
3
+ import { VINEXT_PRERENDER_SPECIAL_ERROR_HEADER } from "./headers.js";
4
+ import { normalizePath } from "./normalize-path.js";
5
+ import { readStaticFileSignal, readStaticFileSignalRequestHeaders } from "./static-file-signal.js";
6
+ import { attachRequestCfMetadata, cloneRequestWithUrl } from "./request-pipeline.js";
7
+ import { handleConfiguredImageOptimization, invalidImageSourceResponse, isImageSourceBodyStatus } from "./image-optimization.js";
8
+ import { createStaticAssetRequest, mergeHeaders } from "./worker-utils.js";
9
+ import { resolveClientBuildFile } from "./client-build-files.js";
10
+ //#region src/server/worker-image-optimization.ts
11
+ /**
12
+ * Image optimization for Worker hosts. A local source is fetched as an
13
+ * anonymous direct request would receive it, like Next.js' fetchInternalImage
14
+ * (packages/next/src/server/image-optimizer.ts), so middleware that denies or
15
+ * redirects a direct request also denies the optimizer.
16
+ */
17
+ const OMITTED_MIDDLEWARE_HEADERS = /* @__PURE__ */ new Set([
18
+ "content-encoding",
19
+ "content-length",
20
+ "content-range",
21
+ "content-type",
22
+ "transfer-encoding",
23
+ VINEXT_PRERENDER_SPECIAL_ERROR_HEADER
24
+ ]);
25
+ function cancelResponseBody(response) {
26
+ const body = response.body;
27
+ if (!body || body.locked) return;
28
+ body.cancel().catch(() => {});
29
+ }
30
+ /**
31
+ * Fetch a local image source. Build output is fetched from the asset binding,
32
+ * which serves it before the Worker and its middleware. Any other source is
33
+ * served only when the application pipeline selects a public file for it.
34
+ */
35
+ async function fetchWorkerImageSource(imageUrl, request, options) {
36
+ const sourceUrl = new URL(imageUrl, request.url);
37
+ let sourcePathname;
38
+ try {
39
+ sourcePathname = normalizePath(normalizePathnameForRouteMatchStrict(sourceUrl.pathname));
40
+ } catch {
41
+ return invalidImageSourceResponse();
42
+ }
43
+ const buildAssetPath = isNextStaticPath(sourcePathname, options.basePath, options.assetPathPrefix) ? sourcePathname : resolveClientBuildFile(sourceUrl.pathname, options.basePath, options.clientBuildFiles);
44
+ if (buildAssetPath !== null) return options.assets.fetch(new Request(new URL(buildAssetPath, request.url)));
45
+ const sourceResponse = await options.fetchPublicFile(attachRequestCfMetadata(new Request(sourceUrl, { signal: request.signal }), request));
46
+ if (sourceResponse && isImageSourceBodyStatus(sourceResponse.status)) return sourceResponse;
47
+ if (sourceResponse) cancelResponseBody(sourceResponse);
48
+ return invalidImageSourceResponse();
49
+ }
50
+ /**
51
+ * Return the public file a framework static-file signal selects, provided the
52
+ * pipeline answered with a body-bearing 2xx outcome. The file is fetched with middleware's
53
+ * request header overrides, as resolveStaticAssetSignal fetches it.
54
+ */
55
+ function fetchSignalledPublicFile(response, sourceRequest, assets) {
56
+ const signal = isImageSourceBodyStatus(response.status) ? readStaticFileSignal(response) : null;
57
+ const requestHeaders = readStaticFileSignalRequestHeaders(response);
58
+ cancelResponseBody(response);
59
+ if (signal === null) return null;
60
+ let assetPath = signal;
61
+ try {
62
+ assetPath = decodeURIComponent(signal);
63
+ } catch {}
64
+ return Promise.resolve(assets.fetch(createStaticAssetRequest(assetPath, sourceRequest, requestHeaders)));
65
+ }
66
+ /**
67
+ * Serve the App Router image endpoint once the request handler admitted it
68
+ * through middleware and rewrites. Middleware's response headers are sent with
69
+ * the image, as Next.js does.
70
+ */
71
+ async function serveWorkerImageOptimization(request, signal, allowedWidths, imageConfig, options) {
72
+ const imageUrl = new URL(request.url);
73
+ imageUrl.search = signal.search;
74
+ const imageRequest = cloneRequestWithUrl(request, imageUrl.href);
75
+ const response = await handleConfiguredImageOptimization(signal.requestHeaders ? new Request(imageRequest, { headers: signal.requestHeaders }) : imageRequest, (sourceUrl) => fetchWorkerImageSource(sourceUrl, imageRequest, options), allowedWidths, imageConfig);
76
+ const middlewareHeaders = {};
77
+ signal.middlewareHeaders.forEach((value, name) => {
78
+ if (name === "set-cookie" || OMITTED_MIDDLEWARE_HEADERS.has(name)) return;
79
+ middlewareHeaders[name] = value;
80
+ });
81
+ const cookies = signal.middlewareHeaders.getSetCookie();
82
+ if (cookies.length > 0) middlewareHeaders["set-cookie"] = cookies;
83
+ return mergeHeaders(response, middlewareHeaders);
84
+ }
85
+ //#endregion
86
+ export { fetchSignalledPublicFile, fetchWorkerImageSource, serveWorkerImageOptimization };
@@ -1,7 +1,7 @@
1
1
  import { VinextResponseStageCacheability, VinextResponseStageTransport } from "./multi-stage.js";
2
2
  import { PagesRenderOptions } from "./pages-request-pipeline.js";
3
3
  //#region src/server/worker-stages.d.ts
4
- export declare const PAGES_RESPONSE_STAGE_PROTOCOL_VERSION = 4;
4
+ export declare const PAGES_RESPONSE_STAGE_PROTOCOL_VERSION = 5;
5
5
  export declare const PAGES_RESPONSE_STAGE_POLICY_OWNER_HEADER = "x-vinext-pages-response-stage-policy-owner";
6
6
  export type PagesResponseStagePolicyOwner = "request-time" | "static";
7
7
  type PagesResponseStageEnvelope = {
@@ -1,5 +1,5 @@
1
1
  //#region src/server/worker-stages.ts
2
- const PAGES_RESPONSE_STAGE_PROTOCOL_VERSION = 4;
2
+ const PAGES_RESPONSE_STAGE_PROTOCOL_VERSION = 5;
3
3
  const PAGES_RESPONSE_STAGE_POLICY_OWNER_HEADER = "x-vinext-pages-response-stage-policy-owner";
4
4
  function isSerializedHeaders(value) {
5
5
  return Array.isArray(value) && value.every((entry) => Array.isArray(entry) && entry.length === 2 && typeof entry[0] === "string" && typeof entry[1] === "string");
@@ -12,7 +12,7 @@ function isResponseStageCacheability(value) {
12
12
  function isPagesResponseStageProps(value) {
13
13
  if (!value || typeof value !== "object") return false;
14
14
  const props = value;
15
- if (props.protocolVersion !== 4 || props.buildId !== null && typeof props.buildId !== "string" || !isResponseStageCacheability(props.cacheability) || typeof props.requestHost !== "string" || props.requestHost.length === 0 || props.stagedHeaders !== null && !isSerializedHeaders(props.stagedHeaders)) return false;
15
+ if (props.protocolVersion !== 5 || props.buildId !== null && typeof props.buildId !== "string" || !isResponseStageCacheability(props.cacheability) || typeof props.requestHost !== "string" || props.requestHost.length === 0 || props.stagedHeaders !== null && !isSerializedHeaders(props.stagedHeaders)) return false;
16
16
  if (props.kind === "pages-api") return typeof props.apiUrl === "string";
17
17
  if (props.kind === "pages-prerender-discovery") return true;
18
18
  if (props.kind !== "pages-page" || typeof props.resolvedUrl !== "string") return false;
@@ -2,8 +2,13 @@
2
2
  export declare function finalizeMissingStaticAssetResponse(response: Response, missingBuildAsset: boolean): Response;
3
3
  export declare function mergeHeaders(response: Response, extraHeaders: Record<string, string | string[]>, statusOverride?: number): Response;
4
4
  export declare function resolveStaticAssetSignal(signalResponse: Response, options: {
5
- fetchAsset(path: string): Promise<Response>;
5
+ /** `requestHeaders` are the post-middleware request headers, when middleware set any. */
6
+ fetchAsset(path: string, requestHeaders: Headers | null): Promise<Response>;
6
7
  }): Promise<Response | null>;
7
- /** Retarget a Worker asset request without dropping its conditional/range fields. */
8
- export declare function createStaticAssetRequest(assetPath: string, sourceRequest: Request): Request;
8
+ /**
9
+ * Retarget a Worker asset request without dropping its conditional/range
10
+ * fields. `headers` replaces the source request's headers with middleware's
11
+ * overrides, so a removed `Range` or replaced validator reaches the asset fetch.
12
+ */
13
+ export declare function createStaticAssetRequest(assetPath: string, sourceRequest: Request, headers?: Headers | null): Request;
9
14
  //#endregion
@@ -1,5 +1,5 @@
1
1
  import { notFoundStaticAssetResponse } from "./http-error-responses.js";
2
- import { readStaticFileSignal } from "./static-file-signal.js";
2
+ import { readStaticFileSignal, readStaticFileSignalRequestHeaders } from "./static-file-signal.js";
3
3
  //#region src/server/worker-utils.ts
4
4
  /**
5
5
  * Shared utilities for Cloudflare Worker entries.
@@ -47,7 +47,7 @@ function buildHeaderRecord(response, omitNames = []) {
47
47
  return headers;
48
48
  }
49
49
  function mergeHeaders(response, extraHeaders, statusOverride) {
50
- const status = statusOverride ?? response.status;
50
+ const status = response.status === 304 ? 304 : statusOverride ?? response.status;
51
51
  const merged = new Headers();
52
52
  for (const [k, v] of Object.entries(extraHeaders)) {
53
53
  if (isContentLengthHeader(k)) continue;
@@ -97,17 +97,22 @@ async function resolveStaticAssetSignal(signalResponse, options) {
97
97
  "content-type",
98
98
  "transfer-encoding"
99
99
  ]);
100
+ const requestHeaders = readStaticFileSignalRequestHeaders(signalResponse);
100
101
  cancelResponseBody(signalResponse);
101
- const assetResponse = await options.fetchAsset(assetPath);
102
+ const assetResponse = await options.fetchAsset(assetPath, requestHeaders);
102
103
  return mergeHeaders(assetResponse, extraHeaders, assetResponse.ok && assetResponse.status !== 206 && signalResponse.status !== 200 ? signalResponse.status : void 0);
103
104
  }
104
- /** Retarget a Worker asset request without dropping its conditional/range fields. */
105
- function createStaticAssetRequest(assetPath, sourceRequest) {
105
+ /**
106
+ * Retarget a Worker asset request without dropping its conditional/range
107
+ * fields. `headers` replaces the source request's headers with middleware's
108
+ * overrides, so a removed `Range` or replaced validator reaches the asset fetch.
109
+ */
110
+ function createStaticAssetRequest(assetPath, sourceRequest, headers = null) {
106
111
  const assetUrl = new URL(assetPath, sourceRequest.url);
107
- if (sourceRequest.method === "GET" || sourceRequest.method === "HEAD") return new Request(assetUrl, sourceRequest);
112
+ if (sourceRequest.method === "GET" || sourceRequest.method === "HEAD") return headers ? new Request(new Request(assetUrl, sourceRequest), { headers }) : new Request(assetUrl, sourceRequest);
108
113
  return new Request(assetUrl, {
109
114
  method: sourceRequest.method,
110
- headers: sourceRequest.headers
115
+ headers: headers ?? sourceRequest.headers
111
116
  });
112
117
  }
113
118
  //#endregion
@@ -1,4 +1,5 @@
1
1
  "use client";
2
+ import { disableSmoothScrollDuringRouteTransition } from "./disable-smooth-scroll.js";
2
3
  import { decodeHashFragment } from "./hash-scroll.js";
3
4
  import { consumeAppRouterScrollIntent, getPendingAppRouterScrollIntent, markAppRouterScrollIntentHeadHoisted } from "./app-router-scroll-state.js";
4
5
  import * as React$1 from "react";
@@ -110,7 +111,9 @@ var AppRouterScrollTargetInner = class extends React$1.Component {
110
111
  const target = next.element;
111
112
  const consumed = consumeAppRouterScrollIntent(intent, this.props.commitId);
112
113
  if (consumed === null) return;
113
- scrollToElement(target, consumed.hash);
114
+ disableSmoothScrollDuringRouteTransition(() => {
115
+ scrollToElement(target, consumed.hash);
116
+ });
114
117
  target.focus();
115
118
  };
116
119
  componentDidMount() {
@@ -0,0 +1,5 @@
1
+ import React from "react";
2
+ //#region src/shims/app-router-tree-context.d.ts
3
+ export declare const AppRouterTreeContext: React.Context<boolean> | null;
4
+ export declare function withAppRouterTree(children: React.ReactElement): React.ReactElement;
5
+ //#endregion
@@ -0,0 +1,27 @@
1
+ import React from "react";
2
+ //#region src/shims/app-router-tree-context.ts
3
+ /**
4
+ * Marks an App Router server render tree. The App Router SSR entry provides
5
+ * `true` at its root; every other server tree (Pages Router pages,
6
+ * `pages/_document`, ad-hoc react-dom/server renders) reads the `false`
7
+ * default. Lets shared shims such as next/dynamic apply App Router semantics
8
+ * only where Next.js does. In the browser, `window.next.appDir` (installed
9
+ * when the App Router browser entry loads) identifies App Router documents.
10
+ *
11
+ * Stored on a global symbol so duplicate module instances share one context,
12
+ * and null in react-server, which has no createContext (RSC is App Router
13
+ * only).
14
+ */
15
+ const APP_ROUTER_TREE_CONTEXT_KEY = Symbol.for("vinext.appRouterTreeContext");
16
+ function getAppRouterTreeContext() {
17
+ if (typeof React.createContext !== "function") return null;
18
+ const globalState = globalThis;
19
+ globalState[APP_ROUTER_TREE_CONTEXT_KEY] ??= React.createContext(false);
20
+ return globalState[APP_ROUTER_TREE_CONTEXT_KEY];
21
+ }
22
+ const AppRouterTreeContext = getAppRouterTreeContext();
23
+ function withAppRouterTree(children) {
24
+ return AppRouterTreeContext ? React.createElement(AppRouterTreeContext.Provider, { value: true }, children) : children;
25
+ }
26
+ //#endregion
27
+ export { AppRouterTreeContext, withAppRouterTree };
@@ -0,0 +1,50 @@
1
+ //#region src/shims/cache-adapter-instantiate.d.ts
2
+ /**
3
+ * Instantiate a declaratively configured cache adapter from its module's
4
+ * default export. The generated `virtual:vinext-cache-adapters` module calls
5
+ * this for both the `cache.data` and `cache.cdn` slots, so every router and
6
+ * runtime (Node.js dev/prod server and Cloudflare Workers) uses the same rule.
7
+ *
8
+ * Contract: the default export must be a function, and it receives one
9
+ * `{ env, options }` argument.
10
+ *
11
+ * - A `class` (class syntax, as Vite and every current toolchain emit it) is
12
+ * invoked with `new`. It is recognised by the source text that
13
+ * `Function.prototype.toString` must return for class syntax, which starts
14
+ * with `class`, on a function that has [[Construct]].
15
+ * - Any other function is called as a factory, with plain-call semantics
16
+ * (`this`, `new.target` and bound receivers are what a call gives them).
17
+ * Existing factories therefore behave exactly as before, whatever their
18
+ * `prototype` looks like (frozen, decorated, or inherited).
19
+ * - A constructor that is not class syntax (an ES5-compiled class, or a
20
+ * bound or Proxy-wrapped class, whose source text is not observable) is
21
+ * structurally indistinguishable from a factory without invoking it, so the
22
+ * module states it explicitly by exporting a factory that constructs it:
23
+ * `export default (args) => new Adapter(args)`.
24
+ *
25
+ * Classification never invokes the export, matches no error messages and
26
+ * never retries, so the export runs exactly once.
27
+ *
28
+ * The produced value must be an adapter (an object or a function, not a
29
+ * Promise) with the slot's required members; anything else throws an error
30
+ * naming what is wrong.
31
+ */
32
+ export type CacheAdapterFactoryArgs = {
33
+ env: unknown;
34
+ options: unknown;
35
+ };
36
+ export type CacheAdapterSlot = "data" | "cdn";
37
+ /**
38
+ * Whether `value` has a [[Construct]] internal method. A Proxy is
39
+ * constructible exactly when its target is; its no-op `construct` trap
40
+ * answers without running the export or reading any of its properties.
41
+ */
42
+ export declare function isConstructor(value: unknown): boolean;
43
+ /**
44
+ * Whether an export is class syntax and must be invoked with `new`. The
45
+ * [[Construct]] check excludes methods named `class`, whose source text
46
+ * also starts with that word.
47
+ */
48
+ export declare function isClassExport(value: unknown): boolean;
49
+ export declare function instantiateCacheAdapter<T>(exported: unknown, args: CacheAdapterFactoryArgs, slot: CacheAdapterSlot): T;
50
+ //#endregion