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,24 +1,28 @@
1
1
  import { VINEXT_PRERENDER_SECRET_HEADER, VINEXT_REVALIDATE_HOST_HEADER } from "../utils/protocol-headers.js";
2
+ import { assetPrefixPathname } from "../utils/asset-prefix.js";
2
3
  import { runWithExecutionContext } from "../shims/request-context.js";
3
4
  import "./server-globals.js";
4
5
  import "./app-rsc-vary.js";
5
6
  import { VINEXT_CACHEABILITY_PROBE_QUERY_PARAM, VINEXT_EXPECTED_WORKER_VERSION_HEADER } from "./headers.js";
6
- import { badRequestResponse, notFoundResponse } from "./http-error-responses.js";
7
- import { isOpenRedirectShaped } from "./open-redirect.js";
8
- import { cloneRequestWithHeaders, filterInternalHeaders } from "./request-pipeline.js";
7
+ import { badRequestResponse } from "./http-error-responses.js";
8
+ import { cloneRequestWithHeaders, filterInternalHeaders, guardProtocolRelativeUrl } from "./request-pipeline.js";
9
9
  import { getExplicitCdnCacheAdapter } from "../shims/cdn-cache-state.js";
10
10
  import { applyCdnResponseIdentityHeaders, validateCdnRequest } from "./cache-control.js";
11
11
  import { registerLazyDataCacheHandler } from "../shims/cache-handler.js";
12
- import { getImageOptimizer, handleConfiguredImageOptimization, isImageOptimizationPath } from "./image-optimization.js";
12
+ import { getImageOptimizer, readImageOptimizationSignal } from "./image-optimization.js";
13
13
  import { consumeFrameworkRequestRoute, traceFrameworkRequest } from "./request-tracing.js";
14
14
  import { createStaticAssetRequest, resolveStaticAssetSignal } from "./worker-utils.js";
15
15
  import { readTrustedPrerenderStateFromHeaders } from "./prerender-route-params.js";
16
+ import { resolveClientBuildFile } from "./client-build-files.js";
16
17
  import { createWorkerRevalidationContext } from "./worker-revalidation-context.js";
17
18
  import { createWorkerPrerenderDiscoveryContext, createWorkerPrerenderReadinessResponse } from "./worker-prerender-discovery.js";
18
- import requestRscHandler, { __ensureHybridPagesApplication, __ensureInstrumentation, __imageAllowedWidths, __imageConfig, __prerenderSecret } from "virtual:vinext-app-request-entry";
19
+ import requestRscHandler, { __assetPrefix, __basePath, __clientBuildFiles, __ensureHybridPagesApplication, __ensureInstrumentation, __imageAllowedWidths, __imageConfig, __prerenderSecret } from "virtual:vinext-app-request-entry";
19
20
  import * as configuredCdnCacheAdapters from "virtual:vinext-cdn-cache-adapter";
20
21
  import { registerConfiguredImageOptimizer } from "virtual:vinext-image-adapters";
21
22
  //#region src/server/app-request-stage-independent-entry.ts
