vinext 0.0.44 → 0.0.46

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 (323) hide show
  1. package/dist/build/google-fonts/build-url.d.ts +10 -0
  2. package/dist/build/google-fonts/build-url.js +30 -0
  3. package/dist/build/google-fonts/build-url.js.map +1 -0
  4. package/dist/build/google-fonts/font-data.js +24985 -0
  5. package/dist/build/google-fonts/font-data.js.map +1 -0
  6. package/dist/build/google-fonts/font-metadata.d.ts +17 -0
  7. package/dist/build/google-fonts/font-metadata.js +7 -0
  8. package/dist/build/google-fonts/font-metadata.js.map +1 -0
  9. package/dist/build/google-fonts/get-axes.d.ts +7 -0
  10. package/dist/build/google-fonts/get-axes.js +39 -0
  11. package/dist/build/google-fonts/get-axes.js.map +1 -0
  12. package/dist/build/google-fonts/sort-variants.d.ts +5 -0
  13. package/dist/build/google-fonts/sort-variants.js +14 -0
  14. package/dist/build/google-fonts/sort-variants.js.map +1 -0
  15. package/dist/build/google-fonts/validate.d.ts +28 -0
  16. package/dist/build/google-fonts/validate.js +56 -0
  17. package/dist/build/google-fonts/validate.js.map +1 -0
  18. package/dist/build/layout-classification.d.ts +1 -1
  19. package/dist/build/layout-classification.js.map +1 -1
  20. package/dist/build/nitro-route-rules.d.ts +1 -1
  21. package/dist/build/nitro-route-rules.js.map +1 -1
  22. package/dist/build/precompress.d.ts +1 -1
  23. package/dist/build/precompress.js.map +1 -1
  24. package/dist/build/prerender.d.ts +1 -7
  25. package/dist/build/prerender.js +17 -6
  26. package/dist/build/prerender.js.map +1 -1
  27. package/dist/build/run-prerender.d.ts +1 -13
  28. package/dist/build/run-prerender.js +5 -1
  29. package/dist/build/run-prerender.js.map +1 -1
  30. package/dist/build/standalone.d.ts +1 -1
  31. package/dist/build/standalone.js +4 -3
  32. package/dist/build/standalone.js.map +1 -1
  33. package/dist/check.js +30 -18
  34. package/dist/check.js.map +1 -1
  35. package/dist/cli.js +4 -0
  36. package/dist/cli.js.map +1 -1
  37. package/dist/cloudflare/kv-cache-handler.d.ts +5 -0
  38. package/dist/cloudflare/kv-cache-handler.js +56 -35
  39. package/dist/cloudflare/kv-cache-handler.js.map +1 -1
  40. package/dist/cloudflare/tpr.d.ts +1 -16
  41. package/dist/cloudflare/tpr.js +1 -1
  42. package/dist/cloudflare/tpr.js.map +1 -1
  43. package/dist/config/config-matchers.js +1 -0
  44. package/dist/config/config-matchers.js.map +1 -1
  45. package/dist/config/dotenv.d.ts +1 -1
  46. package/dist/config/dotenv.js.map +1 -1
  47. package/dist/config/next-config.d.ts +38 -2
  48. package/dist/config/next-config.js +24 -0
  49. package/dist/config/next-config.js.map +1 -1
  50. package/dist/deploy.d.ts +1 -1
  51. package/dist/deploy.js +18 -23
  52. package/dist/deploy.js.map +1 -1
  53. package/dist/entries/app-rsc-entry.js +387 -1718
  54. package/dist/entries/app-rsc-entry.js.map +1 -1
  55. package/dist/entries/app-rsc-manifest.d.ts +24 -0
  56. package/dist/entries/app-rsc-manifest.js +153 -0
  57. package/dist/entries/app-rsc-manifest.js.map +1 -0
  58. package/dist/entries/pages-server-entry.js +13 -103
  59. package/dist/entries/pages-server-entry.js.map +1 -1
  60. package/dist/index.js +59 -34
  61. package/dist/index.js.map +1 -1
  62. package/dist/init.d.ts +1 -1
  63. package/dist/init.js.map +1 -1
  64. package/dist/plugins/async-hooks-stub.d.ts +1 -2
  65. package/dist/plugins/async-hooks-stub.js +2 -2
  66. package/dist/plugins/async-hooks-stub.js.map +1 -1
  67. package/dist/plugins/fonts.d.ts +1 -20
  68. package/dist/plugins/fonts.js +42 -21
  69. package/dist/plugins/fonts.js.map +1 -1
  70. package/dist/plugins/rsc-client-shim-excludes.d.ts +6 -0
  71. package/dist/plugins/rsc-client-shim-excludes.js +27 -0
  72. package/dist/plugins/rsc-client-shim-excludes.js.map +1 -0
  73. package/dist/plugins/server-externals-manifest.d.ts +1 -11
  74. package/dist/plugins/server-externals-manifest.js +1 -1
  75. package/dist/plugins/server-externals-manifest.js.map +1 -1
  76. package/dist/routing/app-router.d.ts +14 -5
  77. package/dist/routing/app-router.js +82 -5
  78. package/dist/routing/app-router.js.map +1 -1
  79. package/dist/routing/file-matcher.d.ts +1 -3
  80. package/dist/routing/file-matcher.js +1 -1
  81. package/dist/routing/file-matcher.js.map +1 -1
  82. package/dist/routing/route-pattern.d.ts +9 -0
  83. package/dist/routing/route-pattern.js +90 -0
  84. package/dist/routing/route-pattern.js.map +1 -0
  85. package/dist/routing/route-trie.js +10 -11
  86. package/dist/routing/route-trie.js.map +1 -1
  87. package/dist/routing/utils.d.ts +1 -29
  88. package/dist/routing/utils.js +1 -1
  89. package/dist/routing/utils.js.map +1 -1
  90. package/dist/server/app-browser-entry.js +63 -5
  91. package/dist/server/app-browser-entry.js.map +1 -1
  92. package/dist/server/app-browser-state.d.ts +1 -1
  93. package/dist/server/app-browser-state.js.map +1 -1
  94. package/dist/server/app-browser-stream.d.ts +1 -1
  95. package/dist/server/app-browser-stream.js.map +1 -1
  96. package/dist/server/app-elements.d.ts +1 -2
  97. package/dist/server/app-elements.js +1 -1
  98. package/dist/server/app-elements.js.map +1 -1
  99. package/dist/server/app-middleware.d.ts +32 -0
  100. package/dist/server/app-middleware.js +147 -0
  101. package/dist/server/app-middleware.js.map +1 -0
  102. package/dist/server/app-page-boundary-render.d.ts +5 -1
  103. package/dist/server/app-page-boundary-render.js +52 -30
  104. package/dist/server/app-page-boundary-render.js.map +1 -1
  105. package/dist/server/app-page-boundary.d.ts +13 -1
  106. package/dist/server/app-page-boundary.js +37 -17
  107. package/dist/server/app-page-boundary.js.map +1 -1
  108. package/dist/server/app-page-cache.d.ts +4 -1
  109. package/dist/server/app-page-cache.js +38 -2
  110. package/dist/server/app-page-cache.js.map +1 -1
  111. package/dist/server/app-page-dispatch.d.ts +120 -0
  112. package/dist/server/app-page-dispatch.js +332 -0
  113. package/dist/server/app-page-dispatch.js.map +1 -0
  114. package/dist/server/app-page-execution.d.ts +6 -3
  115. package/dist/server/app-page-execution.js +22 -10
  116. package/dist/server/app-page-execution.js.map +1 -1
  117. package/dist/server/app-page-head.d.ts +55 -0
  118. package/dist/server/app-page-head.js +196 -0
  119. package/dist/server/app-page-head.js.map +1 -0
  120. package/dist/server/app-page-method.d.ts +16 -0
  121. package/dist/server/app-page-method.js +30 -0
  122. package/dist/server/app-page-method.js.map +1 -0
  123. package/dist/server/app-page-params.d.ts +7 -0
  124. package/dist/server/app-page-params.js +28 -0
  125. package/dist/server/app-page-params.js.map +1 -0
  126. package/dist/server/app-page-probe.d.ts +1 -1
  127. package/dist/server/app-page-probe.js.map +1 -1
  128. package/dist/server/app-page-render.d.ts +4 -3
  129. package/dist/server/app-page-render.js +54 -8
  130. package/dist/server/app-page-render.js.map +1 -1
  131. package/dist/server/app-page-request.d.ts +5 -5
  132. package/dist/server/app-page-request.js.map +1 -1
  133. package/dist/server/app-page-response.d.ts +1 -1
  134. package/dist/server/app-page-response.js.map +1 -1
  135. package/dist/server/app-page-route-wiring.d.ts +15 -11
  136. package/dist/server/app-page-route-wiring.js +31 -9
  137. package/dist/server/app-page-route-wiring.js.map +1 -1
  138. package/dist/server/app-page-stream.d.ts +12 -1
  139. package/dist/server/app-page-stream.js +10 -4
  140. package/dist/server/app-page-stream.js.map +1 -1
  141. package/dist/server/app-prerender-endpoints.d.ts +19 -0
  142. package/dist/server/app-prerender-endpoints.js +96 -0
  143. package/dist/server/app-prerender-endpoints.js.map +1 -0
  144. package/dist/server/app-prerender-static-params.d.ts +16 -0
  145. package/dist/server/app-prerender-static-params.js +14 -0
  146. package/dist/server/app-prerender-static-params.js.map +1 -0
  147. package/dist/server/app-route-handler-cache.d.ts +4 -1
  148. package/dist/server/app-route-handler-cache.js +6 -2
  149. package/dist/server/app-route-handler-cache.js.map +1 -1
  150. package/dist/server/app-route-handler-dispatch.d.ts +42 -0
  151. package/dist/server/app-route-handler-dispatch.js +147 -0
  152. package/dist/server/app-route-handler-dispatch.js.map +1 -0
  153. package/dist/server/app-route-handler-execution.d.ts +7 -3
  154. package/dist/server/app-route-handler-execution.js +32 -6
  155. package/dist/server/app-route-handler-execution.js.map +1 -1
  156. package/dist/server/app-route-handler-policy.d.ts +6 -2
  157. package/dist/server/app-route-handler-policy.js +8 -3
  158. package/dist/server/app-route-handler-policy.js.map +1 -1
  159. package/dist/server/app-route-handler-response.d.ts +2 -1
  160. package/dist/server/app-route-handler-response.js +44 -4
  161. package/dist/server/app-route-handler-response.js.map +1 -1
  162. package/dist/server/app-route-handler-runtime.d.ts +5 -2
  163. package/dist/server/app-route-handler-runtime.js +108 -2
  164. package/dist/server/app-route-handler-runtime.js.map +1 -1
  165. package/dist/server/app-router-entry.js.map +1 -1
  166. package/dist/server/app-rsc-errors.d.ts +27 -0
  167. package/dist/server/app-rsc-errors.js +42 -0
  168. package/dist/server/app-rsc-errors.js.map +1 -0
  169. package/dist/server/app-rsc-route-matching.d.ts +40 -0
  170. package/dist/server/app-rsc-route-matching.js +66 -0
  171. package/dist/server/app-rsc-route-matching.js.map +1 -0
  172. package/dist/server/app-server-action-execution.d.ts +120 -0
  173. package/dist/server/app-server-action-execution.js +355 -0
  174. package/dist/server/app-server-action-execution.js.map +1 -0
  175. package/dist/server/app-ssr-entry.d.ts +7 -0
  176. package/dist/server/app-ssr-entry.js +30 -9
  177. package/dist/server/app-ssr-entry.js.map +1 -1
  178. package/dist/server/app-ssr-stream.d.ts +5 -3
  179. package/dist/server/app-ssr-stream.js +29 -2
  180. package/dist/server/app-ssr-stream.js.map +1 -1
  181. package/dist/server/app-static-generation.d.ts +15 -0
  182. package/dist/server/app-static-generation.js +20 -0
  183. package/dist/server/app-static-generation.js.map +1 -0
  184. package/dist/server/csp.d.ts +1 -2
  185. package/dist/server/csp.js +1 -1
  186. package/dist/server/csp.js.map +1 -1
  187. package/dist/server/dev-module-runner.d.ts +1 -1
  188. package/dist/server/dev-module-runner.js.map +1 -1
  189. package/dist/server/dev-route-files.d.ts +7 -0
  190. package/dist/server/dev-route-files.js +73 -0
  191. package/dist/server/dev-route-files.js.map +1 -0
  192. package/dist/server/dev-server.js +4 -0
  193. package/dist/server/dev-server.js.map +1 -1
  194. package/dist/server/file-based-metadata.d.ts +17 -0
  195. package/dist/server/file-based-metadata.js +356 -0
  196. package/dist/server/file-based-metadata.js.map +1 -0
  197. package/dist/server/implicit-tags.d.ts +6 -0
  198. package/dist/server/implicit-tags.js +42 -0
  199. package/dist/server/implicit-tags.js.map +1 -0
  200. package/dist/server/instrumentation.js.map +1 -1
  201. package/dist/server/isr-cache.d.ts +20 -2
  202. package/dist/server/isr-cache.js +58 -7
  203. package/dist/server/isr-cache.js.map +1 -1
  204. package/dist/server/metadata-route-build-data.d.ts +25 -0
  205. package/dist/server/metadata-route-build-data.js +150 -0
  206. package/dist/server/metadata-route-build-data.js.map +1 -0
  207. package/dist/server/metadata-route-response.d.ts +17 -0
  208. package/dist/server/metadata-route-response.js +187 -0
  209. package/dist/server/metadata-route-response.js.map +1 -0
  210. package/dist/server/metadata-routes.d.ts +42 -4
  211. package/dist/server/metadata-routes.js +127 -11
  212. package/dist/server/metadata-routes.js.map +1 -1
  213. package/dist/server/middleware-matcher.d.ts +15 -0
  214. package/dist/server/middleware-matcher.js +102 -0
  215. package/dist/server/middleware-matcher.js.map +1 -0
  216. package/dist/server/middleware-request-headers.d.ts +1 -3
  217. package/dist/server/middleware-request-headers.js +5 -4
  218. package/dist/server/middleware-request-headers.js.map +1 -1
  219. package/dist/server/middleware-runtime.d.ts +39 -0
  220. package/dist/server/middleware-runtime.js +159 -0
  221. package/dist/server/middleware-runtime.js.map +1 -0
  222. package/dist/server/middleware.d.ts +5 -37
  223. package/dist/server/middleware.js +18 -228
  224. package/dist/server/middleware.js.map +1 -1
  225. package/dist/server/pages-api-route.d.ts +1 -1
  226. package/dist/server/pages-api-route.js.map +1 -1
  227. package/dist/server/pages-i18n.d.ts +2 -3
  228. package/dist/server/pages-i18n.js +1 -1
  229. package/dist/server/pages-i18n.js.map +1 -1
  230. package/dist/server/pages-node-compat.d.ts +1 -2
  231. package/dist/server/pages-node-compat.js +1 -1
  232. package/dist/server/pages-node-compat.js.map +1 -1
  233. package/dist/server/pages-page-data.d.ts +6 -2
  234. package/dist/server/pages-page-data.js +4 -0
  235. package/dist/server/pages-page-data.js.map +1 -1
  236. package/dist/server/pages-page-response.d.ts +1 -1
  237. package/dist/server/pages-page-response.js +2 -1
  238. package/dist/server/pages-page-response.js.map +1 -1
  239. package/dist/server/prerender-work-unit-setup.d.ts +7 -0
  240. package/dist/server/prerender-work-unit-setup.js +30 -0
  241. package/dist/server/prerender-work-unit-setup.js.map +1 -0
  242. package/dist/server/prod-server.js +12 -14
  243. package/dist/server/prod-server.js.map +1 -1
  244. package/dist/server/request-pipeline.d.ts +46 -5
  245. package/dist/server/request-pipeline.js +84 -5
  246. package/dist/server/request-pipeline.js.map +1 -1
  247. package/dist/server/rsc-stream-hints.d.ts +5 -0
  248. package/dist/server/rsc-stream-hints.js +35 -0
  249. package/dist/server/rsc-stream-hints.js.map +1 -0
  250. package/dist/server/seed-cache.js.map +1 -1
  251. package/dist/server/server-action-not-found.d.ts +9 -0
  252. package/dist/server/server-action-not-found.js +40 -0
  253. package/dist/server/server-action-not-found.js.map +1 -0
  254. package/dist/server/socket-error-backstop.d.ts +17 -0
  255. package/dist/server/socket-error-backstop.js +129 -0
  256. package/dist/server/socket-error-backstop.js.map +1 -0
  257. package/dist/server/static-file-cache.d.ts +1 -1
  258. package/dist/server/static-file-cache.js.map +1 -1
  259. package/dist/shims/cache-runtime.js +16 -3
  260. package/dist/shims/cache-runtime.js.map +1 -1
  261. package/dist/shims/cache.d.ts +27 -2
  262. package/dist/shims/cache.js +135 -24
  263. package/dist/shims/cache.js.map +1 -1
  264. package/dist/shims/error-boundary.d.ts +49 -4
  265. package/dist/shims/error-boundary.js +76 -4
  266. package/dist/shims/error-boundary.js.map +1 -1
  267. package/dist/shims/fetch-cache.d.ts +10 -1
  268. package/dist/shims/fetch-cache.js +24 -4
  269. package/dist/shims/fetch-cache.js.map +1 -1
  270. package/dist/shims/font-google-base.d.ts +21 -22
  271. package/dist/shims/font-google-base.js +86 -29
  272. package/dist/shims/font-google-base.js.map +1 -1
  273. package/dist/shims/form.js +1 -1
  274. package/dist/shims/headers.d.ts +14 -2
  275. package/dist/shims/headers.js +127 -17
  276. package/dist/shims/headers.js.map +1 -1
  277. package/dist/shims/image.js +26 -8
  278. package/dist/shims/image.js.map +1 -1
  279. package/dist/shims/internal/make-hanging-promise.d.ts +16 -0
  280. package/dist/shims/internal/make-hanging-promise.js +46 -0
  281. package/dist/shims/internal/make-hanging-promise.js.map +1 -0
  282. package/dist/shims/internal/work-unit-async-storage.d.ts +26 -3
  283. package/dist/shims/internal/work-unit-async-storage.js +6 -3
  284. package/dist/shims/internal/work-unit-async-storage.js.map +1 -1
  285. package/dist/shims/link.js +1 -1
  286. package/dist/shims/metadata.d.ts +38 -26
  287. package/dist/shims/metadata.js +75 -45
  288. package/dist/shims/metadata.js.map +1 -1
  289. package/dist/shims/navigation.d.ts +17 -4
  290. package/dist/shims/navigation.js +29 -6
  291. package/dist/shims/navigation.js.map +1 -1
  292. package/dist/shims/navigation.react-server.d.ts +2 -2
  293. package/dist/shims/navigation.react-server.js +2 -2
  294. package/dist/shims/navigation.react-server.js.map +1 -1
  295. package/dist/shims/offline.d.ts +5 -0
  296. package/dist/shims/offline.js +17 -0
  297. package/dist/shims/offline.js.map +1 -0
  298. package/dist/shims/request-state-types.d.ts +2 -1
  299. package/dist/shims/root-params.d.ts +11 -0
  300. package/dist/shims/root-params.js +24 -0
  301. package/dist/shims/root-params.js.map +1 -0
  302. package/dist/shims/router.js +1 -1
  303. package/dist/shims/server.d.ts +5 -1
  304. package/dist/shims/server.js +101 -10
  305. package/dist/shims/server.js.map +1 -1
  306. package/dist/shims/thenable-params.d.ts +5 -0
  307. package/dist/shims/thenable-params.js +37 -0
  308. package/dist/shims/thenable-params.js.map +1 -0
  309. package/dist/shims/unified-request-context.d.ts +2 -1
  310. package/dist/shims/unified-request-context.js +4 -0
  311. package/dist/shims/unified-request-context.js.map +1 -1
  312. package/dist/shims/url-safety.d.ts +3 -1
  313. package/dist/shims/url-safety.js +5 -1
  314. package/dist/shims/url-safety.js.map +1 -1
  315. package/dist/utils/error-cause.d.ts +5 -0
  316. package/dist/utils/error-cause.js +97 -0
  317. package/dist/utils/error-cause.js.map +1 -0
  318. package/dist/utils/lazy-chunks.d.ts +1 -1
  319. package/dist/utils/lazy-chunks.js.map +1 -1
  320. package/package.json +6 -1
  321. package/dist/server/middleware-codegen.d.ts +0 -54
  322. package/dist/server/middleware-codegen.js +0 -414
  323. package/dist/server/middleware-codegen.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"app-browser-entry.js","names":[],"sources":["../../src/server/app-browser-entry.ts"],"sourcesContent":["/// <reference types=\"vite/client\" />\n\nimport {\n createElement,\n startTransition,\n use,\n useLayoutEffect,\n useRef,\n useState,\n type Dispatch,\n type ReactNode,\n} from \"react\";\nimport {\n createFromFetch,\n createFromReadableStream,\n createTemporaryReferenceSet,\n encodeReply,\n setServerCallback,\n} from \"@vitejs/plugin-rsc/browser\";\nimport { hydrateRoot } from \"react-dom/client\";\nimport \"../client/instrumentation-client.js\";\nimport { notifyAppRouterTransitionStart } from \"../client/instrumentation-client-state.js\";\nimport {\n __basePath,\n activateNavigationSnapshot,\n clearPendingPathname,\n commitClientNavigationState,\n consumePrefetchResponse,\n createClientNavigationRenderSnapshot,\n getCurrentNextUrl,\n getCurrentInterceptionContext,\n getClientNavigationRenderContext,\n getClientNavigationState,\n getPrefetchCache,\n getPrefetchedUrls,\n pushHistoryStateWithoutNotify,\n replaceClientParamsWithoutNotify,\n replaceHistoryStateWithoutNotify,\n restoreRscResponse,\n setClientParams,\n setPendingPathname,\n snapshotRscResponse,\n setMountedSlotsHeader,\n setNavigationContext,\n toRscUrl,\n type CachedRscResponse,\n type ClientNavigationRenderSnapshot,\n} from \"../shims/navigation.js\";\nimport { stripBasePath } from \"../utils/base-path.js\";\nimport {\n chunksToReadableStream,\n createProgressiveRscStream,\n getVinextBrowserGlobal,\n} from \"./app-browser-stream.js\";\nimport {\n createAppPayloadCacheKey,\n getMountedSlotIdsHeader,\n normalizeAppElements,\n readAppElementsMetadata,\n resolveVisitedResponseInterceptionContext,\n type AppElements,\n type AppWireElements,\n type LayoutFlags,\n} from \"./app-elements.js\";\nimport {\n createHistoryStateWithPreviousNextUrl,\n createPendingNavigationCommit,\n readHistoryStatePreviousNextUrl,\n resolveAndClassifyNavigationCommit,\n resolveInterceptionContextFromPreviousNextUrl,\n resolvePendingNavigationCommitDisposition,\n resolveServerActionRequestState,\n routerReducer,\n type AppRouterAction,\n type AppRouterState,\n} from \"./app-browser-state.js\";\nimport { ElementsContext, Slot } from \"../shims/slot.js\";\nimport { devOnCaughtError } from \"./app-browser-error.js\";\n\ntype SearchParamInput = ConstructorParameters<typeof URLSearchParams>[0];\n\ntype ServerActionResult = {\n root: AppWireElements;\n returnValue?: {\n ok: boolean;\n data: unknown;\n };\n};\n\ntype NavigationKind = \"navigate\" | \"traverse\" | \"refresh\";\n\n// Maps NavigationKind to the AppRouterAction type used by the reducer.\n// \"refresh\" is intentionally treated as \"navigate\" (merge, preserve absent slots).\n// Both call sites must stay in sync — update here if NavigationKind gains new values.\nfunction toActionType(kind: NavigationKind): \"navigate\" | \"traverse\" {\n return kind === \"traverse\" ? \"traverse\" : \"navigate\";\n}\n\ntype HistoryUpdateMode = \"push\" | \"replace\";\ntype VisitedResponseCacheEntry = {\n params: Record<string, string | string[]>;\n expiresAt: number;\n response: CachedRscResponse;\n};\n\nconst MAX_VISITED_RESPONSE_CACHE_SIZE = 50;\nconst VISITED_RESPONSE_CACHE_TTL = 5 * 60_000;\nconst MAX_TRAVERSAL_CACHE_TTL = 30 * 60_000;\n\n// These are plain module-level variables, unlike ClientNavigationState in\n// navigation.ts which uses Symbol.for to survive multiple Vite module instances.\n// The browser entry is loaded exactly once (via the RSC plugin's generated\n// bootstrap), so module-level state is safe here. If that assumption ever\n// changes, these should be migrated to a Symbol.for-backed global.\n//\n// The most severe consequence of multiple instances would be Map fragmentation:\n// pendingNavigationCommits and pendingNavigationPrePaintEffects would split\n// across instances, so drainPrePaintEffects in one instance could never drain\n// effects queued by the other, permanently leaking navigationSnapshotActiveCount\n// and causing hooks to prefer stale snapshot values indefinitely.\nlet nextNavigationRenderId = 0;\nlet activeNavigationId = 0;\nconst pendingNavigationCommits = new Map<number, () => void>();\nconst pendingNavigationPrePaintEffects = new Map<number, () => void>();\ntype PendingBrowserRouterState = {\n promise: Promise<AppRouterState>;\n resolve: (state: AppRouterState) => void;\n settled: boolean;\n};\n\nfunction isRouterStatePromise(\n value: AppRouterState | Promise<AppRouterState>,\n): value is Promise<AppRouterState> {\n return value instanceof Promise;\n}\n\nlet setBrowserRouterState: Dispatch<AppRouterState | Promise<AppRouterState>> | null = null;\nlet browserRouterStateRef: { current: AppRouterState } | null = null;\nlet activePendingBrowserRouterState: PendingBrowserRouterState | null = null;\nlet latestClientParams: Record<string, string | string[]> = {};\nconst visitedResponseCache = new Map<string, VisitedResponseCacheEntry>();\n\nfunction isServerActionResult(value: unknown): value is ServerActionResult {\n return !!value && typeof value === \"object\" && \"root\" in value;\n}\n\nfunction getBrowserRouterStateSetter(): Dispatch<AppRouterState | Promise<AppRouterState>> {\n if (!setBrowserRouterState) {\n throw new Error(\"[vinext] Browser router state setter is not initialized\");\n }\n return setBrowserRouterState;\n}\n\nfunction getBrowserRouterState(): AppRouterState {\n if (!browserRouterStateRef) {\n throw new Error(\"[vinext] Browser router state is not initialized\");\n }\n return browserRouterStateRef.current;\n}\n\nfunction beginPendingBrowserRouterState(): PendingBrowserRouterState {\n const setter = getBrowserRouterStateSetter();\n\n if (activePendingBrowserRouterState && !activePendingBrowserRouterState.settled) {\n activePendingBrowserRouterState.settled = true;\n activePendingBrowserRouterState.resolve(getBrowserRouterState());\n }\n\n let resolve!: (state: AppRouterState) => void;\n const promise = new Promise<AppRouterState>((resolvePromise) => {\n resolve = resolvePromise;\n });\n\n const pending: PendingBrowserRouterState = {\n promise,\n resolve,\n settled: false,\n };\n\n activePendingBrowserRouterState = pending;\n setter(promise);\n\n return pending;\n}\n\nfunction settlePendingBrowserRouterState(\n pending: PendingBrowserRouterState | null | undefined,\n): void {\n if (!pending || pending.settled) return;\n\n pending.settled = true;\n pending.resolve(getBrowserRouterState());\n\n if (activePendingBrowserRouterState === pending) {\n activePendingBrowserRouterState = null;\n }\n}\n\nfunction resolvePendingBrowserRouterState(\n pending: PendingBrowserRouterState | null | undefined,\n action: AppRouterAction,\n): void {\n if (!pending || pending.settled) return;\n\n pending.settled = true;\n pending.resolve(routerReducer(getBrowserRouterState(), action));\n\n if (activePendingBrowserRouterState === pending) {\n activePendingBrowserRouterState = null;\n }\n}\n\nfunction applyClientParams(params: Record<string, string | string[]>): void {\n latestClientParams = params;\n setClientParams(params);\n}\n\nfunction stageClientParams(params: Record<string, string | string[]>): void {\n // NB: latestClientParams diverges from ClientNavigationState.clientParams\n // between staging and commit. Server action snapshots (same-URL\n // commitSameUrlNavigatePayload() calls inside registerServerActionCallback)\n // read latestClientParams, so a\n // server action fired during this window would get the pending (not yet\n // committed) params. This is acceptable because the commit effect fires\n // before hooks observe the new URL state, keeping the window vanishingly small.\n latestClientParams = params;\n replaceClientParamsWithoutNotify(params);\n}\n\nfunction clearVisitedResponseCache(): void {\n visitedResponseCache.clear();\n}\n\nfunction clearPrefetchState(): void {\n getPrefetchCache().clear();\n getPrefetchedUrls().clear();\n}\n\nfunction clearClientNavigationCaches(): void {\n clearVisitedResponseCache();\n clearPrefetchState();\n}\n\nfunction queuePrePaintNavigationEffect(renderId: number, effect: (() => void) | null): void {\n if (!effect) {\n return;\n }\n pendingNavigationPrePaintEffects.set(renderId, effect);\n}\n\n/**\n * Run all queued pre-paint effects for renderIds up to and including the\n * given renderId. When React supersedes a startTransition update (rapid\n * clicks on same-route links), the superseded NavigationCommitSignal never\n * mounts, so its pre-paint effect never fires. By draining all effects\n * <= the committed renderId here, the winning transition cleans up after\n * any superseded ones, keeping the counter balanced.\n *\n * Invariant: each superseded navigation gets a commitClientNavigationState()\n * to balance the activateNavigationSnapshot() from its renderNavigationPayload call.\n */\nfunction drainPrePaintEffects(upToRenderId: number): void {\n for (const [id, effect] of pendingNavigationPrePaintEffects) {\n if (id <= upToRenderId) {\n pendingNavigationPrePaintEffects.delete(id);\n if (id === upToRenderId) {\n // Winning navigation: run its actual pre-paint effect\n effect();\n } else {\n // Superseded navigation: balance its activateNavigationSnapshot().\n // Pass undefined navId intentionally so this cleanup cannot clear\n // pendingPathname owned by the current active navigation.\n commitClientNavigationState(undefined);\n }\n }\n }\n}\n\nfunction createNavigationCommitEffect(\n href: string,\n historyUpdateMode: HistoryUpdateMode | undefined,\n navId: number,\n params: Record<string, string | string[]>,\n previousNextUrl: string | null,\n): () => void {\n return () => {\n // Only update URL if this is still the active navigation.\n // A newer navigation would have incremented activeNavigationId.\n if (navId !== activeNavigationId) {\n // This transition was superseded before commit; balance the active\n // snapshot counter without clearing pendingPathname ownership.\n commitClientNavigationState(undefined);\n return;\n }\n\n const targetHref = new URL(href, window.location.origin).href;\n stageClientParams(params);\n const preserveExistingState = historyUpdateMode === \"replace\";\n const historyState = createHistoryStateWithPreviousNextUrl(\n preserveExistingState ? window.history.state : null,\n previousNextUrl,\n );\n\n if (historyUpdateMode === \"replace\" && window.location.href !== targetHref) {\n replaceHistoryStateWithoutNotify(historyState, \"\", href);\n } else if (historyUpdateMode === \"push\" && window.location.href !== targetHref) {\n pushHistoryStateWithoutNotify(historyState, \"\", href);\n }\n\n commitClientNavigationState(navId);\n };\n}\n\nfunction evictVisitedResponseCacheIfNeeded(): void {\n while (visitedResponseCache.size >= MAX_VISITED_RESPONSE_CACHE_SIZE) {\n const oldest = visitedResponseCache.keys().next().value;\n if (oldest === undefined) {\n return;\n }\n visitedResponseCache.delete(oldest);\n }\n}\n\nfunction getVisitedResponse(\n rscUrl: string,\n interceptionContext: string | null,\n mountedSlotsHeader: string | null,\n navigationKind: NavigationKind,\n): VisitedResponseCacheEntry | null {\n const cacheKey = createAppPayloadCacheKey(rscUrl, interceptionContext);\n const cached = visitedResponseCache.get(cacheKey);\n if (!cached) {\n return null;\n }\n\n if ((cached.response.mountedSlotsHeader ?? null) !== mountedSlotsHeader) {\n visitedResponseCache.delete(cacheKey);\n return null;\n }\n\n if (navigationKind === \"refresh\") {\n return null;\n }\n\n if (navigationKind === \"traverse\") {\n const createdAt = cached.expiresAt - VISITED_RESPONSE_CACHE_TTL;\n if (Date.now() - createdAt >= MAX_TRAVERSAL_CACHE_TTL) {\n visitedResponseCache.delete(cacheKey);\n return null;\n }\n // LRU: promote to most-recently-used (delete + re-insert moves to end of Map)\n visitedResponseCache.delete(cacheKey);\n visitedResponseCache.set(cacheKey, cached);\n return cached;\n }\n\n if (cached.expiresAt > Date.now()) {\n // LRU: promote to most-recently-used\n visitedResponseCache.delete(cacheKey);\n visitedResponseCache.set(cacheKey, cached);\n return cached;\n }\n\n visitedResponseCache.delete(cacheKey);\n return null;\n}\n\nfunction storeVisitedResponseSnapshot(\n rscUrl: string,\n interceptionContext: string | null,\n snapshot: CachedRscResponse,\n params: Record<string, string | string[]>,\n): void {\n const cacheKey = createAppPayloadCacheKey(rscUrl, interceptionContext);\n visitedResponseCache.delete(cacheKey);\n evictVisitedResponseCacheIfNeeded();\n const now = Date.now();\n visitedResponseCache.set(cacheKey, {\n params,\n expiresAt: now + VISITED_RESPONSE_CACHE_TTL,\n response: snapshot,\n });\n}\n\ntype NavigationRequestState = {\n interceptionContext: string | null;\n previousNextUrl: string | null;\n};\n\nfunction getRequestState(\n navigationKind: NavigationKind,\n previousNextUrlOverride?: string | null,\n): NavigationRequestState {\n if (previousNextUrlOverride !== undefined) {\n return {\n interceptionContext: resolveInterceptionContextFromPreviousNextUrl(\n previousNextUrlOverride,\n __basePath,\n ),\n previousNextUrl: previousNextUrlOverride,\n };\n }\n\n switch (navigationKind) {\n case \"navigate\":\n return {\n interceptionContext: getCurrentInterceptionContext(),\n previousNextUrl: getCurrentNextUrl(),\n };\n case \"traverse\": {\n const previousNextUrl = readHistoryStatePreviousNextUrl(window.history.state);\n return {\n interceptionContext: resolveInterceptionContextFromPreviousNextUrl(\n previousNextUrl,\n __basePath,\n ),\n previousNextUrl,\n };\n }\n case \"refresh\": {\n const currentPreviousNextUrl = getBrowserRouterState().previousNextUrl;\n return {\n interceptionContext: resolveInterceptionContextFromPreviousNextUrl(\n currentPreviousNextUrl,\n __basePath,\n ),\n previousNextUrl: currentPreviousNextUrl,\n };\n }\n default: {\n const _exhaustive: never = navigationKind;\n throw new Error(\"[vinext] Unknown navigation kind: \" + String(_exhaustive));\n }\n }\n}\n\nfunction createRscRequestHeaders(interceptionContext: string | null): Headers {\n const headers = new Headers({ Accept: \"text/x-component\" });\n if (interceptionContext !== null) {\n headers.set(\"X-Vinext-Interception-Context\", interceptionContext);\n }\n return headers;\n}\n\n/**\n * Resolve all pending navigation commits with renderId <= the committed renderId.\n * Note: Map iteration handles concurrent deletion safely — entries are visited in\n * insertion order and deletion doesn't affect the iterator's view of remaining entries.\n * This pattern is also used in drainPrePaintEffects with the same semantics.\n */\nfunction resolveCommittedNavigations(renderId: number): void {\n for (const [pendingId, resolve] of pendingNavigationCommits) {\n if (pendingId <= renderId) {\n pendingNavigationCommits.delete(pendingId);\n resolve();\n }\n }\n}\n\nfunction NavigationCommitSignal({\n renderId,\n children,\n}: {\n renderId: number;\n children?: ReactNode;\n}) {\n useLayoutEffect(() => {\n drainPrePaintEffects(renderId);\n\n const frame = requestAnimationFrame(() => {\n resolveCommittedNavigations(renderId);\n });\n\n return () => {\n cancelAnimationFrame(frame);\n // Resolve pending commits to prevent callers from hanging if React\n // unmounts this component without committing (e.g., error boundary).\n resolveCommittedNavigations(renderId);\n };\n }, [renderId]);\n\n return children;\n}\n\nfunction normalizeAppElementsPromise(payload: Promise<AppWireElements>): Promise<AppElements> {\n // Wrap in Promise.resolve() because createFromReadableStream() returns a\n // React Flight thenable whose .then() returns undefined (not a new Promise).\n // Without the wrap, chaining .then() produces undefined → use() crashes.\n return Promise.resolve(payload).then((elements) => normalizeAppElements(elements));\n}\n\nasync function commitSameUrlNavigatePayload(\n nextElements: Promise<AppElements>,\n returnValue?: ServerActionResult[\"returnValue\"],\n): Promise<unknown> {\n const navigationSnapshot = createClientNavigationRenderSnapshot(\n window.location.href,\n latestClientParams,\n );\n const currentState = getBrowserRouterState();\n const startedNavigationId = activeNavigationId;\n const { disposition, pending } = await resolveAndClassifyNavigationCommit({\n activeNavigationId,\n currentState,\n navigationSnapshot,\n nextElements,\n renderId: ++nextNavigationRenderId,\n startedNavigationId,\n type: \"navigate\",\n });\n\n // Known limitation: if a same-URL navigation fully commits while this\n // server action is awaiting createPendingNavigationCommit(), the action\n // can still dispatch its older payload afterward. The old pre-2c code had\n // the same race, and Next.js has similar behavior. Tightening this would\n // need a stronger commit-version gate than activeNavigationId alone.\n if (disposition === \"hard-navigate\") {\n window.location.assign(window.location.href);\n return undefined;\n }\n\n if (disposition === \"dispatch\") {\n dispatchBrowserTree(\n pending.action.elements,\n navigationSnapshot,\n pending.action.renderId,\n \"navigate\",\n pending.interceptionContext,\n pending.action.layoutFlags,\n pending.previousNextUrl,\n pending.routeId,\n pending.rootLayoutTreePath,\n null,\n false,\n );\n }\n\n // Same-URL server actions still return their action value even if the UI\n // update was skipped due to a superseding navigation. That preserves the\n // existing caller contract; a future Phase 2 router state model could make\n // skipped UI updates observable to the caller without conflating them here.\n if (returnValue) {\n if (!returnValue.ok) {\n throw returnValue.data;\n }\n return returnValue.data;\n }\n\n return undefined;\n}\n\nfunction BrowserRoot({\n initialElements,\n initialNavigationSnapshot,\n}: {\n initialElements: Promise<AppElements>;\n initialNavigationSnapshot: ClientNavigationRenderSnapshot;\n}) {\n const resolvedElements = use(initialElements);\n const initialMetadata = readAppElementsMetadata(resolvedElements);\n const [treeStateValue, setTreeStateValue] = useState<AppRouterState | Promise<AppRouterState>>({\n elements: resolvedElements,\n interceptionContext: initialMetadata.interceptionContext,\n layoutFlags: initialMetadata.layoutFlags,\n navigationSnapshot: initialNavigationSnapshot,\n previousNextUrl: null,\n renderId: 0,\n rootLayoutTreePath: initialMetadata.rootLayoutTreePath,\n routeId: initialMetadata.routeId,\n });\n const treeState = isRouterStatePromise(treeStateValue) ? use(treeStateValue) : treeStateValue;\n\n // Keep the latest router state in a ref so external callers (navigate(),\n // server actions, HMR) always read the current state. Safe: those readers\n // run from events/effects, never from React render itself.\n // Note: stateRef.current is written during render, not in an effect, to\n // avoid a stale-read window between commit and layout effects. This mirrors\n // the same render-phase ref update pattern used by Next.js's own router.\n const stateRef = useRef(treeState);\n stateRef.current = treeState;\n\n // Publish the stable ref object and dispatch during layout commit. This keeps\n // the module-level escape hatches aligned with React's committed tree without\n // performing module writes during render. __VINEXT_RSC_NAVIGATE__ is assigned\n // after hydrateRoot() returns; by then this layout effect has already run for\n // the hydration commit, so getBrowserRouterState() never observes a null ref.\n useLayoutEffect(() => {\n setBrowserRouterState = setTreeStateValue;\n browserRouterStateRef = stateRef;\n return () => {\n if (setBrowserRouterState === setTreeStateValue) {\n setBrowserRouterState = null;\n }\n if (browserRouterStateRef === stateRef) {\n browserRouterStateRef = null;\n }\n setMountedSlotsHeader(null);\n };\n }, [setTreeStateValue]);\n\n useLayoutEffect(() => {\n setMountedSlotsHeader(getMountedSlotIdsHeader(stateRef.current.elements));\n }, [treeState.elements]);\n\n useLayoutEffect(() => {\n if (treeState.renderId !== 0) {\n return;\n }\n\n replaceHistoryStateWithoutNotify(\n createHistoryStateWithPreviousNextUrl(window.history.state, treeState.previousNextUrl),\n \"\",\n window.location.href,\n );\n }, [treeState.previousNextUrl, treeState.renderId]);\n\n const committedTree = createElement(\n NavigationCommitSignal,\n { renderId: treeState.renderId },\n createElement(\n ElementsContext.Provider,\n { value: treeState.elements },\n createElement(Slot, { id: treeState.routeId }),\n ),\n );\n\n const ClientNavigationRenderContext = getClientNavigationRenderContext();\n if (!ClientNavigationRenderContext) {\n return committedTree;\n }\n\n return createElement(\n ClientNavigationRenderContext.Provider,\n { value: treeState.navigationSnapshot },\n committedTree,\n );\n}\n\nfunction dispatchBrowserTree(\n elements: AppElements,\n navigationSnapshot: ClientNavigationRenderSnapshot,\n renderId: number,\n actionType: \"navigate\" | \"replace\" | \"traverse\",\n interceptionContext: string | null,\n layoutFlags: LayoutFlags,\n previousNextUrl: string | null,\n routeId: string,\n rootLayoutTreePath: string | null,\n pendingRouterState: PendingBrowserRouterState | null,\n useTransitionMode: boolean,\n): void {\n const setter = getBrowserRouterStateSetter();\n const action: AppRouterAction = {\n elements,\n interceptionContext,\n layoutFlags,\n navigationSnapshot,\n previousNextUrl,\n renderId,\n rootLayoutTreePath,\n routeId,\n type: actionType,\n };\n\n const applyAction = () => {\n if (pendingRouterState) {\n // The programmatic navigation is already running inside React.startTransition\n // (from router.push/replace/refresh), so resolving the deferred promise is\n // sufficient — no additional startTransition wrapper is needed below.\n resolvePendingBrowserRouterState(pendingRouterState, action);\n return;\n }\n\n setter(routerReducer(getBrowserRouterState(), action));\n };\n\n if (useTransitionMode) {\n startTransition(applyAction);\n } else {\n applyAction();\n }\n}\n\nasync function renderNavigationPayload(\n payload: Promise<AppElements>,\n navigationSnapshot: ClientNavigationRenderSnapshot,\n targetHref: string,\n navId: number,\n historyUpdateMode: HistoryUpdateMode | undefined,\n params: Record<string, string | string[]>,\n previousNextUrl: string | null,\n pendingRouterState: PendingBrowserRouterState | null,\n useTransition = true,\n actionType: \"navigate\" | \"replace\" | \"traverse\" = \"navigate\",\n): Promise<void> {\n const renderId = ++nextNavigationRenderId;\n const committed = new Promise<void>((resolve) => {\n pendingNavigationCommits.set(renderId, resolve);\n });\n\n let snapshotActivated = false;\n try {\n const currentState = getBrowserRouterState();\n const pending = await createPendingNavigationCommit({\n currentState,\n nextElements: payload,\n navigationSnapshot,\n previousNextUrl,\n renderId,\n type: actionType,\n });\n\n const disposition = resolvePendingNavigationCommitDisposition({\n activeNavigationId,\n currentRootLayoutTreePath: currentState.rootLayoutTreePath,\n nextRootLayoutTreePath: pending.rootLayoutTreePath,\n startedNavigationId: navId,\n });\n\n if (disposition === \"skip\") {\n settlePendingBrowserRouterState(pendingRouterState);\n const resolve = pendingNavigationCommits.get(renderId);\n pendingNavigationCommits.delete(renderId);\n resolve?.();\n return;\n }\n\n if (disposition === \"hard-navigate\") {\n settlePendingBrowserRouterState(pendingRouterState);\n pendingNavigationCommits.delete(renderId);\n window.location.assign(targetHref);\n return;\n }\n\n queuePrePaintNavigationEffect(\n renderId,\n createNavigationCommitEffect(\n targetHref,\n historyUpdateMode,\n navId,\n params,\n pending.previousNextUrl,\n ),\n );\n activateNavigationSnapshot();\n snapshotActivated = true;\n dispatchBrowserTree(\n pending.action.elements,\n navigationSnapshot,\n renderId,\n actionType,\n pending.interceptionContext,\n pending.action.layoutFlags,\n pending.previousNextUrl,\n pending.routeId,\n pending.rootLayoutTreePath,\n pendingRouterState,\n useTransition,\n );\n } catch (error) {\n // Clean up pending state on error. Only decrement the snapshot counter\n // if activateNavigationSnapshot() was actually called — if\n // createPendingNavigationCommit() threw, the counter was never\n // incremented so decrementing would underflow it.\n pendingNavigationPrePaintEffects.delete(renderId);\n const resolve = pendingNavigationCommits.get(renderId);\n pendingNavigationCommits.delete(renderId);\n if (snapshotActivated) {\n commitClientNavigationState(navId);\n }\n settlePendingBrowserRouterState(pendingRouterState);\n resolve?.();\n throw error;\n }\n\n return committed;\n}\n\nfunction restoreHydrationNavigationContext(\n pathname: string,\n searchParams: SearchParamInput,\n params: Record<string, string | string[]>,\n): void {\n setNavigationContext({\n pathname,\n searchParams: new URLSearchParams(searchParams),\n params,\n });\n}\n\nfunction restorePopstateScrollPosition(state: unknown): void {\n if (!(state && typeof state === \"object\" && \"__vinext_scrollY\" in state)) {\n return;\n }\n\n const y = Number(state.__vinext_scrollY);\n const x = \"__vinext_scrollX\" in state ? Number(state.__vinext_scrollX) : 0;\n\n requestAnimationFrame(() => {\n window.scrollTo(x, y);\n });\n}\n\n// Set on pagehide so the RSC navigation catch block can distinguish expected\n// fetch aborts (triggered by the unload itself) from real errors worth logging.\nlet isPageUnloading = false;\n\nconst RSC_RELOAD_KEY = \"__vinext_rsc_initial_reload__\";\n\n// sessionStorage can throw SecurityError in strict-mode iframes, storage-\n// disabled browsers, and some Safari private-browsing configurations. Wrap\n// every access so a recovery path for one error does not crash hydration.\nfunction readReloadFlag(): string | null {\n try {\n return sessionStorage.getItem(RSC_RELOAD_KEY);\n } catch {\n return null;\n }\n}\nfunction writeReloadFlag(path: string): void {\n try {\n sessionStorage.setItem(RSC_RELOAD_KEY, path);\n } catch {}\n}\nfunction clearReloadFlag(): void {\n try {\n sessionStorage.removeItem(RSC_RELOAD_KEY);\n } catch {}\n}\n\n// A non-ok or wrong-content-type RSC response during initial hydration means\n// the server cannot deliver a valid RSC payload for this URL. Parsing the\n// response as RSC causes an opaque parse failure. On the first attempt,\n// reload once so the server has a chance to render the correct error page\n// as HTML. On the second attempt (detected via the sessionStorage flag), the\n// endpoint is persistently broken. Returns null so main() aborts the\n// hydration bootstrap without registering `__VINEXT_RSC_*` globals —\n// including during the brief window between reload() firing and the page\n// actually unloading — so external probes never see a half-hydrated page.\nfunction recoverFromBadInitialRscResponse(reason: string): null {\n const currentPath = window.location.pathname + window.location.search;\n if (readReloadFlag() === currentPath) {\n clearReloadFlag();\n console.error(\n `[vinext] Initial RSC fetch ${reason} after reload; aborting hydration. ` +\n \"Server-rendered HTML remains visible; client components will not hydrate.\",\n );\n return null;\n }\n writeReloadFlag(currentPath);\n // Verify the write persisted. In storage-denied environments (strict-mode\n // iframes, locked-down enterprise policies), every getItem returns null and\n // every setItem silently no-ops, so the reload-loop guard cannot survive\n // the reload — the page would loop forever. Abort instead so the user at\n // least sees the server-rendered HTML.\n if (readReloadFlag() !== currentPath) {\n console.error(\n `[vinext] Initial RSC fetch ${reason}; sessionStorage unavailable so the ` +\n \"reload-loop guard cannot persist — aborting hydration. \" +\n \"Server-rendered HTML remains visible; client components will not hydrate.\",\n );\n return null;\n }\n // One-shot diagnostic so a production reload is traceable. Only fires once\n // per broken path thanks to the sessionStorage flag above; not noisy.\n console.warn(\n `[vinext] Initial RSC fetch ${reason}; reloading once to let the server render the HTML error page`,\n );\n window.location.reload();\n return null;\n}\n\nasync function readInitialRscStream(): Promise<ReadableStream<Uint8Array> | null> {\n const vinext = getVinextBrowserGlobal();\n\n if (vinext.__VINEXT_RSC__ || vinext.__VINEXT_RSC_CHUNKS__ || vinext.__VINEXT_RSC_DONE__) {\n // Reaching the embedded-RSC branch means the server successfully rendered\n // the page — any prior reload flag for this path is stale and must be\n // cleared so a future failure gets its own fresh recovery attempt.\n clearReloadFlag();\n\n if (vinext.__VINEXT_RSC__) {\n const embedData = vinext.__VINEXT_RSC__;\n delete vinext.__VINEXT_RSC__;\n\n const params = embedData.params ?? {};\n if (embedData.params) {\n applyClientParams(embedData.params);\n }\n if (embedData.nav) {\n restoreHydrationNavigationContext(\n embedData.nav.pathname,\n embedData.nav.searchParams,\n params,\n );\n }\n\n return chunksToReadableStream(embedData.rsc);\n }\n\n const params = vinext.__VINEXT_RSC_PARAMS__ ?? {};\n if (vinext.__VINEXT_RSC_PARAMS__) {\n applyClientParams(vinext.__VINEXT_RSC_PARAMS__);\n }\n if (vinext.__VINEXT_RSC_NAV__) {\n restoreHydrationNavigationContext(\n vinext.__VINEXT_RSC_NAV__.pathname,\n vinext.__VINEXT_RSC_NAV__.searchParams,\n params,\n );\n }\n\n return createProgressiveRscStream();\n }\n\n const rscResponse = await fetch(toRscUrl(window.location.pathname + window.location.search));\n\n if (!rscResponse.ok) {\n return recoverFromBadInitialRscResponse(`returned ${rscResponse.status}`);\n }\n // Guard against proxies/CDNs that return 200 with a rewritten Content-Type\n // (e.g. text/html instead of text/x-component). Such responses cannot be\n // parsed as RSC and would throw the same opaque parse error this fallback\n // exists to prevent.\n const contentType = rscResponse.headers.get(\"content-type\") ?? \"\";\n if (!contentType.startsWith(\"text/x-component\")) {\n return recoverFromBadInitialRscResponse(\n `returned non-RSC content-type \"${contentType || \"(missing)\"}\"`,\n );\n }\n // Missing body (e.g. 204 No Content, or an edge worker that returned ok\n // headers without piping the stream) fails the same way downstream.\n // Matches Next.js' `!res.body` branch in fetch-server-response.ts.\n if (!rscResponse.body) {\n return recoverFromBadInitialRscResponse(\"returned empty body\");\n }\n // Successful RSC response clears the guard so a subsequent reload of the\n // same path after a transient failure still gets one recovery attempt.\n clearReloadFlag();\n\n let params: Record<string, string | string[]> = {};\n const paramsHeader = rscResponse.headers.get(\"X-Vinext-Params\");\n if (paramsHeader) {\n try {\n params = JSON.parse(decodeURIComponent(paramsHeader)) as Record<string, string | string[]>;\n applyClientParams(params);\n } catch {\n // Ignore malformed param headers and continue with hydration.\n }\n }\n\n restoreHydrationNavigationContext(window.location.pathname, window.location.search, params);\n\n return rscResponse.body;\n}\n\nfunction registerServerActionCallback(): void {\n setServerCallback(async (id, args) => {\n const temporaryReferences = createTemporaryReferenceSet();\n const body = await encodeReply(args, { temporaryReferences });\n\n // Carry the interception context + mounted slots from the current router\n // state so the server-action re-render rebuilds the intercepted tree\n // instead of replacing it with the direct page. Parity with Next.js,\n // which sends `Next-URL` on action POSTs when the current tree contains\n // an interception route.\n const currentState = getBrowserRouterState();\n const { headers } = resolveServerActionRequestState({\n actionId: id,\n basePath: __basePath,\n elements: currentState.elements,\n previousNextUrl: currentState.previousNextUrl,\n });\n\n const fetchResponse = await fetch(toRscUrl(window.location.pathname + window.location.search), {\n method: \"POST\",\n headers,\n body,\n });\n\n const actionRedirect = fetchResponse.headers.get(\"x-action-redirect\");\n if (actionRedirect) {\n // Check for external URLs that need a hard redirect.\n try {\n const redirectUrl = new URL(actionRedirect, window.location.origin);\n if (redirectUrl.origin !== window.location.origin) {\n window.location.href = actionRedirect;\n return undefined;\n }\n } catch {\n // Fall through to hard redirect below if URL parsing fails.\n }\n\n // Use hard redirect for all action redirects because vinext's server\n // currently returns an empty body for redirect responses. RSC navigation\n // requires a valid RSC payload. This is a known parity gap with Next.js,\n // which pre-renders the redirect target's RSC payload.\n const redirectType = fetchResponse.headers.get(\"x-action-redirect-type\") ?? \"replace\";\n if (redirectType === \"push\") {\n window.location.assign(actionRedirect);\n } else {\n window.location.replace(actionRedirect);\n }\n return undefined;\n }\n\n clearClientNavigationCaches();\n\n const result = await createFromFetch<ServerActionResult | AppWireElements>(\n Promise.resolve(fetchResponse),\n { temporaryReferences },\n );\n\n // Server actions stay on the same URL and use commitSameUrlNavigatePayload()\n // for merge-based dispatch. This path does not call\n // activateNavigationSnapshot() because there is no URL change to commit, so\n // hooks continue reading the live external-store values directly. If server\n // actions ever trigger URL changes via RSC payload (instead of hard\n // redirects), this would need renderNavigationPayload().\n if (isServerActionResult(result)) {\n return commitSameUrlNavigatePayload(\n Promise.resolve(normalizeAppElements(result.root)),\n result.returnValue,\n );\n }\n\n return commitSameUrlNavigatePayload(Promise.resolve(normalizeAppElements(result)));\n });\n}\n\nasync function main(): Promise<void> {\n registerServerActionCallback();\n\n const rscStream = await readInitialRscStream();\n // null signals that readInitialRscStream aborted hydration — either because\n // a reload is in flight (first-attempt recovery) or the endpoint is\n // persistently broken (post-reload). Bootstrap is a separate synchronous\n // helper so the null-branch structurally cannot reach any __VINEXT_RSC_*\n // global assignment, even if a future refactor interposes async work here.\n if (rscStream === null) return;\n bootstrapHydration(rscStream);\n}\n\nfunction bootstrapHydration(rscStream: ReadableStream<Uint8Array>): void {\n const root = normalizeAppElementsPromise(createFromReadableStream<AppWireElements>(rscStream));\n const initialNavigationSnapshot = createClientNavigationRenderSnapshot(\n window.location.href,\n latestClientParams,\n );\n replaceHistoryStateWithoutNotify(\n createHistoryStateWithPreviousNextUrl(window.history.state, null),\n \"\",\n window.location.href,\n );\n\n window.__VINEXT_RSC_ROOT__ = hydrateRoot(\n document,\n createElement(BrowserRoot, {\n initialElements: root,\n initialNavigationSnapshot,\n }),\n import.meta.env.DEV ? { onCaughtError: devOnCaughtError } : undefined,\n );\n window.__VINEXT_HYDRATED_AT = performance.now();\n\n window.__VINEXT_RSC_NAVIGATE__ = async function navigateRsc(\n href: string,\n redirectDepth = 0,\n navigationKind: NavigationKind = \"navigate\",\n historyUpdateMode?: HistoryUpdateMode,\n previousNextUrlOverride?: string | null,\n programmaticTransition = false,\n ): Promise<void> {\n let _snapshotPending = false;\n let pendingRouterState: PendingBrowserRouterState | null = null;\n // Hoist navId above try so the catch and finally blocks can reference it.\n const navId = ++activeNavigationId;\n\n // Loop variables for inline redirect following. On a redirect, these are\n // updated and the loop continues without returning or re-entering navigateRsc,\n // so a single pendingRouterState spans all hops and isPending never flashes.\n let currentHref = href;\n let currentHistoryMode = historyUpdateMode;\n let currentPrevNextUrl = previousNextUrlOverride;\n let redirectCount = redirectDepth;\n\n try {\n if (programmaticTransition) {\n pendingRouterState = beginPendingBrowserRouterState();\n }\n\n while (true) {\n if (redirectCount > 10) {\n console.error(\n \"[vinext] Too many RSC redirects — aborting navigation to prevent infinite loop.\",\n );\n window.location.href = currentHref;\n return;\n }\n\n const url = new URL(currentHref, window.location.origin);\n const rscUrl = toRscUrl(url.pathname + url.search);\n const requestState = getRequestState(navigationKind, currentPrevNextUrl);\n const requestInterceptionContext = requestState.interceptionContext;\n const requestPreviousNextUrl = requestState.previousNextUrl;\n\n // Compare against previous pending navigation first, then committed state.\n // This avoids isSameRoute misclassification during rapid back-to-back clicks.\n const navState = getClientNavigationState();\n const currentPath =\n navState?.pendingPathname ??\n navState?.cachedPathname ??\n stripBasePath(window.location.pathname, __basePath);\n\n const targetPath = stripBasePath(url.pathname, __basePath);\n const isSameRoute = targetPath === currentPath;\n\n // Set this navigation as the pending pathname, overwriting any previous.\n // Pass navId so only this navigation (or a newer one) can clear it later.\n setPendingPathname(url.pathname, navId);\n\n const elementsAtNavStart = getBrowserRouterState().elements;\n const mountedSlotsHeader = getMountedSlotIdsHeader(elementsAtNavStart);\n const cachedRoute = getVisitedResponse(\n rscUrl,\n requestInterceptionContext,\n mountedSlotsHeader,\n navigationKind,\n );\n if (cachedRoute) {\n // Check stale-navigation before and after createFromFetch. The pre-check\n // avoids wasted parse work; the post-check catches supersessions that\n // occur during the await. createFromFetch on a buffered response is fast\n // but still async, so the window exists. The non-cached path (below) places\n // its heavyweight async steps (fetch, snapshotRscResponse, createFromFetch)\n // between navId checks consistently; the cached path omits the check between\n // createClientNavigationRenderSnapshot (synchronous) and createFromFetch\n // because there is no await in that gap.\n if (navId !== activeNavigationId) return;\n const cachedParams = cachedRoute.params;\n // createClientNavigationRenderSnapshot is synchronous (URL parsing + param\n // wrapping only) — no stale-navigation recheck needed between here and the\n // next await.\n const cachedNavigationSnapshot = createClientNavigationRenderSnapshot(\n currentHref,\n cachedParams,\n );\n const cachedPayload = normalizeAppElementsPromise(\n createFromFetch<AppWireElements>(\n Promise.resolve(restoreRscResponse(cachedRoute.response)),\n ),\n );\n if (navId !== activeNavigationId) return;\n _snapshotPending = true; // Set before renderNavigationPayload\n try {\n await renderNavigationPayload(\n cachedPayload,\n cachedNavigationSnapshot,\n currentHref,\n navId,\n currentHistoryMode,\n cachedParams,\n requestPreviousNextUrl,\n pendingRouterState,\n isSameRoute,\n toActionType(navigationKind),\n );\n } finally {\n // Always clear _snapshotPending so the outer catch does not\n // double-decrement if renderNavigationPayload throws.\n _snapshotPending = false;\n }\n return;\n }\n\n // Continue using the slot state captured at navigation start for fetches\n // and prefetch compatibility decisions.\n\n let navResponse: Response | undefined;\n let navResponseUrl: string | null = null;\n if (navigationKind !== \"refresh\") {\n const prefetchedResponse = consumePrefetchResponse(\n rscUrl,\n requestInterceptionContext,\n mountedSlotsHeader,\n );\n if (prefetchedResponse) {\n navResponse = restoreRscResponse(prefetchedResponse, false);\n navResponseUrl = prefetchedResponse.url;\n }\n }\n\n if (!navResponse) {\n const requestHeaders = createRscRequestHeaders(requestInterceptionContext);\n if (mountedSlotsHeader) {\n requestHeaders.set(\"X-Vinext-Mounted-Slots\", mountedSlotsHeader);\n }\n navResponse = await fetch(rscUrl, {\n headers: requestHeaders,\n credentials: \"include\",\n });\n }\n\n if (navId !== activeNavigationId) return;\n\n // Any response that isn't a valid RSC payload (non-ok status,\n // missing/rewritten Content-Type, or missing body) means the server\n // returned something we cannot parse — typically an HTML error page\n // or a proxy-rewritten response. Parsing such a body as an RSC stream\n // throws a cryptic \"Connection closed\" error. Match Next.js behavior\n // (fetch-server-response.ts:211, `!isFlightResponse || !res.ok || !res.body`):\n // hard-navigate to the response URL so the server can render the correct\n // error page as HTML. The outer finally handles\n // settlePendingBrowserRouterState and clearPendingPathname on this\n // return path.\n //\n // Prefer the post-redirect response URL over `currentHref`: on a\n // redirect chain like `/old` → 307 → `/new` → 500, the browser's\n // fetch already followed the redirect, so `navResponse.url` is the\n // failing `/new` destination. Hard-navigating there directly avoids\n // bouncing off `/old` just to re-follow the same 307, which would\n // flash the wrong URL in the address bar and mis-key analytics.\n // Matches Next.js' `doMpaNavigation(responseUrl.toString())`. Falls\n // back to `currentHref` when no response URL is available.\n const navContentType = navResponse.headers.get(\"content-type\") ?? \"\";\n const isRscResponse = navContentType.startsWith(\"text/x-component\");\n if (!navResponse.ok || !isRscResponse || !navResponse.body) {\n const responseUrl = navResponseUrl ?? navResponse.url;\n let hardNavTarget = currentHref;\n if (responseUrl) {\n const parsed = new URL(responseUrl, window.location.origin);\n const origUrl = new URL(currentHref, window.location.origin);\n let pathname = parsed.pathname.replace(/\\.rsc$/, \"\");\n // toRscUrl strips trailing slash before appending .rsc, so the\n // response URL loses it on the round-trip. Restore it when the\n // original href had one so sites with trailingSlash:true don't\n // incur an extra 308 to the canonical form on the error path.\n if (\n origUrl.pathname.length > 1 &&\n origUrl.pathname.endsWith(\"/\") &&\n !pathname.endsWith(\"/\")\n ) {\n pathname += \"/\";\n }\n hardNavTarget = pathname + parsed.search;\n // Preserve the hash from the user's clicked href — a .rsc response\n // URL never carries a fragment, so dropping it would silently strip\n // `/foo#section` down to `/foo`.\n if (origUrl.hash) hardNavTarget += origUrl.hash;\n }\n window.location.href = hardNavTarget;\n return;\n }\n\n const finalUrl = new URL(navResponseUrl ?? navResponse.url, window.location.origin);\n const requestedUrl = new URL(rscUrl, window.location.origin);\n\n if (finalUrl.pathname !== requestedUrl.pathname) {\n // Server-side redirect: update the URL in history and loop to fetch\n // the destination without settling pendingRouterState. This keeps\n // isPending true across all redirect hops instead of flashing false.\n const destinationPath = finalUrl.pathname.replace(/\\.rsc$/, \"\") + finalUrl.search;\n replaceHistoryStateWithoutNotify(\n createHistoryStateWithPreviousNextUrl(null, requestPreviousNextUrl),\n \"\",\n destinationPath,\n );\n\n currentHref = destinationPath;\n // URL already written above; the commit effect must not push/replace again.\n currentHistoryMode = undefined;\n currentPrevNextUrl = requestPreviousNextUrl;\n redirectCount += 1;\n continue;\n }\n\n let navParams: Record<string, string | string[]> = {};\n const paramsHeader = navResponse.headers.get(\"X-Vinext-Params\");\n if (paramsHeader) {\n try {\n navParams = JSON.parse(decodeURIComponent(paramsHeader)) as Record<\n string,\n string | string[]\n >;\n } catch {\n // navParams stays as {}\n }\n }\n // Build snapshot from local params, not latestClientParams\n const navigationSnapshot = createClientNavigationRenderSnapshot(currentHref, navParams);\n\n const responseSnapshot = await snapshotRscResponse(navResponse);\n\n if (navId !== activeNavigationId) return;\n\n const rscPayload = normalizeAppElementsPromise(\n createFromFetch<AppWireElements>(Promise.resolve(restoreRscResponse(responseSnapshot))),\n );\n\n if (navId !== activeNavigationId) return;\n\n _snapshotPending = true; // Set before renderNavigationPayload\n try {\n await renderNavigationPayload(\n rscPayload,\n navigationSnapshot,\n currentHref,\n navId,\n currentHistoryMode,\n navParams,\n requestPreviousNextUrl,\n pendingRouterState,\n isSameRoute,\n toActionType(navigationKind),\n );\n } finally {\n // Always clear _snapshotPending after renderNavigationPayload returns or\n // throws. renderNavigationPayload's inner catch already calls\n // commitClientNavigationState() on synchronous errors and re-throws, so\n // the outer catch must not call it again. Clearing here prevents the outer\n // catch from double-decrementing navigationSnapshotActiveCount.\n _snapshotPending = false;\n }\n // Don't cache the response if this navigation was superseded during\n // renderNavigationPayload's await — the elements were never dispatched.\n if (navId !== activeNavigationId) return;\n // Store the visited response only after renderNavigationPayload succeeds.\n // If we stored it before and renderNavigationPayload threw, a future\n // back/forward navigation could replay a snapshot from a navigation that\n // never actually rendered successfully.\n const resolvedElements = await rscPayload;\n const metadata = readAppElementsMetadata(resolvedElements);\n storeVisitedResponseSnapshot(\n rscUrl,\n resolveVisitedResponseInterceptionContext(\n requestInterceptionContext,\n metadata.interceptionContext,\n ),\n responseSnapshot,\n navParams,\n );\n return;\n }\n } catch (error) {\n // Only decrement counter if snapshot was activated but not yet committed.\n // renderNavigationPayload clears _snapshotPending (via its inner try-finally)\n // before re-throwing, so this guard correctly skips the double-decrement case.\n if (_snapshotPending) {\n _snapshotPending = false;\n commitClientNavigationState(navId);\n }\n // Don't hard-navigate to a stale URL if this navigation was superseded by\n // a newer one — the newer navigation is already in flight and would be clobbered.\n if (navId !== activeNavigationId) return;\n // Suppress the diagnostic when the page is unloading: a hard-nav or anchor\n // click tears down the document and aborts any in-flight RSC fetch, which\n // surfaces here as an error. The page is already going away, so the log\n // is just noise. Mirrors Next.js' isPageUnloading pattern.\n if (!isPageUnloading) {\n console.error(\"[vinext] RSC navigation error:\", error);\n }\n window.location.href = currentHref;\n } finally {\n // Single settlement site: covers normal return, early returns on stale-id\n // checks, and error paths. The finally runs even when the catch returns.\n // settlePendingBrowserRouterState is idempotent via the settled flag.\n settlePendingBrowserRouterState(pendingRouterState);\n // Clear pendingPathname on all exit paths. On the success path this fires\n // before the RAF commit effect, but commitClientNavigationState() in the\n // commit effect clears it again — that double-clear is idempotent. Skipped\n // when superseded so a newer navigation's pendingPathname is not disturbed.\n if (navId === activeNavigationId) {\n clearPendingPathname(navId);\n }\n }\n };\n\n if (\"scrollRestoration\" in history) {\n history.scrollRestoration = \"manual\";\n }\n\n // Note: This popstate handler runs for App Router (RSC navigation available).\n // It coordinates scroll restoration with the pending RSC navigation.\n // Pages Router scroll restoration is handled in shims/navigation.ts:1289 with\n // microtask-based deferral for compatibility with non-RSC navigation.\n // See: https://github.com/vercel/next.js/discussions/41934#discussioncomment-4602607\n window.addEventListener(\"popstate\", (event) => {\n notifyAppRouterTransitionStart(window.location.href, \"traverse\");\n const pendingNavigation =\n window.__VINEXT_RSC_NAVIGATE__?.(window.location.href, 0, \"traverse\") ?? Promise.resolve();\n window.__VINEXT_RSC_PENDING__ = pendingNavigation;\n void pendingNavigation.finally(() => {\n restorePopstateScrollPosition(event.state);\n if (window.__VINEXT_RSC_PENDING__ === pendingNavigation) {\n window.__VINEXT_RSC_PENDING__ = null;\n }\n });\n });\n\n if (import.meta.hot) {\n import.meta.hot.on(\"rsc:update\", async () => {\n try {\n clearClientNavigationCaches();\n const navigationSnapshot = createClientNavigationRenderSnapshot(\n window.location.href,\n latestClientParams,\n );\n // Interception context on HMR re-renders is intentionally deferred:\n // preserving intercepted modal state across HMR reloads is out of scope\n // for the previousNextUrl mechanism.\n const pending = await createPendingNavigationCommit({\n currentState: getBrowserRouterState(),\n nextElements: normalizeAppElementsPromise(\n createFromFetch<AppWireElements>(\n fetch(toRscUrl(window.location.pathname + window.location.search)),\n ),\n ),\n navigationSnapshot,\n renderId: ++nextNavigationRenderId,\n type: \"replace\",\n });\n dispatchBrowserTree(\n pending.action.elements,\n navigationSnapshot,\n pending.action.renderId,\n \"replace\",\n pending.interceptionContext,\n pending.action.layoutFlags,\n pending.previousNextUrl,\n pending.routeId,\n pending.rootLayoutTreePath,\n null,\n false,\n );\n } catch (error) {\n console.error(\"[vinext] RSC HMR error:\", error);\n }\n });\n }\n}\n\nif (typeof document !== \"undefined\") {\n window.addEventListener(\"pagehide\", () => {\n isPageUnloading = true;\n });\n // Reset on pageshow so a bfcache-restored document does not resume with\n // the flag stuck at true, which would silently swallow every subsequent\n // RSC navigation error for the lifetime of that tab. Matches Next.js'\n // fetch-server-response.ts handler pair.\n window.addEventListener(\"pageshow\", () => {\n isPageUnloading = false;\n });\n void main();\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"app-browser-entry.js","names":[],"sources":["../../src/server/app-browser-entry.ts"],"sourcesContent":["/// <reference types=\"vite/client\" />\n\nimport {\n createElement,\n startTransition,\n use,\n useLayoutEffect,\n useRef,\n useState,\n type Dispatch,\n type ReactNode,\n} from \"react\";\nimport {\n createFromFetch,\n createFromReadableStream,\n createTemporaryReferenceSet,\n encodeReply,\n setServerCallback,\n} from \"@vitejs/plugin-rsc/browser\";\nimport { hydrateRoot } from \"react-dom/client\";\nimport \"../client/instrumentation-client.js\";\nimport { notifyAppRouterTransitionStart } from \"../client/instrumentation-client-state.js\";\nimport {\n __basePath,\n activateNavigationSnapshot,\n clearPendingPathname,\n commitClientNavigationState,\n consumePrefetchResponse,\n createClientNavigationRenderSnapshot,\n getCurrentNextUrl,\n getCurrentInterceptionContext,\n getClientNavigationRenderContext,\n getClientNavigationState,\n getPrefetchCache,\n getPrefetchedUrls,\n pushHistoryStateWithoutNotify,\n replaceClientParamsWithoutNotify,\n replaceHistoryStateWithoutNotify,\n restoreRscResponse,\n setClientParams,\n setPendingPathname,\n snapshotRscResponse,\n setMountedSlotsHeader,\n setNavigationContext,\n toRscUrl,\n type CachedRscResponse,\n type ClientNavigationRenderSnapshot,\n} from \"vinext/shims/navigation\";\nimport { stripBasePath } from \"../utils/base-path.js\";\nimport {\n chunksToReadableStream,\n createProgressiveRscStream,\n getVinextBrowserGlobal,\n} from \"./app-browser-stream.js\";\nimport {\n createAppPayloadCacheKey,\n getMountedSlotIdsHeader,\n normalizeAppElements,\n readAppElementsMetadata,\n resolveVisitedResponseInterceptionContext,\n type AppElements,\n type AppWireElements,\n type LayoutFlags,\n} from \"./app-elements.js\";\nimport {\n createHistoryStateWithPreviousNextUrl,\n createPendingNavigationCommit,\n readHistoryStatePreviousNextUrl,\n resolveAndClassifyNavigationCommit,\n resolveInterceptionContextFromPreviousNextUrl,\n resolvePendingNavigationCommitDisposition,\n resolveServerActionRequestState,\n routerReducer,\n type AppRouterAction,\n type AppRouterState,\n} from \"./app-browser-state.js\";\nimport { ElementsContext, Slot } from \"vinext/shims/slot\";\nimport { devOnCaughtError } from \"./app-browser-error.js\";\nimport { DANGEROUS_URL_BLOCK_MESSAGE, isDangerousScheme } from \"vinext/shims/url-safety\";\nimport {\n getServerActionNotFoundClientMessage,\n isServerActionNotFoundResponse,\n} from \"./server-action-not-found.js\";\n\ntype SearchParamInput = ConstructorParameters<typeof URLSearchParams>[0];\n\ntype ServerActionResult = {\n root: AppWireElements;\n returnValue?: {\n ok: boolean;\n data: unknown;\n };\n};\n\ntype NavigationKind = \"navigate\" | \"traverse\" | \"refresh\";\n\n// Maps NavigationKind to the AppRouterAction type used by the reducer.\n// \"refresh\" is intentionally treated as \"navigate\" (merge, preserve absent slots).\n// Both call sites must stay in sync — update here if NavigationKind gains new values.\nfunction toActionType(kind: NavigationKind): \"navigate\" | \"traverse\" {\n return kind === \"traverse\" ? \"traverse\" : \"navigate\";\n}\n\ntype HistoryUpdateMode = \"push\" | \"replace\";\ntype VisitedResponseCacheEntry = {\n params: Record<string, string | string[]>;\n expiresAt: number;\n response: CachedRscResponse;\n};\n\nconst MAX_VISITED_RESPONSE_CACHE_SIZE = 50;\nconst VISITED_RESPONSE_CACHE_TTL = 5 * 60_000;\nconst MAX_TRAVERSAL_CACHE_TTL = 30 * 60_000;\n\n// These are plain module-level variables, unlike ClientNavigationState in\n// navigation.ts which uses Symbol.for to survive multiple Vite module instances.\n// The browser entry is loaded exactly once (via the RSC plugin's generated\n// bootstrap), so module-level state is safe here. If that assumption ever\n// changes, these should be migrated to a Symbol.for-backed global.\n//\n// The most severe consequence of multiple instances would be Map fragmentation:\n// pendingNavigationCommits and pendingNavigationPrePaintEffects would split\n// across instances, so drainPrePaintEffects in one instance could never drain\n// effects queued by the other, permanently leaking navigationSnapshotActiveCount\n// and causing hooks to prefer stale snapshot values indefinitely.\nlet nextNavigationRenderId = 0;\nlet activeNavigationId = 0;\nconst pendingNavigationCommits = new Map<number, () => void>();\nconst pendingNavigationPrePaintEffects = new Map<number, () => void>();\ntype PendingBrowserRouterState = {\n promise: Promise<AppRouterState>;\n resolve: (state: AppRouterState) => void;\n settled: boolean;\n};\n\nfunction isRouterStatePromise(\n value: AppRouterState | Promise<AppRouterState>,\n): value is Promise<AppRouterState> {\n return value instanceof Promise;\n}\n\nlet setBrowserRouterState: Dispatch<AppRouterState | Promise<AppRouterState>> | null = null;\nlet browserRouterStateRef: { current: AppRouterState } | null = null;\nlet activePendingBrowserRouterState: PendingBrowserRouterState | null = null;\nlet latestClientParams: Record<string, string | string[]> = {};\nconst visitedResponseCache = new Map<string, VisitedResponseCacheEntry>();\nlet resolveBrowserRouterStateReady: (() => void) | null = null;\nlet browserRouterStateReadyPromise: Promise<void> | null = null;\nlet browserRouterStateHasCommitted = false;\n\nfunction isServerActionResult(value: unknown): value is ServerActionResult {\n return !!value && typeof value === \"object\" && \"root\" in value;\n}\n\nfunction getBrowserRouterStateSetter(): Dispatch<AppRouterState | Promise<AppRouterState>> {\n if (!setBrowserRouterState) {\n throw new Error(\"[vinext] Browser router state setter is not initialized\");\n }\n return setBrowserRouterState;\n}\n\nfunction getBrowserRouterState(): AppRouterState {\n if (!browserRouterStateRef) {\n throw new Error(\"[vinext] Browser router state is not initialized\");\n }\n return browserRouterStateRef.current;\n}\n\nfunction waitForBrowserRouterStateReady(): Promise<void> {\n if (browserRouterStateRef || browserRouterStateHasCommitted) {\n return Promise.resolve();\n }\n\n if (!browserRouterStateReadyPromise) {\n browserRouterStateReadyPromise = new Promise((resolve) => {\n resolveBrowserRouterStateReady = resolve;\n });\n }\n\n return browserRouterStateReadyPromise;\n}\n\nfunction markBrowserRouterStateReady(): void {\n browserRouterStateHasCommitted = true;\n const resolveReady = resolveBrowserRouterStateReady;\n resolveBrowserRouterStateReady = null;\n browserRouterStateReadyPromise = null;\n resolveReady?.();\n}\n\nfunction beginPendingBrowserRouterState(): PendingBrowserRouterState {\n const setter = getBrowserRouterStateSetter();\n\n if (activePendingBrowserRouterState && !activePendingBrowserRouterState.settled) {\n activePendingBrowserRouterState.settled = true;\n activePendingBrowserRouterState.resolve(getBrowserRouterState());\n }\n\n let resolve!: (state: AppRouterState) => void;\n const promise = new Promise<AppRouterState>((resolvePromise) => {\n resolve = resolvePromise;\n });\n\n const pending: PendingBrowserRouterState = {\n promise,\n resolve,\n settled: false,\n };\n\n activePendingBrowserRouterState = pending;\n setter(promise);\n\n return pending;\n}\n\nfunction settlePendingBrowserRouterState(\n pending: PendingBrowserRouterState | null | undefined,\n): void {\n if (!pending || pending.settled) return;\n\n pending.settled = true;\n pending.resolve(getBrowserRouterState());\n\n if (activePendingBrowserRouterState === pending) {\n activePendingBrowserRouterState = null;\n }\n}\n\nfunction resolvePendingBrowserRouterState(\n pending: PendingBrowserRouterState | null | undefined,\n action: AppRouterAction,\n): void {\n if (!pending || pending.settled) return;\n\n pending.settled = true;\n pending.resolve(routerReducer(getBrowserRouterState(), action));\n\n if (activePendingBrowserRouterState === pending) {\n activePendingBrowserRouterState = null;\n }\n}\n\nfunction applyClientParams(params: Record<string, string | string[]>): void {\n latestClientParams = params;\n setClientParams(params);\n}\n\nfunction stageClientParams(params: Record<string, string | string[]>): void {\n // NB: latestClientParams diverges from ClientNavigationState.clientParams\n // between staging and commit. Server action snapshots (same-URL\n // commitSameUrlNavigatePayload() calls inside registerServerActionCallback)\n // read latestClientParams, so a\n // server action fired during this window would get the pending (not yet\n // committed) params. This is acceptable because the commit effect fires\n // before hooks observe the new URL state, keeping the window vanishingly small.\n latestClientParams = params;\n replaceClientParamsWithoutNotify(params);\n}\n\nfunction clearVisitedResponseCache(): void {\n visitedResponseCache.clear();\n}\n\nfunction clearPrefetchState(): void {\n getPrefetchCache().clear();\n getPrefetchedUrls().clear();\n}\n\nfunction clearClientNavigationCaches(): void {\n clearVisitedResponseCache();\n clearPrefetchState();\n}\n\nfunction queuePrePaintNavigationEffect(renderId: number, effect: (() => void) | null): void {\n if (!effect) {\n return;\n }\n pendingNavigationPrePaintEffects.set(renderId, effect);\n}\n\n/**\n * Run all queued pre-paint effects for renderIds up to and including the\n * given renderId. When React supersedes a startTransition update (rapid\n * clicks on same-route links), the superseded NavigationCommitSignal never\n * mounts, so its pre-paint effect never fires. By draining all effects\n * <= the committed renderId here, the winning transition cleans up after\n * any superseded ones, keeping the counter balanced.\n *\n * Invariant: each superseded navigation gets a commitClientNavigationState()\n * to balance the activateNavigationSnapshot() from its renderNavigationPayload call.\n */\nfunction drainPrePaintEffects(upToRenderId: number): void {\n for (const [id, effect] of pendingNavigationPrePaintEffects) {\n if (id <= upToRenderId) {\n pendingNavigationPrePaintEffects.delete(id);\n if (id === upToRenderId) {\n // Winning navigation: run its actual pre-paint effect\n effect();\n } else {\n // Superseded navigation: balance its activateNavigationSnapshot().\n // Pass undefined navId intentionally so this cleanup cannot clear\n // pendingPathname owned by the current active navigation.\n commitClientNavigationState(undefined, { releaseSnapshot: true });\n }\n }\n }\n}\n\nfunction createNavigationCommitEffect(\n href: string,\n historyUpdateMode: HistoryUpdateMode | undefined,\n navId: number,\n params: Record<string, string | string[]>,\n previousNextUrl: string | null,\n): () => void {\n return () => {\n // Only update URL if this is still the active navigation.\n // A newer navigation would have incremented activeNavigationId.\n if (navId !== activeNavigationId) {\n // This transition was superseded before commit; balance the active\n // snapshot counter without clearing pendingPathname ownership.\n commitClientNavigationState(undefined, { releaseSnapshot: true });\n return;\n }\n\n const targetHref = new URL(href, window.location.origin).href;\n stageClientParams(params);\n const preserveExistingState = historyUpdateMode === \"replace\";\n const historyState = createHistoryStateWithPreviousNextUrl(\n preserveExistingState ? window.history.state : null,\n previousNextUrl,\n );\n\n if (historyUpdateMode === \"replace\" && window.location.href !== targetHref) {\n replaceHistoryStateWithoutNotify(historyState, \"\", href);\n } else if (historyUpdateMode === \"push\" && window.location.href !== targetHref) {\n pushHistoryStateWithoutNotify(historyState, \"\", href);\n }\n\n commitClientNavigationState(navId);\n };\n}\n\nfunction evictVisitedResponseCacheIfNeeded(): void {\n while (visitedResponseCache.size >= MAX_VISITED_RESPONSE_CACHE_SIZE) {\n const oldest = visitedResponseCache.keys().next().value;\n if (oldest === undefined) {\n return;\n }\n visitedResponseCache.delete(oldest);\n }\n}\n\nfunction getVisitedResponse(\n rscUrl: string,\n interceptionContext: string | null,\n mountedSlotsHeader: string | null,\n navigationKind: NavigationKind,\n): VisitedResponseCacheEntry | null {\n const cacheKey = createAppPayloadCacheKey(rscUrl, interceptionContext);\n const cached = visitedResponseCache.get(cacheKey);\n if (!cached) {\n return null;\n }\n\n if ((cached.response.mountedSlotsHeader ?? null) !== mountedSlotsHeader) {\n visitedResponseCache.delete(cacheKey);\n return null;\n }\n\n if (navigationKind === \"refresh\") {\n return null;\n }\n\n if (navigationKind === \"traverse\") {\n const createdAt = cached.expiresAt - VISITED_RESPONSE_CACHE_TTL;\n if (Date.now() - createdAt >= MAX_TRAVERSAL_CACHE_TTL) {\n visitedResponseCache.delete(cacheKey);\n return null;\n }\n // LRU: promote to most-recently-used (delete + re-insert moves to end of Map)\n visitedResponseCache.delete(cacheKey);\n visitedResponseCache.set(cacheKey, cached);\n return cached;\n }\n\n if (cached.expiresAt > Date.now()) {\n // LRU: promote to most-recently-used\n visitedResponseCache.delete(cacheKey);\n visitedResponseCache.set(cacheKey, cached);\n return cached;\n }\n\n visitedResponseCache.delete(cacheKey);\n return null;\n}\n\nfunction storeVisitedResponseSnapshot(\n rscUrl: string,\n interceptionContext: string | null,\n snapshot: CachedRscResponse,\n params: Record<string, string | string[]>,\n): void {\n const cacheKey = createAppPayloadCacheKey(rscUrl, interceptionContext);\n visitedResponseCache.delete(cacheKey);\n evictVisitedResponseCacheIfNeeded();\n const now = Date.now();\n visitedResponseCache.set(cacheKey, {\n params,\n expiresAt: now + VISITED_RESPONSE_CACHE_TTL,\n response: snapshot,\n });\n}\n\ntype NavigationRequestState = {\n interceptionContext: string | null;\n previousNextUrl: string | null;\n};\n\nfunction getRequestState(\n navigationKind: NavigationKind,\n previousNextUrlOverride?: string | null,\n): NavigationRequestState {\n if (previousNextUrlOverride !== undefined) {\n return {\n interceptionContext: resolveInterceptionContextFromPreviousNextUrl(\n previousNextUrlOverride,\n __basePath,\n ),\n previousNextUrl: previousNextUrlOverride,\n };\n }\n\n switch (navigationKind) {\n case \"navigate\":\n return {\n interceptionContext: getCurrentInterceptionContext(),\n previousNextUrl: getCurrentNextUrl(),\n };\n case \"traverse\": {\n const previousNextUrl = readHistoryStatePreviousNextUrl(window.history.state);\n return {\n interceptionContext: resolveInterceptionContextFromPreviousNextUrl(\n previousNextUrl,\n __basePath,\n ),\n previousNextUrl,\n };\n }\n case \"refresh\": {\n const currentPreviousNextUrl = getBrowserRouterState().previousNextUrl;\n return {\n interceptionContext: resolveInterceptionContextFromPreviousNextUrl(\n currentPreviousNextUrl,\n __basePath,\n ),\n previousNextUrl: currentPreviousNextUrl,\n };\n }\n default: {\n const _exhaustive: never = navigationKind;\n throw new Error(\"[vinext] Unknown navigation kind: \" + String(_exhaustive));\n }\n }\n}\n\nfunction createRscRequestHeaders(interceptionContext: string | null): Headers {\n const headers = new Headers({ Accept: \"text/x-component\" });\n if (interceptionContext !== null) {\n headers.set(\"X-Vinext-Interception-Context\", interceptionContext);\n }\n return headers;\n}\n\n/**\n * Resolve all pending navigation commits with renderId <= the committed renderId.\n * Note: Map iteration handles concurrent deletion safely — entries are visited in\n * insertion order and deletion doesn't affect the iterator's view of remaining entries.\n * This pattern is also used in drainPrePaintEffects with the same semantics.\n */\nfunction resolveCommittedNavigations(renderId: number): void {\n for (const [pendingId, resolve] of pendingNavigationCommits) {\n if (pendingId <= renderId) {\n pendingNavigationCommits.delete(pendingId);\n resolve();\n }\n }\n}\n\nfunction NavigationCommitSignal({\n renderId,\n children,\n}: {\n renderId: number;\n children?: ReactNode;\n}) {\n useLayoutEffect(() => {\n drainPrePaintEffects(renderId);\n\n const frame = requestAnimationFrame(() => {\n resolveCommittedNavigations(renderId);\n });\n\n return () => {\n cancelAnimationFrame(frame);\n // Resolve pending commits to prevent callers from hanging if React\n // unmounts this component without committing (e.g., error boundary).\n resolveCommittedNavigations(renderId);\n };\n }, [renderId]);\n\n return children;\n}\n\nfunction normalizeAppElementsPromise(payload: Promise<AppWireElements>): Promise<AppElements> {\n // Wrap in Promise.resolve() because createFromReadableStream() returns a\n // React Flight thenable whose .then() returns undefined (not a new Promise).\n // Without the wrap, chaining .then() produces undefined → use() crashes.\n return Promise.resolve(payload).then((elements) => normalizeAppElements(elements));\n}\n\nasync function commitSameUrlNavigatePayload(\n nextElements: Promise<AppElements>,\n returnValue?: ServerActionResult[\"returnValue\"],\n): Promise<unknown> {\n const navigationSnapshot = createClientNavigationRenderSnapshot(\n window.location.href,\n latestClientParams,\n );\n const currentState = getBrowserRouterState();\n const startedNavigationId = activeNavigationId;\n const { disposition, pending } = await resolveAndClassifyNavigationCommit({\n activeNavigationId,\n currentState,\n navigationSnapshot,\n nextElements,\n renderId: ++nextNavigationRenderId,\n startedNavigationId,\n type: \"navigate\",\n });\n\n // Known limitation: if a same-URL navigation fully commits while this\n // server action is awaiting createPendingNavigationCommit(), the action\n // can still dispatch its older payload afterward. The old pre-2c code had\n // the same race, and Next.js has similar behavior. Tightening this would\n // need a stronger commit-version gate than activeNavigationId alone.\n if (disposition === \"hard-navigate\") {\n window.location.assign(window.location.href);\n return undefined;\n }\n\n if (disposition === \"dispatch\") {\n dispatchBrowserTree(\n pending.action.elements,\n navigationSnapshot,\n pending.action.renderId,\n \"navigate\",\n pending.interceptionContext,\n pending.action.layoutFlags,\n pending.previousNextUrl,\n pending.routeId,\n pending.rootLayoutTreePath,\n null,\n false,\n );\n }\n\n // Same-URL server actions still return their action value even if the UI\n // update was skipped due to a superseding navigation. That preserves the\n // existing caller contract; a future Phase 2 router state model could make\n // skipped UI updates observable to the caller without conflating them here.\n if (returnValue) {\n if (!returnValue.ok) {\n throw returnValue.data;\n }\n return returnValue.data;\n }\n\n return undefined;\n}\n\nfunction BrowserRoot({\n initialElements,\n initialNavigationSnapshot,\n}: {\n initialElements: Promise<AppElements>;\n initialNavigationSnapshot: ClientNavigationRenderSnapshot;\n}) {\n const resolvedElements = use(initialElements);\n const initialMetadata = readAppElementsMetadata(resolvedElements);\n const [treeStateValue, setTreeStateValue] = useState<AppRouterState | Promise<AppRouterState>>({\n elements: resolvedElements,\n interceptionContext: initialMetadata.interceptionContext,\n layoutFlags: initialMetadata.layoutFlags,\n navigationSnapshot: initialNavigationSnapshot,\n previousNextUrl: null,\n renderId: 0,\n rootLayoutTreePath: initialMetadata.rootLayoutTreePath,\n routeId: initialMetadata.routeId,\n });\n const treeState = isRouterStatePromise(treeStateValue) ? use(treeStateValue) : treeStateValue;\n\n // Keep the latest router state in a ref so external callers (navigate(),\n // server actions, HMR) always read the current state. Safe: those readers\n // run from events/effects, never from React render itself.\n // Note: stateRef.current is written during render, not in an effect, to\n // avoid a stale-read window between commit and layout effects. This mirrors\n // the same render-phase ref update pattern used by Next.js's own router.\n const stateRef = useRef(treeState);\n stateRef.current = treeState;\n\n // Publish the stable ref object and dispatch during layout commit. This keeps\n // the module-level escape hatches aligned with React's committed tree without\n // performing module writes during render. __VINEXT_RSC_NAVIGATE__ is assigned\n // after hydrateRoot() returns; by then this layout effect has already run for\n // the hydration commit, so getBrowserRouterState() never observes a null ref.\n useLayoutEffect(() => {\n setBrowserRouterState = setTreeStateValue;\n browserRouterStateRef = stateRef;\n markBrowserRouterStateReady();\n return () => {\n if (setBrowserRouterState === setTreeStateValue) {\n setBrowserRouterState = null;\n }\n if (browserRouterStateRef === stateRef) {\n browserRouterStateRef = null;\n browserRouterStateHasCommitted = false;\n }\n setMountedSlotsHeader(null);\n };\n }, [setTreeStateValue]);\n\n useLayoutEffect(() => {\n setMountedSlotsHeader(getMountedSlotIdsHeader(stateRef.current.elements));\n }, [treeState.elements]);\n\n useLayoutEffect(() => {\n if (treeState.renderId !== 0) {\n return;\n }\n\n replaceHistoryStateWithoutNotify(\n createHistoryStateWithPreviousNextUrl(window.history.state, treeState.previousNextUrl),\n \"\",\n window.location.href,\n );\n }, [treeState.previousNextUrl, treeState.renderId]);\n\n const committedTree = createElement(\n NavigationCommitSignal,\n { renderId: treeState.renderId },\n createElement(\n ElementsContext.Provider,\n { value: treeState.elements },\n createElement(Slot, { id: treeState.routeId }),\n ),\n );\n\n const ClientNavigationRenderContext = getClientNavigationRenderContext();\n if (!ClientNavigationRenderContext) {\n return committedTree;\n }\n\n return createElement(\n ClientNavigationRenderContext.Provider,\n { value: treeState.navigationSnapshot },\n committedTree,\n );\n}\n\nfunction dispatchBrowserTree(\n elements: AppElements,\n navigationSnapshot: ClientNavigationRenderSnapshot,\n renderId: number,\n actionType: \"navigate\" | \"replace\" | \"traverse\",\n interceptionContext: string | null,\n layoutFlags: LayoutFlags,\n previousNextUrl: string | null,\n routeId: string,\n rootLayoutTreePath: string | null,\n pendingRouterState: PendingBrowserRouterState | null,\n useTransitionMode: boolean,\n): void {\n const setter = getBrowserRouterStateSetter();\n const action: AppRouterAction = {\n elements,\n interceptionContext,\n layoutFlags,\n navigationSnapshot,\n previousNextUrl,\n renderId,\n rootLayoutTreePath,\n routeId,\n type: actionType,\n };\n\n const applyAction = () => {\n if (pendingRouterState) {\n // The programmatic navigation is already running inside React.startTransition\n // (from router.push/replace/refresh), so resolving the deferred promise is\n // sufficient — no additional startTransition wrapper is needed below.\n resolvePendingBrowserRouterState(pendingRouterState, action);\n return;\n }\n\n setter(routerReducer(getBrowserRouterState(), action));\n };\n\n if (useTransitionMode) {\n startTransition(applyAction);\n } else {\n applyAction();\n }\n}\n\nasync function renderNavigationPayload(\n payload: Promise<AppElements>,\n navigationSnapshot: ClientNavigationRenderSnapshot,\n targetHref: string,\n navId: number,\n historyUpdateMode: HistoryUpdateMode | undefined,\n params: Record<string, string | string[]>,\n previousNextUrl: string | null,\n pendingRouterState: PendingBrowserRouterState | null,\n useTransition = true,\n actionType: \"navigate\" | \"replace\" | \"traverse\" = \"navigate\",\n): Promise<void> {\n const renderId = ++nextNavigationRenderId;\n const committed = new Promise<void>((resolve) => {\n pendingNavigationCommits.set(renderId, resolve);\n });\n\n let snapshotActivated = false;\n try {\n const currentState = getBrowserRouterState();\n const pending = await createPendingNavigationCommit({\n currentState,\n nextElements: payload,\n navigationSnapshot,\n previousNextUrl,\n renderId,\n type: actionType,\n });\n\n const disposition = resolvePendingNavigationCommitDisposition({\n activeNavigationId,\n currentRootLayoutTreePath: currentState.rootLayoutTreePath,\n nextRootLayoutTreePath: pending.rootLayoutTreePath,\n startedNavigationId: navId,\n });\n\n if (disposition === \"skip\") {\n settlePendingBrowserRouterState(pendingRouterState);\n const resolve = pendingNavigationCommits.get(renderId);\n pendingNavigationCommits.delete(renderId);\n resolve?.();\n return;\n }\n\n if (disposition === \"hard-navigate\") {\n settlePendingBrowserRouterState(pendingRouterState);\n pendingNavigationCommits.delete(renderId);\n window.location.assign(targetHref);\n return;\n }\n\n queuePrePaintNavigationEffect(\n renderId,\n createNavigationCommitEffect(\n targetHref,\n historyUpdateMode,\n navId,\n params,\n pending.previousNextUrl,\n ),\n );\n activateNavigationSnapshot();\n snapshotActivated = true;\n dispatchBrowserTree(\n pending.action.elements,\n navigationSnapshot,\n renderId,\n actionType,\n pending.interceptionContext,\n pending.action.layoutFlags,\n pending.previousNextUrl,\n pending.routeId,\n pending.rootLayoutTreePath,\n pendingRouterState,\n useTransition,\n );\n } catch (error) {\n // Clean up pending state on error. Only decrement the snapshot counter\n // if activateNavigationSnapshot() was actually called — if\n // createPendingNavigationCommit() threw, the counter was never\n // incremented so decrementing would underflow it.\n pendingNavigationPrePaintEffects.delete(renderId);\n const resolve = pendingNavigationCommits.get(renderId);\n pendingNavigationCommits.delete(renderId);\n if (snapshotActivated) {\n commitClientNavigationState(navId);\n }\n settlePendingBrowserRouterState(pendingRouterState);\n resolve?.();\n throw error;\n }\n\n return committed;\n}\n\nfunction restoreHydrationNavigationContext(\n pathname: string,\n searchParams: SearchParamInput,\n params: Record<string, string | string[]>,\n): void {\n setNavigationContext({\n pathname,\n searchParams: new URLSearchParams(searchParams),\n params,\n });\n}\n\nfunction decodeHashFragment(fragment: string): string {\n try {\n return decodeURIComponent(fragment);\n } catch {\n return fragment;\n }\n}\n\nfunction scrollToHashTarget(hash: string): void {\n const fragment = decodeHashFragment(hash.startsWith(\"#\") ? hash.slice(1) : hash);\n\n requestAnimationFrame(() => {\n if (fragment === \"\" || fragment === \"top\") {\n window.scrollTo(0, 0);\n return;\n }\n\n const idElement = document.getElementById(fragment);\n if (idElement) {\n idElement.scrollIntoView({ behavior: \"auto\" });\n return;\n }\n\n document.getElementsByName(fragment)[0]?.scrollIntoView({ behavior: \"auto\" });\n });\n}\n\nfunction restorePopstateScrollPosition(state: unknown): void {\n if (!(state && typeof state === \"object\" && \"__vinext_scrollY\" in state)) {\n if (window.location.hash) {\n scrollToHashTarget(window.location.hash);\n }\n return;\n }\n\n const y = Number(state.__vinext_scrollY);\n const x = \"__vinext_scrollX\" in state ? Number(state.__vinext_scrollX) : 0;\n\n requestAnimationFrame(() => {\n window.scrollTo(x, y);\n });\n}\n\n// Set on pagehide so the RSC navigation catch block can distinguish expected\n// fetch aborts (triggered by the unload itself) from real errors worth logging.\nlet isPageUnloading = false;\n\nconst RSC_RELOAD_KEY = \"__vinext_rsc_initial_reload__\";\n\n// sessionStorage can throw SecurityError in strict-mode iframes, storage-\n// disabled browsers, and some Safari private-browsing configurations. Wrap\n// every access so a recovery path for one error does not crash hydration.\nfunction readReloadFlag(): string | null {\n try {\n return sessionStorage.getItem(RSC_RELOAD_KEY);\n } catch {\n return null;\n }\n}\nfunction writeReloadFlag(path: string): void {\n try {\n sessionStorage.setItem(RSC_RELOAD_KEY, path);\n } catch {}\n}\nfunction clearReloadFlag(): void {\n try {\n sessionStorage.removeItem(RSC_RELOAD_KEY);\n } catch {}\n}\n\n// A non-ok or wrong-content-type RSC response during initial hydration means\n// the server cannot deliver a valid RSC payload for this URL. Parsing the\n// response as RSC causes an opaque parse failure. On the first attempt,\n// reload once so the server has a chance to render the correct error page\n// as HTML. On the second attempt (detected via the sessionStorage flag), the\n// endpoint is persistently broken. Returns null so main() aborts the\n// hydration bootstrap without registering `__VINEXT_RSC_*` globals —\n// including during the brief window between reload() firing and the page\n// actually unloading — so external probes never see a half-hydrated page.\nfunction recoverFromBadInitialRscResponse(reason: string): null {\n const currentPath = window.location.pathname + window.location.search;\n if (readReloadFlag() === currentPath) {\n clearReloadFlag();\n console.error(\n `[vinext] Initial RSC fetch ${reason} after reload; aborting hydration. ` +\n \"Server-rendered HTML remains visible; client components will not hydrate.\",\n );\n return null;\n }\n writeReloadFlag(currentPath);\n // Verify the write persisted. In storage-denied environments (strict-mode\n // iframes, locked-down enterprise policies), every getItem returns null and\n // every setItem silently no-ops, so the reload-loop guard cannot survive\n // the reload — the page would loop forever. Abort instead so the user at\n // least sees the server-rendered HTML.\n if (readReloadFlag() !== currentPath) {\n console.error(\n `[vinext] Initial RSC fetch ${reason}; sessionStorage unavailable so the ` +\n \"reload-loop guard cannot persist — aborting hydration. \" +\n \"Server-rendered HTML remains visible; client components will not hydrate.\",\n );\n return null;\n }\n // One-shot diagnostic so a production reload is traceable. Only fires once\n // per broken path thanks to the sessionStorage flag above; not noisy.\n console.warn(\n `[vinext] Initial RSC fetch ${reason}; reloading once to let the server render the HTML error page`,\n );\n window.location.reload();\n return null;\n}\n\nasync function readInitialRscStream(): Promise<ReadableStream<Uint8Array> | null> {\n const vinext = getVinextBrowserGlobal();\n\n if (vinext.__VINEXT_RSC__ || vinext.__VINEXT_RSC_CHUNKS__ || vinext.__VINEXT_RSC_DONE__) {\n // Reaching the embedded-RSC branch means the server successfully rendered\n // the page — any prior reload flag for this path is stale and must be\n // cleared so a future failure gets its own fresh recovery attempt.\n clearReloadFlag();\n\n if (vinext.__VINEXT_RSC__) {\n const embedData = vinext.__VINEXT_RSC__;\n delete vinext.__VINEXT_RSC__;\n\n const params = embedData.params ?? {};\n if (embedData.params) {\n applyClientParams(embedData.params);\n }\n if (embedData.nav) {\n restoreHydrationNavigationContext(\n embedData.nav.pathname,\n embedData.nav.searchParams,\n params,\n );\n }\n\n return chunksToReadableStream(embedData.rsc);\n }\n\n const params = vinext.__VINEXT_RSC_PARAMS__ ?? {};\n if (vinext.__VINEXT_RSC_PARAMS__) {\n applyClientParams(vinext.__VINEXT_RSC_PARAMS__);\n }\n if (vinext.__VINEXT_RSC_NAV__) {\n restoreHydrationNavigationContext(\n vinext.__VINEXT_RSC_NAV__.pathname,\n vinext.__VINEXT_RSC_NAV__.searchParams,\n params,\n );\n }\n\n return createProgressiveRscStream();\n }\n\n const rscResponse = await fetch(toRscUrl(window.location.pathname + window.location.search));\n\n if (!rscResponse.ok) {\n return recoverFromBadInitialRscResponse(`returned ${rscResponse.status}`);\n }\n // Guard against proxies/CDNs that return 200 with a rewritten Content-Type\n // (e.g. text/html instead of text/x-component). Such responses cannot be\n // parsed as RSC and would throw the same opaque parse error this fallback\n // exists to prevent.\n const contentType = rscResponse.headers.get(\"content-type\") ?? \"\";\n if (!contentType.startsWith(\"text/x-component\")) {\n return recoverFromBadInitialRscResponse(\n `returned non-RSC content-type \"${contentType || \"(missing)\"}\"`,\n );\n }\n // Missing body (e.g. 204 No Content, or an edge worker that returned ok\n // headers without piping the stream) fails the same way downstream.\n // Matches Next.js' `!res.body` branch in fetch-server-response.ts.\n if (!rscResponse.body) {\n return recoverFromBadInitialRscResponse(\"returned empty body\");\n }\n // Successful RSC response clears the guard so a subsequent reload of the\n // same path after a transient failure still gets one recovery attempt.\n clearReloadFlag();\n\n let params: Record<string, string | string[]> = {};\n const paramsHeader = rscResponse.headers.get(\"X-Vinext-Params\");\n if (paramsHeader) {\n try {\n params = JSON.parse(decodeURIComponent(paramsHeader)) as Record<string, string | string[]>;\n applyClientParams(params);\n } catch {\n // Ignore malformed param headers and continue with hydration.\n }\n }\n\n restoreHydrationNavigationContext(window.location.pathname, window.location.search, params);\n\n return rscResponse.body;\n}\n\nfunction registerServerActionCallback(): void {\n setServerCallback(async (id, args) => {\n const temporaryReferences = createTemporaryReferenceSet();\n const body = await encodeReply(args, { temporaryReferences });\n\n // Carry the interception context + mounted slots from the current router\n // state so the server-action re-render rebuilds the intercepted tree\n // instead of replacing it with the direct page. Parity with Next.js,\n // which sends `Next-URL` on action POSTs when the current tree contains\n // an interception route.\n const currentState = getBrowserRouterState();\n const { headers } = resolveServerActionRequestState({\n actionId: id,\n basePath: __basePath,\n elements: currentState.elements,\n previousNextUrl: currentState.previousNextUrl,\n });\n\n const fetchResponse = await fetch(toRscUrl(window.location.pathname + window.location.search), {\n method: \"POST\",\n headers,\n body,\n });\n\n if (isServerActionNotFoundResponse(fetchResponse)) {\n throw new Error(getServerActionNotFoundClientMessage(id));\n }\n\n const actionRedirect = fetchResponse.headers.get(\"x-action-redirect\");\n if (actionRedirect) {\n if (isDangerousScheme(actionRedirect)) {\n console.error(DANGEROUS_URL_BLOCK_MESSAGE);\n return undefined;\n }\n\n // Check for external URLs that need a hard redirect.\n try {\n const redirectUrl = new URL(actionRedirect, window.location.origin);\n if (redirectUrl.origin !== window.location.origin) {\n window.location.href = actionRedirect;\n return undefined;\n }\n } catch {\n // Fall through to hard redirect below if URL parsing fails.\n }\n\n // Use hard redirect for all action redirects because vinext's server\n // currently returns an empty body for redirect responses. RSC navigation\n // requires a valid RSC payload. This is a known parity gap with Next.js,\n // which pre-renders the redirect target's RSC payload.\n const redirectType = fetchResponse.headers.get(\"x-action-redirect-type\") ?? \"replace\";\n if (redirectType === \"push\") {\n window.location.assign(actionRedirect);\n } else {\n window.location.replace(actionRedirect);\n }\n return undefined;\n }\n\n clearClientNavigationCaches();\n\n const result = await createFromFetch<ServerActionResult | AppWireElements>(\n Promise.resolve(fetchResponse),\n { temporaryReferences },\n );\n\n // Server actions stay on the same URL and use commitSameUrlNavigatePayload()\n // for merge-based dispatch. This path does not call\n // activateNavigationSnapshot() because there is no URL change to commit, so\n // hooks continue reading the live external-store values directly. If server\n // actions ever trigger URL changes via RSC payload (instead of hard\n // redirects), this would need renderNavigationPayload().\n if (isServerActionResult(result)) {\n return commitSameUrlNavigatePayload(\n Promise.resolve(normalizeAppElements(result.root)),\n result.returnValue,\n );\n }\n\n return commitSameUrlNavigatePayload(Promise.resolve(normalizeAppElements(result)));\n });\n}\n\nasync function main(): Promise<void> {\n registerServerActionCallback();\n\n const rscStream = await readInitialRscStream();\n // null signals that readInitialRscStream aborted hydration — either because\n // a reload is in flight (first-attempt recovery) or the endpoint is\n // persistently broken (post-reload). Bootstrap is a separate synchronous\n // helper so the null-branch structurally cannot reach any __VINEXT_RSC_*\n // global assignment, even if a future refactor interposes async work here.\n if (rscStream === null) return;\n bootstrapHydration(rscStream);\n}\n\nfunction bootstrapHydration(rscStream: ReadableStream<Uint8Array>): void {\n const root = normalizeAppElementsPromise(createFromReadableStream<AppWireElements>(rscStream));\n const initialNavigationSnapshot = createClientNavigationRenderSnapshot(\n window.location.href,\n latestClientParams,\n );\n replaceHistoryStateWithoutNotify(\n createHistoryStateWithPreviousNextUrl(window.history.state, null),\n \"\",\n window.location.href,\n );\n\n window.__VINEXT_RSC_ROOT__ = hydrateRoot(\n document,\n createElement(BrowserRoot, {\n initialElements: root,\n initialNavigationSnapshot,\n }),\n import.meta.env.DEV ? { onCaughtError: devOnCaughtError } : undefined,\n );\n window.__VINEXT_HYDRATED_AT = performance.now();\n\n window.__VINEXT_RSC_NAVIGATE__ = async function navigateRsc(\n href: string,\n redirectDepth = 0,\n navigationKind: NavigationKind = \"navigate\",\n historyUpdateMode?: HistoryUpdateMode,\n previousNextUrlOverride?: string | null,\n programmaticTransition = false,\n ): Promise<void> {\n let _snapshotPending = false;\n let pendingRouterState: PendingBrowserRouterState | null = null;\n // Hoist navId above try so the catch and finally blocks can reference it.\n const navId = ++activeNavigationId;\n\n // Loop variables for inline redirect following. On a redirect, these are\n // updated and the loop continues without returning or re-entering navigateRsc,\n // so a single pendingRouterState spans all hops and isPending never flashes.\n let currentHref = href;\n let currentHistoryMode = historyUpdateMode;\n let currentPrevNextUrl = previousNextUrlOverride;\n let redirectCount = redirectDepth;\n\n try {\n if (programmaticTransition && browserRouterStateRef) {\n pendingRouterState = beginPendingBrowserRouterState();\n } else {\n await waitForBrowserRouterStateReady();\n if (navId !== activeNavigationId) return;\n\n if (programmaticTransition) {\n pendingRouterState = beginPendingBrowserRouterState();\n }\n }\n\n while (true) {\n if (redirectCount > 10) {\n console.error(\n \"[vinext] Too many RSC redirects — aborting navigation to prevent infinite loop.\",\n );\n window.location.href = currentHref;\n return;\n }\n\n const url = new URL(currentHref, window.location.origin);\n const rscUrl = toRscUrl(url.pathname + url.search);\n const requestState = getRequestState(navigationKind, currentPrevNextUrl);\n const requestInterceptionContext = requestState.interceptionContext;\n const requestPreviousNextUrl = requestState.previousNextUrl;\n\n // Compare against previous pending navigation first, then committed state.\n // This avoids isSameRoute misclassification during rapid back-to-back clicks.\n const navState = getClientNavigationState();\n const currentPath =\n navState?.pendingPathname ??\n navState?.cachedPathname ??\n stripBasePath(window.location.pathname, __basePath);\n\n const targetPath = stripBasePath(url.pathname, __basePath);\n const isSameRoute = targetPath === currentPath;\n\n // Set this navigation as the pending pathname, overwriting any previous.\n // Pass navId so only this navigation (or a newer one) can clear it later.\n setPendingPathname(url.pathname, navId);\n\n const elementsAtNavStart = getBrowserRouterState().elements;\n const mountedSlotsHeader = getMountedSlotIdsHeader(elementsAtNavStart);\n const cachedRoute = getVisitedResponse(\n rscUrl,\n requestInterceptionContext,\n mountedSlotsHeader,\n navigationKind,\n );\n if (cachedRoute) {\n // Check stale-navigation before and after createFromFetch. The pre-check\n // avoids wasted parse work; the post-check catches supersessions that\n // occur during the await. createFromFetch on a buffered response is fast\n // but still async, so the window exists. The non-cached path (below) places\n // its heavyweight async steps (fetch, snapshotRscResponse, createFromFetch)\n // between navId checks consistently; the cached path omits the check between\n // createClientNavigationRenderSnapshot (synchronous) and createFromFetch\n // because there is no await in that gap.\n if (navId !== activeNavigationId) return;\n const cachedParams = cachedRoute.params;\n // createClientNavigationRenderSnapshot is synchronous (URL parsing + param\n // wrapping only) — no stale-navigation recheck needed between here and the\n // next await.\n const cachedNavigationSnapshot = createClientNavigationRenderSnapshot(\n currentHref,\n cachedParams,\n );\n const cachedPayload = normalizeAppElementsPromise(\n createFromFetch<AppWireElements>(\n Promise.resolve(restoreRscResponse(cachedRoute.response)),\n ),\n );\n if (navId !== activeNavigationId) return;\n _snapshotPending = true; // Set before renderNavigationPayload\n try {\n await renderNavigationPayload(\n cachedPayload,\n cachedNavigationSnapshot,\n currentHref,\n navId,\n currentHistoryMode,\n cachedParams,\n requestPreviousNextUrl,\n pendingRouterState,\n isSameRoute,\n toActionType(navigationKind),\n );\n } finally {\n // Always clear _snapshotPending so the outer catch does not\n // double-decrement if renderNavigationPayload throws.\n _snapshotPending = false;\n }\n return;\n }\n\n // Continue using the slot state captured at navigation start for fetches\n // and prefetch compatibility decisions.\n\n let navResponse: Response | undefined;\n let navResponseUrl: string | null = null;\n if (navigationKind !== \"refresh\") {\n const prefetchedResponse = consumePrefetchResponse(\n rscUrl,\n requestInterceptionContext,\n mountedSlotsHeader,\n );\n if (prefetchedResponse) {\n navResponse = restoreRscResponse(prefetchedResponse, false);\n navResponseUrl = prefetchedResponse.url;\n }\n }\n\n if (!navResponse) {\n const requestHeaders = createRscRequestHeaders(requestInterceptionContext);\n if (mountedSlotsHeader) {\n requestHeaders.set(\"X-Vinext-Mounted-Slots\", mountedSlotsHeader);\n }\n navResponse = await fetch(rscUrl, {\n headers: requestHeaders,\n credentials: \"include\",\n });\n }\n\n if (navId !== activeNavigationId) return;\n\n // Any response that isn't a valid RSC payload (non-ok status,\n // missing/rewritten Content-Type, or missing body) means the server\n // returned something we cannot parse — typically an HTML error page\n // or a proxy-rewritten response. Parsing such a body as an RSC stream\n // throws a cryptic \"Connection closed\" error. Match Next.js behavior\n // (fetch-server-response.ts:211, `!isFlightResponse || !res.ok || !res.body`):\n // hard-navigate to the response URL so the server can render the correct\n // error page as HTML. The outer finally handles\n // settlePendingBrowserRouterState and clearPendingPathname on this\n // return path.\n //\n // Prefer the post-redirect response URL over `currentHref`: on a\n // redirect chain like `/old` → 307 → `/new` → 500, the browser's\n // fetch already followed the redirect, so `navResponse.url` is the\n // failing `/new` destination. Hard-navigating there directly avoids\n // bouncing off `/old` just to re-follow the same 307, which would\n // flash the wrong URL in the address bar and mis-key analytics.\n // Matches Next.js' `doMpaNavigation(responseUrl.toString())`. Falls\n // back to `currentHref` when no response URL is available.\n const navContentType = navResponse.headers.get(\"content-type\") ?? \"\";\n const isRscResponse = navContentType.startsWith(\"text/x-component\");\n if (!navResponse.ok || !isRscResponse || !navResponse.body) {\n const responseUrl = navResponseUrl ?? navResponse.url;\n let hardNavTarget = currentHref;\n if (responseUrl) {\n const parsed = new URL(responseUrl, window.location.origin);\n const origUrl = new URL(currentHref, window.location.origin);\n let pathname = parsed.pathname.replace(/\\.rsc$/, \"\");\n // toRscUrl strips trailing slash before appending .rsc, so the\n // response URL loses it on the round-trip. Restore it when the\n // original href had one so sites with trailingSlash:true don't\n // incur an extra 308 to the canonical form on the error path.\n if (\n origUrl.pathname.length > 1 &&\n origUrl.pathname.endsWith(\"/\") &&\n !pathname.endsWith(\"/\")\n ) {\n pathname += \"/\";\n }\n hardNavTarget = pathname + parsed.search;\n // Preserve the hash from the user's clicked href — a .rsc response\n // URL never carries a fragment, so dropping it would silently strip\n // `/foo#section` down to `/foo`.\n if (origUrl.hash) hardNavTarget += origUrl.hash;\n }\n window.location.href = hardNavTarget;\n return;\n }\n\n const finalUrl = new URL(navResponseUrl ?? navResponse.url, window.location.origin);\n const requestedUrl = new URL(rscUrl, window.location.origin);\n\n if (finalUrl.pathname !== requestedUrl.pathname) {\n // Server-side redirect: update the URL in history and loop to fetch\n // the destination without settling pendingRouterState. This keeps\n // isPending true across all redirect hops instead of flashing false.\n const destinationPath = finalUrl.pathname.replace(/\\.rsc$/, \"\") + finalUrl.search;\n replaceHistoryStateWithoutNotify(\n createHistoryStateWithPreviousNextUrl(null, requestPreviousNextUrl),\n \"\",\n destinationPath,\n );\n\n currentHref = destinationPath;\n // URL already written above; the commit effect must not push/replace again.\n currentHistoryMode = undefined;\n currentPrevNextUrl = requestPreviousNextUrl;\n redirectCount += 1;\n continue;\n }\n\n let navParams: Record<string, string | string[]> = {};\n const paramsHeader = navResponse.headers.get(\"X-Vinext-Params\");\n if (paramsHeader) {\n try {\n navParams = JSON.parse(decodeURIComponent(paramsHeader)) as Record<\n string,\n string | string[]\n >;\n } catch {\n // navParams stays as {}\n }\n }\n // Build snapshot from local params, not latestClientParams\n const navigationSnapshot = createClientNavigationRenderSnapshot(currentHref, navParams);\n\n const responseSnapshot = await snapshotRscResponse(navResponse);\n\n if (navId !== activeNavigationId) return;\n\n const rscPayload = normalizeAppElementsPromise(\n createFromFetch<AppWireElements>(Promise.resolve(restoreRscResponse(responseSnapshot))),\n );\n\n if (navId !== activeNavigationId) return;\n\n _snapshotPending = true; // Set before renderNavigationPayload\n try {\n await renderNavigationPayload(\n rscPayload,\n navigationSnapshot,\n currentHref,\n navId,\n currentHistoryMode,\n navParams,\n requestPreviousNextUrl,\n pendingRouterState,\n isSameRoute,\n toActionType(navigationKind),\n );\n } finally {\n // Always clear _snapshotPending after renderNavigationPayload returns or\n // throws. renderNavigationPayload's inner catch already calls\n // commitClientNavigationState() on synchronous errors and re-throws, so\n // the outer catch must not call it again. Clearing here prevents the outer\n // catch from double-decrementing navigationSnapshotActiveCount.\n _snapshotPending = false;\n }\n // Don't cache the response if this navigation was superseded during\n // renderNavigationPayload's await — the elements were never dispatched.\n if (navId !== activeNavigationId) return;\n // Store the visited response only after renderNavigationPayload succeeds.\n // If we stored it before and renderNavigationPayload threw, a future\n // back/forward navigation could replay a snapshot from a navigation that\n // never actually rendered successfully.\n const resolvedElements = await rscPayload;\n const metadata = readAppElementsMetadata(resolvedElements);\n storeVisitedResponseSnapshot(\n rscUrl,\n resolveVisitedResponseInterceptionContext(\n requestInterceptionContext,\n metadata.interceptionContext,\n ),\n responseSnapshot,\n navParams,\n );\n return;\n }\n } catch (error) {\n // Only decrement counter if snapshot was activated but not yet committed.\n // renderNavigationPayload clears _snapshotPending (via its inner try-finally)\n // before re-throwing, so this guard correctly skips the double-decrement case.\n if (_snapshotPending) {\n _snapshotPending = false;\n commitClientNavigationState(navId);\n }\n // Don't hard-navigate to a stale URL if this navigation was superseded by\n // a newer one — the newer navigation is already in flight and would be clobbered.\n if (navId !== activeNavigationId) return;\n // Suppress the diagnostic when the page is unloading: a hard-nav or anchor\n // click tears down the document and aborts any in-flight RSC fetch, which\n // surfaces here as an error. The page is already going away, so the log\n // is just noise. Mirrors Next.js' isPageUnloading pattern.\n if (!isPageUnloading) {\n console.error(\"[vinext] RSC navigation error:\", error);\n }\n window.location.href = currentHref;\n } finally {\n // Single settlement site: covers normal return, early returns on stale-id\n // checks, and error paths. The finally runs even when the catch returns.\n // settlePendingBrowserRouterState is idempotent via the settled flag.\n settlePendingBrowserRouterState(pendingRouterState);\n // Clear pendingPathname on all exit paths. On the success path this fires\n // before the RAF commit effect, but commitClientNavigationState() in the\n // commit effect clears it again — that double-clear is idempotent. Skipped\n // when superseded so a newer navigation's pendingPathname is not disturbed.\n if (navId === activeNavigationId) {\n clearPendingPathname(navId);\n }\n }\n };\n\n if (\"scrollRestoration\" in history) {\n history.scrollRestoration = \"manual\";\n }\n\n // Note: This popstate handler runs for App Router (RSC navigation available).\n // It coordinates scroll restoration with the pending RSC navigation.\n // Pages Router scroll restoration is handled in shims/navigation.ts:1289 with\n // microtask-based deferral for compatibility with non-RSC navigation.\n // See: https://github.com/vercel/next.js/discussions/41934#discussioncomment-4602607\n window.addEventListener(\"popstate\", (event) => {\n notifyAppRouterTransitionStart(window.location.href, \"traverse\");\n const pendingNavigation =\n window.__VINEXT_RSC_NAVIGATE__?.(window.location.href, 0, \"traverse\") ?? Promise.resolve();\n window.__VINEXT_RSC_PENDING__ = pendingNavigation;\n void pendingNavigation.finally(() => {\n restorePopstateScrollPosition(event.state);\n if (window.__VINEXT_RSC_PENDING__ === pendingNavigation) {\n window.__VINEXT_RSC_PENDING__ = null;\n }\n });\n });\n\n if (import.meta.hot) {\n import.meta.hot.on(\"rsc:update\", async () => {\n try {\n clearClientNavigationCaches();\n const navigationSnapshot = createClientNavigationRenderSnapshot(\n window.location.href,\n latestClientParams,\n );\n // Interception context on HMR re-renders is intentionally deferred:\n // preserving intercepted modal state across HMR reloads is out of scope\n // for the previousNextUrl mechanism.\n const pending = await createPendingNavigationCommit({\n currentState: getBrowserRouterState(),\n nextElements: normalizeAppElementsPromise(\n createFromFetch<AppWireElements>(\n fetch(toRscUrl(window.location.pathname + window.location.search)),\n ),\n ),\n navigationSnapshot,\n renderId: ++nextNavigationRenderId,\n type: \"replace\",\n });\n dispatchBrowserTree(\n pending.action.elements,\n navigationSnapshot,\n pending.action.renderId,\n \"replace\",\n pending.interceptionContext,\n pending.action.layoutFlags,\n pending.previousNextUrl,\n pending.routeId,\n pending.rootLayoutTreePath,\n null,\n false,\n );\n } catch (error) {\n console.error(\"[vinext] RSC HMR error:\", error);\n }\n });\n }\n}\n\nif (typeof document !== \"undefined\") {\n window.addEventListener(\"pagehide\", () => {\n isPageUnloading = true;\n });\n // Reset on pageshow so a bfcache-restored document does not resume with\n // the flag stuck at true, which would silently swallow every subsequent\n // RSC navigation error for the lifetime of that tab. Matches Next.js'\n // fetch-server-response.ts handler pair.\n window.addEventListener(\"pageshow\", () => {\n isPageUnloading = false;\n });\n void main();\n}\n"],"mappings":"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"}
@@ -89,5 +89,5 @@ declare function resolveAndClassifyNavigationCommit(options: {
89
89
  type: "navigate" | "replace" | "traverse";
90
90
  }): Promise<ClassifiedPendingNavigationCommit>;
91
91
  //#endregion
92
- export { AppRouterAction, AppRouterState, ClassifiedPendingNavigationCommit, PendingNavigationCommit, PendingNavigationCommitDisposition, ResolveServerActionRequestStateOptions, ResolveServerActionRequestStateResult, createHistoryStateWithPreviousNextUrl, createPendingNavigationCommit, readHistoryStatePreviousNextUrl, resolveAndClassifyNavigationCommit, resolveInterceptionContextFromPreviousNextUrl, resolvePendingNavigationCommitDisposition, resolveServerActionRequestState, routerReducer, shouldHardNavigate };
92
+ export { AppRouterAction, AppRouterState, createHistoryStateWithPreviousNextUrl, createPendingNavigationCommit, readHistoryStatePreviousNextUrl, resolveAndClassifyNavigationCommit, resolveInterceptionContextFromPreviousNextUrl, resolvePendingNavigationCommitDisposition, resolveServerActionRequestState, routerReducer, shouldHardNavigate };
93
93
  //# sourceMappingURL=app-browser-state.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"app-browser-state.js","names":[],"sources":["../../src/server/app-browser-state.ts"],"sourcesContent":["import { mergeElements } from \"../shims/slot.js\";\nimport { stripBasePath } from \"../utils/base-path.js\";\nimport {\n getMountedSlotIdsHeader,\n readAppElementsMetadata,\n type AppElements,\n type LayoutFlags,\n} from \"./app-elements.js\";\nimport type { ClientNavigationRenderSnapshot } from \"../shims/navigation.js\";\n\nconst VINEXT_PREVIOUS_NEXT_URL_HISTORY_STATE_KEY = \"__vinext_previousNextUrl\";\n\ntype HistoryStateRecord = {\n [key: string]: unknown;\n};\n\nexport type AppRouterState = {\n elements: AppElements;\n interceptionContext: string | null;\n layoutFlags: LayoutFlags;\n previousNextUrl: string | null;\n renderId: number;\n navigationSnapshot: ClientNavigationRenderSnapshot;\n rootLayoutTreePath: string | null;\n routeId: string;\n};\n\nexport type AppRouterAction = {\n elements: AppElements;\n interceptionContext: string | null;\n layoutFlags: LayoutFlags;\n navigationSnapshot: ClientNavigationRenderSnapshot;\n previousNextUrl: string | null;\n renderId: number;\n rootLayoutTreePath: string | null;\n routeId: string;\n type: \"navigate\" | \"replace\" | \"traverse\";\n};\n\nexport type PendingNavigationCommit = {\n action: AppRouterAction;\n interceptionContext: string | null;\n previousNextUrl: string | null;\n rootLayoutTreePath: string | null;\n routeId: string;\n};\n\nexport type PendingNavigationCommitDisposition = \"dispatch\" | \"hard-navigate\" | \"skip\";\nexport type ClassifiedPendingNavigationCommit = {\n disposition: PendingNavigationCommitDisposition;\n pending: PendingNavigationCommit;\n};\n\nfunction cloneHistoryState(state: unknown): HistoryStateRecord {\n if (!state || typeof state !== \"object\") {\n return {};\n }\n\n const nextState: HistoryStateRecord = {};\n for (const [key, value] of Object.entries(state)) {\n nextState[key] = value;\n }\n return nextState;\n}\n\nexport function createHistoryStateWithPreviousNextUrl(\n state: unknown,\n previousNextUrl: string | null,\n): HistoryStateRecord | null {\n const nextState = cloneHistoryState(state);\n\n if (previousNextUrl === null) {\n delete nextState[VINEXT_PREVIOUS_NEXT_URL_HISTORY_STATE_KEY];\n } else {\n nextState[VINEXT_PREVIOUS_NEXT_URL_HISTORY_STATE_KEY] = previousNextUrl;\n }\n\n return Object.keys(nextState).length > 0 ? nextState : null;\n}\n\nexport function readHistoryStatePreviousNextUrl(state: unknown): string | null {\n const value = cloneHistoryState(state)[VINEXT_PREVIOUS_NEXT_URL_HISTORY_STATE_KEY];\n return typeof value === \"string\" ? value : null;\n}\n\nexport function resolveInterceptionContextFromPreviousNextUrl(\n previousNextUrl: string | null,\n basePath: string = \"\",\n): string | null {\n if (previousNextUrl === null) {\n return null;\n }\n\n const parsedUrl = new URL(previousNextUrl, \"http://localhost\");\n return stripBasePath(parsedUrl.pathname, basePath);\n}\n\nexport type ResolveServerActionRequestStateOptions = {\n actionId: string;\n basePath: string;\n elements: AppElements;\n previousNextUrl: string | null;\n};\n\nexport type ResolveServerActionRequestStateResult = {\n headers: Headers;\n};\n\n/**\n * Pure: builds the fetch Headers for a server-action POST. Carries the same\n * interception-context and mounted-slots headers the refresh path already\n * sends, so the server-action re-render can rebuild the intercepted tree\n * instead of replacing it with the direct route.\n *\n * Next.js sends `Next-URL: state.previousNextUrl || state.nextUrl` on action\n * POSTs when `hasInterceptionRouteInCurrentTree(state.tree)`. Vinext's\n * X-Vinext-Interception-Context is the equivalent signal for the server-side\n * `findIntercept` lookup.\n */\nexport function resolveServerActionRequestState(\n options: ResolveServerActionRequestStateOptions,\n): ResolveServerActionRequestStateResult {\n const headers = new Headers({\n Accept: \"text/x-component\",\n \"x-rsc-action\": options.actionId,\n });\n\n const interceptionContext = resolveInterceptionContextFromPreviousNextUrl(\n options.previousNextUrl,\n options.basePath,\n );\n if (interceptionContext !== null) {\n headers.set(\"X-Vinext-Interception-Context\", interceptionContext);\n }\n\n const mountedSlotsHeader = getMountedSlotIdsHeader(options.elements);\n if (mountedSlotsHeader !== null) {\n headers.set(\"X-Vinext-Mounted-Slots\", mountedSlotsHeader);\n }\n\n return { headers };\n}\n\nexport function routerReducer(state: AppRouterState, action: AppRouterAction): AppRouterState {\n switch (action.type) {\n case \"traverse\":\n case \"navigate\":\n return {\n elements: mergeElements(state.elements, action.elements, action.type === \"traverse\"),\n interceptionContext: action.interceptionContext,\n layoutFlags: { ...state.layoutFlags, ...action.layoutFlags },\n navigationSnapshot: action.navigationSnapshot,\n previousNextUrl: action.previousNextUrl,\n renderId: action.renderId,\n rootLayoutTreePath: action.rootLayoutTreePath,\n routeId: action.routeId,\n };\n case \"replace\":\n return {\n elements: action.elements,\n interceptionContext: action.interceptionContext,\n layoutFlags: action.layoutFlags,\n navigationSnapshot: action.navigationSnapshot,\n previousNextUrl: action.previousNextUrl,\n renderId: action.renderId,\n rootLayoutTreePath: action.rootLayoutTreePath,\n routeId: action.routeId,\n };\n default: {\n const _exhaustive: never = action.type;\n throw new Error(\"[vinext] Unknown router action: \" + String(_exhaustive));\n }\n }\n}\n\nexport function shouldHardNavigate(\n currentRootLayoutTreePath: string | null,\n nextRootLayoutTreePath: string | null,\n): boolean {\n // `null` means the payload could not identify an enclosing root layout\n // boundary. Treat that as soft-navigation compatible so fallback payloads\n // do not force a hard reload purely because metadata is absent.\n return (\n currentRootLayoutTreePath !== null &&\n nextRootLayoutTreePath !== null &&\n currentRootLayoutTreePath !== nextRootLayoutTreePath\n );\n}\n\nexport function resolvePendingNavigationCommitDisposition(options: {\n activeNavigationId: number;\n currentRootLayoutTreePath: string | null;\n nextRootLayoutTreePath: string | null;\n startedNavigationId: number;\n}): PendingNavigationCommitDisposition {\n if (options.startedNavigationId !== options.activeNavigationId) {\n return \"skip\";\n }\n\n if (shouldHardNavigate(options.currentRootLayoutTreePath, options.nextRootLayoutTreePath)) {\n return \"hard-navigate\";\n }\n\n return \"dispatch\";\n}\n\nexport async function createPendingNavigationCommit(options: {\n currentState: AppRouterState;\n nextElements: Promise<AppElements>;\n navigationSnapshot: ClientNavigationRenderSnapshot;\n previousNextUrl?: string | null;\n renderId: number;\n type: \"navigate\" | \"replace\" | \"traverse\";\n}): Promise<PendingNavigationCommit> {\n const elements = await options.nextElements;\n const metadata = readAppElementsMetadata(elements);\n const previousNextUrl =\n options.previousNextUrl !== undefined\n ? options.previousNextUrl\n : options.currentState.previousNextUrl;\n\n return {\n action: {\n elements,\n interceptionContext: metadata.interceptionContext,\n layoutFlags: metadata.layoutFlags,\n navigationSnapshot: options.navigationSnapshot,\n previousNextUrl,\n renderId: options.renderId,\n rootLayoutTreePath: metadata.rootLayoutTreePath,\n routeId: metadata.routeId,\n type: options.type,\n },\n // Convenience aliases — always equal action.interceptionContext / action.rootLayoutTreePath / action.routeId.\n interceptionContext: metadata.interceptionContext,\n previousNextUrl,\n rootLayoutTreePath: metadata.rootLayoutTreePath,\n routeId: metadata.routeId,\n };\n}\n\nexport async function resolveAndClassifyNavigationCommit(options: {\n activeNavigationId: number;\n currentState: AppRouterState;\n navigationSnapshot: ClientNavigationRenderSnapshot;\n nextElements: Promise<AppElements>;\n previousNextUrl?: string | null;\n renderId: number;\n startedNavigationId: number;\n type: \"navigate\" | \"replace\" | \"traverse\";\n}): Promise<ClassifiedPendingNavigationCommit> {\n const pending = await createPendingNavigationCommit({\n currentState: options.currentState,\n nextElements: options.nextElements,\n navigationSnapshot: options.navigationSnapshot,\n previousNextUrl: options.previousNextUrl,\n renderId: options.renderId,\n type: options.type,\n });\n\n return {\n disposition: resolvePendingNavigationCommitDisposition({\n activeNavigationId: options.activeNavigationId,\n currentRootLayoutTreePath: options.currentState.rootLayoutTreePath,\n nextRootLayoutTreePath: pending.rootLayoutTreePath,\n startedNavigationId: options.startedNavigationId,\n }),\n pending,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"app-browser-state.js","names":[],"sources":["../../src/server/app-browser-state.ts"],"sourcesContent":["import { mergeElements } from \"vinext/shims/slot\";\nimport { stripBasePath } from \"../utils/base-path.js\";\nimport {\n getMountedSlotIdsHeader,\n readAppElementsMetadata,\n type AppElements,\n type LayoutFlags,\n} from \"./app-elements.js\";\nimport type { ClientNavigationRenderSnapshot } from \"vinext/shims/navigation\";\n\nconst VINEXT_PREVIOUS_NEXT_URL_HISTORY_STATE_KEY = \"__vinext_previousNextUrl\";\n\ntype HistoryStateRecord = {\n [key: string]: unknown;\n};\n\nexport type AppRouterState = {\n elements: AppElements;\n interceptionContext: string | null;\n layoutFlags: LayoutFlags;\n previousNextUrl: string | null;\n renderId: number;\n navigationSnapshot: ClientNavigationRenderSnapshot;\n rootLayoutTreePath: string | null;\n routeId: string;\n};\n\nexport type AppRouterAction = {\n elements: AppElements;\n interceptionContext: string | null;\n layoutFlags: LayoutFlags;\n navigationSnapshot: ClientNavigationRenderSnapshot;\n previousNextUrl: string | null;\n renderId: number;\n rootLayoutTreePath: string | null;\n routeId: string;\n type: \"navigate\" | \"replace\" | \"traverse\";\n};\n\ntype PendingNavigationCommit = {\n action: AppRouterAction;\n interceptionContext: string | null;\n previousNextUrl: string | null;\n rootLayoutTreePath: string | null;\n routeId: string;\n};\n\ntype PendingNavigationCommitDisposition = \"dispatch\" | \"hard-navigate\" | \"skip\";\ntype ClassifiedPendingNavigationCommit = {\n disposition: PendingNavigationCommitDisposition;\n pending: PendingNavigationCommit;\n};\n\nfunction cloneHistoryState(state: unknown): HistoryStateRecord {\n if (!state || typeof state !== \"object\") {\n return {};\n }\n\n const nextState: HistoryStateRecord = {};\n for (const [key, value] of Object.entries(state)) {\n nextState[key] = value;\n }\n return nextState;\n}\n\nexport function createHistoryStateWithPreviousNextUrl(\n state: unknown,\n previousNextUrl: string | null,\n): HistoryStateRecord | null {\n const nextState = cloneHistoryState(state);\n\n if (previousNextUrl === null) {\n delete nextState[VINEXT_PREVIOUS_NEXT_URL_HISTORY_STATE_KEY];\n } else {\n nextState[VINEXT_PREVIOUS_NEXT_URL_HISTORY_STATE_KEY] = previousNextUrl;\n }\n\n return Object.keys(nextState).length > 0 ? nextState : null;\n}\n\nexport function readHistoryStatePreviousNextUrl(state: unknown): string | null {\n const value = cloneHistoryState(state)[VINEXT_PREVIOUS_NEXT_URL_HISTORY_STATE_KEY];\n return typeof value === \"string\" ? value : null;\n}\n\nexport function resolveInterceptionContextFromPreviousNextUrl(\n previousNextUrl: string | null,\n basePath: string = \"\",\n): string | null {\n if (previousNextUrl === null) {\n return null;\n }\n\n const parsedUrl = new URL(previousNextUrl, \"http://localhost\");\n return stripBasePath(parsedUrl.pathname, basePath);\n}\n\ntype ResolveServerActionRequestStateOptions = {\n actionId: string;\n basePath: string;\n elements: AppElements;\n previousNextUrl: string | null;\n};\n\ntype ResolveServerActionRequestStateResult = {\n headers: Headers;\n};\n\n/**\n * Pure: builds the fetch Headers for a server-action POST. Carries the same\n * interception-context and mounted-slots headers the refresh path already\n * sends, so the server-action re-render can rebuild the intercepted tree\n * instead of replacing it with the direct route.\n *\n * Next.js sends `Next-URL: state.previousNextUrl || state.nextUrl` on action\n * POSTs when `hasInterceptionRouteInCurrentTree(state.tree)`. Vinext's\n * X-Vinext-Interception-Context is the equivalent signal for the server-side\n * `findIntercept` lookup.\n */\nexport function resolveServerActionRequestState(\n options: ResolveServerActionRequestStateOptions,\n): ResolveServerActionRequestStateResult {\n const headers = new Headers({\n Accept: \"text/x-component\",\n \"x-rsc-action\": options.actionId,\n });\n\n const interceptionContext = resolveInterceptionContextFromPreviousNextUrl(\n options.previousNextUrl,\n options.basePath,\n );\n if (interceptionContext !== null) {\n headers.set(\"X-Vinext-Interception-Context\", interceptionContext);\n }\n\n const mountedSlotsHeader = getMountedSlotIdsHeader(options.elements);\n if (mountedSlotsHeader !== null) {\n headers.set(\"X-Vinext-Mounted-Slots\", mountedSlotsHeader);\n }\n\n return { headers };\n}\n\nexport function routerReducer(state: AppRouterState, action: AppRouterAction): AppRouterState {\n switch (action.type) {\n case \"traverse\":\n case \"navigate\":\n return {\n elements: mergeElements(state.elements, action.elements, action.type === \"traverse\"),\n interceptionContext: action.interceptionContext,\n layoutFlags: { ...state.layoutFlags, ...action.layoutFlags },\n navigationSnapshot: action.navigationSnapshot,\n previousNextUrl: action.previousNextUrl,\n renderId: action.renderId,\n rootLayoutTreePath: action.rootLayoutTreePath,\n routeId: action.routeId,\n };\n case \"replace\":\n return {\n elements: action.elements,\n interceptionContext: action.interceptionContext,\n layoutFlags: action.layoutFlags,\n navigationSnapshot: action.navigationSnapshot,\n previousNextUrl: action.previousNextUrl,\n renderId: action.renderId,\n rootLayoutTreePath: action.rootLayoutTreePath,\n routeId: action.routeId,\n };\n default: {\n const _exhaustive: never = action.type;\n throw new Error(\"[vinext] Unknown router action: \" + String(_exhaustive));\n }\n }\n}\n\nexport function shouldHardNavigate(\n currentRootLayoutTreePath: string | null,\n nextRootLayoutTreePath: string | null,\n): boolean {\n // `null` means the payload could not identify an enclosing root layout\n // boundary. Treat that as soft-navigation compatible so fallback payloads\n // do not force a hard reload purely because metadata is absent.\n return (\n currentRootLayoutTreePath !== null &&\n nextRootLayoutTreePath !== null &&\n currentRootLayoutTreePath !== nextRootLayoutTreePath\n );\n}\n\nexport function resolvePendingNavigationCommitDisposition(options: {\n activeNavigationId: number;\n currentRootLayoutTreePath: string | null;\n nextRootLayoutTreePath: string | null;\n startedNavigationId: number;\n}): PendingNavigationCommitDisposition {\n if (options.startedNavigationId !== options.activeNavigationId) {\n return \"skip\";\n }\n\n if (shouldHardNavigate(options.currentRootLayoutTreePath, options.nextRootLayoutTreePath)) {\n return \"hard-navigate\";\n }\n\n return \"dispatch\";\n}\n\nexport async function createPendingNavigationCommit(options: {\n currentState: AppRouterState;\n nextElements: Promise<AppElements>;\n navigationSnapshot: ClientNavigationRenderSnapshot;\n previousNextUrl?: string | null;\n renderId: number;\n type: \"navigate\" | \"replace\" | \"traverse\";\n}): Promise<PendingNavigationCommit> {\n const elements = await options.nextElements;\n const metadata = readAppElementsMetadata(elements);\n const previousNextUrl =\n options.previousNextUrl !== undefined\n ? options.previousNextUrl\n : options.currentState.previousNextUrl;\n\n return {\n action: {\n elements,\n interceptionContext: metadata.interceptionContext,\n layoutFlags: metadata.layoutFlags,\n navigationSnapshot: options.navigationSnapshot,\n previousNextUrl,\n renderId: options.renderId,\n rootLayoutTreePath: metadata.rootLayoutTreePath,\n routeId: metadata.routeId,\n type: options.type,\n },\n // Convenience aliases — always equal action.interceptionContext / action.rootLayoutTreePath / action.routeId.\n interceptionContext: metadata.interceptionContext,\n previousNextUrl,\n rootLayoutTreePath: metadata.rootLayoutTreePath,\n routeId: metadata.routeId,\n };\n}\n\nexport async function resolveAndClassifyNavigationCommit(options: {\n activeNavigationId: number;\n currentState: AppRouterState;\n navigationSnapshot: ClientNavigationRenderSnapshot;\n nextElements: Promise<AppElements>;\n previousNextUrl?: string | null;\n renderId: number;\n startedNavigationId: number;\n type: \"navigate\" | \"replace\" | \"traverse\";\n}): Promise<ClassifiedPendingNavigationCommit> {\n const pending = await createPendingNavigationCommit({\n currentState: options.currentState,\n nextElements: options.nextElements,\n navigationSnapshot: options.navigationSnapshot,\n previousNextUrl: options.previousNextUrl,\n renderId: options.renderId,\n type: options.type,\n });\n\n return {\n disposition: resolvePendingNavigationCommitDisposition({\n activeNavigationId: options.activeNavigationId,\n currentRootLayoutTreePath: options.currentState.rootLayoutTreePath,\n nextRootLayoutTreePath: pending.rootLayoutTreePath,\n startedNavigationId: options.startedNavigationId,\n }),\n pending,\n };\n}\n"],"mappings":"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"}
@@ -29,5 +29,5 @@ declare function chunksToReadableStream(chunks: readonly string[]): ReadableStre
29
29
  */
30
30
  declare function createProgressiveRscStream(): ReadableStream<Uint8Array>;
31
31
  //#endregion
32
- export { LegacyRscEmbedData, NavigationSnapshot, VinextBrowserGlobals, chunksToReadableStream, createProgressiveRscStream, getVinextBrowserGlobal };
32
+ export { chunksToReadableStream, createProgressiveRscStream, getVinextBrowserGlobal };
33
33
  //# sourceMappingURL=app-browser-stream.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"app-browser-stream.js","names":[],"sources":["../../src/server/app-browser-stream.ts"],"sourcesContent":["export type NavigationSnapshot = {\n pathname: string;\n searchParams: [string, string][];\n};\n\nexport type LegacyRscEmbedData = {\n rsc: string[];\n params?: Record<string, string | string[]>;\n nav?: NavigationSnapshot;\n};\n\nexport type VinextBrowserGlobals = {\n __VINEXT_RSC__?: LegacyRscEmbedData;\n __VINEXT_RSC_CHUNKS__?: string[];\n __VINEXT_RSC_DONE__?: boolean;\n __VINEXT_RSC_PARAMS__?: Record<string, string | string[]>;\n __VINEXT_RSC_NAV__?: NavigationSnapshot;\n};\n\nexport function getVinextBrowserGlobal(): typeof globalThis & VinextBrowserGlobals {\n return globalThis as typeof globalThis & VinextBrowserGlobals;\n}\n\n/**\n * Convert embedded text chunks back to a ReadableStream of Uint8Array chunks.\n */\nexport function chunksToReadableStream(chunks: readonly string[]): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder();\n return new ReadableStream<Uint8Array>({\n start(controller) {\n for (const chunk of chunks) {\n controller.enqueue(encoder.encode(chunk));\n }\n controller.close();\n },\n });\n}\n\n/**\n * Create a ReadableStream from progressively-embedded RSC chunks.\n *\n * The server pushes chunks into `__VINEXT_RSC_CHUNKS__` via inline <script>\n * tags. We monkey-patch `push()` so new chunks stream to React immediately\n * instead of polling with setTimeout.\n */\nexport function createProgressiveRscStream(): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder();\n\n return new ReadableStream<Uint8Array>({\n start(controller) {\n const vinext = getVinextBrowserGlobal();\n const initialChunks = vinext.__VINEXT_RSC_CHUNKS__ ?? [];\n\n for (const chunk of initialChunks) {\n controller.enqueue(encoder.encode(chunk));\n }\n\n if (vinext.__VINEXT_RSC_DONE__) {\n controller.close();\n return;\n }\n\n let closed = false;\n const closeOnce = () => {\n if (!closed) {\n closed = true;\n controller.close();\n }\n };\n\n const arr = (vinext.__VINEXT_RSC_CHUNKS__ ??= []);\n arr.push = function (...chunks: string[]): number {\n const length = Array.prototype.push.apply(this, chunks);\n\n if (closed) return length;\n\n for (const chunk of chunks) {\n controller.enqueue(encoder.encode(chunk));\n }\n\n if (vinext.__VINEXT_RSC_DONE__) {\n closeOnce();\n }\n\n return length;\n };\n\n if (typeof document !== \"undefined\") {\n if (document.readyState === \"loading\") {\n document.addEventListener(\"DOMContentLoaded\", closeOnce);\n } else {\n closeOnce();\n }\n }\n },\n });\n}\n"],"mappings":";AAmBA,SAAgB,yBAAmE;AACjF,QAAO;;;;;AAMT,SAAgB,uBAAuB,QAAuD;CAC5F,MAAM,UAAU,IAAI,aAAa;AACjC,QAAO,IAAI,eAA2B,EACpC,MAAM,YAAY;AAChB,OAAK,MAAM,SAAS,OAClB,YAAW,QAAQ,QAAQ,OAAO,MAAM,CAAC;AAE3C,aAAW,OAAO;IAErB,CAAC;;;;;;;;;AAUJ,SAAgB,6BAAyD;CACvE,MAAM,UAAU,IAAI,aAAa;AAEjC,QAAO,IAAI,eAA2B,EACpC,MAAM,YAAY;EAChB,MAAM,SAAS,wBAAwB;EACvC,MAAM,gBAAgB,OAAO,yBAAyB,EAAE;AAExD,OAAK,MAAM,SAAS,cAClB,YAAW,QAAQ,QAAQ,OAAO,MAAM,CAAC;AAG3C,MAAI,OAAO,qBAAqB;AAC9B,cAAW,OAAO;AAClB;;EAGF,IAAI,SAAS;EACb,MAAM,kBAAkB;AACtB,OAAI,CAAC,QAAQ;AACX,aAAS;AACT,eAAW,OAAO;;;EAItB,MAAM,MAAO,OAAO,0BAA0B,EAAE;AAChD,MAAI,OAAO,SAAU,GAAG,QAA0B;GAChD,MAAM,SAAS,MAAM,UAAU,KAAK,MAAM,MAAM,OAAO;AAEvD,OAAI,OAAQ,QAAO;AAEnB,QAAK,MAAM,SAAS,OAClB,YAAW,QAAQ,QAAQ,OAAO,MAAM,CAAC;AAG3C,OAAI,OAAO,oBACT,YAAW;AAGb,UAAO;;AAGT,MAAI,OAAO,aAAa,YACtB,KAAI,SAAS,eAAe,UAC1B,UAAS,iBAAiB,oBAAoB,UAAU;MAExD,YAAW;IAIlB,CAAC"}
1
+ {"version":3,"file":"app-browser-stream.js","names":[],"sources":["../../src/server/app-browser-stream.ts"],"sourcesContent":["type NavigationSnapshot = {\n pathname: string;\n searchParams: [string, string][];\n};\n\ntype LegacyRscEmbedData = {\n rsc: string[];\n params?: Record<string, string | string[]>;\n nav?: NavigationSnapshot;\n};\n\ntype VinextBrowserGlobals = {\n __VINEXT_RSC__?: LegacyRscEmbedData;\n __VINEXT_RSC_CHUNKS__?: string[];\n __VINEXT_RSC_DONE__?: boolean;\n __VINEXT_RSC_PARAMS__?: Record<string, string | string[]>;\n __VINEXT_RSC_NAV__?: NavigationSnapshot;\n};\n\nexport function getVinextBrowserGlobal(): typeof globalThis & VinextBrowserGlobals {\n return globalThis as typeof globalThis & VinextBrowserGlobals;\n}\n\n/**\n * Convert embedded text chunks back to a ReadableStream of Uint8Array chunks.\n */\nexport function chunksToReadableStream(chunks: readonly string[]): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder();\n return new ReadableStream<Uint8Array>({\n start(controller) {\n for (const chunk of chunks) {\n controller.enqueue(encoder.encode(chunk));\n }\n controller.close();\n },\n });\n}\n\n/**\n * Create a ReadableStream from progressively-embedded RSC chunks.\n *\n * The server pushes chunks into `__VINEXT_RSC_CHUNKS__` via inline <script>\n * tags. We monkey-patch `push()` so new chunks stream to React immediately\n * instead of polling with setTimeout.\n */\nexport function createProgressiveRscStream(): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder();\n\n return new ReadableStream<Uint8Array>({\n start(controller) {\n const vinext = getVinextBrowserGlobal();\n const initialChunks = vinext.__VINEXT_RSC_CHUNKS__ ?? [];\n\n for (const chunk of initialChunks) {\n controller.enqueue(encoder.encode(chunk));\n }\n\n if (vinext.__VINEXT_RSC_DONE__) {\n controller.close();\n return;\n }\n\n let closed = false;\n const closeOnce = () => {\n if (!closed) {\n closed = true;\n controller.close();\n }\n };\n\n const arr = (vinext.__VINEXT_RSC_CHUNKS__ ??= []);\n arr.push = function (...chunks: string[]): number {\n const length = Array.prototype.push.apply(this, chunks);\n\n if (closed) return length;\n\n for (const chunk of chunks) {\n controller.enqueue(encoder.encode(chunk));\n }\n\n if (vinext.__VINEXT_RSC_DONE__) {\n closeOnce();\n }\n\n return length;\n };\n\n if (typeof document !== \"undefined\") {\n if (document.readyState === \"loading\") {\n document.addEventListener(\"DOMContentLoaded\", closeOnce);\n } else {\n closeOnce();\n }\n }\n },\n });\n}\n"],"mappings":";AAmBA,SAAgB,yBAAmE;AACjF,QAAO;;;;;AAMT,SAAgB,uBAAuB,QAAuD;CAC5F,MAAM,UAAU,IAAI,aAAa;AACjC,QAAO,IAAI,eAA2B,EACpC,MAAM,YAAY;AAChB,OAAK,MAAM,SAAS,OAClB,YAAW,QAAQ,QAAQ,OAAO,MAAM,CAAC;AAE3C,aAAW,OAAO;IAErB,CAAC;;;;;;;;;AAUJ,SAAgB,6BAAyD;CACvE,MAAM,UAAU,IAAI,aAAa;AAEjC,QAAO,IAAI,eAA2B,EACpC,MAAM,YAAY;EAChB,MAAM,SAAS,wBAAwB;EACvC,MAAM,gBAAgB,OAAO,yBAAyB,EAAE;AAExD,OAAK,MAAM,SAAS,cAClB,YAAW,QAAQ,QAAQ,OAAO,MAAM,CAAC;AAG3C,MAAI,OAAO,qBAAqB;AAC9B,cAAW,OAAO;AAClB;;EAGF,IAAI,SAAS;EACb,MAAM,kBAAkB;AACtB,OAAI,CAAC,QAAQ;AACX,aAAS;AACT,eAAW,OAAO;;;EAItB,MAAM,MAAO,OAAO,0BAA0B,EAAE;AAChD,MAAI,OAAO,SAAU,GAAG,QAA0B;GAChD,MAAM,SAAS,MAAM,UAAU,KAAK,MAAM,MAAM,OAAO;AAEvD,OAAI,OAAQ,QAAO;AAEnB,QAAK,MAAM,SAAS,OAClB,YAAW,QAAQ,QAAQ,OAAO,MAAM,CAAC;AAG3C,OAAI,OAAO,oBACT,YAAW;AAGb,UAAO;;AAGT,MAAI,OAAO,aAAa,YACtB,KAAI,SAAS,eAAe,UAC1B,UAAS,iBAAiB,oBAAoB,UAAU;MAExD,YAAW;IAIlB,CAAC"}
@@ -35,7 +35,6 @@ type AppElementsMetadata = {
35
35
  routeId: string;
36
36
  rootLayoutTreePath: string | null;
37
37
  };
38
- declare function normalizeMountedSlotsHeader(header: string | null | undefined): string | null;
39
38
  declare function getMountedSlotIds(elements: AppElements): string[];
40
39
  declare function getMountedSlotIdsHeader(elements: AppElements): string | null;
41
40
  declare function createAppPayloadRouteId(routePath: string, interceptionContext: string | null): string;
@@ -88,5 +87,5 @@ declare function buildOutgoingAppPayload(input: {
88
87
  */
89
88
  declare function readAppElementsMetadata(elements: Readonly<Record<string, unknown>>): AppElementsMetadata;
90
89
  //#endregion
91
- export { APP_INTERCEPTION_CONTEXT_KEY, APP_LAYOUT_FLAGS_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementValue, AppElements, AppElementsMetadata, AppOutgoingElements, AppWireElementValue, AppWireElements, LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, createAppPayloadCacheKey, createAppPayloadPageId, createAppPayloadRouteId, getMountedSlotIds, getMountedSlotIdsHeader, isAppElementsRecord, normalizeAppElements, normalizeMountedSlotsHeader, readAppElementsMetadata, resolveVisitedResponseInterceptionContext, withLayoutFlags };
90
+ export { APP_INTERCEPTION_CONTEXT_KEY, APP_LAYOUT_FLAGS_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementValue, AppElements, AppOutgoingElements, AppWireElements, LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, createAppPayloadCacheKey, createAppPayloadPageId, createAppPayloadRouteId, getMountedSlotIds, getMountedSlotIdsHeader, isAppElementsRecord, normalizeAppElements, readAppElementsMetadata, resolveVisitedResponseInterceptionContext, withLayoutFlags };
92
91
  //# sourceMappingURL=app-elements.d.ts.map
@@ -117,6 +117,6 @@ function readAppElementsMetadata(elements) {
117
117
  };
118
118
  }
119
119
  //#endregion
120
- export { APP_INTERCEPTION_CONTEXT_KEY, APP_LAYOUT_FLAGS_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, UNMATCHED_SLOT, buildOutgoingAppPayload, createAppPayloadCacheKey, createAppPayloadPageId, createAppPayloadRouteId, getMountedSlotIds, getMountedSlotIdsHeader, isAppElementsRecord, normalizeAppElements, normalizeMountedSlotsHeader, readAppElementsMetadata, resolveVisitedResponseInterceptionContext, withLayoutFlags };
120
+ export { APP_INTERCEPTION_CONTEXT_KEY, APP_LAYOUT_FLAGS_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, UNMATCHED_SLOT, buildOutgoingAppPayload, createAppPayloadCacheKey, createAppPayloadPageId, createAppPayloadRouteId, getMountedSlotIds, getMountedSlotIdsHeader, isAppElementsRecord, normalizeAppElements, readAppElementsMetadata, resolveVisitedResponseInterceptionContext, withLayoutFlags };
121
121
 
122
122
  //# sourceMappingURL=app-elements.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"app-elements.js","names":[],"sources":["../../src/server/app-elements.ts"],"sourcesContent":["import { isValidElement, type ReactNode } from \"react\";\n\nconst APP_INTERCEPTION_SEPARATOR = \"\\0\";\n\nexport const APP_INTERCEPTION_CONTEXT_KEY = \"__interceptionContext\";\nexport const APP_LAYOUT_FLAGS_KEY = \"__layoutFlags\";\nexport const APP_ROUTE_KEY = \"__route\";\nexport const APP_ROOT_LAYOUT_KEY = \"__rootLayout\";\nexport const APP_UNMATCHED_SLOT_WIRE_VALUE = \"__VINEXT_UNMATCHED_SLOT__\";\n\nexport const UNMATCHED_SLOT = Symbol.for(\"vinext.unmatchedSlot\");\n\nexport type AppElementValue = ReactNode | typeof UNMATCHED_SLOT | string | null;\nexport type AppWireElementValue = ReactNode | string | null;\n\nexport type AppElements = Readonly<Record<string, AppElementValue>>;\nexport type AppWireElements = Readonly<Record<string, AppWireElementValue>>;\n\n/**\n * Per-layout static/dynamic flags. `\"s\"` = static (skippable on next nav);\n * `\"d\"` = dynamic (must always render).\n *\n * Lifecycle (partial — later PRs extend this):\n *\n * 1. PROBE — probeAppPageLayouts (server/app-page-execution.ts) returns\n * LayoutFlags for every layout in the route at render time.\n *\n * 2. ATTACH — withLayoutFlags (this file) writes `__layoutFlags` into the\n * outgoing App Router payload record.\n *\n * 3. WIRE — renderToReadableStream serializes the record as RSC row 0.\n *\n * 4. PARSE — readAppElementsMetadata (this file) extracts layoutFlags from\n * the wire payload on the client side.\n */\nexport type LayoutFlags = Readonly<Record<string, \"s\" | \"d\">>;\n\nexport type AppElementsMetadata = {\n interceptionContext: string | null;\n layoutFlags: LayoutFlags;\n routeId: string;\n rootLayoutTreePath: string | null;\n};\n\nexport function normalizeMountedSlotsHeader(header: string | null | undefined): string | null {\n if (!header) {\n return null;\n }\n\n const slotIds = Array.from(new Set(header.split(/\\s+/).filter(Boolean))).sort();\n\n return slotIds.length > 0 ? slotIds.join(\" \") : null;\n}\n\nexport function getMountedSlotIds(elements: AppElements): string[] {\n return Object.keys(elements)\n .filter((key) => {\n const value = elements[key];\n return (\n key.startsWith(\"slot:\") && value !== null && value !== undefined && value !== UNMATCHED_SLOT\n );\n })\n .sort();\n}\n\nexport function getMountedSlotIdsHeader(elements: AppElements): string | null {\n return normalizeMountedSlotsHeader(getMountedSlotIds(elements).join(\" \"));\n}\n\nfunction appendInterceptionContext(identity: string, interceptionContext: string | null): string {\n return interceptionContext === null\n ? identity\n : `${identity}${APP_INTERCEPTION_SEPARATOR}${interceptionContext}`;\n}\n\nexport function createAppPayloadRouteId(\n routePath: string,\n interceptionContext: string | null,\n): string {\n return appendInterceptionContext(`route:${routePath}`, interceptionContext);\n}\n\nexport function createAppPayloadPageId(\n routePath: string,\n interceptionContext: string | null,\n): string {\n return appendInterceptionContext(`page:${routePath}`, interceptionContext);\n}\n\nexport function createAppPayloadCacheKey(\n rscUrl: string,\n interceptionContext: string | null,\n): string {\n return appendInterceptionContext(rscUrl, interceptionContext);\n}\n\nexport function resolveVisitedResponseInterceptionContext(\n requestInterceptionContext: string | null,\n payloadInterceptionContext: string | null,\n): string | null {\n return payloadInterceptionContext ?? requestInterceptionContext;\n}\n\nexport function normalizeAppElements(elements: AppWireElements): AppElements {\n let needsNormalization = false;\n for (const [key, value] of Object.entries(elements)) {\n if (key.startsWith(\"slot:\") && value === APP_UNMATCHED_SLOT_WIRE_VALUE) {\n needsNormalization = true;\n break;\n }\n }\n\n if (!needsNormalization) {\n return elements;\n }\n\n const normalized: Record<string, AppElementValue> = {};\n for (const [key, value] of Object.entries(elements)) {\n normalized[key] =\n key.startsWith(\"slot:\") && value === APP_UNMATCHED_SLOT_WIRE_VALUE ? UNMATCHED_SLOT : value;\n }\n\n return normalized;\n}\n\nfunction isLayoutFlagsRecord(value: unknown): value is LayoutFlags {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n for (const v of Object.values(value)) {\n if (v !== \"s\" && v !== \"d\") return false;\n }\n return true;\n}\n\nfunction parseLayoutFlags(value: unknown): LayoutFlags {\n if (isLayoutFlagsRecord(value)) return value;\n return {};\n}\n\n/**\n * Type predicate for a plain (non-null, non-array) record of app payload values.\n * Used to distinguish the App Router payload object from bare React elements at\n * the render boundary. Narrows to `Readonly<Record<string, unknown>>` because\n * the outgoing payload carries heterogeneous values (ReactNodes for the rendered\n * tree, plus metadata like `__layoutFlags` which is a plain object). Delegates\n * to React's canonical `isValidElement` so we don't depend on React's internal\n * `$$typeof` marker scheme.\n */\nexport function isAppElementsRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n if (typeof value !== \"object\" || value === null) return false;\n if (Array.isArray(value)) return false;\n if (isValidElement(value)) return false;\n return true;\n}\n\n/**\n * Pure: returns a new record with `__layoutFlags` attached. Owns the write\n * boundary for the layout flags key so the write side sits next to\n * `readAppElementsMetadata`.\n *\n * See `LayoutFlags` type docblock in this file for lifecycle.\n */\nexport function withLayoutFlags<T extends Record<string, unknown>>(\n elements: T,\n layoutFlags: LayoutFlags,\n): T & { [APP_LAYOUT_FLAGS_KEY]: LayoutFlags } {\n return { ...elements, [APP_LAYOUT_FLAGS_KEY]: layoutFlags };\n}\n\n/**\n * The outgoing wire payload shape. Includes ReactNode values for the\n * rendered tree plus metadata values like LayoutFlags attached under\n * known keys (e.g. __layoutFlags). Distinct from AppElements / AppWireElements\n * which only carry render-time values.\n */\nexport type AppOutgoingElements = Readonly<Record<string, ReactNode | LayoutFlags>>;\n\n/**\n * Pure: builds the outgoing payload for the wire. Non-record inputs (e.g. a\n * bare React element) are returned unchanged. Record inputs get a fresh copy\n * with `__layoutFlags` attached. Never mutates `input.element`.\n */\nexport function buildOutgoingAppPayload(input: {\n element: ReactNode | Readonly<Record<string, ReactNode>>;\n layoutFlags: LayoutFlags;\n}): ReactNode | AppOutgoingElements {\n if (!isAppElementsRecord(input.element)) {\n return input.element;\n }\n return withLayoutFlags(input.element, input.layoutFlags);\n}\n\n/**\n * Parses metadata from the wire payload. Accepts `Record<string, unknown>`\n * because the RSC payload carries heterogeneous values (React elements,\n * strings, and plain objects like layout flags) under the same record type.\n *\n * See `LayoutFlags` type docblock in this file for lifecycle.\n */\nexport function readAppElementsMetadata(\n elements: Readonly<Record<string, unknown>>,\n): AppElementsMetadata {\n const routeId = elements[APP_ROUTE_KEY];\n if (typeof routeId !== \"string\") {\n throw new Error(\"[vinext] Missing __route string in App Router payload\");\n }\n\n const interceptionContext = elements[APP_INTERCEPTION_CONTEXT_KEY];\n if (\n interceptionContext !== undefined &&\n interceptionContext !== null &&\n typeof interceptionContext !== \"string\"\n ) {\n throw new Error(\"[vinext] Invalid __interceptionContext in App Router payload\");\n }\n\n const rootLayoutTreePath = elements[APP_ROOT_LAYOUT_KEY];\n if (rootLayoutTreePath === undefined) {\n throw new Error(\"[vinext] Missing __rootLayout key in App Router payload\");\n }\n if (rootLayoutTreePath !== null && typeof rootLayoutTreePath !== \"string\") {\n throw new Error(\"[vinext] Invalid __rootLayout in App Router payload: expected string or null\");\n }\n\n const layoutFlags = parseLayoutFlags(elements[APP_LAYOUT_FLAGS_KEY]);\n\n return {\n interceptionContext: interceptionContext ?? null,\n layoutFlags,\n routeId,\n rootLayoutTreePath,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"app-elements.js","names":[],"sources":["../../src/server/app-elements.ts"],"sourcesContent":["import { isValidElement, type ReactNode } from \"react\";\n\nconst APP_INTERCEPTION_SEPARATOR = \"\\0\";\n\nexport const APP_INTERCEPTION_CONTEXT_KEY = \"__interceptionContext\";\nexport const APP_LAYOUT_FLAGS_KEY = \"__layoutFlags\";\nexport const APP_ROUTE_KEY = \"__route\";\nexport const APP_ROOT_LAYOUT_KEY = \"__rootLayout\";\nexport const APP_UNMATCHED_SLOT_WIRE_VALUE = \"__VINEXT_UNMATCHED_SLOT__\";\n\nexport const UNMATCHED_SLOT = Symbol.for(\"vinext.unmatchedSlot\");\n\nexport type AppElementValue = ReactNode | typeof UNMATCHED_SLOT | string | null;\ntype AppWireElementValue = ReactNode | string | null;\n\nexport type AppElements = Readonly<Record<string, AppElementValue>>;\nexport type AppWireElements = Readonly<Record<string, AppWireElementValue>>;\n\n/**\n * Per-layout static/dynamic flags. `\"s\"` = static (skippable on next nav);\n * `\"d\"` = dynamic (must always render).\n *\n * Lifecycle (partial — later PRs extend this):\n *\n * 1. PROBE — probeAppPageLayouts (server/app-page-execution.ts) returns\n * LayoutFlags for every layout in the route at render time.\n *\n * 2. ATTACH — withLayoutFlags (this file) writes `__layoutFlags` into the\n * outgoing App Router payload record.\n *\n * 3. WIRE — renderToReadableStream serializes the record as RSC row 0.\n *\n * 4. PARSE — readAppElementsMetadata (this file) extracts layoutFlags from\n * the wire payload on the client side.\n */\nexport type LayoutFlags = Readonly<Record<string, \"s\" | \"d\">>;\n\ntype AppElementsMetadata = {\n interceptionContext: string | null;\n layoutFlags: LayoutFlags;\n routeId: string;\n rootLayoutTreePath: string | null;\n};\n\nfunction normalizeMountedSlotsHeader(header: string | null | undefined): string | null {\n if (!header) {\n return null;\n }\n\n const slotIds = Array.from(new Set(header.split(/\\s+/).filter(Boolean))).sort();\n\n return slotIds.length > 0 ? slotIds.join(\" \") : null;\n}\n\nexport function getMountedSlotIds(elements: AppElements): string[] {\n return Object.keys(elements)\n .filter((key) => {\n const value = elements[key];\n return (\n key.startsWith(\"slot:\") && value !== null && value !== undefined && value !== UNMATCHED_SLOT\n );\n })\n .sort();\n}\n\nexport function getMountedSlotIdsHeader(elements: AppElements): string | null {\n return normalizeMountedSlotsHeader(getMountedSlotIds(elements).join(\" \"));\n}\n\nfunction appendInterceptionContext(identity: string, interceptionContext: string | null): string {\n return interceptionContext === null\n ? identity\n : `${identity}${APP_INTERCEPTION_SEPARATOR}${interceptionContext}`;\n}\n\nexport function createAppPayloadRouteId(\n routePath: string,\n interceptionContext: string | null,\n): string {\n return appendInterceptionContext(`route:${routePath}`, interceptionContext);\n}\n\nexport function createAppPayloadPageId(\n routePath: string,\n interceptionContext: string | null,\n): string {\n return appendInterceptionContext(`page:${routePath}`, interceptionContext);\n}\n\nexport function createAppPayloadCacheKey(\n rscUrl: string,\n interceptionContext: string | null,\n): string {\n return appendInterceptionContext(rscUrl, interceptionContext);\n}\n\nexport function resolveVisitedResponseInterceptionContext(\n requestInterceptionContext: string | null,\n payloadInterceptionContext: string | null,\n): string | null {\n return payloadInterceptionContext ?? requestInterceptionContext;\n}\n\nexport function normalizeAppElements(elements: AppWireElements): AppElements {\n let needsNormalization = false;\n for (const [key, value] of Object.entries(elements)) {\n if (key.startsWith(\"slot:\") && value === APP_UNMATCHED_SLOT_WIRE_VALUE) {\n needsNormalization = true;\n break;\n }\n }\n\n if (!needsNormalization) {\n return elements;\n }\n\n const normalized: Record<string, AppElementValue> = {};\n for (const [key, value] of Object.entries(elements)) {\n normalized[key] =\n key.startsWith(\"slot:\") && value === APP_UNMATCHED_SLOT_WIRE_VALUE ? UNMATCHED_SLOT : value;\n }\n\n return normalized;\n}\n\nfunction isLayoutFlagsRecord(value: unknown): value is LayoutFlags {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n for (const v of Object.values(value)) {\n if (v !== \"s\" && v !== \"d\") return false;\n }\n return true;\n}\n\nfunction parseLayoutFlags(value: unknown): LayoutFlags {\n if (isLayoutFlagsRecord(value)) return value;\n return {};\n}\n\n/**\n * Type predicate for a plain (non-null, non-array) record of app payload values.\n * Used to distinguish the App Router payload object from bare React elements at\n * the render boundary. Narrows to `Readonly<Record<string, unknown>>` because\n * the outgoing payload carries heterogeneous values (ReactNodes for the rendered\n * tree, plus metadata like `__layoutFlags` which is a plain object). Delegates\n * to React's canonical `isValidElement` so we don't depend on React's internal\n * `$$typeof` marker scheme.\n */\nexport function isAppElementsRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n if (typeof value !== \"object\" || value === null) return false;\n if (Array.isArray(value)) return false;\n if (isValidElement(value)) return false;\n return true;\n}\n\n/**\n * Pure: returns a new record with `__layoutFlags` attached. Owns the write\n * boundary for the layout flags key so the write side sits next to\n * `readAppElementsMetadata`.\n *\n * See `LayoutFlags` type docblock in this file for lifecycle.\n */\nexport function withLayoutFlags<T extends Record<string, unknown>>(\n elements: T,\n layoutFlags: LayoutFlags,\n): T & { [APP_LAYOUT_FLAGS_KEY]: LayoutFlags } {\n return { ...elements, [APP_LAYOUT_FLAGS_KEY]: layoutFlags };\n}\n\n/**\n * The outgoing wire payload shape. Includes ReactNode values for the\n * rendered tree plus metadata values like LayoutFlags attached under\n * known keys (e.g. __layoutFlags). Distinct from AppElements / AppWireElements\n * which only carry render-time values.\n */\nexport type AppOutgoingElements = Readonly<Record<string, ReactNode | LayoutFlags>>;\n\n/**\n * Pure: builds the outgoing payload for the wire. Non-record inputs (e.g. a\n * bare React element) are returned unchanged. Record inputs get a fresh copy\n * with `__layoutFlags` attached. Never mutates `input.element`.\n */\nexport function buildOutgoingAppPayload(input: {\n element: ReactNode | Readonly<Record<string, ReactNode>>;\n layoutFlags: LayoutFlags;\n}): ReactNode | AppOutgoingElements {\n if (!isAppElementsRecord(input.element)) {\n return input.element;\n }\n return withLayoutFlags(input.element, input.layoutFlags);\n}\n\n/**\n * Parses metadata from the wire payload. Accepts `Record<string, unknown>`\n * because the RSC payload carries heterogeneous values (React elements,\n * strings, and plain objects like layout flags) under the same record type.\n *\n * See `LayoutFlags` type docblock in this file for lifecycle.\n */\nexport function readAppElementsMetadata(\n elements: Readonly<Record<string, unknown>>,\n): AppElementsMetadata {\n const routeId = elements[APP_ROUTE_KEY];\n if (typeof routeId !== \"string\") {\n throw new Error(\"[vinext] Missing __route string in App Router payload\");\n }\n\n const interceptionContext = elements[APP_INTERCEPTION_CONTEXT_KEY];\n if (\n interceptionContext !== undefined &&\n interceptionContext !== null &&\n typeof interceptionContext !== \"string\"\n ) {\n throw new Error(\"[vinext] Invalid __interceptionContext in App Router payload\");\n }\n\n const rootLayoutTreePath = elements[APP_ROOT_LAYOUT_KEY];\n if (rootLayoutTreePath === undefined) {\n throw new Error(\"[vinext] Missing __rootLayout key in App Router payload\");\n }\n if (rootLayoutTreePath !== null && typeof rootLayoutTreePath !== \"string\") {\n throw new Error(\"[vinext] Invalid __rootLayout in App Router payload: expected string or null\");\n }\n\n const layoutFlags = parseLayoutFlags(elements[APP_LAYOUT_FLAGS_KEY]);\n\n return {\n interceptionContext: interceptionContext ?? null,\n layoutFlags,\n routeId,\n rootLayoutTreePath,\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import { NextI18nConfig } from "../config/next-config.js";
2
+ import { MiddlewareModule } from "./middleware-runtime.js";
3
+
4
+ //#region src/server/app-middleware.d.ts
5
+ type AppMiddlewareContext = {
6
+ headers: Headers | null;
7
+ requestHeaders: Headers | null;
8
+ status: number | null;
9
+ };
10
+ type ApplyAppMiddlewareOptions = {
11
+ basePath?: string;
12
+ cleanPathname: string;
13
+ context: AppMiddlewareContext;
14
+ i18nConfig?: NextI18nConfig | null;
15
+ isProxy: boolean;
16
+ module: MiddlewareModule;
17
+ request: Request;
18
+ };
19
+ type ApplyAppMiddlewareResult = {
20
+ kind: "continue";
21
+ cleanPathname: string;
22
+ search: string | null;
23
+ } | {
24
+ kind: "response";
25
+ response: Response;
26
+ };
27
+ declare function isExternalMiddlewareRewrite(rewriteUrl: string, request: Request): boolean;
28
+ declare function proxyExternalMiddlewareRewrite(request: Request, rewriteUrl: string, context: AppMiddlewareContext): Promise<Response>;
29
+ declare function applyAppMiddleware(options: ApplyAppMiddlewareOptions): Promise<ApplyAppMiddlewareResult>;
30
+ //#endregion
31
+ export { AppMiddlewareContext, ApplyAppMiddlewareOptions, ApplyAppMiddlewareResult, applyAppMiddleware, isExternalMiddlewareRewrite, proxyExternalMiddlewareRewrite };
32
+ //# sourceMappingURL=app-middleware.d.ts.map