vinext 0.0.51 → 0.0.52

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 (307) hide show
  1. package/dist/build/precompress.d.ts +7 -7
  2. package/dist/build/precompress.js +18 -17
  3. package/dist/build/precompress.js.map +1 -1
  4. package/dist/build/prerender.d.ts +3 -14
  5. package/dist/build/prerender.js +40 -40
  6. package/dist/build/prerender.js.map +1 -1
  7. package/dist/check.js +4 -0
  8. package/dist/check.js.map +1 -1
  9. package/dist/cli-args.d.ts +1 -0
  10. package/dist/cli-args.js +5 -0
  11. package/dist/cli-args.js.map +1 -1
  12. package/dist/cli.js +39 -0
  13. package/dist/cli.js.map +1 -1
  14. package/dist/client/navigation-runtime.d.ts +47 -0
  15. package/dist/client/navigation-runtime.js +156 -0
  16. package/dist/client/navigation-runtime.js.map +1 -0
  17. package/dist/client/pages-router-link-navigation.d.ts +26 -0
  18. package/dist/client/pages-router-link-navigation.js +14 -0
  19. package/dist/client/pages-router-link-navigation.js.map +1 -0
  20. package/dist/client/vinext-next-data.d.ts +12 -2
  21. package/dist/client/vinext-next-data.js +50 -1
  22. package/dist/client/vinext-next-data.js.map +1 -0
  23. package/dist/cloudflare/kv-cache-handler.js +2 -1
  24. package/dist/cloudflare/kv-cache-handler.js.map +1 -1
  25. package/dist/config/config-matchers.d.ts +63 -16
  26. package/dist/config/config-matchers.js +143 -8
  27. package/dist/config/config-matchers.js.map +1 -1
  28. package/dist/config/next-config.d.ts +20 -2
  29. package/dist/config/next-config.js +11 -1
  30. package/dist/config/next-config.js.map +1 -1
  31. package/dist/deploy.js +101 -39
  32. package/dist/deploy.js.map +1 -1
  33. package/dist/entries/app-browser-entry.js +9 -3
  34. package/dist/entries/app-browser-entry.js.map +1 -1
  35. package/dist/entries/app-rsc-entry.js +53 -13
  36. package/dist/entries/app-rsc-entry.js.map +1 -1
  37. package/dist/entries/app-rsc-manifest.d.ts +1 -0
  38. package/dist/entries/app-rsc-manifest.js +53 -6
  39. package/dist/entries/app-rsc-manifest.js.map +1 -1
  40. package/dist/entries/app-ssr-entry.d.ts +3 -3
  41. package/dist/entries/app-ssr-entry.js +4 -4
  42. package/dist/entries/app-ssr-entry.js.map +1 -1
  43. package/dist/entries/pages-client-entry.js +18 -2
  44. package/dist/entries/pages-client-entry.js.map +1 -1
  45. package/dist/entries/pages-server-entry.js +58 -8
  46. package/dist/entries/pages-server-entry.js.map +1 -1
  47. package/dist/entries/runtime-entry-module.d.ts +2 -1
  48. package/dist/entries/runtime-entry-module.js +9 -3
  49. package/dist/entries/runtime-entry-module.js.map +1 -1
  50. package/dist/index.js +132 -40
  51. package/dist/index.js.map +1 -1
  52. package/dist/plugins/css-data-url.d.ts +7 -0
  53. package/dist/plugins/css-data-url.js +81 -0
  54. package/dist/plugins/css-data-url.js.map +1 -0
  55. package/dist/plugins/fonts.js +5 -3
  56. package/dist/plugins/fonts.js.map +1 -1
  57. package/dist/plugins/middleware-server-only.d.ts +54 -0
  58. package/dist/plugins/middleware-server-only.js +91 -0
  59. package/dist/plugins/middleware-server-only.js.map +1 -0
  60. package/dist/plugins/optimize-imports.js +4 -4
  61. package/dist/plugins/optimize-imports.js.map +1 -1
  62. package/dist/plugins/strip-server-exports.js +5 -8
  63. package/dist/plugins/strip-server-exports.js.map +1 -1
  64. package/dist/routing/app-route-graph.d.ts +20 -1
  65. package/dist/routing/app-route-graph.js +58 -6
  66. package/dist/routing/app-route-graph.js.map +1 -1
  67. package/dist/routing/app-router.d.ts +2 -2
  68. package/dist/routing/app-router.js +2 -2
  69. package/dist/routing/app-router.js.map +1 -1
  70. package/dist/routing/utils.d.ts +2 -1
  71. package/dist/routing/utils.js +4 -1
  72. package/dist/routing/utils.js.map +1 -1
  73. package/dist/server/api-handler.js +139 -37
  74. package/dist/server/api-handler.js.map +1 -1
  75. package/dist/server/app-browser-entry.js +293 -149
  76. package/dist/server/app-browser-entry.js.map +1 -1
  77. package/dist/server/app-browser-interception-context.d.ts +24 -0
  78. package/dist/server/app-browser-interception-context.js +32 -0
  79. package/dist/server/app-browser-interception-context.js.map +1 -0
  80. package/dist/server/app-browser-navigation-controller.d.ts +3 -1
  81. package/dist/server/app-browser-navigation-controller.js +5 -1
  82. package/dist/server/app-browser-navigation-controller.js.map +1 -1
  83. package/dist/server/app-browser-rsc-redirect.d.ts +2 -1
  84. package/dist/server/app-browser-rsc-redirect.js +2 -2
  85. package/dist/server/app-browser-rsc-redirect.js.map +1 -1
  86. package/dist/server/app-browser-state.d.ts +18 -1
  87. package/dist/server/app-browser-state.js +19 -1
  88. package/dist/server/app-browser-state.js.map +1 -1
  89. package/dist/server/app-browser-stream.d.ts +5 -14
  90. package/dist/server/app-browser-stream.js +13 -7
  91. package/dist/server/app-browser-stream.js.map +1 -1
  92. package/dist/server/app-browser-visible-commit.d.ts +2 -1
  93. package/dist/server/app-browser-visible-commit.js +1 -0
  94. package/dist/server/app-browser-visible-commit.js.map +1 -1
  95. package/dist/server/app-elements-wire.d.ts +10 -5
  96. package/dist/server/app-elements-wire.js +84 -2
  97. package/dist/server/app-elements-wire.js.map +1 -1
  98. package/dist/server/app-elements.d.ts +3 -2
  99. package/dist/server/app-elements.js +3 -2
  100. package/dist/server/app-elements.js.map +1 -1
  101. package/dist/server/app-fallback-renderer.js +5 -3
  102. package/dist/server/app-fallback-renderer.js.map +1 -1
  103. package/dist/server/app-middleware.d.ts +13 -0
  104. package/dist/server/app-middleware.js +3 -1
  105. package/dist/server/app-middleware.js.map +1 -1
  106. package/dist/server/app-optimistic-routing.d.ts +54 -0
  107. package/dist/server/app-optimistic-routing.js +200 -0
  108. package/dist/server/app-optimistic-routing.js.map +1 -0
  109. package/dist/server/app-page-cache.d.ts +13 -1
  110. package/dist/server/app-page-cache.js +61 -6
  111. package/dist/server/app-page-cache.js.map +1 -1
  112. package/dist/server/app-page-dispatch.d.ts +2 -0
  113. package/dist/server/app-page-dispatch.js +28 -1
  114. package/dist/server/app-page-dispatch.js.map +1 -1
  115. package/dist/server/app-page-element-builder.js +2 -1
  116. package/dist/server/app-page-element-builder.js.map +1 -1
  117. package/dist/server/app-page-execution.d.ts +28 -1
  118. package/dist/server/app-page-execution.js +89 -4
  119. package/dist/server/app-page-execution.js.map +1 -1
  120. package/dist/server/app-page-head.js +21 -2
  121. package/dist/server/app-page-head.js.map +1 -1
  122. package/dist/server/app-page-probe.js +1 -1
  123. package/dist/server/app-page-render.d.ts +2 -0
  124. package/dist/server/app-page-render.js +2 -1
  125. package/dist/server/app-page-render.js.map +1 -1
  126. package/dist/server/app-page-response.js +4 -3
  127. package/dist/server/app-page-response.js.map +1 -1
  128. package/dist/server/app-page-route-wiring.js +17 -10
  129. package/dist/server/app-page-route-wiring.js.map +1 -1
  130. package/dist/server/app-page-stream.d.ts +3 -0
  131. package/dist/server/app-page-stream.js +1 -0
  132. package/dist/server/app-page-stream.js.map +1 -1
  133. package/dist/server/app-prerender-static-params.d.ts +2 -1
  134. package/dist/server/app-prerender-static-params.js +44 -8
  135. package/dist/server/app-prerender-static-params.js.map +1 -1
  136. package/dist/server/app-route-handler-cache.d.ts +2 -2
  137. package/dist/server/app-route-handler-cache.js +3 -2
  138. package/dist/server/app-route-handler-cache.js.map +1 -1
  139. package/dist/server/app-route-handler-dispatch.d.ts +6 -1
  140. package/dist/server/app-route-handler-dispatch.js +1 -1
  141. package/dist/server/app-route-handler-dispatch.js.map +1 -1
  142. package/dist/server/app-route-handler-execution.d.ts +17 -2
  143. package/dist/server/app-route-handler-execution.js.map +1 -1
  144. package/dist/server/app-route-handler-response.js +5 -4
  145. package/dist/server/app-route-handler-response.js.map +1 -1
  146. package/dist/server/app-router-entry.js +6 -2
  147. package/dist/server/app-router-entry.js.map +1 -1
  148. package/dist/server/app-rsc-handler.d.ts +9 -1
  149. package/dist/server/app-rsc-handler.js +32 -14
  150. package/dist/server/app-rsc-handler.js.map +1 -1
  151. package/dist/server/app-rsc-render-mode.d.ts +4 -3
  152. package/dist/server/app-rsc-render-mode.js +7 -1
  153. package/dist/server/app-rsc-render-mode.js.map +1 -1
  154. package/dist/server/app-rsc-request-normalization.d.ts +4 -1
  155. package/dist/server/app-rsc-request-normalization.js +4 -1
  156. package/dist/server/app-rsc-request-normalization.js.map +1 -1
  157. package/dist/server/app-rsc-response-finalizer.d.ts +8 -1
  158. package/dist/server/app-rsc-response-finalizer.js +10 -3
  159. package/dist/server/app-rsc-response-finalizer.js.map +1 -1
  160. package/dist/server/app-rsc-route-matching.js +2 -2
  161. package/dist/server/app-rsc-route-matching.js.map +1 -1
  162. package/dist/server/app-server-action-execution.js +1 -1
  163. package/dist/server/app-ssr-entry.d.ts +2 -0
  164. package/dist/server/app-ssr-entry.js +56 -55
  165. package/dist/server/app-ssr-entry.js.map +1 -1
  166. package/dist/server/app-ssr-stream.d.ts +6 -1
  167. package/dist/server/app-ssr-stream.js +17 -3
  168. package/dist/server/app-ssr-stream.js.map +1 -1
  169. package/dist/server/artifact-compatibility.d.ts +1 -1
  170. package/dist/server/artifact-compatibility.js.map +1 -1
  171. package/dist/server/cache-headers.d.ts +7 -0
  172. package/dist/server/cache-headers.js +19 -0
  173. package/dist/server/cache-headers.js.map +1 -0
  174. package/dist/server/cache-proof.d.ts +49 -3
  175. package/dist/server/cache-proof.js +78 -22
  176. package/dist/server/cache-proof.js.map +1 -1
  177. package/dist/server/client-reuse-manifest.d.ts +99 -0
  178. package/dist/server/client-reuse-manifest.js +212 -0
  179. package/dist/server/client-reuse-manifest.js.map +1 -0
  180. package/dist/server/default-global-error-module.d.ts +20 -0
  181. package/dist/server/default-global-error-module.js +20 -0
  182. package/dist/server/default-global-error-module.js.map +1 -0
  183. package/dist/server/dev-server.d.ts +9 -1
  184. package/dist/server/dev-server.js +76 -29
  185. package/dist/server/dev-server.js.map +1 -1
  186. package/dist/server/edge-api-runtime.d.ts +5 -0
  187. package/dist/server/edge-api-runtime.js +8 -0
  188. package/dist/server/edge-api-runtime.js.map +1 -0
  189. package/dist/server/headers.d.ts +18 -1
  190. package/dist/server/headers.js +18 -1
  191. package/dist/server/headers.js.map +1 -1
  192. package/dist/server/http-error-responses.d.ts +16 -1
  193. package/dist/server/http-error-responses.js +21 -1
  194. package/dist/server/http-error-responses.js.map +1 -1
  195. package/dist/server/isr-cache.d.ts +6 -2
  196. package/dist/server/isr-cache.js +20 -4
  197. package/dist/server/isr-cache.js.map +1 -1
  198. package/dist/server/middleware-runtime.d.ts +15 -0
  199. package/dist/server/middleware-runtime.js +59 -7
  200. package/dist/server/middleware-runtime.js.map +1 -1
  201. package/dist/server/middleware.d.ts +1 -1
  202. package/dist/server/middleware.js +4 -2
  203. package/dist/server/middleware.js.map +1 -1
  204. package/dist/server/navigation-planner.d.ts +9 -3
  205. package/dist/server/navigation-planner.js +98 -25
  206. package/dist/server/navigation-planner.js.map +1 -1
  207. package/dist/server/navigation-trace.d.ts +2 -1
  208. package/dist/server/navigation-trace.js +1 -0
  209. package/dist/server/navigation-trace.js.map +1 -1
  210. package/dist/server/pages-api-route.d.ts +27 -1
  211. package/dist/server/pages-api-route.js +24 -3
  212. package/dist/server/pages-api-route.js.map +1 -1
  213. package/dist/server/pages-data-route.d.ts +77 -0
  214. package/dist/server/pages-data-route.js +97 -0
  215. package/dist/server/pages-data-route.js.map +1 -0
  216. package/dist/server/pages-i18n.d.ts +51 -1
  217. package/dist/server/pages-i18n.js +61 -1
  218. package/dist/server/pages-i18n.js.map +1 -1
  219. package/dist/server/pages-page-data.d.ts +29 -2
  220. package/dist/server/pages-page-data.js +31 -17
  221. package/dist/server/pages-page-data.js.map +1 -1
  222. package/dist/server/pages-page-response.d.ts +11 -1
  223. package/dist/server/pages-page-response.js +5 -3
  224. package/dist/server/pages-page-response.js.map +1 -1
  225. package/dist/server/prod-server.d.ts +13 -15
  226. package/dist/server/prod-server.js +109 -56
  227. package/dist/server/prod-server.js.map +1 -1
  228. package/dist/server/request-pipeline.d.ts +11 -2
  229. package/dist/server/request-pipeline.js +28 -11
  230. package/dist/server/request-pipeline.js.map +1 -1
  231. package/dist/server/seed-cache.d.ts +12 -31
  232. package/dist/server/seed-cache.js +22 -35
  233. package/dist/server/seed-cache.js.map +1 -1
  234. package/dist/server/server-action-not-found.js +8 -3
  235. package/dist/server/server-action-not-found.js.map +1 -1
  236. package/dist/server/skip-cache-proof.d.ts +41 -0
  237. package/dist/server/skip-cache-proof.js +101 -0
  238. package/dist/server/skip-cache-proof.js.map +1 -0
  239. package/dist/server/static-file-cache.d.ts +1 -1
  240. package/dist/server/static-file-cache.js +7 -6
  241. package/dist/server/static-file-cache.js.map +1 -1
  242. package/dist/shims/client-locale.d.ts +15 -0
  243. package/dist/shims/client-locale.js +13 -0
  244. package/dist/shims/client-locale.js.map +1 -0
  245. package/dist/shims/default-global-error.d.ts +32 -0
  246. package/dist/shims/default-global-error.js +181 -0
  247. package/dist/shims/default-global-error.js.map +1 -0
  248. package/dist/shims/document.d.ts +59 -3
  249. package/dist/shims/document.js +36 -5
  250. package/dist/shims/document.js.map +1 -1
  251. package/dist/shims/error-boundary.d.ts +2 -2
  252. package/dist/shims/form.js +13 -6
  253. package/dist/shims/form.js.map +1 -1
  254. package/dist/shims/link.d.ts +21 -3
  255. package/dist/shims/link.js +131 -22
  256. package/dist/shims/link.js.map +1 -1
  257. package/dist/shims/metadata.js +4 -4
  258. package/dist/shims/metadata.js.map +1 -1
  259. package/dist/shims/navigation.d.ts +8 -2
  260. package/dist/shims/navigation.js +36 -15
  261. package/dist/shims/navigation.js.map +1 -1
  262. package/dist/shims/og.d.ts +18 -2
  263. package/dist/shims/og.js +49 -1
  264. package/dist/shims/og.js.map +1 -0
  265. package/dist/shims/request-state-types.d.ts +1 -1
  266. package/dist/shims/root-params.d.ts +3 -1
  267. package/dist/shims/root-params.js +11 -3
  268. package/dist/shims/root-params.js.map +1 -1
  269. package/dist/shims/router-state.d.ts +1 -0
  270. package/dist/shims/router-state.js.map +1 -1
  271. package/dist/shims/router.d.ts +12 -5
  272. package/dist/shims/router.js +172 -22
  273. package/dist/shims/router.js.map +1 -1
  274. package/dist/shims/server.d.ts +21 -4
  275. package/dist/shims/server.js +29 -9
  276. package/dist/shims/server.js.map +1 -1
  277. package/dist/shims/slot.js +5 -1
  278. package/dist/shims/slot.js.map +1 -1
  279. package/dist/shims/unified-request-context.d.ts +1 -1
  280. package/dist/shims/url-safety.d.ts +23 -1
  281. package/dist/shims/url-safety.js +29 -2
  282. package/dist/shims/url-safety.js.map +1 -1
  283. package/dist/typegen.d.ts +10 -0
  284. package/dist/typegen.js +242 -0
  285. package/dist/typegen.js.map +1 -0
  286. package/dist/utils/asset-prefix.d.ts +33 -5
  287. package/dist/utils/asset-prefix.js +39 -6
  288. package/dist/utils/asset-prefix.js.map +1 -1
  289. package/dist/utils/cache-control-metadata.d.ts +2 -1
  290. package/dist/utils/cache-control-metadata.js +1 -3
  291. package/dist/utils/cache-control-metadata.js.map +1 -1
  292. package/dist/utils/domain-locale.d.ts +2 -1
  293. package/dist/utils/domain-locale.js +9 -1
  294. package/dist/utils/domain-locale.js.map +1 -1
  295. package/dist/utils/lazy-chunks.d.ts +1 -1
  296. package/dist/utils/lazy-chunks.js +1 -1
  297. package/dist/utils/lazy-chunks.js.map +1 -1
  298. package/dist/utils/prerender-output-paths.d.ts +15 -0
  299. package/dist/utils/prerender-output-paths.js +24 -0
  300. package/dist/utils/prerender-output-paths.js.map +1 -0
  301. package/dist/utils/query.d.ts +17 -1
  302. package/dist/utils/query.js +36 -1
  303. package/dist/utils/query.js.map +1 -1
  304. package/dist/utils/record.d.ts +5 -0
  305. package/dist/utils/record.js +8 -0
  306. package/dist/utils/record.js.map +1 -0
  307. package/package.json +11 -3