23
+ const clientBuildFiles = new Set(__clientBuildFiles);
24
+ const assetPathPrefix = assetPrefixPathname(__assetPrefix);
25
+ const rejectResponseStage = () => Promise.resolve(new Response(null, { status: 404 }));
22
26
  function handleRequestStage(request, env, ctx, dispatchResponseStage) {
23
27
  const originalRequest = request;
24
28
  const handleStage = async () => {
@@ -43,6 +47,7 @@ async function handleRequest(request, env, platformCtx, dispatchResponseStage, a
43
47
  (await import("virtual:vinext-cache-adapters")).registerConfiguredCacheAdapters(env);
44
48
  });
45
49
  registerConfiguredImageOptimizer(env);
50
+ const requestCtx = ctx;
46
51
  ctx = createWorkerPrerenderDiscoveryContext(ctx, request, __prerenderSecret);
47
52
  const readinessResponse = createWorkerPrerenderReadinessResponse(ctx, request);
48
53
  let didValidateCdnRequest = false;
@@ -70,13 +75,18 @@ async function handleRequest(request, env, platformCtx, dispatchResponseStage, a
70
75
  if (cdnValidationResponse) return cdnValidationResponse;
71
76
  }
72
77
  const url = new URL(request.url);
73
- if (isImageOptimizationPath(url.pathname) && assets && getImageOptimizer()) return handleConfiguredImageOptimization(request, (assetPath) => Promise.resolve(assets.fetch(new Request(new URL(assetPath, request.url)))), __imageAllowedWidths, __imageConfig);
74
- if (isOpenRedirectShaped(url.pathname)) return notFoundResponse();
78
+ const servesImages = Boolean(assets) && getImageOptimizer() !== null;
79
+ const protocolRelativeGuard = guardProtocolRelativeUrl(url.pathname, url.search);
80
+ if (protocolRelativeGuard) return protocolRelativeGuard;
75
81
  try {
76
82
  decodeURIComponent(url.pathname);
77
83
  } catch {
78
84
  return badRequestResponse();
79
85
  }
86
+ if (assets && (request.method === "GET" || request.method === "HEAD")) {
87
+ const clientBuildFile = resolveClientBuildFile(url.pathname, __basePath, clientBuildFiles);
88
+ if (clientBuildFile) return await assets.fetch(createStaticAssetRequest(clientBuildFile, request));
89
+ }
80
90
  const trustedPrerenderState = readTrustedPrerenderStateFromHeaders(request.headers, __prerenderSecret);
81
91
  const filteredHeaders = ctx.isInternalPagesRevalidation ? new Headers(request.headers) : filterInternalHeaders(request.headers);
82
92
  filteredHeaders.delete(VINEXT_PRERENDER_SECRET_HEADER);
@@ -94,8 +104,18 @@ async function handleRequest(request, env, platformCtx, dispatchResponseStage, a
94
104
  };
95
105
  const handle = () => requestRscHandler(request, ctx, trackedDispatchResponseStage, probeMode, ctx.isPrerenderPathDiscovery === true, trustedPrerenderState);
96
106
  let response = await runWithExecutionContext(ctx, handle);
97
- if (assets) {
98
- const assetResponse = await resolveStaticAssetSignal(response, { fetchAsset: (path) => Promise.resolve(assets.fetch(createStaticAssetRequest(path, request))) });
107
+ const imageSignal = servesImages ? readImageOptimizationSignal(response) : null;
108
+ if (imageSignal && assets) {
109
+ const { fetchSignalledPublicFile, serveWorkerImageOptimization } = await import("./worker-image-optimization.js");
110
+ response = await serveWorkerImageOptimization(request, imageSignal, __imageAllowedWidths, __imageConfig, {
111
+ assets,
112
+ basePath: __basePath,
113
+ assetPathPrefix,
114
+ clientBuildFiles,
115
+ fetchPublicFile: async (sourceRequest) => fetchSignalledPublicFile(await runWithExecutionContext(requestCtx, () => requestRscHandler(sourceRequest, requestCtx, rejectResponseStage, null, false, null)), sourceRequest, assets)
116
+ });
117
+ } else if (assets) {
118
+ const assetResponse = await resolveStaticAssetSignal(response, { fetchAsset: (path, requestHeaders) => Promise.resolve(assets.fetch(createStaticAssetRequest(path, request, requestHeaders))) });
99
119
  if (assetResponse) response = assetResponse;
100
120
  }
101
121
  if (probeMode && probeRoute && !responseStageDispatched) {
@@ -3,6 +3,8 @@
3
3
  export declare function markFrameworkLinkHeaders(headers: Headers, linkHeader: string | string[] | null | undefined): void;
4
4
  /** Whether the response carries renderer-owned Link values that config may prepend to. */
5
5
  export declare function hasFrameworkLinkHeaders(headers: Headers): boolean;
6
+ /** The renderer-owned part of the response's Link header, without middleware's. */
7
+ export declare function getFrameworkLinkHeader(headers: Headers): string | null;
6
8
  /** Mark Link values returned by an Edge route handler after config and middleware. */
7
9
  export declare function markEdgeRouteHandlerLinkHeaders(headers: Headers, linkHeader: string | null | undefined): void;
8
10
  /** Whether config must precede a later framework or Edge-handler Link value. */
@@ -1,17 +1,22 @@
1
1
  import { preserveFullyBufferedBodyMetadata } from "./fully-buffered-response.js";
2
2
  import "../shims/unified-request-context.js";
3
3
  //#region src/server/app-response-header-provenance.ts
4
- const frameworkLinkHeaders = /* @__PURE__ */ new WeakSet();
4
+ const frameworkLinkHeaders = /* @__PURE__ */ new WeakMap();
5
5
  const edgeRouteHandlerLinkHeaders = /* @__PURE__ */ new WeakSet();
6
6
  const APP_RESPONSE_STAGE_LINK_PROVENANCE_HEADER = "x-vinext-app-stage-post-config-link";
7
7
  /** Mark response headers whose Link value was emitted by the App page renderer. */
8
8
  function markFrameworkLinkHeaders(headers, linkHeader) {
9
- if (linkHeader && (typeof linkHeader === "string" || linkHeader.length > 0)) frameworkLinkHeaders.add(headers);
9
+ const value = Array.isArray(linkHeader) ? linkHeader.join(", ") : linkHeader;
10
+ if (value) frameworkLinkHeaders.set(headers, value);
10
11
  }
11
12
  /** Whether the response carries renderer-owned Link values that config may prepend to. */
12
13
  function hasFrameworkLinkHeaders(headers) {
13
14
  return frameworkLinkHeaders.has(headers);
14
15
  }
16
+ /** The renderer-owned part of the response's Link header, without middleware's. */
17
+ function getFrameworkLinkHeader(headers) {
18
+ return frameworkLinkHeaders.get(headers) ?? null;
19
+ }
15
20
  /** Mark Link values returned by an Edge route handler after config and middleware. */
16
21
  function markEdgeRouteHandlerLinkHeaders(headers, linkHeader) {
17
22
  if (linkHeader) edgeRouteHandlerLinkHeaders.add(headers);
@@ -22,7 +27,8 @@ function hasPostConfigLinkHeaders(headers) {
22
27
  }
23
28
  /** Preserve Link provenance when a response wrapper reconstructs a Response. */
24
29
  function copyLinkHeaderProvenance(source, target) {
25
- if (frameworkLinkHeaders.has(source)) frameworkLinkHeaders.add(target);
30
+ const frameworkLink = frameworkLinkHeaders.get(source);
31
+ if (frameworkLink !== void 0) frameworkLinkHeaders.set(target, frameworkLink);
26
32
  if (edgeRouteHandlerLinkHeaders.has(source)) edgeRouteHandlerLinkHeaders.add(target);
27
33
  }
28
34
  /** Serialize otherwise process-local Link provenance across a response-stage transport. */
@@ -56,4 +62,4 @@ function consumeResponseStageLinkProvenance(response) {
56
62
  };
57
63
  }
58
64
  //#endregion
59
- export { consumeResponseStageLinkProvenance, copyLinkHeaderProvenance, hasFrameworkLinkHeaders, hasPostConfigLinkHeaders, markEdgeRouteHandlerLinkHeaders, markFrameworkLinkHeaders, serializeResponseStageLinkProvenance };
65
+ export { consumeResponseStageLinkProvenance, copyLinkHeaderProvenance, getFrameworkLinkHeader, hasFrameworkLinkHeaders, hasPostConfigLinkHeaders, markEdgeRouteHandlerLinkHeaders, markFrameworkLinkHeaders, serializeResponseStageLinkProvenance };
@@ -1,8 +1,11 @@
1
1
  import { createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
2
2
  import { runWithExecutionContext } from "../shims/request-context.js";
3
+ import { runInWorkStoreScope } from "../shims/internal/work-store-scope.js";
3
4
  import { serializeStaticFileSignalForTransport } from "./static-file-signal.js";
5
+ import { attachRequestCfMetadata } from "./request-pipeline.js";
4
6
  import { validateCdnRequest } from "./cache-control.js";
5
7
  import { ensureFetchPatch } from "../shims/fetch-cache.js";
8
+ import { serializeImageOptimizationSignalForTransport } from "./image-optimization.js";
6
9
  import { serializeResponseStageLinkProvenance } from "./app-response-header-provenance.js";
7
10
  import { attachFrameworkRequestError, attachFrameworkRequestRoute, captureFrameworkRequestRoute, clearFrameworkRequestError } from "./request-tracing.js";
8
11
  import { isAppWorkerResponseStageProps } from "./app-worker-stages.js";
@@ -26,10 +29,11 @@ async function invokeCacheFunction(invocation, env, platformCtx, dispatchRequest
26
29
  executionContext,
27
30
  rootParams: invocation.rootParams
28
31
  });
29
- await runWithRequestContext(context, () => invokeRegisteredCacheFunction(invocation, loadServerAction));
32
+ await runWithRequestContext(context, () => runInWorkStoreScope(() => invokeRegisteredCacheFunction(invocation, loadServerAction)));
30
33
  }
31
34
  async function handleResponseStage(request, env, platformCtx, props, dispatchRequestStage, options = { cache: "bypass" }) {
32
35
  if (!isAppWorkerResponseStageProps(props)) return new Response("Invalid vinext App response stage", { status: 400 });
36
+ if (props.kind === "app-full-request" && props.headRequest) request = attachRequestCfMetadata(new Request(request, { method: "HEAD" }), request);
33
37
  if (props.requestOrigin !== new URL(request.url).origin) return new Response("Invalid vinext App response stage", { status: 400 });
34
38
  const currentBuildId = process.env.__VINEXT_BUILD_ID ?? null;
35
39
  if (props.buildId !== currentBuildId) return new Response("Incompatible vinext App response stage", { status: 409 });
@@ -41,6 +45,10 @@ async function handleResponseStage(request, env, platformCtx, props, dispatchReq
41
45
  ...ctx,
42
46
  isPrerenderPathDiscovery: true
43
47
  };
48
+ else if (props.kind === "hybrid-pages" && options.regeneratesStoredEntry === true) ctx = {
49
+ ...ctx,
50
+ isStoredEntryRegeneration: true
51
+ };
44
52
  return withResponseStageCacheability({
45
53
  buildId: process.env.__VINEXT_BUILD_ID,
46
54
  cache: options.cache,
@@ -76,7 +84,7 @@ async function handleResponseStage(request, env, platformCtx, props, dispatchReq
76
84
  failure = error;
77
85
  result = new Response("Internal Server Error", { status: 500 });
78
86
  }
79
- const serialized = serializeStaticFileSignalForTransport(result, props.staticFileSignalToken);
87
+ const serialized = serializeImageOptimizationSignalForTransport(serializeStaticFileSignalForTransport(result, props.staticFileSignalToken), props.staticFileSignalToken);
80
88
  return attachFrameworkRequestRoute(failed ? attachFrameworkRequestError(serialized, failure) : clearFrameworkRequestError(serialized), route);
81
89
  }
82
90
  const render = () => rscHandler.handleResponseStage(request, cacheabilityContext, props, options);
@@ -19,6 +19,7 @@ type ReadAppRouteHandlerCacheOptions = {
19
19
  handlerFn: AppRouteHandlerFunction;
20
20
  i18n?: NextI18nConfig | null;
21
21
  trailingSlash?: boolean;
22
+ skipTrailingSlashRedirect?: boolean;
22
23
  isAutoHead: boolean;
23
24
  appendResponseLink?: boolean;
24
25
  isrDebug?: AppRouteDebugLogger;
@@ -49,6 +49,7 @@ async function readAppRouteHandlerCacheResponse(options) {
49
49
  handlerFn: options.handlerFn,
50
50
  i18n: options.i18n,
51
51
  trailingSlash: options.trailingSlash,
52
+ skipTrailingSlashRedirect: options.skipTrailingSlashRedirect,
52
53
  markDynamicUsage: options.markDynamicUsage,
53
54
  params: options.params === null ? null : makeThenableParams(options.params),
54
55
  request: new Request(options.requestUrl, { method: "GET" }),
@@ -31,6 +31,7 @@ type DispatchAppRouteHandlerOptions = {
31
31
  isrRouteKey: (pathname: string) => string;
32
32
  isrSet: RouteHandlerCacheSetter;
33
33
  trailingSlash?: boolean;
34
+ skipTrailingSlashRedirect?: boolean;
34
35
  middlewareContext: RouteHandlerMiddlewareContext;
35
36
  middlewareRequestHeaders?: Headers | null;
36
37
  /**
@@ -1,6 +1,7 @@
1
1
  import { closeAfterResponse, createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
2
2
  import "../utils/protocol-headers.js";
3
3
  import { getRequestExecutionContext } from "../shims/request-context.js";
4
+ import { runInWorkStoreScope } from "../shims/internal/work-store-scope.js";
4
5
  import { reportRequestError } from "./instrumentation.js";
5
6
  import { beginRouteCacheability, getRouteCacheabilityDynamicReason } from "../shims/cacheability-classification.js";
6
7
  import { applyCdnResponseBuildIdentityHeaders } from "./cache-control.js";
@@ -9,12 +10,12 @@ import { markDynamicUsage } from "../shims/internal/headers-state.js";
9
10
  import { consumeDynamicUsage, getActiveDraftModeState, getAndClearPendingCookies, getDraftModeCookieHeader, isDraftModeRequest, setHeadersAccessPhase } from "../shims/headers.js";
10
11
  import { _drainPendingRevalidations } from "../shims/cache-request-state.js";
11
12
  import { ensureFetchPatch, getCollectedFetchTags, setCurrentFetchCacheMode, setCurrentFetchRevalidate, setCurrentFetchSoftTags, setCurrentForceDynamicFetchDefault } from "../shims/fetch-cache.js";
13
+ import { resolveAppRouteHandlerFetchCacheMode } from "./app-segment-config.js";
12
14
  import { setNavigationContext } from "../shims/navigation-context-state.js";
13
15
  import { makeThenableParams } from "../shims/thenable-params.js";
14
16
  import { traceResponseStart } from "./response-start-tracing.js";
15
17
  import { buildPageCacheTags } from "./implicit-tags.js";
16
18
  import { applyRouteHandlerMiddlewareContext, finalizeRouteHandlerResponse } from "./app-route-handler-response.js";
17
- import { resolveAppRouteHandlerFetchCacheMode } from "./app-segment-config.js";
18
19
  import "../shims/navigation.js";
19
20
  import { isKnownDynamicAppRoute, isValidHTTPMethod } from "./app-route-handler-runtime.js";
20
21
  import { getAppRouteHandlerRevalidateSeconds, hasAppRouteHandlerDefaultExport, hasNonStaticAppRouteHandlerMethods, resolveAppRouteHandlerMethod, shouldReadAppRouteHandlerCache } from "./app-route-handler-policy.js";
@@ -41,7 +42,7 @@ async function runInRouteHandlerRevalidationContext(options, renderFn) {
41
42
  executionContext: getRequestExecutionContext(),
42
43
  unstableCacheRevalidation: "foreground"
43
44
  });
44
- const revalidation = runWithRequestContext(requestContext, async () => {
45
+ const revalidation = runWithRequestContext(requestContext, () => runInWorkStoreScope(async () => {
45
46
  ensureFetchPatch();
46
47
  setCurrentFetchSoftTags(buildRouteHandlerPageCacheTags(options.cleanPathname, [], options.routeSegments));
47
48
  setCurrentFetchCacheMode(options.fetchCacheMode);
@@ -52,7 +53,7 @@ async function runInRouteHandlerRevalidationContext(options, renderFn) {
52
53
  } finally {
53
54
  await _drainPendingRevalidations();
54
55
  }
55
- });
56
+ }));
56
57
  try {
57
58
  await revalidation;
58
59
  } finally {
@@ -122,6 +123,7 @@ async function dispatchAppRouteHandlerImpl(options) {
122
123
  handlerFn: resolvedHandlerFn,
123
124
  i18n: options.i18n,
124
125
  trailingSlash: options.trailingSlash,
126
+ skipTrailingSlashRedirect: options.skipTrailingSlashRedirect,
125
127
  isAutoHead,
126
128
  appendResponseLink,
127
129
  isrDebug: options.isrDebug,
@@ -184,6 +186,7 @@ async function dispatchAppRouteHandlerImpl(options) {
184
186
  handlerFn: resolvedHandlerFn,
185
187
  i18n: options.i18n,
186
188
  trailingSlash: options.trailingSlash,
189
+ skipTrailingSlashRedirect: options.skipTrailingSlashRedirect,
187
190
  isAutoHead,
188
191
  initialDraftModeCookie,
189
192
  isDraftMode,
@@ -47,6 +47,7 @@ type RunAppRouteHandlerOptions = {
47
47
  i18n?: NextI18nConfig | null;
48
48
  isDraftMode?: boolean;
49
49
  trailingSlash?: boolean;
50
+ skipTrailingSlashRedirect?: boolean;
50
51
  markDynamicUsage: MarkAppRouteDynamicUsageFn;
51
52
  middlewareRequestHeaders?: Headers | null;
52
53
  /**
@@ -112,6 +112,7 @@ async function runAppRouteHandler(options) {
112
112
  basePath: options.basePath,
113
113
  i18n: options.i18n,
114
114
  trailingSlash: options.trailingSlash,
115
+ skipTrailingSlashRedirect: options.skipTrailingSlashRedirect,
115
116
  middlewareHeaders: options.middlewareRequestHeaders,
116
117
  onDynamicAccess() {
117
118
  options.markDynamicUsage();
@@ -17,13 +17,16 @@ export declare function buildRouteHandlerAllowHeader(exportedMethods: readonly s
17
17
  export declare function isKnownDynamicAppRoute(pattern: string): boolean;
18
18
  export declare function markKnownDynamicAppRoute(pattern: string): void;
19
19
  type RequestDynamicAccess = "request.headers" | "request.cookies" | "request.cf" | "request.ip" | "request.geo" | "request.url" | "request.body" | "request.blob" | "request.bytes" | "request.json" | "request.text" | "request.arrayBuffer" | "request.formData";
20
- type NextUrlDynamicAccess = "nextUrl.search" | "nextUrl.searchParams" | "nextUrl.url" | "nextUrl.href" | "nextUrl.toJSON" | "nextUrl.toString" | "nextUrl.origin";
20
+ type NextUrlDynamicAccess = "nextUrl.search" | "nextUrl.searchParams" | "nextUrl.url" | "nextUrl.href" | "nextUrl.toJSON" | "nextUrl.toString" | "nextUrl.origin" | HostDerivedNextUrlDynamicAccess;
21
+ type HostDerivedNextUrlDynamicAccess = "nextUrl.protocol" | "nextUrl.username" | "nextUrl.password" | "nextUrl.host" | "nextUrl.hostname" | "nextUrl.port" | DomainLocaleNextUrlDynamicAccess;
22
+ type DomainLocaleNextUrlDynamicAccess = "nextUrl.locale" | "nextUrl.defaultLocale" | "nextUrl.domainLocale";
21
23
  type AppRouteDynamicRequestAccess = RequestDynamicAccess | NextUrlDynamicAccess;
22
24
  type AppRouteRequestMode = "auto" | "force-static" | "error";
23
25
  type TrackedAppRouteRequestOptions = {
24
26
  basePath?: string;
25
27
  i18n?: NextI18nConfig | null;
26
28
  trailingSlash?: boolean;
29
+ skipTrailingSlashRedirect?: boolean;
27
30
  middlewareHeaders?: Headers | null;
28
31
  onDynamicAccess?: (access: AppRouteDynamicRequestAccess) => void;
29
32
  requestMode?: AppRouteRequestMode;
@@ -64,11 +64,12 @@ function getRequestProperty(target, prop, receiver, builtInProperties) {
64
64
  return bindMethodIfNeeded(Reflect.get(target, prop, bindingTarget), bindingTarget);
65
65
  }
66
66
  function buildNextConfig(options) {
67
- if (!options.basePath && !options.i18n && !options.trailingSlash) return null;
67
+ if (!options.basePath && !options.i18n && !options.trailingSlash && !options.skipTrailingSlashRedirect) return null;
68
68
  return {
69
69
  basePath: options.basePath,
70
70
  i18n: options.i18n ?? void 0,
71
- trailingSlash: options.trailingSlash
71
+ trailingSlash: options.trailingSlash,
72
+ skipTrailingSlashRedirect: options.skipTrailingSlashRedirect
72
73
  };
73
74
  }
74
75
  function createForceStaticNextRequest(input, nextConfig) {
@@ -128,21 +129,41 @@ function createTrackedAppRouteRequest(request, options = {}) {
128
129
  didAccessDynamicRequest = true;
129
130
  options.onDynamicAccess?.(access);
130
131
  };
132
+ const isNextDynamicNextUrlProperty = (prop) => {
133
+ switch (prop) {
134
+ case "search":
135
+ case "searchParams":
136
+ case "url":
137
+ case "href":
138
+ case "toJSON":
139
+ case "toString":
140
+ case "origin": return true;
141
+ default: return false;
142
+ }
143
+ };
144
+ const hasI18nDomains = (options.i18n?.domains?.length ?? 0) > 0;
145
+ const isHostDerivedNextUrlProperty = (prop) => {
146
+ switch (prop) {
147
+ case "protocol":
148
+ case "username":
149
+ case "password":
150
+ case "host":
151
+ case "hostname":
152
+ case "port": return true;
153
+ case "locale":
154
+ case "defaultLocale":
155
+ case "domainLocale": return hasI18nDomains;
156
+ default: return false;
157
+ }
158
+ };
131
159
  const wrapNextUrl = (nextUrl) => {
132
160
  return new Proxy(nextUrl, { get(target, prop) {
133
- switch (prop) {
134
- case "search":
135
- case "searchParams":
136
- case "url":
137
- case "href":
138
- case "toJSON":
139
- case "toString":
140
- case "origin":
141
- markDynamicAccess(`nextUrl.${String(prop)}`);
142
- return bindMethodIfNeeded(Reflect.get(target, prop, target), target);
143
- case "clone": return () => wrapNextUrl(target.clone());
144
- default: return bindMethodIfNeeded(Reflect.get(target, prop, target), target);
161
+ if (isNextDynamicNextUrlProperty(prop) || isHostDerivedNextUrlProperty(prop)) {
162
+ markDynamicAccess(`nextUrl.${String(prop)}`);
163
+ return bindMethodIfNeeded(Reflect.get(target, prop, target), target);
145
164
  }
165
+ if (prop === "clone") return () => wrapNextUrl(target.clone());
166
+ return bindMethodIfNeeded(Reflect.get(target, prop, target), target);
146
167
  } });
147
168
  };
148
169
  const wrapForceStaticNextUrl = (nextUrl) => {
@@ -165,18 +186,18 @@ function createTrackedAppRouteRequest(request, options = {}) {
165
186
  throw new Error(options.staticGenerationErrorMessage?.(expression) ?? `Route handler with \`dynamic = "error"\` used ${expression}.`);
166
187
  };
167
188
  const wrapRequireStaticNextUrl = (nextUrl) => {
189
+ let staticNextUrl = null;
168
190
  return new Proxy(nextUrl, { get(target, prop) {
169
- switch (prop) {
170
- case "search":
171
- case "searchParams":
172
- case "url":
173
- case "href":
174
- case "toJSON":
175
- case "toString":
176
- case "origin": return throwStaticGenerationError(`nextUrl.${String(prop)}`);
177
- case "clone": return () => wrapRequireStaticNextUrl(target.clone());
178
- default: return bindMethodIfNeeded(Reflect.get(target, prop, target), target);
191
+ if (isNextDynamicNextUrlProperty(prop)) return throwStaticGenerationError(`nextUrl.${String(prop)}`);
192
+ if (isHostDerivedNextUrlProperty(prop)) {
193
+ if (staticNextUrl === null) {
194
+ staticNextUrl = target.clone();
195
+ staticNextUrl.href = cleanStaticUrl(target.href);
196
+ }
197
+ return Reflect.get(staticNextUrl, prop, staticNextUrl);
179
198
  }
199
+ if (prop === "clone") return () => wrapRequireStaticNextUrl(target.clone());
200
+ return bindMethodIfNeeded(Reflect.get(target, prop, target), target);
180
201
  } });
181
202
  };
182
203
  const wrapRequest = (rawInput) => {
@@ -5,21 +5,22 @@ import "./server-globals.js";
5
5
  import "./app-rsc-vary.js";
6
6
  import { VINEXT_CACHEABILITY_PROBE_QUERY_PARAM } from "./headers.js";
7
7
  import { badRequestResponse, notFoundResponse, notFoundStaticAssetResponse } from "./http-error-responses.js";
8
- import { isOpenRedirectShaped } from "./open-redirect.js";
9
- import { cloneRequestWithHeaders, filterInternalHeaders } from "./request-pipeline.js";
8
+ import { cloneRequestWithHeaders, filterInternalHeaders, guardProtocolRelativeUrl } from "./request-pipeline.js";
10
9
  import { getCdnCacheAdapter } from "../shims/cdn-cache.js";
11
10
  import { applyCdnResponseIdentityHeaders, validateCdnRequest } from "./cache-control.js";
12
- import { getImageOptimizer, handleConfiguredImageOptimization, isImageOptimizationPath } from "./image-optimization.js";
11
+ import { getImageOptimizer, readImageOptimizationSignal } from "./image-optimization.js";
13
12
  import { traceFrameworkRequest } from "./request-tracing.js";
14
13
  import { createStaticAssetRequest, resolveStaticAssetSignal } from "./worker-utils.js";
15
14
  import { readTrustedPrerenderRouteParams, serializePrerenderRouteParamsHeader } from "./prerender-route-params.js";
15
+ import { resolveClientBuildFile } from "./client-build-files.js";
16
16
  import { createWorkerRevalidationContext } from "./worker-revalidation-context.js";
17
17
  import { createWorkerPrerenderDiscoveryContext, createWorkerPrerenderReadinessResponse } from "./worker-prerender-discovery.js";
18
18
  import { registerConfiguredImageOptimizer } from "virtual:vinext-image-adapters";
19
19
  import { registerConfiguredCacheAdapters } from "virtual:vinext-cache-adapters";
20
- import rscHandler, { __assetPrefix, __basePath, __cacheabilityManifest, __ensureHybridPagesApplication, __ensureInstrumentation, __imageAllowedWidths, __imageConfig, __prerenderSecret } from "virtual:vinext-rsc-entry";
20
+ import rscHandler, { __assetPrefix, __basePath, __cacheabilityManifest, __clientBuildFiles, __ensureHybridPagesApplication, __ensureInstrumentation, __imageAllowedWidths, __imageConfig, __prerenderSecret } from "virtual:vinext-rsc-entry";
21
21
  //#region src/server/app-router-entry.ts
22
22
  const __workerBasePath = typeof __basePath === "string" ? __basePath : "";
23
+ const __workerClientBuildFiles = new Set(Array.isArray(__clientBuildFiles) ? __clientBuildFiles : []);
23
24
  const __workerAssetPathPrefix = assetPrefixPathname(typeof __assetPrefix === "string" ? __assetPrefix : "");
24
25
  function isPotentialCompletedAdmissionRequest(request) {
25
26
  if (request.method !== "GET" && request.method !== "HEAD") return false;
@@ -82,13 +83,18 @@ async function handleRequest(request, env, platformCtx) {
82
83
  const cdnValidationResponse = await validateCdnRequest(request);
83
84
  if (cdnValidationResponse) return cdnValidationResponse;
84
85
  const url = new URL(request.url);
85
- if (isImageOptimizationPath(url.pathname) && assets && getImageOptimizer()) return handleConfiguredImageOptimization(request, (assetPath) => Promise.resolve(assets.fetch(new Request(new URL(assetPath, request.url)))), __imageAllowedWidths, __imageConfig);
86
- if (isOpenRedirectShaped(url.pathname)) return notFoundResponse();
86
+ const servesImages = Boolean(assets) && getImageOptimizer() !== null;
87
+ const protocolRelativeGuard = guardProtocolRelativeUrl(url.pathname, url.search);
88
+ if (protocolRelativeGuard) return protocolRelativeGuard;
87
89
  try {
88
90
  decodeURIComponent(url.pathname);
89
91
  } catch {
90
92
  return badRequestResponse();
91
93
  }
94
+ if (assets && (request.method === "GET" || request.method === "HEAD")) {
95
+ const clientBuildFile = resolveClientBuildFile(url.pathname, __workerBasePath, __workerClientBuildFiles);
96
+ if (clientBuildFile) return await assets.fetch(createStaticAssetRequest(clientBuildFile, request));
97
+ }
92
98
  const missingBuildAsset = isNextStaticPath(url.pathname, __workerBasePath, __workerAssetPathPrefix);
93
99
  {
94
100
  const trustedPrerenderRouteParams = ctx.hostRuntime === "node" ? readTrustedPrerenderRouteParams(request) : null;
@@ -103,8 +109,21 @@ async function handleRequest(request, env, platformCtx) {
103
109
  const result = await (ctx ? runWithExecutionContext(ctx, handleFn) : handleFn());
104
110
  if (result instanceof Response) {
105
111
  let response = result;
106
- if (assets) {
107
- const assetResponse = await resolveStaticAssetSignal(response, { fetchAsset: (path) => Promise.resolve(assets.fetch(createStaticAssetRequest(path, request))) });
112
+ const imageSignal = servesImages ? readImageOptimizationSignal(response) : null;
113
+ if (imageSignal && assets) {
114
+ const { fetchSignalledPublicFile, serveWorkerImageOptimization } = await import("./worker-image-optimization.js");
115
+ response = await serveWorkerImageOptimization(request, imageSignal, __imageAllowedWidths, __imageConfig, {
116
+ assets,
117
+ basePath: __workerBasePath,
118
+ assetPathPrefix: __workerAssetPathPrefix,
119
+ clientBuildFiles: __workerClientBuildFiles,
120
+ fetchPublicFile: async (sourceRequest) => {
121
+ const sourceResult = await runWithExecutionContext(requestCtx, () => rscHandler(sourceRequest, requestCtx));
122
+ return sourceResult instanceof Response ? fetchSignalledPublicFile(sourceResult, sourceRequest, assets) : null;
123
+ }
124
+ });
125
+ } else if (assets) {
126
+ const assetResponse = await resolveStaticAssetSignal(response, { fetchAsset: (path, requestHeaders) => Promise.resolve(assets.fetch(createStaticAssetRequest(path, request, requestHeaders))) });
108
127
  if (assetResponse) response = assetResponse;
109
128
  }
110
129
  return finalizeCacheabilityResponse ? finalizeCacheabilityResponse(response, ctx) : response;
@@ -1,7 +1,7 @@
1
1
  import { NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERCEPTION_ID_HEADER, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_RSC_STATE_FINGERPRINT_HEADER, VINEXT_RSC_VARY_HEADER } from "./app-rsc-vary.js";
2
2
  import { NEXTJS_DEPLOYMENT_ID_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER } from "./headers.js";
3
- import { fnv1a64 } from "../utils/hash.js";
4
3
  import { APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL, parseAppRscRenderMode } from "./app-rsc-render-mode.js";
4
+ import { fnv1a64 } from "../utils/hash.js";
5
5
  import { applyDeploymentIdHeader, getDeploymentId } from "../utils/deployment-id.js";
6
6
  import { createAppRscStateFingerprint } from "./app-rsc-state-fingerprint.js";
7
7
  //#region src/server/app-rsc-cache-busting.ts
@@ -1,6 +1,7 @@
1
1
  import { isNavigationSignalError } from "../utils/navigation-signal.js";
2
2
  import { resolveAppPageSpecialError } from "./app-page-execution.js";
3
3
  import { isAppRenderAbortError } from "./app-render-abort-error.js";
4
+ import { getProperError } from "./proper-error.js";
4
5
  //#region src/server/app-rsc-errors.ts
5
6
  const ORIGINAL_SERVER_ERROR = Symbol.for("vinext.originalServerError");
6
7
  function hasDigest(error) {
@@ -23,11 +24,14 @@ function getDigestForWellKnownError(error) {
23
24
  const digest = String(error.digest);
24
25
  if (isNavigationSignalError(error) || digest === BAILOUT_TO_CSR_DIGEST || digest === DYNAMIC_SERVER_USAGE_DIGEST) return digest;
25
26
  }
26
- function getThrownValueMessage(error) {
27
- return error instanceof Error ? error.message : String(error);
28
- }
29
- function getThrownValueStack(error) {
30
- return error instanceof Error ? error.stack || "" : "";
27
+ /**
28
+ * Next.js hashes a thrown string as is, and other values once they are an
29
+ * Error (packages/next/src/server/app-render/create-error-handler.tsx).
30
+ */
31
+ function getThrownValueDigest(error) {
32
+ if (typeof error === "string") return errorDigest(error);
33
+ const properError = getProperError(error);
34
+ return errorDigest(properError.message + (properError.stack || ""));
31
35
  }
32
36
  /**
33
37
  * djb2 hash matching Next.js's string-hash package for RSC error digests.
@@ -41,7 +45,7 @@ function sanitizeErrorForClient(error, nodeEnv = process.env.NODE_ENV) {
41
45
  if (resolveAppPageSpecialError(error)) return error;
42
46
  if (nodeEnv !== "production") return error;
43
47
  const sanitized = /* @__PURE__ */ new Error("An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.");
44
- sanitized.digest = hasDigest(error) ? String(error.digest) : errorDigest(getThrownValueMessage(error) + getThrownValueStack(error));
48
+ sanitized.digest = hasDigest(error) ? String(error.digest) : getThrownValueDigest(error);
45
49
  Object.defineProperty(sanitized, ORIGINAL_SERVER_ERROR, {
46
50
  configurable: false,
47
51
  enumerable: false,
@@ -55,6 +59,7 @@ function createRscOnErrorHandler(options) {
55
59
  return (error) => {
56
60
  const nodeEnv = options.nodeEnv ?? process.env.NODE_ENV;
57
61
  const reportableError = error && typeof error === "object" && ORIGINAL_SERVER_ERROR in error ? Reflect.get(error, ORIGINAL_SERVER_ERROR) : error;
62
+ if (typeof reportableError === "string") return hasDigest(error) ? String(error.digest) : errorDigest(reportableError);
58
63
  if (isAppRenderAbortError(error) || isAppRenderAbortError(reportableError)) return;
59
64
  const wellKnownDigest = getDigestForWellKnownError(error) ?? getDigestForWellKnownError(reportableError);
60
65
  if (wellKnownDigest !== void 0) return wellKnownDigest;
@@ -62,22 +67,21 @@ function createRscOnErrorHandler(options) {
62
67
  console.error("[vinext] RSC serialization error: a non-plain object was passed from a Server Component to a Client Component.\n\nCommon causes:\n * Passing a module namespace (import * as X) directly as a prop.\n Unlike Next.js (webpack), Vite produces real ESM module namespace objects\n which are not serializable. Fix: pass individual values instead,\n e.g. <Comp value={module.value} />\n * Passing a class instance (new Foo()) as a prop.\n Fix: convert to a plain object, e.g. { id: foo.id, name: foo.name }\n * Passing a Date, Map, or Set. Use .toISOString(), [...map.entries()], etc.\n * Passing Object.create(null). Use { ...obj } to restore a prototype.\n\nOriginal error:", error.message);
63
68
  return;
64
69
  }
65
- if (options.requestInfo && options.errorContext && error) options.reportRequestError(reportableError, options.requestInfo, options.errorContext);
70
+ const thrownHasDigest = hasDigest(error);
71
+ const properError = getProperError(reportableError);
72
+ const digest = thrownHasDigest ? String(error.digest) : errorDigest(properError.message + (properError.stack || ""));
73
+ if (!hasDigest(properError) && (properError !== reportableError || options.attachDigest !== false)) try {
74
+ Object.assign(properError, { digest });
75
+ } catch {}
76
+ if (options.requestInfo && options.errorContext) options.reportRequestError(properError, options.requestInfo, options.errorContext);
66
77
  if (process.env.VINEXT_PRERENDER === "1" && error) {
67
78
  if (!loggedPrerenderErrors?.has(reportableError)) {
68
79
  (loggedPrerenderErrors ??= /* @__PURE__ */ new Set()).add(reportableError);
69
80
  const route = options.requestInfo?.path ?? options.errorContext?.routePath ?? "<unknown>";
70
81
  console.error(`[vinext] Error prerendering route ${JSON.stringify(route)}:`, reportableError);
71
82
  }
72
- } else if (nodeEnv !== "production" && error && !hasDigest(error)) console.error("[vinext] Server render error:", reportableError);
73
- if (hasDigest(error)) return String(error.digest);
74
- if (error) {
75
- const digest = errorDigest(getThrownValueMessage(error) + getThrownValueStack(error));
76
- if (options.attachDigest !== false && error instanceof Error) try {
77
- Object.assign(error, { digest });
78
- } catch {}
79
- return digest;
80
- }
83
+ } else if (nodeEnv !== "production" && !thrownHasDigest) console.error("[vinext] Server render error:", properError);
84
+ return digest;
81
85
  };
82
86
  }
83
87
  //#endregion
@@ -85,6 +85,8 @@ type DispatchMatchedPageOptions<TRoute> = {
85
85
  scriptNonce?: string;
86
86
  searchParams: URLSearchParams;
87
87
  renderMode: AppRscRenderMode;
88
+ /** Render the document whole before its first byte (a regeneration or warm-up). */
89
+ renderWholeDocument?: boolean;
88
90
  };
89
91
  type DispatchMatchedRouteHandlerOptions<TRoute> = {
90
92
  /**
@@ -202,6 +204,11 @@ export type CreateAppRscHandlerOptions<TRoute extends AppRscHandlerRoute> = {
202
204
  fallback: NextRewrite[];
203
205
  };
204
206
  draftModeSecret: string;
207
+ /**
208
+ * Dev-only key the hybrid Pages handler seals x-vinext-mw-ctx with. Null
209
+ * outside `vite dev`, so a forwarded middleware context is never honored.
210
+ */
211
+ devForwardedMiddlewareContextKey?: string | null;
205
212
  dispatchMatchedPage: (options: DispatchMatchedPageOptions<TRoute>) => Promise<Response>;
206
213
  dispatchMatchedRouteHandler: (options: DispatchMatchedRouteHandlerOptions<TRoute>) => Promise<Response>;
207
214
  /**
@@ -235,6 +242,8 @@ export type CreateAppRscHandlerOptions<TRoute extends AppRscHandlerRoute> = {
235
242
  matchInterceptRoute?: (pathname: string, sourcePathname: string, interceptionId?: string | null) => AppRscRouteMatch<TRoute> | null;
236
243
  matchRoute: (pathname: string) => AppRscRouteMatch<TRoute> | null;
237
244
  matchRequestRoute?: (pathname: string) => AppRscRouteMatch<TRoute> | null;
245
+ /** `matchRequestRoute` without its decoded static page substitution. */
246
+ matchRawRequestRoute?: (pathname: string) => AppRscRouteMatch<TRoute> | null;
238
247
  runMiddleware?: (options: RunAppMiddlewareOptions) => Promise<ApplyAppMiddlewareResult>;
239
248
  publicFiles: ReadonlySet<string>;
240
249
  prefetchInlining?: PrefetchInliningConfig;
@@ -242,6 +251,8 @@ export type CreateAppRscHandlerOptions<TRoute extends AppRscHandlerRoute> = {
242
251
  renderPagesFallback?: (options: RenderPagesFallbackOptions) => Promise<Response | null>;
243
252
  rootParamNamesByPattern?: RootParamNamesMap;
244
253
  setNavigationContext: (context: NavigationContextValue) => void;
254
+ /** next.config `skipTrailingSlashRedirect`: serve both slash forms without a 308. */
255
+ skipTrailingSlashRedirect?: boolean;
245
256
  staticParamsMap: StaticParamsMap;
246
257
  trailingSlash: boolean;
247
258
  validateDevRequestOrigin?: (request: Request) => Response | null;