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
@@ -114,6 +114,49 @@ async function runWithIsolatedDynamicUsage(fn) {
114
114
  };
115
115
  return await headersShimAls.run(childState, () => runInChildState(childState));
116
116
  }
117
+ /**
118
+ * Run a pre-render probe without letting its dynamic API usage classify the
119
+ * request. Next.js has no probe: only the render decides whether a page is
120
+ * dynamic, and the render runs the probed layouts and page again. Returns the
121
+ * probe's own usage and cacheLife for a caller whose probe response replaces
122
+ * the render.
123
+ */
124
+ async function runWithDetachedDynamicUsage(fn) {
125
+ const runInChildState = async (childState, cacheLifeSink) => {
126
+ return {
127
+ result: await fn(),
128
+ cacheLife: cacheLifeSink?.cacheLife ?? null,
129
+ dynamicDetected: childState.dynamicUsageDetected || childState.renderDynamicLatch.dynamic
130
+ };
131
+ };
132
+ if (isInsideUnifiedScope()) {
133
+ let childState = null;
134
+ const cacheLifeSink = { cacheLife: null };
135
+ return await runWithUnifiedStateMutation((context) => {
136
+ context.cacheLifeSink = cacheLifeSink;
137
+ context.dynamicUsageDetected = false;
138
+ context.renderDynamicLatch = createRenderDynamicLatch();
139
+ context.renderRequestApiUsage = /* @__PURE__ */ new Set();
140
+ context.requestCache = /* @__PURE__ */ new WeakMap();
141
+ context.cacheableFetchUrls = /* @__PURE__ */ new Set();
142
+ context.currentRequestTags = [];
143
+ context.dynamicFetchUrls = /* @__PURE__ */ new Set();
144
+ context.requestScopedCacheLife = null;
145
+ context.unstableCacheObservations = /* @__PURE__ */ new Map();
146
+ childState = context;
147
+ }, () => {
148
+ if (!childState) throw new Error("Dynamic usage scope was not initialized");
149
+ return runInChildState(childState, cacheLifeSink);
150
+ });
151
+ }
152
+ const childState = {
153
+ ...getHeadersShimState(),
154
+ dynamicUsageDetected: false,
155
+ renderDynamicLatch: createRenderDynamicLatch(),
156
+ renderRequestApiUsage: /* @__PURE__ */ new Set()
157
+ };
158
+ return await headersShimAls.run(childState, () => runInChildState(childState, null));
159
+ }
117
160
  async function runWithConnectionProbe(fn) {
118
161
  const parentState = getHeadersShimState();
119
162
  const parentInvalidDynamicUsageError = parentState.invalidDynamicUsageError;
@@ -129,8 +172,7 @@ async function runWithConnectionProbe(fn) {
129
172
  if (probe.interrupted) return;
130
173
  probe.interrupted = true;
131
174
  interruptProbe();
132
- },
133
- pending: new Promise(() => {})
175
+ }
134
176
  };