@@ -1,22 +1,24 @@
1
1
  import { stripBasePath } from "../utils/base-path.js";
2
- import { ACTION_REDIRECT_HEADER, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_PARAMS_HEADER } from "./headers.js";
2
+ import { ACTION_REDIRECT_HEADER, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_PARAMS_HEADER, VINEXT_RSC_REDIRECT_HEADER } from "./headers.js";
3
3
  import { DANGEROUS_URL_BLOCK_MESSAGE, isDangerousScheme } from "../shims/url-safety.js";
4
4
  import { APP_RSC_RENDER_MODE_REFRESH_PRESERVE_UI } from "./app-rsc-render-mode.js";
5
5
  import { installWindowNext } from "../client/window-next.js";
6
6
  import { scrollToHashTargetOnNextFrame } from "../shims/hash-scroll.js";
7
+ import { getNavigationRuntime, registerNavigationRuntimeBootstrap, registerNavigationRuntimeFunctions } from "../client/navigation-runtime.js";
7
8
  import { notifyAppRouterTransitionStart } from "../client/instrumentation-client-state.js";
8
9
  import { AppElementsWire } from "./app-elements-wire.js";
9
10
  import { getMountedSlotIdsHeader, resolveVisitedResponseInterceptionContext } from "./app-elements.js";
11
+ import { resolveManifestNavigationInterceptionContext } from "./app-browser-interception-context.js";
10
12
  import { createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent } from "./app-history-state.js";
11
13
  import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, createRscRequestHeaders, createRscRequestUrl, getVinextRscCompatibilityId, resolveHardNavigationTargetFromRscResponse, resolveRscCompatibilityNavigationDecision } from "./app-rsc-cache-busting.js";
12
14
  import { AppRouterContext } from "../shims/internal/app-router-context.js";
13
- import { __basePath, appRouterInstance, commitClientNavigationState, consumePrefetchResponse, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, getClientNavigationRenderContext, getCurrentInterceptionContext, getCurrentNextUrl, invalidatePrefetchCache, pushHistoryStateWithoutNotify, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, restoreRscResponse, setClientParams, setMountedSlotsHeader, setNavigationContext, setPendingPathname } from "../shims/navigation.js";
15
+ import { __basePath, appRouterInstance, commitClientNavigationState, consumePrefetchResponse, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, getClientNavigationRenderContext, getPrefetchCache, invalidatePrefetchCache, pushHistoryStateWithoutNotify, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, restoreRscResponse, setClientParams, setMountedSlotsHeader, setNavigationContext, setPendingPathname } from "../shims/navigation.js";
14
16
  import { DevRecoveryBoundary, RedirectBoundary } from "../shims/error-boundary.js";
15
17
  import { ElementsContext, Slot } from "../shims/slot.js";
16
18
  import "../client/instrumentation-client.js";
17
19
  import { createDiscardedServerActionRefreshScheduler, createServerActionInitiationSnapshot, isServerActionResult, parseServerActionRevalidationHeader, shouldClearClientNavigationCachesForServerActionResult } from "./app-browser-action-result.js";