135
177
  const runInChildState = async (childState) => {
136
178
  try {
@@ -141,6 +183,7 @@ async function runWithConnectionProbe(fn) {
141
183
  return await Promise.race([completed, interrupted]);
142
184
  } finally {
143
185
  probe.active = false;
186
+ interruptProbe();
144
187
  childState.connectionProbe = parentState.connectionProbe ?? probe;
145
188
  if (childState.dynamicUsageDetected) parentState.dynamicUsageDetected = true;
146
189
  if (childState.invalidDynamicUsageError !== parentInvalidDynamicUsageError && parentState.invalidDynamicUsageError === parentInvalidDynamicUsageError) parentState.invalidDynamicUsageError = childState.invalidDynamicUsageError;
@@ -167,7 +210,7 @@ function suspendConnectionProbe() {
167
210
  const probe = getHeadersShimState().connectionProbe;
168
211
  if (!probe?.active) return null;
169
212
  probe.interrupt();
170
- return probe.pending;
213
+ return new Promise(() => {});
171
214
  }
172
215
  function peekRenderRequestApiUsage() {
173
216
  return [...getHeadersShimState().renderRequestApiUsage].sort();
@@ -834,4 +877,4 @@ function serializeMutableCookie(cookie) {
834
877
  });
835
878
  }
836
879
  //#endregion
837
- export { applyEffectiveRequestCookieHeader, applyMiddlewareRequestHeaders, consumeDynamicUsage, consumeInvalidDynamicUsageError, consumeRenderRequestApiUsage, cookies, createRenderDynamicLatch, draftMode, getActiveDraftModeState, getAndClearPendingCookies, getDraftModeCookieHeader, getEffectiveRequestCookieHeader, getHeadersAccessPhase, getHeadersContext, hasDraftModeCookieHeader, hasEffectiveRequestCookieChanges, headers, headersContextFromRequest, isDraftModeEnabled, isDraftModeRequest, isInsideAnyCacheScope, isRenderDynamicLatched, markDynamicUsage, markRenderRequestApiUsage, onRenderDynamicLatched, peekDynamicUsage, peekRenderRequestApiUsage, replaceHeadersContext, restoreDraftModeTransition, runWithConnectionProbe, runWithHeadersContext, runWithIsolatedDynamicUsage, setHeadersAccessPhase, setHeadersContext, suspendConnectionProbe, throwIfInsideCacheScope, throwIfStaticGenerationAccessError };
880
+ export { applyEffectiveRequestCookieHeader, applyMiddlewareRequestHeaders, consumeDynamicUsage, consumeInvalidDynamicUsageError, consumeRenderRequestApiUsage, cookies, createRenderDynamicLatch, draftMode, getActiveDraftModeState, getAndClearPendingCookies, getDraftModeCookieHeader, getEffectiveRequestCookieHeader, getHeadersAccessPhase, getHeadersContext, hasDraftModeCookieHeader, hasEffectiveRequestCookieChanges, headers, headersContextFromRequest, isDraftModeEnabled, isDraftModeRequest, isInsideAnyCacheScope, isRenderDynamicLatched, markDynamicUsage, markRenderRequestApiUsage, onRenderDynamicLatched, peekDynamicUsage, peekRenderRequestApiUsage, replaceHeadersContext, restoreDraftModeTransition, runWithConnectionProbe, runWithDetachedDynamicUsage, runWithHeadersContext, runWithIsolatedDynamicUsage, setHeadersAccessPhase, setHeadersContext, suspendConnectionProbe, throwIfInsideCacheScope, throwIfStaticGenerationAccessError };
@@ -258,6 +258,7 @@ function extractLocalDeploymentId(src) {
258
258
  deploymentId
259
259
  };
260
260
  }
261
+ const __imageEndpoint = `${process.env.__NEXT_ROUTER_BASEPATH ?? ""}/_next/image${process.env.__VINEXT_TRAILING_SLASH === "true" ? "/" : ""}`;
261
262
  /**
262
263
  * Build a `/_next/image` optimization URL.
263
264
  *
@@ -268,7 +269,7 @@ function extractLocalDeploymentId(src) {
268
269
  function imageOptimizationUrl(src, width, quality = 75) {
269
270
  const source = extractLocalDeploymentId(src);
270
271
  const deploymentQuery = source.src.startsWith("/") && source.deploymentId ? `&dpl=${source.deploymentId}` : "";
271
- return `/_next/image?url=${encodeURIComponent(source.src)}&w=${width}&q=${quality}${deploymentQuery}`;
272
+ return `${__imageEndpoint}?url=${encodeURIComponent(source.src)}&w=${width}&q=${quality}${deploymentQuery}`;
272
273
  }
273
274
  function preloadImageResource(input) {
274
275
  if (!input.shouldPreload) return;
@@ -5,8 +5,6 @@
5
5
  * props before a server component is invoked.
6
6
  */
7
7
  export declare const APP_PAGE_USE_CACHE_MARKER = "$$isPage";
8
- export declare function markAppPagePropsForUseCache<T extends object>(props: T): T;
9
- export declare function isMarkedAppPagePropsObject(value: object): boolean;
10
8
  /**
11
9
  * Whether `fn` is a transformed `"use cache"` function, including a bound
12
10
  * one. Like Next.js's `isUseCacheFunction`, this survives `.bind()`: React's
@@ -23,6 +21,8 @@ export declare function isUseCacheFunctionReference(fn: unknown): boolean;
23
21
  * module, or bound.
24
22
  */
25
23
  export declare function withUseCachePageMarker<T extends Record<string, unknown>>(fn: unknown, props: T): T;
24
+ /** Layout components and their metadata resolvers retain framework params too. */
25
+ export declare function withUseCacheLayoutMarker<T extends Record<string, unknown>>(fn: unknown, props: T): T;
26
26
  /**
27
27
  * Whether `value` is page props carrying the `$$isPage` marker. Only plain
28
28
  * objects qualify: the framework always passes a plain props object, and
@@ -30,4 +30,7 @@ export declare function withUseCachePageMarker<T extends Record<string, unknown>
30
30
  * observed as a param access.
31
31
  */
32
32
  export declare function hasUseCachePageMarker(value: unknown): value is Record<string, unknown>;
33
+ export declare function hasUseCacheLayoutMarker(value: unknown): value is Record<string, unknown>;
34
+ /** Remove only this invocation's marker before Flight keys and decodes props. */
35
+ export declare function withoutUseCacheSegmentMarker(props: Record<string, unknown>, isPage: boolean): Record<string, unknown>;
33
36
  //#endregion
@@ -1,5 +1,4 @@
1
1
  //#region src/shims/internal/app-page-props-cache-key.ts
2
- const APP_PAGE_PROPS_CACHE_KEY_MARKER = Symbol.for("vinext.appPagePropsCacheKeyMarker");
3
2
  const USE_CACHE_FUNCTION_SYMBOL = Symbol.for("vinext.useCacheFunction");
4
3
  const SERVER_REFERENCE_TAG = Symbol.for("react.server.reference");
5
4
  /**
@@ -15,18 +14,8 @@ const USE_CACHE_SERVER_REFERENCE_ID_RE = /#\$\$vinext_cache_[0-9a-f]{64}$/;
15
14
  * props before a server component is invoked.
16
15
  */
17
16
  const APP_PAGE_USE_CACHE_MARKER = "$$isPage";
18
- function markAppPagePropsForUseCache(props) {
19
- Object.defineProperty(props, APP_PAGE_PROPS_CACHE_KEY_MARKER, {
20
- configurable: false,
21
- enumerable: false,
22
- value: true,
23
- writable: false
24
- });
25
- return props;
26
- }
27
- function isMarkedAppPagePropsObject(value) {
28
- return Reflect.get(value, APP_PAGE_PROPS_CACHE_KEY_MARKER) === true;
29
- }
17
+ /** Layout marker, matching Next.js's `$$isLayout` prop (create-component-tree.tsx). */
18
+ const APP_LAYOUT_USE_CACHE_MARKER = "$$isLayout";
30
19
  /**
31
20
  * Whether `fn` is a transformed `"use cache"` function, including a bound
32
21
  * one. Like Next.js's `isUseCacheFunction`, this survives `.bind()`: React's
@@ -53,6 +42,13 @@ function withUseCachePageMarker(fn, props) {
53
42
  [APP_PAGE_USE_CACHE_MARKER]: true
54
43
  } : props;
55
44
  }
45
+ /** Layout components and their metadata resolvers retain framework params too. */
46
+ function withUseCacheLayoutMarker(fn, props) {
47
+ return isUseCacheFunctionReference(fn) ? {
48
+ ...props,
49
+ [APP_LAYOUT_USE_CACHE_MARKER]: true
50
+ } : props;
51
+ }
56
52
  /**
57
53
  * Whether `value` is page props carrying the `$$isPage` marker. Only plain
58
54
  * objects qualify: the framework always passes a plain props object, and
@@ -60,9 +56,22 @@ function withUseCachePageMarker(fn, props) {
60
56
  * observed as a param access.
61
57
  */
62
58
  function hasUseCachePageMarker(value) {
59
+ return hasUseCacheSegmentMarker(value, APP_PAGE_USE_CACHE_MARKER);
60
+ }
61
+ function hasUseCacheLayoutMarker(value) {
62
+ return hasUseCacheSegmentMarker(value, APP_LAYOUT_USE_CACHE_MARKER);
63
+ }
64
+ /** Remove only this invocation's marker before Flight keys and decodes props. */
65
+ function withoutUseCacheSegmentMarker(props, isPage) {
66
+ const marker = isPage ? APP_PAGE_USE_CACHE_MARKER : APP_LAYOUT_USE_CACHE_MARKER;
67
+ if (props[marker] !== true) return props;
68
+ const { [marker]: _marker, ...segmentProps } = props;
69
+ return segmentProps;
70
+ }
71
+ function hasUseCacheSegmentMarker(value, marker) {
63
72
  if (value === null || typeof value !== "object") return false;
64
73
  const prototype = Object.getPrototypeOf(value);
65
- return (prototype === Object.prototype || prototype === null) && value["$$isPage"] === true;
74
+ return (prototype === Object.prototype || prototype === null) && value[marker] === true;
66
75
  }
67
76
  //#endregion
68
- export { APP_PAGE_USE_CACHE_MARKER, hasUseCachePageMarker, isMarkedAppPagePropsObject, isUseCacheFunctionReference, markAppPagePropsForUseCache, withUseCachePageMarker };
77
+ export { APP_PAGE_USE_CACHE_MARKER, hasUseCacheLayoutMarker, hasUseCachePageMarker, isUseCacheFunctionReference, withUseCacheLayoutMarker, withUseCachePageMarker, withoutUseCacheSegmentMarker };
@@ -30,7 +30,6 @@ export type ConnectionProbeState = {
30
30
  dynamicUsageTarget: VinextHeadersShimState;
31
31
  interrupted: boolean;
32
32
  interrupt: () => void;
33
- pending: Promise<never>;
34
33
  };
35
34
  export type ConnectionProbeResult<T> = {
36
35
  completed: true;
@@ -0,0 +1,5 @@
1
+ //#region src/shims/internal/work-store-scope.d.ts
2
+ export declare function runInWorkStoreScope<T>(fn: () => T): T;
3
+ export declare function runOutsideWorkStoreScope<T>(fn: () => T): T;
4
+ export declare function isInsideWorkStoreScope(): boolean;
5
+ //#endregion
@@ -0,0 +1,24 @@
1
+ import { getOrCreateAls } from "./als-registry.js";
2
+ //#region src/shims/internal/work-store-scope.ts
3
+ /**
4
+ * Marks the work that Next.js runs with a work store (`workAsyncStorage`):
5
+ * App Router renders, Server Actions, route handlers and metadata routes,
6
+ * `generateStaticParams`, and middleware. Pages Router renders, API routes
7
+ * and `getStaticPaths` run without one.
8
+ *
9
+ * Next.js only applies some rules inside a work store, such as skipping the
10
+ * read for an `unstable_cache` nested in another's callback.
11
+ * Source: https://github.com/vercel/next.js/blob/canary/packages/next/src/server/web/spec-extension/unstable-cache.ts
12
+ */
13
+ const _workStoreScopeAls = getOrCreateAls("vinext.workStoreScope.als");
14
+ function runInWorkStoreScope(fn) {
15
+ return _workStoreScopeAls.run(true, fn);
16
+ }
17
+ function runOutsideWorkStoreScope(fn) {
18
+ return _workStoreScopeAls.run(false, fn);
19
+ }
20
+ function isInsideWorkStoreScope() {
21
+ return _workStoreScopeAls.getStore() === true;
22
+ }
23
+ //#endregion
24
+ export { isInsideWorkStoreScope, runInWorkStoreScope, runOutsideWorkStoreScope };
@@ -1,6 +1,6 @@
1
1
  import { isAbsoluteOrProtocolRelativeUrl } from "./url-utils.js";
2
+ import { withUseCacheLayoutMarker, withUseCachePageMarker } from "./internal/app-page-props-cache-key.js";
2
3
  import { makeThenableParams } from "./thenable-params.js";
3
- import { withUseCachePageMarker } from "./internal/app-page-props-cache-key.js";
4
4
  import React from "react";
5
5
  import { Fragment as Fragment$1, jsx } from "react/jsx-runtime";
6
6
  //#region src/shims/metadata.tsx
@@ -19,7 +19,7 @@ const USE_CACHE_ACCEPTS_SECOND_ARGUMENT_SYMBOL = Symbol.for("vinext.useCacheAcce
19
19
  async function resolveModuleViewport(mod, params = {}, searchParams, parent = Promise.resolve(mergeViewport([])), searchParamsObserver) {
20
20
  if (typeof mod.generateViewport === "function") {
21
21
  const asyncParams = makeThenableParams(params);
22
- const props = searchParams === void 0 ? { params: asyncParams } : withUseCachePageMarker(mod.generateViewport, {
22
+ const props = searchParams === void 0 ? withUseCacheLayoutMarker(mod.generateViewport, { params: asyncParams }) : withUseCachePageMarker(mod.generateViewport, {
23
23
  params: asyncParams,
24
24
  searchParams: makeThenableParams(searchParams, searchParamsObserver)
25
25
  });
@@ -268,7 +268,7 @@ async function resolveModuleMetadata(mod, params = {}, searchParams, parent = Pr
268
268
  if (typeof mod.generateMetadata === "function") {
269
269
  const generateMetadata = mod.generateMetadata;
270
270
  const asyncParams = makeThenableParams(params);
271
- const props = searchParams === void 0 ? { params: asyncParams } : withUseCachePageMarker(generateMetadata, {
271
+ const props = searchParams === void 0 ? withUseCacheLayoutMarker(generateMetadata, { params: asyncParams }) : withUseCachePageMarker(generateMetadata, {
272
272
  params: asyncParams,
273
273
  searchParams: makeThenableParams(searchParams, searchParamsObserver)
274
274
  });
@@ -12,6 +12,12 @@ export declare enum RedirectType {
12
12
  push = "push",
13
13
  replace = "replace"
14
14
  }
15
+ /**
16
+ * Whether `error` was thrown by redirect(), notFound() or another navigation
17
+ * function in the render that caught it, rather than decoded from an RSC
18
+ * render's digest.
19
+ */
20
+ export declare function isThrownNavigationError(error: unknown): boolean;
15
21
  /**
16
22
  * The omitted redirect type is resolved by the catch site: push for Server
17
23
  * Actions and replace for ordinary SSR/RSC rendering.
@@ -25,14 +25,24 @@ let RedirectType = /* @__PURE__ */ function(RedirectType) {
25
25
  RedirectType["replace"] = "replace";
26
26
  return RedirectType;
27
27
  }({});
28
+ const THROWN_NAVIGATION_ERROR_MARKER = Symbol.for("vinext.navigationError.thrown");
28
29
  var VinextNavigationError = class extends Error {
29
30
  digest;
31
+ [THROWN_NAVIGATION_ERROR_MARKER] = true;
30
32
  constructor(message, digest) {
31
33
  super(message);
32
34
  this.digest = digest;
33
35
  }
34
36
  };
35
37
  /**
38
+ * Whether `error` was thrown by redirect(), notFound() or another navigation
39
+ * function in the render that caught it, rather than decoded from an RSC
40
+ * render's digest.
41
+ */
42
+ function isThrownNavigationError(error) {
43
+ return typeof error === "object" && error !== null && Reflect.get(error, THROWN_NAVIGATION_ERROR_MARKER) === true;
44
+ }
45
+ /**
36
46
  * The omitted redirect type is resolved by the catch site: push for Server
37
47
  * Actions and replace for ordinary SSR/RSC rendering.
38
48
  */
@@ -103,4 +113,4 @@ function unstable_rethrow(error) {
103
113
  if (error instanceof Error && "cause" in error) unstable_rethrow(error.cause);
104
114
  }
105
115
  //#endregion
106
- export { BailoutToCSRError, DynamicServerError, HTTP_ERROR_FALLBACK_ERROR_CODE, RedirectType, decodeRedirectError, forbidden, getAccessFallbackHTTPStatus, isBailoutToCSRError, isDynamicServerError, isHTTPAccessFallbackError, isNextRouterError, isRedirectError, notFound, permanentRedirect, redirect, unauthorized, unstable_rethrow };
116
+ export { BailoutToCSRError, DynamicServerError, HTTP_ERROR_FALLBACK_ERROR_CODE, RedirectType, decodeRedirectError, forbidden, getAccessFallbackHTTPStatus, isBailoutToCSRError, isDynamicServerError, isHTTPAccessFallbackError, isNextRouterError, isRedirectError, isThrownNavigationError, notFound, permanentRedirect, redirect, unauthorized, unstable_rethrow };
@@ -49,6 +49,13 @@ export type CachedRscResponse = {
49
49
  mountedSlotsHeader?: string | null;
50
50
  paramsHeader: string | null;
51
51
  preparedElements?: AppElements;
52
+ /**
53
+ * Streamed `redirect()` side-channel headers. A replayed snapshot must keep
54
+ * them so the navigation follows the redirect instead of decoding the
55
+ * redirect payload as a page.
56
+ */
57
+ redirectHeader?: string;
58
+ redirectTypeHeader?: string;
52
59
  renderedPathAndSearch: string | null;
53
60
  serverStaleTime?: ServerStaleTime;
54
61
  url: string;
@@ -2,21 +2,22 @@ import { isBotUserAgent } from "../utils/html-limited-bots.js";
2
2
  import { isExternalUrl } from "../utils/external-url.js";
3
3
  import { stripBasePath } from "../utils/base-path.js";
4
4
  import { NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_RSC_RENDER_MODE_HEADER } from "../server/app-rsc-vary.js";
5
- import { NEXT_ROUTER_STALE_TIME_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_PARAMS_HEADER, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, VINEXT_RSC_COMPLETION_METADATA_HEADER, VINEXT_STALE_TIME_PENDING_HEADER } from "../server/headers.js";
5
+ import { NEXT_ROUTER_STALE_TIME_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_PARAMS_HEADER, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, VINEXT_RSC_COMPLETION_METADATA_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_REDIRECT_TYPE_HEADER, VINEXT_STALE_TIME_PENDING_HEADER } from "../server/headers.js";
6
6
  import { assertSafeNavigationUrl } from "./url-safety.js";
7
7
  import { APP_RSC_RENDER_MODE_PREFETCH_DYNAMIC_SHELL, APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL } from "../server/app-rsc-render-mode.js";
8
- import { AppElementsWire } from "../server/app-elements-wire.js";
9
- import "../server/app-elements.js";
10
8
  import { getPprFallbackShellState, markPprFallbackShellDynamicBoundary } from "./ppr-fallback-shell.js";
11
9
  import { AppRouterContext } from "./internal/app-router-context.js";
12
10
  import { resolveDirectHybridClientRouteOwner } from "./internal/hybrid-client-route-owner-direct.js";
13
11
  import { isHashOnlyBrowserUrlChange, toCanonicalBrowserNavigationHref, toSameOriginAppPath, withBasePath } from "./url-utils.js";
14
- import { retryScrollTo, scrollToHashTarget, scrollToHashTargetOnNextFrame } from "./hash-scroll.js";
12
+ import { disableSmoothScrollDuringRouteTransition } from "./disable-smooth-scroll.js";
13
+ import { retryScrollTo, scrollToHashTarget } from "./hash-scroll.js";
14
+ import { AppElementsWire } from "../server/app-elements-wire.js";
15
+ import "../server/app-elements.js";
15
16
  import { GLOBAL_ACCESSORS_KEY, ServerInsertedHTMLContext, _registerStateAccessors, clearClientHydrationContext, clearServerInsertedHTML, flushServerInsertedHTML, getBfcacheIdMapContext, getBfcacheSegmentIdContext, getLayoutSegmentContext, getNavigationContext, registerServerInsertedHTMLCallback, renderServerInsertedHTML, setNavigationContext } from "./navigation-context-state.js";
16
17
  import { BailoutToCSRError, DynamicServerError, HTTP_ERROR_FALLBACK_ERROR_CODE, RedirectType, decodeRedirectError, forbidden, getAccessFallbackHTTPStatus, isBailoutToCSRError, isDynamicServerError, isHTTPAccessFallbackError, isNextRouterError, isRedirectError, notFound, permanentRedirect, redirect, unauthorized, unstable_rethrow } from "./navigation-errors.js";
17
18
  import { clearAppNavigationFailureTarget, stageAppNavigationFailureTarget } from "../client/app-nav-failure-handler.js";
18
19
  import { beginAppRouterScrollIntent, clearAppRouterScrollIntent, consumeAppRouterScrollIntent, getPendingAppRouterScrollIntent, isLatestAppRouterScrollIntent } from "./app-router-scroll-state.js";
19
- import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, createRscRequestHeaders, createRscRequestUrl, stripRscCacheBustingSearchParam, stripRscSuffix } from "../server/app-rsc-cache-busting.js";
20
+ import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, createRscRequestHeaders, createRscRequestUrl, stripRscCacheBustingSearchParam, stripRscSuffix } from "../server/app-rsc-cache-busting.js";
20
21
  import { notifyAppRouterTransitionStart } from "../client/instrumentation-client-state.js";
21
22
  import { getNavigationRuntime, hasAppNavigationRuntime } from "../client/navigation-runtime.js";
22
23
  import { UnrecognizedActionError, unstable_isUnrecognizedActionError } from "./unrecognized-action-error.js";
@@ -662,6 +663,8 @@ function createCachedRscResponseSnapshot(response, buffer, responseUrl = null) {
662
663
  kind: "resolved",
663
664
  seconds: extracted.metadata.serverStaleTimeSeconds
664
665
  } : parsedServerStaleTime;
666
+ const redirectHeader = response.headers.get(VINEXT_RSC_REDIRECT_HEADER);
667
+ const redirectTypeHeader = response.headers.get(VINEXT_RSC_REDIRECT_TYPE_HEADER);
665
668
  return {
666
669
  compatibilityIdHeader: response.headers.get(VINEXT_RSC_COMPATIBILITY_ID_HEADER),
667
670
  buffer: extracted.buffer,
@@ -670,6 +673,8 @@ function createCachedRscResponseSnapshot(response, buffer, responseUrl = null) {
670
673
  ...dynamicStaleTimeSeconds !== void 0 ? { dynamicStaleTimeSeconds } : {},
671
674
  mountedSlotsHeader: response.headers.get(VINEXT_MOUNTED_SLOTS_HEADER),
672
675
  paramsHeader: response.headers.get(VINEXT_PARAMS_HEADER),
676
+ ...redirectHeader === null ? {} : { redirectHeader },
677
+ ...redirectTypeHeader === null ? {} : { redirectTypeHeader },
673
678
  renderedPathAndSearch: parseRenderedPathAndSearchHeader(response.headers.get(VINEXT_RENDERED_PATH_AND_SEARCH_HEADER)),
674
679
  ...serverStaleTime === void 0 ? {} : { serverStaleTime },
675
680
  url: responseUrl ?? response.url
@@ -739,6 +744,8 @@ function restoreRscResponse(cached, copy = true) {
739
744
  if (cached.serverStaleTime?.kind === "pending") headers.set(VINEXT_STALE_TIME_PENDING_HEADER, "1");
740
745
  else if (cached.serverStaleTime !== void 0) headers.set(NEXT_ROUTER_STALE_TIME_HEADER, String(cached.serverStaleTime.seconds));
741
746
  if (cached.paramsHeader != null) headers.set(VINEXT_PARAMS_HEADER, cached.paramsHeader);
747
+ if (cached.redirectHeader !== void 0) headers.set(VINEXT_RSC_REDIRECT_HEADER, cached.redirectHeader);
748
+ if (cached.redirectTypeHeader !== void 0) headers.set(VINEXT_RSC_REDIRECT_TYPE_HEADER, cached.redirectTypeHeader);
742
749
  if (cached.renderedPathAndSearch != null) headers.set(VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, encodeURIComponent(cached.renderedPathAndSearch));
743
750
  const response = new Response(copy ? cached.buffer.slice(0) : cached.buffer, {
744
751
  status: 200,
@@ -791,6 +798,22 @@ async function fetchRouteTreeGatedPrefetch(options) {
791
798
  return fetchFullRscPayload();
792
799
  }
793
800
  /**
801
+ * Whether a prefetch response may be decoded as Flight. A successful response
802
+ * that is not Flight (e.g. a Route Handler's text download) is a miss: decoding
803
+ * its bytes would let text shaped like Flight resource hints insert scripts.
804
+ * Navigation then fetches it and falls back to a document navigation.
805
+ *
806
+ * Ported from Next.js: fetchPrefetchResponse in
807
+ * packages/next/src/client/components/segment-cache/cache.ts, which skips the
808
+ * check in `output: "export"` because a static host, not Next.js, chooses the
809
+ * MIME type of the exported `.txt` payloads.
810
+ */
811
+ function isFlightPrefetchResponse(response) {
812
+ if (!response.ok) return false;
813
+ if (process.env.NODE_ENV === "production" && process.env.__NEXT_CONFIG_OUTPUT === "export") return true;
814
+ return response.headers.get("content-type")?.toLowerCase().startsWith(VINEXT_RSC_CONTENT_TYPE) === true;
815
+ }
816
+ /**
794
817
  * Prefetch an RSC response and snapshot it for later consumption.
795
818
  * Stores the in-flight promise so immediate clicks can await it instead
796
819
  * of firing a duplicate fetch.
@@ -818,7 +841,7 @@ function prefetchRscResponse(rscUrl, fetchPromise, interceptionContext = null, m
818
841
  addPrefetchInvalidationCallback(entry, options?.onInvalidate);
819
842
  entry.fetchPromise = fetchPromise;
820
843
  entry.pending = fetchPromise.then(async (response) => {
821
- if (response.ok) {
844
+ if (isFlightPrefetchResponse(response)) {
822
845
  const snapshot = await snapshotRscResponse(response);
823
846
  if (cache.get(cacheKey) !== entry) return;
824
847
  const previousSize = getPrefetchCacheEntrySize(entry);
@@ -826,7 +849,7 @@ function prefetchRscResponse(rscUrl, fetchPromise, interceptionContext = null, m
826
849
  entry.size = snapshot.buffer.byteLength;
827
850
  adjustPrefetchCacheByteSize(cache, entry.size - previousSize);
828
851
  entry.expiresAt = resolvePrefetchedRscResponseExpiresAt(entry.timestamp, entry.snapshot, behavior.fallbackTtlMs ?? PREFETCH_CACHE_TTL, behavior.searchAgnosticShell === true ? "ignore" : behavior.dynamicStaleTime ?? (behavior.optimisticRouteShell === true ? "ignore" : "verbatim"));
829
- if (behavior.prepareSnapshot) try {
852
+ if (behavior.prepareSnapshot && snapshot.redirectHeader === void 0) try {
830
853
  const preparedElements = await behavior.prepareSnapshot(snapshot);
831
854
  if (cache.get(cacheKey) !== entry) return;
832
855
  entry.preparedElements = preparedElements;
@@ -835,6 +858,7 @@ function prefetchRscResponse(rscUrl, fetchPromise, interceptionContext = null, m
835
858
  evictPrefetchCacheIfNeeded();
836
859
  } else {
837
860
  releaseAppPrefetchFetchSlot(response);
861
+ response.body?.cancel().catch(() => {});
838
862
  deletePrefetchCacheEntry(cache, prefetched, cacheKey, entry, false);
839
863
  }
840
864
  }).catch(() => {
@@ -1327,11 +1351,19 @@ function commitHashOnlyHistoryState(href, mode, scroll) {
1327
1351
  function applyAppRouterScrollFallback(intent) {
1328
1352
  if (typeof document === "undefined" || typeof window === "undefined") return;
1329
1353
  if (intent.hash !== null) {
1330
- scrollToHashTargetOnNextFrame(intent.hash, () => isLatestAppRouterScrollIntent(intent));
1354
+ const hash = intent.hash;
1355
+ requestAnimationFrame(() => {
1356
+ if (!isLatestAppRouterScrollIntent(intent)) return;
1357
+ disableSmoothScrollDuringRouteTransition(() => {
1358
+ scrollToHashTarget(hash);
1359
+ });
1360
+ });
1331
1361
  return;
1332
1362
  }
1333
1363
  if (intent.targetHoistedInHead) return;
1334
- document.documentElement.scrollTop = 0;
1364
+ disableSmoothScrollDuringRouteTransition(() => {
1365
+ document.documentElement.scrollTop = 0;
1366
+ });
1335
1367
  }
1336
1368
  function scheduleAppRouterScrollFallback(intent) {
1337
1369
  queueMicrotask(() => {
@@ -1781,6 +1813,7 @@ if (!isServer) {
1781
1813
  }
1782
1814
  });
1783
1815
  window.history.pushState = function patchedPushState(data, unused, url) {
1816
+ getNavigationRuntime()?.functions.flushCommittingNavigationUrl?.();
1784
1817
  if (isAppOwnedHistoryState(data)) {
1785
1818
  const previousHistoryState = window.history.state;
1786
1819
  state.originalPushState.call(window.history, data, unused, url);
@@ -1792,10 +1825,12 @@ if (!isServer) {
1792
1825
  getNavigationRuntime()?.functions.claimCurrentHistoryTreeSnapshot?.("push", previousHistoryState);
1793
1826
  if (state.suppressUrlNotifyCount === 0) {
1794
1827
  resetStaleLinkStatus();
1828
+ if (url) getNavigationRuntime()?.functions.discardPendingNavigation?.();
1795
1829
  commitClientNavigationState();
1796
1830
  }
1797
1831
  };
1798
1832
  window.history.replaceState = function patchedReplaceState(data, unused, url) {
1833
+ getNavigationRuntime()?.functions.flushCommittingNavigationUrl?.();
1799
1834
  if (isAppOwnedHistoryState(data)) {
1800
1835
  const previousHistoryState = window.history.state;
1801
1836
  state.originalReplaceState.call(window.history, data, unused, url);
@@ -1807,6 +1842,7 @@ if (!isServer) {
1807
1842
  getNavigationRuntime()?.functions.claimCurrentHistoryTreeSnapshot?.("replace", previousHistoryState);
1808
1843
  if (state.suppressUrlNotifyCount === 0) {
1809
1844
  resetStaleLinkStatus();
1845
+ if (url) getNavigationRuntime()?.functions.discardPendingNavigation?.();
1810
1846
  commitClientNavigationState();
1811
1847
  }
1812
1848
  };
@@ -44,6 +44,17 @@ export type ExecutionContextLike = {
44
44
  isInternalPagesRevalidation?: boolean;
45
45
  /** Marks a build-secret-authorized Worker request that may run prerender discovery hooks. */
46
46
  isPrerenderPathDiscovery?: boolean;
47
+ /** Marks an adapter-invoked regeneration of an entry stored for this build. */
48
+ isStoredEntryRegeneration?: boolean;
49
+ /**
50
+ * Installed only by the prerender server: records the page's special error
51
+ * that escaped the shell, with the headers to store, for the build.
52
+ */
53
+ recordPrerenderSpecialError?: (marker: PrerenderSpecialErrorMarker) => void;
54
+ };
55
+ export type PrerenderSpecialErrorMarker = {
56
+ headers: Record<string, string>;
57
+ status: number;
47
58
  };
48
59
  /**
49
60
  * Run `fn` with the given `ExecutionContext` available via
@@ -3,7 +3,8 @@ import { NavigationContext } from "./navigation-context-state.js";
3
3
  import "./navigation.js";
4
4
  import { CacheLifeConfig, CacheState } from "./cache-request-state.js";
5
5
  import { RootParamsState } from "./root-params.js";
6
- import { FetchCacheState } from "./fetch-cache.js";
6
+ import { FetchCacheState } from "./fetch-cache-state.js";
7
+ import "./fetch-cache.js";
7
8
  import { HeadersAccessPhase, VinextHeadersShimState } from "./internal/headers-state.js";
8
9
  import { HeadersContext } from "./headers.js";
9
10
  import { RouterState, SSRContext } from "./router-state.js";
@@ -1,6 +1,7 @@
1
1
  import { isUnknownRecord } from "../utils/record.js";
2
2
  import { parseCookieHeader } from "../utils/parse-cookie.js";
3
3
  import { isExternalUrl } from "../utils/external-url.js";
4
+ import { substituteDestinationParams } from "../config/destination-params.js";
4
5
  import { sortRoutes, splitPathSegments } from "../routing/utils.js";
5
6
  import { hasBasePath, removeTrailingSlash, stripBasePath } from "../utils/base-path.js";
6
7
  import { assertSafeNavigationUrl } from "./url-safety.js";
@@ -19,6 +20,7 @@ import { resolveDirectHybridClientRouteOwner } from "./internal/hybrid-client-ro
19
20
  import { installWindowNext } from "../client/window-next.js";
20
21
  import { getWindowOrigin, isAbsoluteOrProtocolRelativeUrl, isAbsoluteUrl, isHashOnlyBrowserUrlChange, normalizePathTrailingSlash, toBrowserNavigationHref, toSameOriginAppPath, toSameOriginPath, withBasePath } from "./url-utils.js";
21
22
  import { addQueryParam, mergeRewriteQuery, mergeRouteParamsIntoQuery, parseQueryString } from "../utils/query.js";
23
+ import { disableSmoothScrollDuringRouteTransition } from "./disable-smooth-scroll.js";
22
24
  import { scrollToHashTarget } from "./hash-scroll.js";
23
25
  import { installPagesRouterRuntime, setPagesRouterPopStateHandler, setStampInitialHistoryState } from "./pages-router-runtime.js";
24
26
  import { interpolateDynamicRouteHref, resolveDynamicRouteHref } from "./internal/interpolate-as.js";
@@ -129,16 +131,9 @@ function scrollToPagesRouterPosition({ x, y }) {
129
131
  window.scrollTo(x, y);
130
132
  return;
131
133
  }
132
- const htmlElement = document.documentElement;
133
- if (!(htmlElement.dataset.scrollBehavior === "smooth")) {
134
+ disableSmoothScrollDuringRouteTransition(() => {
134
135
  window.scrollTo(x, y);
135
- return;
136
- }
137
- const previousScrollBehavior = htmlElement.style.scrollBehavior;
138
- htmlElement.style.scrollBehavior = "auto";
139
- htmlElement.getClientRects();
140
- window.scrollTo(x, y);
141
- htmlElement.style.scrollBehavior = previousScrollBehavior;
136
+ });
142
137
  }
143
138
  function isAtScrollPosition({ x, y }) {
144
139
  return Math.abs(window.scrollX - x) <= SCROLL_RESTORE_TOLERANCE_PX && Math.abs(window.scrollY - y) <= SCROLL_RESTORE_TOLERANCE_PX;
@@ -1020,10 +1015,10 @@ async function resolveClientConfigRedirect(href) {
1020
1015
  if (!redirects || redirects.length === 0) return null;
1021
1016
  const routeContext = getClientConfigRouteContext(href);
1022
1017
  if (!routeContext) return null;
1023
- const { matchRedirect, preserveRedirectDestinationQuery } = await import("../config/config-matchers.js");
1024
- const redirect = matchRedirect(routeContext.pathname, redirects, routeContext.context, routeContext.basePathState);
1018
+ const [{ matchClientRedirect }, { preserveRedirectDestinationQuery }] = await Promise.all([import("../client/client-redirect-matcher.js"), import("../config/config-matchers.js")]);
1019
+ const redirect = matchClientRedirect(routeContext.pathname, redirects, routeContext.context, routeContext.basePathState);
1025
1020
  if (!redirect) return null;
1026
- return preserveRedirectDestinationQuery(__basePath && routeContext.basePathState.hadBasePath && !isExternalUrl(redirect.destination) && !hasBasePath(redirect.destination, __basePath) ? __basePath + redirect.destination : redirect.destination, routeContext.search);
1021
+ return preserveRedirectDestinationQuery(__basePath && routeContext.basePathState.hadBasePath && !isExternalUrl(redirect.destination) && !hasBasePath(redirect.destination, __basePath) ? __basePath + redirect.destination : redirect.destination, routeContext.search, redirect.destinationQuery);
1027
1022
  }
1028
1023
  async function applyClientConfigRewrite(href, rewrite) {
1029
1024
  const routeContext = getClientConfigRouteContext(href);
@@ -1076,12 +1071,6 @@ function simpleClientConfigSourceCouldMatch(pathname, source) {
1076
1071
  const normalizedPathname = removeTrailingSlash(pathname);
1077
1072
  return normalizedPathname === normalizedPrefix || normalizedPathname.startsWith(`${normalizedPrefix}/`);
1078
1073
  }
1079
- function substituteSimpleClientConfigDestination(destination, params) {
1080
- const keys = Object.keys(params);
1081
- if (keys.length === 0) return destination;
1082
- const alternation = keys.sort((a, b) => b.length - a.length).map((key) => key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
1083
- return destination.replace(new RegExp(`:(${alternation})([+*])?(?![A-Za-z0-9_])`, "g"), (_token, key) => params[key] ?? _token);
1084
- }
1085
1074
  function isExternalClientConfigUrl(url) {
1086
1075
  return /^[a-z][a-z0-9+.-]*:/i.test(url) || url.startsWith("//");
1087
1076
  }
@@ -1111,7 +1100,7 @@ function resolveClientConfigRewriteSync(href) {
1111
1100
  const params = matchSimpleClientConfigPattern(routeContext.pathname, rewrite.source);
1112
1101
  if (params === void 0) return void 0;
1113
1102
  if (params === null) continue;
1114
- const rewritten = substituteSimpleClientConfigDestination(rewrite.destination, params);
1103
+ const rewritten = substituteDestinationParams(rewrite.destination, params, "rewrite");
1115
1104
  if (isExternalClientConfigUrl(rewritten)) return { kind: "document" };
1116
1105
  currentHref = mergeRewriteQuery(currentHref, rewritten);
1117
1106
  matched = true;
@@ -2018,7 +2007,10 @@ See more info: https://nextjs.org/docs/messages/invalid-relative-url-external-as
2018
2007
  emitBeforeHistoryChange();
2019
2008
  if (doScroll) {
2020
2009
  if (hash) scrollToHashTarget(hash);
2021
- else window.scrollTo(0, 0);
2010
+ else scrollToPagesRouterPosition({
2011
+ x: 0,
2012
+ y: 0
2013
+ });
2022
2014
  }
2023
2015
  }
2024
2016
  onStateUpdate?.();
@@ -26,6 +26,7 @@ export type RequestInit = globalThis.RequestInit & {
26
26
  }>;
27
27
  } | null;
28
28
  trailingSlash?: boolean;
29
+ skipTrailingSlashRedirect?: boolean;
29
30
  };
30
31
  signal?: AbortSignal;
31
32
  duplex?: "half";
@@ -109,6 +110,14 @@ export type NextURLConfig = {
109
110
  * honour the user's `trailingSlash` config.
110
111
  */
111
112
  trailingSlash?: boolean;
113
+ /**
114
+ * When true, the trailing slash follows the parsed URL instead, and
115
+ * `trailingSlash` only decides the root, like Next.js's
116
+ * getNextPathnameInfo. Without the trailing-slash redirect, requests
117
+ * arrive in either form, so the config can no longer be applied as a
118
+ * policy.
119
+ */
120
+ skipTrailingSlashRedirect?: boolean;
112
121
  };
113
122
  };
114
123
  export declare class NextURL {
@@ -121,6 +130,8 @@ export declare class NextURL {
121
130
  */
122
131
  private _configBasePath;
123
132
  private _basePath;
133
+ private _configTrailingSlash;
134
+ private _manualTrailingSlash;
124
135
  private _trailingSlash;
125
136
  private _locale;
126
137
  private _configDefaultLocale;
@@ -129,6 +140,11 @@ export declare class NextURL {
129
140
  private _domains;
130
141
  private _domainLocale;
131
142
  constructor(input: string | URL, base?: string | URL, config?: NextURLConfig);
143
+ /**
144
+ * With `skipTrailingSlashRedirect`, take the slash from the parsed pathname
145
+ * (before basePath and locale are stripped), as getNextPathnameInfo does.
146
+ */
147
+ private _analyzeTrailingSlash;
132
148
  /** Strip basePath prefix from the internal pathname.
133
149
  * Mirrors Next.js's getNextPathnameInfo (re-run by NextURL.analyze() on
134
150
  * every parse, including `href` reassignment): basePath is only considered