18
20
  import { chunksToReadableStream, createProgressiveRscStream, getVinextBrowserGlobal } from "./app-browser-stream.js";
19
- import { resolveInterceptionContextFromPreviousNextUrl, resolveServerActionRequestState } from "./app-browser-state.js";
21
+ import { FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, VISITED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN, isCacheRestorableAppPayloadMetadata, resolveInterceptionContextFromPreviousNextUrl, resolveServerActionRequestState } from "./app-browser-state.js";
20
22
  import { clearHardNavigationLoopGuard, createAppBrowserNavigationController } from "./app-browser-navigation-controller.js";
21
23
  import { consumeInitialFormState, createVinextHydrateRootOptions, hydrateRootInTransition } from "./app-browser-hydration.js";
22
24
  import { createPopstateRestoreHandler } from "./app-browser-popstate.js";
@@ -25,6 +27,7 @@ import { dismissOverlay } from "./dev-error-overlay-store.js";
25
27
  import { devOnCaughtError, devOnUncaughtError, installDevErrorOverlay } from "./dev-error-overlay.js";
26
28
  import { throwOnServerActionNotFound } from "./server-action-not-found.js";
27
29
  import { resolveRscRedirectLifecycleHop } from "./app-browser-rsc-redirect.js";
30
+ import { createOptimisticRouteTemplate, getOptimisticPrefetchSourceKey, getOptimisticRouteTemplateKey, resolveOptimisticNavigationPayload } from "./app-optimistic-routing.js";
28
31
  import { createElement, startTransition, use, useLayoutEffect, useRef, useState } from "react";
29
32
  import { createFromFetch, createFromReadableStream, createTemporaryReferenceSet, encodeReply, setServerCallback } from "@vitejs/plugin-rsc/browser";
30
33
  import { hydrateRoot } from "react-dom/client";
@@ -44,8 +47,11 @@ const MAX_VISITED_RESPONSE_CACHE_SIZE = 50;
44
47
  const VISITED_RESPONSE_CACHE_TTL = 5 * 6e4;
45
48
  const MAX_TRAVERSAL_CACHE_TTL = 30 * 6e4;
46
49
  const CLIENT_RSC_COMPATIBILITY_ID = getVinextRscCompatibilityId();
50
+ const optimisticRouteTemplates = /* @__PURE__ */ new Map();
51
+ const optimisticRouteTemplateSources = /* @__PURE__ */ new Set();
52
+ const optimisticRouteTemplateLearning = /* @__PURE__ */ new Map();
47
53
  function getBrowserRouteManifest() {
48
- return window.__VINEXT_ROUTE_MANIFEST__ ?? null;
54
+ return getNavigationRuntime()?.bootstrap.routeManifest ?? null;
49
55
  }
50
56
  const browserNavigationController = createAppBrowserNavigationController({
51
57
  getRouteManifest: getBrowserRouteManifest,
@@ -53,9 +59,7 @@ const browserNavigationController = createAppBrowserNavigationController({
53
59
  });
54
60
  const discardedServerActionRefreshScheduler = createDiscardedServerActionRefreshScheduler({ runRefresh() {
55
61
  clearClientNavigationCaches();
56
- const rscNavigate = window.__VINEXT_RSC_NAVIGATE__;
57
- if (typeof rscNavigate !== "function") return;
58
- rscNavigate(window.location.href, 0, "refresh", void 0, void 0, true);
62
+ getNavigationRuntime()?.functions.navigate?.(window.location.href, 0, "refresh", void 0, void 0, true);
59
63
  } });
60
64
  const NavigationCommitSignal = browserNavigationController.NavigationCommitSignal;
61
65
  function parseEncodedJsonHeader(value) {
@@ -139,11 +143,80 @@ function clearVisitedResponseCache() {
139
143
  }
140
144
  function clearPrefetchState() {
141
145
  invalidatePrefetchCache();
146
+ optimisticRouteTemplates.clear();
147
+ optimisticRouteTemplateSources.clear();
148
+ optimisticRouteTemplateLearning.clear();
142
149
  }
143
150
  function clearClientNavigationCaches() {
144
151
  clearVisitedResponseCache();
145
152
  clearPrefetchState();
146
153
  }
154
+ function isSettledPrefetchCacheEntry(entry) {
155
+ return entry.outcome === "cache-seeded" && entry.pending === void 0 && entry.snapshot !== void 0;
156
+ }
157
+ function parsePrefetchCacheKey(cacheKey) {
158
+ const separatorIndex = cacheKey.indexOf("\0");
159
+ if (separatorIndex === -1) return {
160
+ interceptionContext: null,
161
+ rscUrl: cacheKey
162
+ };
163
+ return {
164
+ interceptionContext: cacheKey.slice(separatorIndex + 1),
165
+ rscUrl: cacheKey.slice(0, separatorIndex)
166
+ };
167
+ }
168
+ async function learnOptimisticRouteTemplateFromPrefetch(options) {
169
+ const source = parsePrefetchCacheKey(options.cacheKey);
170
+ if (source.interceptionContext !== options.interceptionContext) return false;
171
+ if ((options.entry.snapshot.mountedSlotsHeader ?? null) !== options.mountedSlotsHeader) return false;
172
+ if (options.interceptionContext !== null) return false;
173
+ const elements = await decodeAppElementsPromise(createFromFetch(Promise.resolve(restoreRscResponse(options.entry.snapshot))));
174
+ const template = createOptimisticRouteTemplate({
175
+ allowLoadingShell: options.entry.optimisticRouteShell === true,
176
+ basePath: __basePath,
177
+ elements,
178
+ href: options.entry.snapshot.url || source.rscUrl,
179
+ interceptionContext: options.interceptionContext,
180
+ mountedSlotsHeader: options.mountedSlotsHeader,
181
+ routeManifest: options.routeManifest
182
+ });
183
+ if (template === null) return false;
184
+ optimisticRouteTemplates.set(getOptimisticRouteTemplateKey({
185
+ interceptionContext: options.interceptionContext,
186
+ mountedSlotsHeader: options.mountedSlotsHeader,
187
+ routeId: template.routeId
188
+ }), template);
189
+ return true;
190
+ }
191
+ async function learnOptimisticRouteTemplatesFromPrefetchCache(options) {
192
+ if (options.routeManifest === null) return;
193
+ const learning = [...optimisticRouteTemplateLearning.values()];
194
+ for (const [cacheKey, entry] of getPrefetchCache()) {
195
+ const sourceKey = getOptimisticPrefetchSourceKey({
196
+ cacheKey,
197
+ interceptionContext: options.interceptionContext,
198
+ mountedSlotsHeader: options.mountedSlotsHeader
199
+ });
200
+ if (optimisticRouteTemplateSources.has(sourceKey)) continue;
201
+ if (optimisticRouteTemplateLearning.has(sourceKey)) continue;
202
+ if (!isSettledPrefetchCacheEntry(entry)) continue;
203
+ const promise = learnOptimisticRouteTemplateFromPrefetch({
204
+ cacheKey,
205
+ entry,
206
+ interceptionContext: options.interceptionContext,
207
+ mountedSlotsHeader: options.mountedSlotsHeader,
208
+ routeManifest: options.routeManifest
209
+ }).then((learned) => {
210
+ if (learned) optimisticRouteTemplateSources.add(sourceKey);
211
+ }).finally(() => {
212
+ optimisticRouteTemplateLearning.delete(sourceKey);
213
+ });
214
+ optimisticRouteTemplateLearning.set(sourceKey, promise);
215
+ learning.push(promise);
216
+ }
217
+ if (learning.length === 0) return;
218
+ await Promise.allSettled(learning);
219
+ }
147
220
  function syncCurrentHistoryStatePreviousNextUrl(previousNextUrl) {
148
221
  if (readHistoryStatePreviousNextUrl(window.history.state) === previousNextUrl) return;
149
222
  const nextHistoryState = createHistoryStateWithPreviousNextUrl(window.history.state, previousNextUrl);
@@ -194,7 +267,7 @@ function createNavigationCommitEffect(options) {
194
267
  commitClientNavigationState(navId);
195
268
  };
196
269
  }
197
- async function renderNavigationPayload(payload, navigationSnapshot, targetHref, navId, historyUpdateMode, params, previousNextUrl, pendingRouterState, actionType = "navigate", operationLane = "navigation", traversalIntent = null) {
270
+ async function renderNavigationPayload(payload, navigationSnapshot, targetHref, navId, historyUpdateMode, params, previousNextUrl, pendingRouterState, payloadOrigin, actionType = "navigate", operationLane = "navigation", traversalIntent = null) {
198
271
  try {
199
272
  return await browserNavigationController.renderNavigationPayload({
200
273
  actionType,
@@ -206,6 +279,7 @@ async function renderNavigationPayload(payload, navigationSnapshot, targetHref,
206
279
  navigationSnapshot,
207
280
  nextElements: payload,
208
281
  operationLane,
282
+ payloadOrigin,
209
283
  params,
210
284
  pendingRouterState,
211
285
  previousNextUrl,
@@ -274,7 +348,7 @@ function storeVisitedResponseSnapshot(rscUrl, interceptionContext, snapshot, par
274
348
  response: snapshot
275
349
  });
276
350
  }
277
- function getRequestState(navigationKind, previousNextUrlOverride, traverseHistoryState) {
351
+ function getRequestState(navigationKind, targetPathname, previousNextUrlOverride, traverseHistoryState) {
278
352
  if (previousNextUrlOverride !== void 0) return {
279
353
  interceptionContext: resolveInterceptionContextFromPreviousNextUrl(previousNextUrlOverride, __basePath),
280
354
  previousNextUrl: previousNextUrlOverride
@@ -286,9 +360,19 @@ function getRequestState(navigationKind, previousNextUrlOverride, traverseHistor
286
360
  interceptionContext: resolveInterceptionContextFromPreviousNextUrl(currentPreviousNextUrl, __basePath),
287
361
  previousNextUrl: currentPreviousNextUrl
288
362
  };
363
+ const manifestInterceptionContext = resolveManifestNavigationInterceptionContext({
364
+ basePath: __basePath,
365
+ currentPathname: window.location.pathname,
366
+ routeManifest: getBrowserRouteManifest(),
367
+ targetPathname
368
+ });
369
+ if (manifestInterceptionContext !== null) return {
370
+ interceptionContext: manifestInterceptionContext,
371
+ previousNextUrl: window.location.pathname + window.location.search
372
+ };
289
373
  return {
290
- interceptionContext: getCurrentInterceptionContext(),
291
- previousNextUrl: getCurrentNextUrl()
374
+ interceptionContext: null,
375
+ previousNextUrl: null
292
376
  };
293
377
  }
294
378
  case "traverse": {
@@ -338,7 +422,11 @@ function BrowserRoot({ initialElements, initialNavigationSnapshot }) {
338
422
  useLayoutEffect(() => {
339
423
  const detach = browserNavigationController.attachBrowserRouterState(setTreeStateValue, stateRef);
340
424
  browserRouterStateHasEverCommitted = true;
341
- window.__VINEXT_HYDRATED_AT = performance.now();
425
+ const hydratedAt = performance.now();
426
+ window.__VINEXT_HYDRATED_AT = hydratedAt;
427
+ window.__NEXT_HYDRATED = true;
428
+ window.__NEXT_HYDRATED_AT = hydratedAt;
429
+ window.__NEXT_HYDRATED_CB?.();
342
430
  return () => {
343
431
  detach();
344
432
  setMountedSlotsHeader(null);
@@ -346,7 +434,7 @@ function BrowserRoot({ initialElements, initialNavigationSnapshot }) {
346
434
  }, [setTreeStateValue]);
347
435
  useLayoutEffect(() => {
348
436
  setMountedSlotsHeader(getMountedSlotIdsHeader(stateRef.current.elements));
349
- window.__VINEXT_PING_VISIBLE_LINKS__?.();
437
+ getNavigationRuntime()?.functions.pingVisibleLinks?.();
350
438
  }, [treeState.elements]);
351
439
  useLayoutEffect(() => {
352
440
  if (treeState.renderId !== 0) return;
@@ -429,16 +517,17 @@ function recoverFromBadInitialRscResponse(reason) {
429
517
  }
430
518
  async function readInitialRscStream() {
431
519
  const vinext = getVinextBrowserGlobal();
432
- if (vinext.__VINEXT_RSC__ || vinext.__VINEXT_RSC_CHUNKS__ || vinext.__VINEXT_RSC_DONE__) {
520
+ const runtimeRsc = getNavigationRuntime()?.bootstrap.rsc;
521
+ if (runtimeRsc || vinext.__VINEXT_RSC_CHUNKS__ || vinext.__VINEXT_RSC_DONE__) {
433
522
  clearReloadFlag();
434
523
  clearHardNavigationLoopGuard();
435
- if (vinext.__VINEXT_RSC__) {
436
- const embedData = vinext.__VINEXT_RSC__;
437
- delete vinext.__VINEXT_RSC__;
438
- const params = embedData.params ?? {};
439
- if (embedData.params) applyClientParams(embedData.params);
440
- if (embedData.nav) restoreHydrationNavigationContext(embedData.nav.pathname, embedData.nav.searchParams, params);
441
- return chunksToReadableStream(embedData.rsc);
524
+ if (runtimeRsc) {
525
+ applyRuntimeRscBootstrap(runtimeRsc);
526
+ if (runtimeRsc.done) {
527
+ registerNavigationRuntimeBootstrap({ rsc: void 0 });
528
+ return chunksToReadableStream(runtimeRsc.rsc);
529
+ }
530
+ return createProgressiveRscStream();
442
531
  }
443
532
  const params = vinext.__VINEXT_RSC_PARAMS__ ?? {};
444
533
  if (vinext.__VINEXT_RSC_PARAMS__) applyClientParams(vinext.__VINEXT_RSC_PARAMS__);
@@ -464,6 +553,11 @@ async function readInitialRscStream() {
464
553
  restoreHydrationNavigationContext(window.location.pathname, window.location.search, params);
465
554
  return rscResponse.body;
466
555
  }
556
+ function applyRuntimeRscBootstrap(rsc) {
557
+ const params = rsc.params ?? {};
558
+ if (rsc.params) applyClientParams(rsc.params);
559
+ if (rsc.nav) restoreHydrationNavigationContext(rsc.nav.pathname, rsc.nav.searchParams, params);
560
+ }
467
561
  function registerServerActionCallback() {
468
562
  setServerCallback(async (id, args) => {
469
563
  const temporaryReferences = createTemporaryReferenceSet();
@@ -490,13 +584,13 @@ function registerServerActionCallback() {
490
584
  }
491
585
  try {
492
586
  if (new URL(actionRedirect, window.location.origin).origin !== window.location.origin) {
493
- window.location.href = actionRedirect;
587
+ browserNavigationController.performHardNavigation(actionRedirect);
494
588
  return;
495
589
  }
496
590
  } catch {}
497
591
  clearClientNavigationCaches();
498
- if ((fetchResponse.headers.get("x-action-redirect-type") ?? "replace") === "push") window.location.assign(actionRedirect);
499
- else window.location.replace(actionRedirect);
592
+ if ((fetchResponse.headers.get("x-action-redirect-type") ?? "replace") === "push") browserNavigationController.performHardNavigation(actionRedirect, "assign");
593
+ else browserNavigationController.performHardNavigation(actionRedirect, "replace");
500
594
  return;
501
595
  }
502
596
  if (resolveRscCompatibilityNavigationDecision({
@@ -506,7 +600,7 @@ function registerServerActionCallback() {
506
600
  responseCompatibilityId: fetchResponse.headers.get("X-Vinext-RSC-Compatibility-Id"),
507
601
  responseUrl: fetchResponse.url
508
602
  }).kind === "hard-navigate") {
509
- window.location.reload();
603
+ browserNavigationController.performHardNavigation(actionInitiation.href);
510
604
  return;
511
605
  }
512
606
  const revalidation = parseServerActionRevalidationHeader(fetchResponse.headers);
@@ -557,150 +651,200 @@ function bootstrapHydration(rscStream) {
557
651
  options: hydrateRootOptions,
558
652
  startTransition
559
653
  });
560
- window.__VINEXT_CLEAR_NAV_CACHES__ = clearClientNavigationCaches;
561
- window.__VINEXT_RSC_COMMIT_HASH_NAVIGATION__ = commitHashOnlyNavigation;
562
- window.__VINEXT_RSC_NAVIGATE__ = async function navigateRsc(href, redirectDepth = 0, navigationKind = "navigate", historyUpdateMode, previousNextUrlOverride, programmaticTransition = false, traversalIntent) {
563
- let pendingRouterState = null;
564
- const navId = browserNavigationController.beginNavigation();
565
- discardedServerActionRefreshScheduler.markNavigationStart();
566
- let currentHref = href;
567
- let currentHistoryMode = historyUpdateMode;
568
- let currentPrevNextUrl = previousNextUrlOverride;
569
- let redirectCount = redirectDepth;
570
- const activeTraversalIntent = navigationKind === "traverse" ? traversalIntent ?? resolveHistoryTraversalIntent({
571
- currentHistoryIndex: currentHistoryTraversalIndex,
572
- historyState: window.history.state
573
- }) : null;
574
- try {
575
- const shouldUsePendingRouterState = programmaticTransition;
576
- if (shouldUsePendingRouterState && hasBrowserRouterState()) pendingRouterState = beginPendingBrowserRouterState();
577
- else {
578
- await waitForBrowserRouterStateReady();
579
- if (!browserNavigationController.isCurrentNavigation(navId)) return;
580
- if (shouldUsePendingRouterState) pendingRouterState = beginPendingBrowserRouterState();
581
- }
582
- while (true) {
583
- const url = new URL(currentHref, window.location.origin);
584
- const requestState = getRequestState(navigationKind, currentPrevNextUrl, activeTraversalIntent?.historyState);
585
- const requestInterceptionContext = requestState.interceptionContext;
586
- const requestPreviousNextUrl = requestState.previousNextUrl;
587
- if (navigationKind === "refresh") syncCurrentHistoryStatePreviousNextUrl(requestPreviousNextUrl);
588
- setPendingPathname(url.pathname, navId);
589
- const elementsAtNavStart = getBrowserRouterState().elements;
590
- const mountedSlotsHeader = getMountedSlotIdsHeader(elementsAtNavStart);
591
- const requestHeaders = createRscRequestHeaders({
592
- interceptionContext: requestInterceptionContext,
593
- renderMode: navigationKind === "refresh" ? APP_RSC_RENDER_MODE_REFRESH_PRESERVE_UI : void 0
594
- });
595
- if (mountedSlotsHeader) requestHeaders.set(VINEXT_MOUNTED_SLOTS_HEADER, mountedSlotsHeader);
596
- const rscUrl = await createRscRequestUrl(url.pathname + url.search, requestHeaders);
597
- const cachedRoute = getVisitedResponse(rscUrl, requestInterceptionContext, mountedSlotsHeader, navigationKind);
598
- if (cachedRoute) {
654
+ registerNavigationRuntimeFunctions({
655
+ clearNavigationCaches: clearClientNavigationCaches,
656
+ commitHashNavigation: commitHashOnlyNavigation,
657
+ navigate: async function navigateRsc(href, redirectDepth = 0, navigationKind = "navigate", historyUpdateMode, previousNextUrlOverride, programmaticTransition = false, traversalIntent) {
658
+ let pendingRouterState = null;
659
+ const navId = browserNavigationController.beginNavigation();
660
+ discardedServerActionRefreshScheduler.markNavigationStart();
661
+ let currentHref = href;
662
+ let currentHistoryMode = historyUpdateMode;
663
+ let currentPrevNextUrl = previousNextUrlOverride;
664
+ let redirectCount = redirectDepth;
665
+ let detachedNavigationCommits = false;
666
+ const activeTraversalIntent = navigationKind === "traverse" ? traversalIntent ?? resolveHistoryTraversalIntent({
667
+ currentHistoryIndex: currentHistoryTraversalIndex,
668
+ historyState: window.history.state
669
+ }) : null;
670
+ try {
671
+ const shouldUsePendingRouterState = programmaticTransition;
672
+ if (shouldUsePendingRouterState && hasBrowserRouterState()) pendingRouterState = beginPendingBrowserRouterState();
673
+ else {
674
+ await waitForBrowserRouterStateReady();
675
+ if (!browserNavigationController.isCurrentNavigation(navId)) return;
676
+ if (shouldUsePendingRouterState) pendingRouterState = beginPendingBrowserRouterState();
677
+ }
678
+ while (true) {
679
+ const url = new URL(currentHref, window.location.origin);
680
+ const requestState = getRequestState(navigationKind, url.pathname, currentPrevNextUrl, activeTraversalIntent?.historyState);
681
+ const requestInterceptionContext = requestState.interceptionContext;
682
+ const requestPreviousNextUrl = requestState.previousNextUrl;
683
+ if (navigationKind === "refresh") syncCurrentHistoryStatePreviousNextUrl(requestPreviousNextUrl);
684
+ setPendingPathname(url.pathname, navId);
685
+ const elementsAtNavStart = getBrowserRouterState().elements;
686
+ const mountedSlotsHeader = getMountedSlotIdsHeader(elementsAtNavStart);
687
+ const requestHeaders = createRscRequestHeaders({
688
+ interceptionContext: requestInterceptionContext,
689
+ renderMode: navigationKind === "refresh" ? APP_RSC_RENDER_MODE_REFRESH_PRESERVE_UI : void 0
690
+ });
691
+ if (mountedSlotsHeader) requestHeaders.set(VINEXT_MOUNTED_SLOTS_HEADER, mountedSlotsHeader);
692
+ const rscUrl = await createRscRequestUrl(url.pathname + url.search, requestHeaders);
693
+ const cachedRoute = getVisitedResponse(rscUrl, requestInterceptionContext, mountedSlotsHeader, navigationKind);
694
+ if (cachedRoute) {
695
+ const compatibilityDecision = resolveRscCompatibilityNavigationDecision({
696
+ clientCompatibilityId: CLIENT_RSC_COMPATIBILITY_ID,
697
+ currentHref,
698
+ origin: window.location.origin,
699
+ responseCompatibilityId: cachedRoute.response.compatibilityIdHeader,
700
+ responseUrl: cachedRoute.response.url
701
+ });
702
+ if (compatibilityDecision.kind === "hard-navigate") {
703
+ browserNavigationController.performHardNavigation(compatibilityDecision.hardNavigationTarget);
704
+ return;
705
+ }
706
+ if (!browserNavigationController.isCurrentNavigation(navId)) return;
707
+ const cachedParams = cachedRoute.params;
708
+ const cachedNavigationSnapshot = createClientNavigationRenderSnapshot(currentHref, cachedParams);
709
+ const cachedPayload = decodeAppElementsPromise(createFromFetch(Promise.resolve(restoreRscResponse(cachedRoute.response))));
710
+ if (!browserNavigationController.isCurrentNavigation(navId)) return;
711
+ await renderNavigationPayload(cachedPayload, cachedNavigationSnapshot, currentHref, navId, currentHistoryMode, cachedParams, requestPreviousNextUrl, detachedNavigationCommits ? null : pendingRouterState, VISITED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN, toActionType(navigationKind), toOperationLane(navigationKind), activeTraversalIntent);
712
+ return;
713
+ }
714
+ let navResponse;
715
+ let navResponseUrl = null;
716
+ if (navigationKind !== "refresh") {
717
+ const prefetchedResponse = consumePrefetchResponse(rscUrl, requestInterceptionContext, mountedSlotsHeader);
718
+ if (prefetchedResponse) {
719
+ navResponse = restoreRscResponse(prefetchedResponse, false);
720
+ navResponseUrl = prefetchedResponse.url;
721
+ }
722
+ }
723
+ if (!navResponse && navigationKind === "navigate") {
724
+ const routeManifest = getBrowserRouteManifest();
725
+ await learnOptimisticRouteTemplatesFromPrefetchCache({
726
+ interceptionContext: requestInterceptionContext,
727
+ mountedSlotsHeader,
728
+ routeManifest
729
+ });
730
+ if (!browserNavigationController.isCurrentNavigation(navId)) return;
731
+ if (routeManifest !== null) {
732
+ const optimisticPayload = resolveOptimisticNavigationPayload({
733
+ basePath: __basePath,
734
+ href: currentHref,
735
+ interceptionContext: requestInterceptionContext,
736
+ mountedSlotsHeader,
737
+ routeManifest,
738
+ templates: optimisticRouteTemplates
739
+ });
740
+ if (optimisticPayload !== null) {
741
+ detachedNavigationCommits = true;
742
+ const optimisticNavigationSnapshot = createClientNavigationRenderSnapshot(currentHref, optimisticPayload.params);
743
+ renderNavigationPayload(Promise.resolve(optimisticPayload.elements), optimisticNavigationSnapshot, currentHref, navId, currentHistoryMode, optimisticPayload.params, requestPreviousNextUrl, null, FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, toActionType(navigationKind), toOperationLane(navigationKind), activeTraversalIntent).catch((error) => {
744
+ if (browserNavigationController.isCurrentNavigation(navId)) console.error("[vinext] Optimistic RSC navigation error:", error);
745
+ });
746
+ }
747
+ }
748
+ }
749
+ if (!navResponse) navResponse = await fetch(rscUrl, {
750
+ headers: requestHeaders,
751
+ credentials: "include"
752
+ });
753
+ if (!browserNavigationController.isCurrentNavigation(navId)) return;
754
+ const isRscResponse = (navResponse.headers.get("content-type") ?? "").startsWith("text/x-component");
755
+ if (!navResponse.ok || !isRscResponse || !navResponse.body) {
756
+ const responseUrl = navResponseUrl ?? navResponse.url;
757
+ browserNavigationController.performHardNavigation(resolveHardNavigationTargetFromRscResponse(responseUrl, currentHref, window.location.origin));
758
+ return;
759
+ }
599
760
  const compatibilityDecision = resolveRscCompatibilityNavigationDecision({
600
761
  clientCompatibilityId: CLIENT_RSC_COMPATIBILITY_ID,
601
762
  currentHref,
602
763
  origin: window.location.origin,
603
- responseCompatibilityId: cachedRoute.response.compatibilityIdHeader,
604
- responseUrl: cachedRoute.response.url
764
+ responseCompatibilityId: navResponse.headers.get(VINEXT_RSC_COMPATIBILITY_ID_HEADER),
765
+ responseUrl: navResponseUrl ?? navResponse.url
605
766
  });
606
767
  if (compatibilityDecision.kind === "hard-navigate") {
607
- window.location.href = compatibilityDecision.hardNavigationTarget;
768
+ browserNavigationController.performHardNavigation(compatibilityDecision.hardNavigationTarget);
608
769
  return;
609
770
  }
771
+ const redirectDecision = resolveRscRedirectLifecycleHop({
772
+ currentHref,
773
+ historyUpdateMode: currentHistoryMode ?? "replace",
774
+ origin: window.location.origin,
775
+ redirectDepth: redirectCount,
776
+ requestPreviousNextUrl,
777
+ responseUrl: navResponseUrl ?? navResponse.url
778
+ });
779
+ if (redirectDecision.kind === "terminal-hard-navigation") {
780
+ if (redirectDecision.reason === "maxRedirectsExceeded") console.error("[vinext] Too many RSC redirects — aborting navigation to prevent infinite loop.");
781
+ browserNavigationController.performHardNavigation(redirectDecision.href);
782
+ return;
783
+ }
784
+ if (redirectDecision.kind === "follow") {
785
+ currentHref = redirectDecision.href;
786
+ currentHistoryMode = redirectDecision.historyUpdateMode;
787
+ currentPrevNextUrl = redirectDecision.previousNextUrl;
788
+ redirectCount = redirectDecision.redirectDepth;
789
+ continue;
790
+ }
791
+ const flightRedirectTarget = navResponse.headers.get(VINEXT_RSC_REDIRECT_HEADER);
792
+ if (flightRedirectTarget) {
793
+ navResponse.body?.cancel().catch(() => {});
794
+ const resolvedTarget = new URL(flightRedirectTarget, window.location.origin);
795
+ if (resolvedTarget.origin !== window.location.origin) {
796
+ browserNavigationController.performHardNavigation(resolvedTarget.href);
797
+ return;
798
+ }
799
+ if (redirectCount >= 10) {
800
+ console.error("[vinext] Too many RSC redirects — aborting navigation to prevent infinite loop.");
801
+ browserNavigationController.performHardNavigation(resolvedTarget.href);
802
+ return;
803
+ }
804
+ currentHref = `${resolvedTarget.pathname}${resolvedTarget.search}${resolvedTarget.hash}`;
805
+ redirectCount += 1;
806
+ continue;
807
+ }
808
+ const navParams = parseEncodedJsonHeader(navResponse.headers.get("X-Vinext-Params")) ?? {};
809
+ const navigationSnapshot = createClientNavigationRenderSnapshot(currentHref, navParams);
810
+ const navBody = navResponse.body;
811
+ if (!navBody) return;
812
+ const [reactBranch, cacheBranch] = navBody.tee();
813
+ const reactResponse = new Response(reactBranch, {
814
+ status: navResponse.status,
815
+ headers: navResponse.headers
816
+ });
817
+ const cacheBufferPromise = new Response(cacheBranch).arrayBuffer();
610
818
  if (!browserNavigationController.isCurrentNavigation(navId)) return;
611
- const cachedParams = cachedRoute.params;
612
- const cachedNavigationSnapshot = createClientNavigationRenderSnapshot(currentHref, cachedParams);
613
- const cachedPayload = decodeAppElementsPromise(createFromFetch(Promise.resolve(restoreRscResponse(cachedRoute.response))));
819
+ const rscPayload = decodeAppElementsPromise(createFromFetch(Promise.resolve(reactResponse)));
614
820
  if (!browserNavigationController.isCurrentNavigation(navId)) return;
615
- await renderNavigationPayload(cachedPayload, cachedNavigationSnapshot, currentHref, navId, currentHistoryMode, cachedParams, requestPreviousNextUrl, pendingRouterState, toActionType(navigationKind), toOperationLane(navigationKind), activeTraversalIntent);
616
- return;
617
- }
618
- let navResponse;
619
- let navResponseUrl = null;
620
- if (navigationKind !== "refresh") {
621
- const prefetchedResponse = consumePrefetchResponse(rscUrl, requestInterceptionContext, mountedSlotsHeader);
622
- if (prefetchedResponse) {
623
- navResponse = restoreRscResponse(prefetchedResponse, false);
624
- navResponseUrl = prefetchedResponse.url;
821
+ if (await renderNavigationPayload(rscPayload, navigationSnapshot, currentHref, navId, currentHistoryMode, navParams, requestPreviousNextUrl, detachedNavigationCommits ? null : pendingRouterState, FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, toActionType(navigationKind), toOperationLane(navigationKind), activeTraversalIntent) !== "committed") return;
822
+ if (!browserNavigationController.isCurrentNavigation(navId)) return;
823
+ const resolvedElements = await rscPayload;
824
+ const metadata = AppElementsWire.readMetadata(resolvedElements);
825
+ if (!isCacheRestorableAppPayloadMetadata(metadata)) {
826
+ cacheBufferPromise.catch(() => {});
827
+ return;
625
828
  }
626
- }
627
- if (!navResponse) navResponse = await fetch(rscUrl, {
628
- headers: requestHeaders,
629
- credentials: "include"
630
- });
631
- if (!browserNavigationController.isCurrentNavigation(navId)) return;
632
- const isRscResponse = (navResponse.headers.get("content-type") ?? "").startsWith("text/x-component");
633
- if (!navResponse.ok || !isRscResponse || !navResponse.body) {
634
- const responseUrl = navResponseUrl ?? navResponse.url;
635
- window.location.href = resolveHardNavigationTargetFromRscResponse(responseUrl, currentHref, window.location.origin);
636
- return;
637
- }
638
- const compatibilityDecision = resolveRscCompatibilityNavigationDecision({
639
- clientCompatibilityId: CLIENT_RSC_COMPATIBILITY_ID,
640
- currentHref,
641
- origin: window.location.origin,
642
- responseCompatibilityId: navResponse.headers.get(VINEXT_RSC_COMPATIBILITY_ID_HEADER),
643
- responseUrl: navResponseUrl ?? navResponse.url
644
- });
645
- if (compatibilityDecision.kind === "hard-navigate") {
646
- window.location.href = compatibilityDecision.hardNavigationTarget;
829
+ const cacheBuffer = await cacheBufferPromise;
830
+ storeVisitedResponseSnapshot(rscUrl, resolveVisitedResponseInterceptionContext(requestInterceptionContext, metadata.interceptionContext), createCachedRscResponseSnapshot(navResponse, cacheBuffer, navResponseUrl), navParams);
647
831
  return;
648
832
  }
649
- const redirectDecision = resolveRscRedirectLifecycleHop({
650
- currentHref,
651
- historyUpdateMode: currentHistoryMode ?? "replace",
652
- origin: window.location.origin,
653
- redirectDepth: redirectCount,
654
- requestPreviousNextUrl,
655
- responseUrl: navResponseUrl ?? navResponse.url
656
- });
657
- if (redirectDecision.kind === "terminal-hard-navigation") {
658
- if (redirectDecision.reason === "maxRedirectsExceeded") console.error("[vinext] Too many RSC redirects — aborting navigation to prevent infinite loop.");
659
- window.location.href = redirectDecision.href;
660
- return;
661
- }
662
- if (redirectDecision.kind === "follow") {
663
- currentHref = redirectDecision.href;
664
- currentHistoryMode = redirectDecision.historyUpdateMode;
665
- currentPrevNextUrl = redirectDecision.previousNextUrl;
666
- redirectCount = redirectDecision.redirectDepth;
667
- continue;
668
- }
669
- const navParams = parseEncodedJsonHeader(navResponse.headers.get("X-Vinext-Params")) ?? {};
670
- const navigationSnapshot = createClientNavigationRenderSnapshot(currentHref, navParams);
671
- const navBody = navResponse.body;
672
- if (!navBody) return;
673
- const [reactBranch, cacheBranch] = navBody.tee();
674
- const reactResponse = new Response(reactBranch, {
675
- status: navResponse.status,
676
- headers: navResponse.headers
677
- });
678
- const cacheBufferPromise = new Response(cacheBranch).arrayBuffer();
679
- if (!browserNavigationController.isCurrentNavigation(navId)) return;
680
- const rscPayload = decodeAppElementsPromise(createFromFetch(Promise.resolve(reactResponse)));
681
- if (!browserNavigationController.isCurrentNavigation(navId)) return;
682
- if (await renderNavigationPayload(rscPayload, navigationSnapshot, currentHref, navId, currentHistoryMode, navParams, requestPreviousNextUrl, pendingRouterState, toActionType(navigationKind), toOperationLane(navigationKind), activeTraversalIntent) !== "committed") return;
833
+ } catch (error) {
683
834
  if (!browserNavigationController.isCurrentNavigation(navId)) return;
684
- const resolvedElements = await rscPayload;
685
- const metadata = AppElementsWire.readMetadata(resolvedElements);
686
- const cacheBuffer = await cacheBufferPromise;
687
- storeVisitedResponseSnapshot(rscUrl, resolveVisitedResponseInterceptionContext(requestInterceptionContext, metadata.interceptionContext), createCachedRscResponseSnapshot(navResponse, cacheBuffer, navResponseUrl), navParams);
688
- return;
835
+ if (!isPageUnloading) console.error("[vinext] RSC navigation error:", error);
836
+ browserNavigationController.performHardNavigation(currentHref);
837
+ } finally {
838
+ browserNavigationController.finalizeNavigation(navId, pendingRouterState);
839
+ discardedServerActionRefreshScheduler.markNavigationSettled();
689
840
  }
690
- } catch (error) {
691
- if (!browserNavigationController.isCurrentNavigation(navId)) return;
692
- if (!isPageUnloading) console.error("[vinext] RSC navigation error:", error);
693
- window.location.href = currentHref;
694
- } finally {
695
- browserNavigationController.finalizeNavigation(navId, pendingRouterState);
696
- discardedServerActionRefreshScheduler.markNavigationSettled();
697
841
  }
698
- };
842
+ });
699
843
  if ("scrollRestoration" in history) history.scrollRestoration = "manual";
700
844
  const handlePopstate = createPopstateRestoreHandler({
701
845
  getActiveNavigationId: browserNavigationController.getActiveNavigationId.bind(browserNavigationController),
702
846
  getPendingNavigation: () => window.__VINEXT_RSC_PENDING__,
703
- getNavigate: () => window.__VINEXT_RSC_NAVIGATE__,
847
+ getNavigate: () => getNavigationRuntime()?.functions.navigate,
704
848
  isCurrentNavigation: browserNavigationController.isCurrentNavigation.bind(browserNavigationController),
705
849
  notifyAppRouterTransitionStart: (href) => {
706
850
  notifyAppRouterTransitionStart(href, "traverse");