vinext 0.1.1 → 0.1.3

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 (266) hide show
  1. package/README.md +2 -5
  2. package/dist/build/client-build-config.d.ts +7 -1
  3. package/dist/build/client-build-config.js +9 -1
  4. package/dist/build/prerender.d.ts +9 -1
  5. package/dist/build/prerender.js +41 -12
  6. package/dist/build/run-prerender.d.ts +10 -2
  7. package/dist/build/run-prerender.js +15 -1
  8. package/dist/check.js +4 -3
  9. package/dist/client/app-nav-failure-handler.d.ts +8 -0
  10. package/dist/client/app-nav-failure-handler.js +44 -0
  11. package/dist/client/navigation-runtime.d.ts +3 -2
  12. package/dist/client/vinext-next-data.d.ts +18 -1
  13. package/dist/client/window-next.d.ts +8 -5
  14. package/dist/client/window-next.js +12 -1
  15. package/dist/cloudflare/src/cache/cdn-adapter.runtime.js +6 -1
  16. package/dist/config/config-matchers.d.ts +11 -4
  17. package/dist/config/config-matchers.js +88 -16
  18. package/dist/config/next-config.d.ts +59 -4
  19. package/dist/config/next-config.js +149 -48
  20. package/dist/deploy.d.ts +30 -11
  21. package/dist/deploy.js +189 -101
  22. package/dist/entries/app-browser-entry.d.ts +9 -3
  23. package/dist/entries/app-browser-entry.js +21 -3
  24. package/dist/entries/app-rsc-entry.d.ts +2 -0
  25. package/dist/entries/app-rsc-entry.js +71 -6
  26. package/dist/entries/app-rsc-manifest.js +2 -0
  27. package/dist/entries/app-ssr-entry.js +1 -1
  28. package/dist/entries/pages-client-entry.js +54 -9
  29. package/dist/entries/pages-server-entry.js +48 -11
  30. package/dist/index.d.ts +0 -2
  31. package/dist/index.js +285 -139
  32. package/dist/plugins/dynamic-preload-metadata.d.ts +13 -0
  33. package/dist/plugins/dynamic-preload-metadata.js +415 -0
  34. package/dist/plugins/extensionless-dynamic-import.d.ts +6 -0
  35. package/dist/plugins/extensionless-dynamic-import.js +152 -0
  36. package/dist/plugins/og-assets.js +2 -2
  37. package/dist/plugins/optimize-imports.d.ts +10 -5
  38. package/dist/plugins/optimize-imports.js +27 -21
  39. package/dist/plugins/postcss.js +7 -7
  40. package/dist/plugins/sass.d.ts +53 -24
  41. package/dist/plugins/sass.js +249 -1
  42. package/dist/plugins/typeof-window.d.ts +14 -0
  43. package/dist/plugins/typeof-window.js +150 -0
  44. package/dist/plugins/wasm-module-import.d.ts +15 -0
  45. package/dist/plugins/wasm-module-import.js +50 -0
  46. package/dist/routing/app-route-graph.d.ts +25 -2
  47. package/dist/routing/app-route-graph.js +91 -22
  48. package/dist/routing/file-matcher.d.ts +10 -1
  49. package/dist/routing/file-matcher.js +23 -2
  50. package/dist/routing/pages-router.js +3 -3
  51. package/dist/routing/utils.d.ts +35 -6
  52. package/dist/routing/utils.js +59 -7
  53. package/dist/server/api-handler.d.ts +6 -1
  54. package/dist/server/api-handler.js +21 -15
  55. package/dist/server/app-browser-action-result.d.ts +19 -6
  56. package/dist/server/app-browser-action-result.js +19 -10
  57. package/dist/server/app-browser-entry.js +269 -297
  58. package/dist/server/app-browser-error.d.ts +10 -3
  59. package/dist/server/app-browser-error.js +47 -6
  60. package/dist/server/app-browser-history-controller.d.ts +104 -0
  61. package/dist/server/app-browser-history-controller.js +210 -0
  62. package/dist/server/app-browser-hydration.d.ts +2 -0
  63. package/dist/server/app-browser-hydration.js +1 -0
  64. package/dist/server/app-browser-navigation-controller.d.ts +7 -4
  65. package/dist/server/app-browser-navigation-controller.js +33 -9
  66. package/dist/server/app-browser-rsc-redirect.d.ts +11 -2
  67. package/dist/server/app-browser-rsc-redirect.js +30 -8
  68. package/dist/server/app-browser-server-action-navigation.d.ts +6 -0
  69. package/dist/server/app-browser-server-action-navigation.js +9 -0
  70. package/dist/server/app-browser-state.js +4 -7
  71. package/dist/server/app-browser-stream.js +86 -43
  72. package/dist/server/app-browser-visible-commit.js +1 -1
  73. package/dist/server/app-elements-wire.d.ts +6 -1
  74. package/dist/server/app-elements-wire.js +14 -4
  75. package/dist/server/app-elements.d.ts +2 -2
  76. package/dist/server/app-elements.js +2 -2
  77. package/dist/server/app-fallback-renderer.d.ts +3 -1
  78. package/dist/server/app-fallback-renderer.js +6 -2
  79. package/dist/server/app-middleware.js +1 -0
  80. package/dist/server/app-optimistic-routing.js +24 -3
  81. package/dist/server/app-page-boundary-render.d.ts +3 -1
  82. package/dist/server/app-page-boundary-render.js +31 -16
  83. package/dist/server/app-page-cache-render.d.ts +53 -0
  84. package/dist/server/app-page-cache-render.js +91 -0
  85. package/dist/server/app-page-cache.d.ts +16 -2
  86. package/dist/server/app-page-cache.js +71 -8
  87. package/dist/server/app-page-dispatch.d.ts +34 -0
  88. package/dist/server/app-page-dispatch.js +167 -97
  89. package/dist/server/app-page-element-builder.d.ts +23 -2
  90. package/dist/server/app-page-element-builder.js +42 -10
  91. package/dist/server/app-page-execution.d.ts +7 -2
  92. package/dist/server/app-page-execution.js +53 -18
  93. package/dist/server/app-page-probe.d.ts +1 -0
  94. package/dist/server/app-page-probe.js +4 -0
  95. package/dist/server/app-page-render-observation.d.ts +3 -1
  96. package/dist/server/app-page-render-observation.js +17 -1
  97. package/dist/server/app-page-render.d.ts +13 -2
  98. package/dist/server/app-page-render.js +48 -17
  99. package/dist/server/app-page-request.d.ts +3 -0
  100. package/dist/server/app-page-request.js +5 -3
  101. package/dist/server/app-page-response.js +1 -1
  102. package/dist/server/app-page-route-wiring.d.ts +5 -1
  103. package/dist/server/app-page-route-wiring.js +21 -11
  104. package/dist/server/app-page-stream.d.ts +16 -9
  105. package/dist/server/app-page-stream.js +12 -9
  106. package/dist/server/app-pages-bridge.d.ts +18 -0
  107. package/dist/server/app-pages-bridge.js +22 -5
  108. package/dist/server/app-ppr-fallback-shell-render.d.ts +17 -0
  109. package/dist/server/app-ppr-fallback-shell-render.js +26 -0
  110. package/dist/server/app-ppr-fallback-shell.d.ts +13 -1
  111. package/dist/server/app-ppr-fallback-shell.js +8 -1
  112. package/dist/server/app-route-handler-dispatch.js +9 -2
  113. package/dist/server/app-route-handler-policy.d.ts +1 -0
  114. package/dist/server/app-route-handler-response.js +11 -10
  115. package/dist/server/app-route-handler-runtime.js +12 -1
  116. package/dist/server/app-router-entry.js +5 -0
  117. package/dist/server/app-rsc-cache-busting.js +2 -0
  118. package/dist/server/app-rsc-handler.d.ts +25 -0
  119. package/dist/server/app-rsc-handler.js +153 -53
  120. package/dist/server/app-rsc-response-finalizer.js +1 -1
  121. package/dist/server/app-rsc-route-matching.d.ts +3 -0
  122. package/dist/server/app-rsc-route-matching.js +2 -0
  123. package/dist/server/app-segment-config.d.ts +9 -1
  124. package/dist/server/app-segment-config.js +12 -3
  125. package/dist/server/app-server-action-execution.d.ts +12 -0
  126. package/dist/server/app-server-action-execution.js +47 -15
  127. package/dist/server/app-ssr-entry.d.ts +2 -0
  128. package/dist/server/app-ssr-entry.js +81 -8
  129. package/dist/server/app-ssr-stream.js +9 -1
  130. package/dist/server/cache-control.js +4 -0
  131. package/dist/server/dev-lockfile.js +2 -1
  132. package/dist/server/dev-server.d.ts +2 -2
  133. package/dist/server/dev-server.js +287 -63
  134. package/dist/server/headers.d.ts +8 -1
  135. package/dist/server/headers.js +8 -1
  136. package/dist/server/hybrid-route-priority.d.ts +22 -0
  137. package/dist/server/hybrid-route-priority.js +33 -0
  138. package/dist/server/image-optimization.d.ts +18 -9
  139. package/dist/server/image-optimization.js +37 -23
  140. package/dist/server/implicit-tags.d.ts +2 -1
  141. package/dist/server/implicit-tags.js +4 -1
  142. package/dist/server/instrumentation-runtime.d.ts +6 -0
  143. package/dist/server/instrumentation-runtime.js +8 -0
  144. package/dist/server/isr-decision.d.ts +79 -0
  145. package/dist/server/isr-decision.js +70 -0
  146. package/dist/server/metadata-route-response.js +5 -3
  147. package/dist/server/middleware-runtime.d.ts +13 -0
  148. package/dist/server/middleware-runtime.js +11 -7
  149. package/dist/server/middleware.js +1 -0
  150. package/dist/server/navigation-planner.d.ts +186 -22
  151. package/dist/server/navigation-planner.js +302 -0
  152. package/dist/server/navigation-trace.d.ts +18 -1
  153. package/dist/server/navigation-trace.js +18 -1
  154. package/dist/server/normalize-path.d.ts +0 -8
  155. package/dist/server/normalize-path.js +3 -1
  156. package/dist/server/otel-tracer-extension.d.ts +45 -0
  157. package/dist/server/otel-tracer-extension.js +89 -0
  158. package/dist/server/pages-api-route.d.ts +20 -3
  159. package/dist/server/pages-api-route.js +19 -3
  160. package/dist/server/pages-asset-tags.d.ts +16 -4
  161. package/dist/server/pages-asset-tags.js +22 -12
  162. package/dist/server/pages-data-route.d.ts +8 -1
  163. package/dist/server/pages-data-route.js +16 -3
  164. package/dist/server/pages-get-initial-props.d.ts +54 -4
  165. package/dist/server/pages-get-initial-props.js +43 -1
  166. package/dist/server/pages-node-compat.d.ts +3 -11
  167. package/dist/server/pages-node-compat.js +175 -122
  168. package/dist/server/pages-page-data.d.ts +39 -2
  169. package/dist/server/pages-page-data.js +261 -46
  170. package/dist/server/pages-page-handler.d.ts +5 -2
  171. package/dist/server/pages-page-handler.js +78 -25
  172. package/dist/server/pages-page-response.d.ts +47 -2
  173. package/dist/server/pages-page-response.js +73 -9
  174. package/dist/server/pages-readiness.d.ts +1 -1
  175. package/dist/server/pages-request-pipeline.d.ts +16 -1
  176. package/dist/server/pages-request-pipeline.js +96 -38
  177. package/dist/server/pregenerated-concrete-paths.d.ts +1 -17
  178. package/dist/server/pregenerated-concrete-paths.js +2 -19
  179. package/dist/server/prerender-manifest.d.ts +33 -0
  180. package/dist/server/prerender-manifest.js +54 -0
  181. package/dist/server/prerender-route-params.d.ts +1 -2
  182. package/dist/server/prod-server.d.ts +39 -1
  183. package/dist/server/prod-server.js +107 -37
  184. package/dist/server/request-pipeline.d.ts +3 -15
  185. package/dist/server/request-pipeline.js +58 -47
  186. package/dist/server/rsc-stream-hints.d.ts +5 -1
  187. package/dist/server/rsc-stream-hints.js +6 -1
  188. package/dist/server/seed-cache.js +10 -18
  189. package/dist/shims/app-router-scroll-state.d.ts +3 -1
  190. package/dist/shims/app-router-scroll-state.js +14 -2
  191. package/dist/shims/app-router-scroll.d.ts +3 -0
  192. package/dist/shims/app-router-scroll.js +28 -18
  193. package/dist/shims/cache-runtime.js +12 -4
  194. package/dist/shims/cache.d.ts +1 -0
  195. package/dist/shims/cache.js +1 -1
  196. package/dist/shims/cdn-cache.d.ts +5 -5
  197. package/dist/shims/dynamic-preload-chunks.d.ts +8 -0
  198. package/dist/shims/dynamic-preload-chunks.js +79 -0
  199. package/dist/shims/dynamic.d.ts +4 -0
  200. package/dist/shims/dynamic.js +4 -2
  201. package/dist/shims/error-boundary.d.ts +6 -4
  202. package/dist/shims/error-boundary.js +7 -0
  203. package/dist/shims/error.js +38 -11
  204. package/dist/shims/error.react-server.d.ts +9 -0
  205. package/dist/shims/error.react-server.js +6 -0
  206. package/dist/shims/fetch-cache.d.ts +11 -1
  207. package/dist/shims/fetch-cache.js +55 -20
  208. package/dist/shims/hash-scroll.js +6 -1
  209. package/dist/shims/head.js +6 -1
  210. package/dist/shims/headers.d.ts +16 -2
  211. package/dist/shims/headers.js +66 -5
  212. package/dist/shims/image-config.js +7 -1
  213. package/dist/shims/internal/als-registry.js +28 -1
  214. package/dist/shims/internal/app-route-detection.d.ts +6 -3
  215. package/dist/shims/internal/app-route-detection.js +18 -23
  216. package/dist/shims/internal/app-router-context.d.ts +5 -0
  217. package/dist/shims/internal/hybrid-client-route-owner.d.ts +31 -0
  218. package/dist/shims/internal/hybrid-client-route-owner.js +143 -0
  219. package/dist/shims/internal/navigation-untracked.d.ts +35 -0
  220. package/dist/shims/internal/navigation-untracked.js +55 -0
  221. package/dist/shims/internal/pages-data-target.d.ts +7 -2
  222. package/dist/shims/internal/pages-data-target.js +17 -8
  223. package/dist/shims/internal/pages-router-accessor.d.ts +19 -0
  224. package/dist/shims/internal/pages-router-accessor.js +13 -0
  225. package/dist/shims/internal/router-context.d.ts +2 -1
  226. package/dist/shims/internal/router-context.js +3 -1
  227. package/dist/shims/link.js +12 -5
  228. package/dist/shims/metadata.d.ts +6 -2
  229. package/dist/shims/metadata.js +32 -14
  230. package/dist/shims/navigation.d.ts +14 -17
  231. package/dist/shims/navigation.js +93 -46
  232. package/dist/shims/ppr-fallback-shell.d.ts +5 -1
  233. package/dist/shims/ppr-fallback-shell.js +28 -7
  234. package/dist/shims/router.d.ts +13 -2
  235. package/dist/shims/router.js +434 -116
  236. package/dist/shims/script-nonce-context.d.ts +1 -1
  237. package/dist/shims/script-nonce-context.js +11 -3
  238. package/dist/shims/server.d.ts +33 -2
  239. package/dist/shims/server.js +75 -18
  240. package/dist/shims/slot.js +1 -1
  241. package/dist/shims/unified-request-context.js +2 -0
  242. package/dist/typegen.js +1 -0
  243. package/dist/utils/built-asset-url.d.ts +4 -0
  244. package/dist/utils/built-asset-url.js +11 -0
  245. package/dist/utils/client-build-manifest.js +15 -5
  246. package/dist/utils/client-runtime-metadata.d.ts +45 -0
  247. package/dist/utils/client-runtime-metadata.js +63 -0
  248. package/dist/utils/commonjs-loader.d.ts +16 -0
  249. package/dist/utils/commonjs-loader.js +100 -0
  250. package/dist/utils/deployment-id.d.ts +8 -0
  251. package/dist/utils/deployment-id.js +22 -0
  252. package/dist/utils/hash.d.ts +17 -1
  253. package/dist/utils/hash.js +36 -1
  254. package/dist/utils/html-limited-bots.d.ts +18 -1
  255. package/dist/utils/html-limited-bots.js +23 -1
  256. package/dist/utils/lazy-chunks.d.ts +27 -1
  257. package/dist/utils/lazy-chunks.js +65 -1
  258. package/dist/utils/manifest-paths.d.ts +20 -2
  259. package/dist/utils/manifest-paths.js +38 -3
  260. package/dist/utils/parse-cookie.d.ts +13 -0
  261. package/dist/utils/parse-cookie.js +52 -0
  262. package/dist/utils/path.d.ts +8 -1
  263. package/dist/utils/path.js +13 -1
  264. package/package.json +2 -2
  265. package/dist/shims/internal/parse-cookie-header.d.ts +0 -14
  266. package/dist/shims/internal/parse-cookie-header.js +0 -30
@@ -1,43 +1,46 @@
1
- import { stripBasePath } from "../utils/base-path.js";
2
1
  import { ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_PARAMS_HEADER, VINEXT_RSC_REDIRECT_HEADER } from "./headers.js";
3
2
  import { DANGEROUS_URL_BLOCK_MESSAGE, isDangerousScheme } from "../shims/url-safety.js";
4
3
  import { AppElementsWire } from "./app-elements-wire.js";
5
4
  import { APP_RSC_RENDER_MODE_REFRESH_PRESERVE_UI } from "./app-rsc-render-mode.js";
6
5
  import { getMountedSlotIdsHeader, resolveVisitedResponseInterceptionContext } from "./app-elements.js";
7
6
  import { AppRouterContext } from "../shims/internal/app-router-context.js";
8
- import { installWindowNext } from "../client/window-next.js";
7
+ import { installWindowNext, setWindowNextInternalSourcePage } from "../client/window-next.js";
9
8
  import { retryScrollTo, scrollToHashTargetOnNextFrame } from "../shims/hash-scroll.js";
10
9
  import { getNavigationRuntime, registerNavigationRuntimeBootstrap, registerNavigationRuntimeFunctions } from "../client/navigation-runtime.js";
11
10
  import { notifyAppRouterTransitionStart } from "../client/instrumentation-client-state.js";
11
+ import { clearAppNavigationFailureTarget, installAppNavigationFailureListeners } from "../client/app-nav-failure-handler.js";
12
12
  import { resolveManifestNavigationInterceptionContext, resolveMiddlewareRewriteNavigationInterceptionContext } from "./app-browser-interception-context.js";
13
- import { RestorableClientStateController, createHistoryStateWithNavigationMetadata, readHistoryStateBfcacheIds, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent } from "./app-history-state.js";
14
- import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, createRscRequestHeaders, createRscRequestUrl, createServerActionRequestUrl, getVinextRscCompatibilityId, resolveHardNavigationTargetFromRscResponse, resolveRscCompatibilityNavigationDecision } from "./app-rsc-cache-busting.js";
13
+ import { readHistoryStatePreviousNextUrl } from "./app-history-state.js";
14
+ import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, createRscRequestHeaders, createRscRequestUrl, createServerActionRequestUrl, getVinextRscCompatibilityId } from "./app-rsc-cache-busting.js";
15
15
  import { AppBrowserMpaNavigationScheduler } from "./app-browser-mpa-navigation.js";
16
+ import { navigationPlanner } from "./navigation-planner.js";
16
17
  import { beginAppRouterScrollIntent, consumeAppRouterScrollIntent } from "../shims/app-router-scroll-state.js";
17
- import { __basePath, appRouterInstance, commitClientNavigationState, consumePrefetchResponseForNavigation, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, decodeRedirectError, getBfcacheIdMapContext, getClientNavigationRenderContext, getPrefetchCache, invalidatePrefetchCache, isRedirectError, pushHistoryStateWithoutNotify, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, resolvePrefetchCacheEntryMountedSlotsHeader, restoreRscResponse, saveScrollPosition, setClientParams, setMountedSlotsHeader, setNavigationContext, setPendingPathname, useRouter } from "../shims/navigation.js";
18
- import { DevRecoveryBoundary, RedirectBoundary } from "../shims/error-boundary.js";
18
+ import { __basePath, appRouterInstance, commitClientNavigationState, consumePrefetchResponseForNavigation, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, createSnapshotPathAndSearch, decodeRedirectError, getBfcacheIdMapContext, getClientNavigationRenderContext, getPrefetchCache, hasPrefetchCacheEntryForNavigation, invalidatePrefetchCache, isRedirectError, pushHistoryStateWithoutNotify, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, resolvePrefetchCacheEntryMountedSlotsHeader, restoreRscResponse, saveScrollPosition, setClientParams, setMountedSlotsHeader, setNavigationContext, setPendingPathname, useRouter } from "../shims/navigation.js";
19
+ import DefaultGlobalError from "../shims/default-global-error.js";
20
+ import { DevRecoveryBoundary, GlobalErrorBoundary, RedirectBoundary } from "../shims/error-boundary.js";
19
21
  import { AppRouterScrollCommitProvider } from "../shims/app-router-scroll.js";
20
22
  import { BfcacheStateKeyMapContext, ElementsContext, Slot } from "../shims/slot.js";
21
23
  import "../client/instrumentation-client.js";
22
- import { createDiscardedServerActionRefreshScheduler, createServerActionInitiationSnapshot, isServerActionResult, normalizeServerActionThrownValue, parseServerActionRevalidationHeader, readInvalidServerActionResponseError, resolveServerActionRedirectCompatibilityHardNavigationTarget, shouldCheckRscCompatibilityForServerActionResponse, shouldClearClientNavigationCachesForServerActionResult } from "./app-browser-action-result.js";
24
+ import { createDiscardedServerActionRefreshScheduler, createServerActionInitiationSnapshot, createServerActionResultFacts, isServerActionResult, normalizeServerActionThrownValue, parseServerActionRevalidationHeader, readInvalidServerActionResponseError, shouldClearClientNavigationCachesForServerActionResult } from "./app-browser-action-result.js";
23
25
  import { createClientReuseManifestHeaderFromVisibleAppState } from "./app-browser-client-reuse-manifest.js";
24
26
  import { chunksToReadableStream, createProgressiveRscStream, getVinextBrowserGlobal } from "./app-browser-stream.js";
25
27
  import { FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, VISITED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN, createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap, isCacheRestorableAppPayloadMetadata, resolveInterceptionContextFromPreviousNextUrl, resolveServerActionRequestState } from "./app-browser-state.js";
26
- import { clearHardNavigationLoopGuard, createAppBrowserNavigationController, createBasePathStrippedPathAndSearch, createSnapshotPathAndSearch } from "./app-browser-navigation-controller.js";
28
+ import { clearHardNavigationLoopGuard, createAppBrowserNavigationController, createBasePathStrippedPathAndSearch } from "./app-browser-navigation-controller.js";
29
+ import { applyServerActionResultDecision } from "./app-browser-server-action-navigation.js";
27
30
  import { consumeInitialFormState, createVinextHydrateRootOptions, hydrateRootInTransition } from "./app-browser-hydration.js";
31
+ import { AppBrowserHistoryController } from "./app-browser-history-controller.js";
28
32
  import { createVisitedResponseCacheEntry, isVisitedResponseCacheEntryFresh } from "./app-visited-response-cache.js";
29
33
  import { createPopstateRestoreHandler, restoreSynchronousPopstateScrollPosition } from "./app-browser-popstate.js";
30
- import { createOnUncaughtError } from "./app-browser-error.js";
34
+ import { createDevOnCaughtError, createOnUncaughtError, createProdOnCaughtError, prodOnRecoverableError } from "./app-browser-error.js";
31
35
  import { dismissOverlay } from "./dev-error-overlay-store.js";
32
- import { devOnCaughtError, devOnUncaughtError, installDevErrorOverlay, installViteHmrErrorHandler, reportInitialDevServerErrors } from "./dev-error-overlay.js";
36
+ import { devOnCaughtError, installDevErrorOverlay, installViteHmrErrorHandler, reportInitialDevServerErrors } from "./dev-error-overlay.js";
33
37
  import { throwOnServerActionNotFound } from "./server-action-not-found.js";
34
- import { resolveRscRedirectLifecycleHop } from "./app-browser-rsc-redirect.js";
35
38
  import { createOptimisticRouteTemplate, getOptimisticPrefetchSourceKey, getOptimisticRouteTemplateKey, resolveOptimisticNavigationPayload } from "./app-optimistic-routing.js";
36
39
  import { removeStylesheetLinksCoveredByInlineCss } from "./app-inline-css-client.js";
37
40
  import { createElement, startTransition, use, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
38
41
  import { flushSync } from "react-dom";
39
42
  import { createFromFetch, createFromReadableStream, createTemporaryReferenceSet, encodeReply, setServerCallback } from "@vitejs/plugin-rsc/browser";
40
- import { hydrateRoot } from "react-dom/client";
43
+ import { createRoot, hydrateRoot } from "react-dom/client";
41
44
  //#region src/server/app-browser-entry.ts
42
45
  function toActionType(kind) {
43
46
  return kind === "traverse" ? "traverse" : "navigate";
@@ -55,13 +58,37 @@ const CLIENT_RSC_COMPATIBILITY_ID = getVinextRscCompatibilityId();
55
58
  const optimisticRouteTemplates = /* @__PURE__ */ new Map();
56
59
  const optimisticRouteTemplateSources = /* @__PURE__ */ new Set();
57
60
  const optimisticRouteTemplateLearning = /* @__PURE__ */ new Map();
61
+ function claimInitialAppRouterBootstrap() {
62
+ if (window.__VINEXT_RSC_ROOT__ || window.__VINEXT_RSC_BOOTSTRAP_STATE__) return false;
63
+ window.__VINEXT_RSC_BOOTSTRAP_STATE__ = "starting";
64
+ return true;
65
+ }
66
+ function markInitialAppRouterBootstrapHydrated() {
67
+ window.__VINEXT_RSC_BOOTSTRAP_STATE__ = "hydrated";
68
+ }
58
69
  function getBrowserRouteManifest() {
59
70
  return getNavigationRuntime()?.bootstrap.routeManifest ?? null;
60
71
  }
72
+ const historyController = new AppBrowserHistoryController({
73
+ initialHistoryState: window.history.state,
74
+ maxHistoryStateSnapshots: 50,
75
+ readHistoryState: () => window.history.state,
76
+ readCurrentHref: () => window.location.href,
77
+ pushHistoryState: (state, href) => pushHistoryStateWithoutNotify(state, "", href),
78
+ replaceHistoryState: (state, href) => replaceHistoryStateWithoutNotify(state, "", href),
79
+ readVisibleNavigationMetadata: () => {
80
+ if (!hasBrowserRouterState()) return null;
81
+ const routerState = getBrowserRouterState();
82
+ return {
83
+ bfcacheIds: routerState.bfcacheIds,
84
+ previousNextUrl: routerState.previousNextUrl
85
+ };
86
+ }
87
+ });
61
88
  const browserNavigationController = createAppBrowserNavigationController({
62
89
  basePath: __basePath,
63
90
  getRouteManifest: getBrowserRouteManifest,
64
- syncHistoryStatePreviousNextUrl: syncCurrentHistoryStatePreviousNextUrl
91
+ syncHistoryStatePreviousNextUrl: (previousNextUrl, bfcacheIds) => historyController.syncCurrentHistoryStatePreviousNextUrl(previousNextUrl, bfcacheIds)
65
92
  });
66
93
  const discardedServerActionRefreshScheduler = createDiscardedServerActionRefreshScheduler({ runRefresh() {
67
94
  clearClientNavigationCaches();
@@ -93,79 +120,30 @@ function isRouterStatePromise(value) {
93
120
  let latestClientParams = {};
94
121
  const visitedResponseCache = /* @__PURE__ */ new Map();
95
122
  let browserRouterStateHasEverCommitted = false;
96
- let pendingNavigationRecoveryHref = null;
97
123
  const mpaNavigationScheduler = new AppBrowserMpaNavigationScheduler();
98
124
  const unresolvedMpaNavigation = new Promise(() => {});
99
125
  const RSC_HMR_SETTLE_DELAY_MS = 150;
126
+ const DEFAULT_GLOBAL_ERROR_COMPONENT = DefaultGlobalError;
100
127
  let latestRscHmrUpdateId = 0;
101
- let currentHistoryTraversalIndex = readHistoryStateTraversalIndex(window.history.state) ?? 0;
102
- let nextHistoryTraversalIndex = currentHistoryTraversalIndex;
103
128
  let synchronousPopstateScrollRestoreNavigationId = null;
104
- const restorableClientState = new RestorableClientStateController({
105
- initialHistoryState: window.history.state,
106
- maxHistoryStateSnapshots: 50
107
- });
108
129
  function waitForRscHmrSettle(delayMs = RSC_HMR_SETTLE_DELAY_MS) {
109
130
  return new Promise((resolve) => {
110
131
  window.setTimeout(resolve, delayMs);
111
132
  });
112
133
  }
113
- function allocateNavigationHistoryTraversalIndex(historyUpdateMode) {
114
- switch (historyUpdateMode) {
115
- case "push": return nextHistoryTraversalIndex + 1;
116
- case "replace": return currentHistoryTraversalIndex;
117
- case void 0: return null;
118
- default: throw new Error("[vinext] Unknown history update mode: " + String(historyUpdateMode));
119
- }
120
- }
121
- function commitHistoryTraversalIndex(index) {
122
- currentHistoryTraversalIndex = index;
123
- if (index !== null) nextHistoryTraversalIndex = Math.max(nextHistoryTraversalIndex, index);
124
- }
125
- function commitHashOnlyNavigation(href, historyUpdateMode, scroll) {
126
- const navigationHistoryIndex = allocateNavigationHistoryTraversalIndex(historyUpdateMode);
127
- const previousNextUrl = hasBrowserRouterState() ? getBrowserRouterState().previousNextUrl : readHistoryStatePreviousNextUrl(window.history.state);
128
- const bfcacheIds = hasBrowserRouterState() ? getBrowserRouterState().bfcacheIds : restorableClientState.readCurrentBfcacheVersionHistoryIds(window.history.state);
129
- const historyState = createHistoryStateWithNavigationMetadata(createHashOnlyNavigationBaseHistoryState(historyUpdateMode, scroll), {
130
- bfcacheIds,
131
- bfcacheVersion: bfcacheIds === null ? void 0 : restorableClientState.currentBfcacheVersion,
132
- previousNextUrl,
133
- traversalIndex: navigationHistoryIndex
134
- });
135
- if (historyUpdateMode === "replace") replaceHistoryStateWithoutNotify(historyState, "", href);
136
- else pushHistoryStateWithoutNotify(historyState, "", href);
137
- commitHistoryTraversalIndex(navigationHistoryIndex);
138
- }
139
- function createHashOnlyNavigationBaseHistoryState(historyUpdateMode, scroll) {
140
- if (historyUpdateMode !== "replace") return null;
141
- return scroll ? stripVinextScrollState(window.history.state) : window.history.state;
142
- }
143
- function stripVinextScrollState(state) {
144
- if (!state || typeof state !== "object") return state;
145
- const nextState = {};
146
- for (const [key, value] of Object.entries(state)) {
147
- if (key === "__vinext_scrollX" || key === "__vinext_scrollY") continue;
148
- nextState[key] = value;
149
- }
150
- return Object.keys(nextState).length > 0 ? nextState : null;
151
- }
152
- function commitTraversalIndexFromHistoryState(historyState) {
153
- commitHistoryTraversalIndex(readHistoryStateTraversalIndex(historyState));
154
- }
155
134
  function restoreHistoryStateSnapshot(historyState) {
156
- const decision = restorableClientState.resolveHistoryStateSnapshotRestore(historyState);
157
- if (decision.kind === "skip") return false;
158
135
  const navId = browserNavigationController.getActiveNavigationId();
159
136
  let restored = false;
160
137
  flushSync(() => {
161
- restored = browserNavigationController.restoreHistorySnapshotVisibleState({
162
- beforeCommit: () => {
163
- commitHistoryTraversalIndex(decision.targetHistoryIndex);
164
- stageClientParams(decision.state.navigationSnapshot.params);
165
- },
166
- navId,
167
- state: decision.state,
168
- targetHref: window.location.href
138
+ restored = historyController.restoreHistorySnapshot({
139
+ historyState,
140
+ stageClientParams,
141
+ approveVisibleRestore: ({ state, beforeCommit }) => browserNavigationController.restoreHistorySnapshotVisibleState({
142
+ beforeCommit,
143
+ navId,
144
+ state,
145
+ targetHref: window.location.href
146
+ })
169
147
  });
170
148
  });
171
149
  if (!restored) return false;
@@ -204,7 +182,7 @@ function clearPrefetchState() {
204
182
  function clearClientNavigationCaches() {
205
183
  clearVisitedResponseCache();
206
184
  clearPrefetchState();
207
- restorableClientState.invalidateClientState();
185
+ historyController.invalidateRestorableClientState();
208
186
  }
209
187
  function isSettledPrefetchCacheEntry(entry) {
210
188
  return entry.outcome === "cache-seeded" && entry.pending === void 0 && entry.snapshot !== void 0;
@@ -272,28 +250,6 @@ async function learnOptimisticRouteTemplatesFromPrefetchCache(options) {
272
250
  if (learning.length === 0) return;
273
251
  await Promise.allSettled(learning);
274
252
  }
275
- function areBfcacheIdMapsEqual(a, b) {
276
- if (a === b) return true;
277
- if (a === null || b === null) return false;
278
- const aEntries = Object.entries(a);
279
- const bEntries = Object.entries(b);
280
- if (aEntries.length !== bEntries.length) return false;
281
- return aEntries.every(([key, value]) => b[key] === value);
282
- }
283
- function isHistoryStateNavigationMetadataInSync(state, previousNextUrl, bfcacheIds) {
284
- return readHistoryStatePreviousNextUrl(state) === previousNextUrl && (bfcacheIds === void 0 || areBfcacheIdMapsEqual(readHistoryStateBfcacheIds(state), bfcacheIds) && restorableClientState.isCurrentBfcacheVersion(state));
285
- }
286
- function syncCurrentHistoryStatePreviousNextUrl(previousNextUrl, bfcacheIds) {
287
- if (isHistoryStateNavigationMetadataInSync(window.history.state, previousNextUrl, bfcacheIds)) return;
288
- const nextHistoryState = createHistoryStateWithNavigationMetadata(window.history.state, {
289
- bfcacheIds,
290
- bfcacheVersion: bfcacheIds === void 0 ? void 0 : restorableClientState.currentBfcacheVersion,
291
- previousNextUrl
292
- });
293
- replaceHistoryStateWithoutNotify(nextHistoryState, "", window.location.href);
294
- if (isHistoryStateNavigationMetadataInSync(window.history.state, previousNextUrl, bfcacheIds)) return;
295
- replaceHistoryStateWithoutNotify(nextHistoryState, "", window.location.href);
296
- }
297
253
  function createActionInitiationSnapshot() {
298
254
  const routerState = getBrowserRouterState();
299
255
  return createServerActionInitiationSnapshot({
@@ -309,64 +265,39 @@ function createNavigationCommitEffect(options) {
309
265
  commitClientNavigationState(void 0, { releaseSnapshot: true });
310
266
  return;
311
267
  }
312
- const targetHref = new URL(href, window.location.origin).href;
313
- const preserveExistingState = historyUpdateMode === "replace";
314
- const navigationHistoryIndex = targetHistoryIndex !== void 0 ? targetHistoryIndex : allocateNavigationHistoryTraversalIndex(historyUpdateMode);
315
- const historyState = createHistoryStateWithNavigationMetadata(preserveExistingState ? window.history.state : null, {
268
+ historyController.commitNavigationHistory({
316
269
  bfcacheIds,
317
- bfcacheVersion: restorableClientState.currentBfcacheVersion,
270
+ href,
271
+ historyUpdateMode,
318
272
  previousNextUrl,
319
- traversalIndex: navigationHistoryIndex
273
+ stageClientParams: () => stageClientParams(params),
274
+ targetHistoryIndex
320
275
  });
321
- let wroteHistoryState = false;
322
- if (historyUpdateMode === "replace" && window.location.href !== targetHref) {
323
- stageClientParams(params);
324
- replaceHistoryStateWithoutNotify(historyState, "", href);
325
- wroteHistoryState = true;
326
- commitHistoryTraversalIndex(navigationHistoryIndex);
327
- } else if (historyUpdateMode === "push" && window.location.href !== targetHref) {
328
- stageClientParams(params);
329
- pushHistoryStateWithoutNotify(historyState, "", href);
330
- wroteHistoryState = true;
331
- commitHistoryTraversalIndex(navigationHistoryIndex);
332
- }
333
- if (!wroteHistoryState) {
334
- syncCurrentHistoryStatePreviousNextUrl(previousNextUrl, bfcacheIds);
335
- stageClientParams(params);
336
- if (targetHistoryIndex !== void 0) commitHistoryTraversalIndex(targetHistoryIndex);
337
- }
338
- pendingNavigationRecoveryHref = null;
276
+ clearAppNavigationFailureTarget(href);
339
277
  commitClientNavigationState(navId);
340
278
  };
341
279
  }
342
- async function renderNavigationPayload(payload, navigationSnapshot, targetHref, navId, historyUpdateMode, params, previousNextUrl, pendingRouterState, payloadOrigin, actionType = "navigate", operationLane = "navigation", traversalIntent = null, scrollIntent = null, restoredBfcacheIds = null, reuseCurrentBfcacheIds = true) {
280
+ async function renderNavigationPayload(payload, navigationSnapshot, targetHref, navId, historyUpdateMode, params, previousNextUrl, pendingRouterState, payloadOrigin, actionType = "navigate", operationLane = "navigation", traversalIntent = null, scrollIntent = null, restoredBfcacheIds = null, reuseCurrentBfcacheIds = true, visibleCommitMode = "transition") {
343
281
  syncServerActionHttpFallbackHead(null);
344
- try {
345
- return await browserNavigationController.renderNavigationPayload({
346
- actionType,
347
- createNavigationCommitEffect: (options) => {
348
- pendingNavigationRecoveryHref = options.href;
349
- return createNavigationCommitEffect(options);
350
- },
351
- historyUpdateMode,
352
- navigationSnapshot,
353
- nextElements: payload,
354
- operationLane,
355
- payloadOrigin,
356
- params,
357
- pendingRouterState,
358
- previousNextUrl,
359
- scrollIntent,
360
- restoredBfcacheIds,
361
- reuseCurrentBfcacheIds,
362
- targetHistoryIndex: traversalIntent === null ? void 0 : traversalIntent.targetHistoryIndex,
363
- targetHref,
364
- navId
365
- });
366
- } catch (error) {
367
- pendingNavigationRecoveryHref = null;
368
- throw error;
369
- }
282
+ return browserNavigationController.renderNavigationPayload({
283
+ actionType,
284
+ createNavigationCommitEffect,
285
+ historyUpdateMode,
286
+ navigationSnapshot,
287
+ nextElements: payload,
288
+ operationLane,
289
+ payloadOrigin,
290
+ params,
291
+ pendingRouterState,
292
+ previousNextUrl,
293
+ scrollIntent,
294
+ restoredBfcacheIds,
295
+ reuseCurrentBfcacheIds,
296
+ targetHistoryIndex: traversalIntent === null ? void 0 : traversalIntent.targetHistoryIndex,
297
+ targetHref,
298
+ navId,
299
+ visibleCommitMode
300
+ });
370
301
  }
371
302
  function resolveActionRedirectTarget(response) {
372
303
  const actionRedirect = response.headers.get(ACTION_REDIRECT_HEADER);
@@ -432,23 +363,39 @@ function evictVisitedResponseCacheIfNeeded() {
432
363
  visitedResponseCache.delete(oldest);
433
364
  }
434
365
  }
435
- function getVisitedResponse(rscUrl, interceptionContext, mountedSlotsHeader, navigationKind) {
366
+ function readVisitedResponseCacheCandidate(rscUrl, interceptionContext, mountedSlotsHeader, navigationKind) {
436
367
  const cacheKey = AppElementsWire.encodeCacheKey(rscUrl, interceptionContext);
437
368
  const cached = visitedResponseCache.get(cacheKey);
438
- if (!cached) return null;
439
- if ((cached.response.mountedSlotsHeader ?? null) !== mountedSlotsHeader) {
440
- visitedResponseCache.delete(cacheKey);
441
- return null;
442
- }
443
- if (isVisitedResponseCacheEntryFresh(cached, {
444
- navigationKind,
445
- now: Date.now()
446
- })) {
447
- visitedResponseCache.delete(cacheKey);
448
- visitedResponseCache.set(cacheKey, cached);
449
- return cached;
369
+ if (!cached) return {
370
+ cacheKey,
371
+ entry: null,
372
+ facts: {
373
+ candidate: "missing",
374
+ navigationKind
375
+ }
376
+ };
377
+ return {
378
+ cacheKey,
379
+ entry: cached,
380
+ facts: {
381
+ candidate: "present",
382
+ fresh: isVisitedResponseCacheEntryFresh(cached, {
383
+ navigationKind,
384
+ now: Date.now()
385
+ }),
386
+ mountedSlotsMatch: (cached.response.mountedSlotsHeader ?? null) === mountedSlotsHeader,
387
+ navigationKind
388
+ }
389
+ };
390
+ }
391
+ function applyVisitedResponseCacheCandidateDecision(candidate, decision) {
392
+ if (candidate.entry === null) return null;
393
+ if (decision.kind === "reuse") {
394
+ visitedResponseCache.delete(candidate.cacheKey);
395
+ visitedResponseCache.set(candidate.cacheKey, candidate.entry);
396
+ return candidate.entry;
450
397
  }
451
- visitedResponseCache.delete(cacheKey);
398
+ visitedResponseCache.delete(candidate.cacheKey);
452
399
  return null;
453
400
  }
454
401
  function deleteVisitedResponse(rscUrl, interceptionContext) {
@@ -465,9 +412,8 @@ function storeVisitedResponseSnapshot(rscUrl, interceptionContext, snapshot, par
465
412
  response: snapshot
466
413
  }));
467
414
  }
468
- function isSamePageSearchNavigation(currentSnapshot, targetUrl) {
469
- if (stripBasePath(targetUrl.pathname, __basePath) !== currentSnapshot.pathname) return false;
470
- return targetUrl.searchParams.toString() !== currentSnapshot.searchParams.toString();
415
+ function clientNavigationSnapshotHref(snapshot) {
416
+ return `${window.location.origin}${createSnapshotPathAndSearch(snapshot)}`;
471
417
  }
472
418
  function getRequestState(navigationKind, targetPathname, previousNextUrlOverride, traverseHistoryState) {
473
419
  if (previousNextUrlOverride !== void 0) return {
@@ -598,23 +544,25 @@ function BrowserRoot({ initialElements, initialNavigationSnapshot }) {
598
544
  return new Promise(() => {});
599
545
  } });
600
546
  browserRouterStateHasEverCommitted = true;
601
- const hydratedAt = performance.now();
602
- window.__VINEXT_HYDRATED_AT = hydratedAt;
603
- window.__NEXT_HYDRATED = true;
604
- window.__NEXT_HYDRATED_AT = hydratedAt;
605
- window.__NEXT_HYDRATED_CB?.();
606
547
  return () => {
607
548
  registerNavigationRuntimeFunctions({ navigateExternal: void 0 });
608
549
  detach();
609
550
  setMountedSlotsHeader(null);
610
551
  };
611
552
  }, [setTreeStateValue]);
553
+ useEffect(() => {
554
+ const hydratedAt = performance.now();
555
+ window.__VINEXT_HYDRATED_AT = hydratedAt;
556
+ window.__NEXT_HYDRATED = true;
557
+ window.__NEXT_HYDRATED_AT = hydratedAt;
558
+ window.__NEXT_HYDRATED_CB?.();
559
+ }, []);
612
560
  useLayoutEffect(() => {
613
- restorableClientState.rememberHistoryStateSnapshot({
614
- historyIndex: currentHistoryTraversalIndex,
615
- state: treeState
616
- });
561
+ historyController.rememberHistoryStateSnapshot(treeState);
617
562
  }, [treeState]);
563
+ useEffect(() => {
564
+ setWindowNextInternalSourcePage(AppElementsWire.readMetadata(treeState.elements).sourcePage);
565
+ }, [treeState.elements]);
618
566
  useLayoutEffect(() => {
619
567
  setMountedSlotsHeader(getMountedSlotIdsHeader(stateRef.current.elements));
620
568
  removeStylesheetLinksCoveredByInlineCss();
@@ -622,12 +570,10 @@ function BrowserRoot({ initialElements, initialNavigationSnapshot }) {
622
570
  }, [treeState.elements]);
623
571
  useLayoutEffect(() => {
624
572
  if (treeState.renderId !== 0) return;
625
- replaceHistoryStateWithoutNotify(createHistoryStateWithNavigationMetadata(window.history.state, {
573
+ historyController.writeHydratedHistoryMetadata({
626
574
  bfcacheIds: treeState.bfcacheIds,
627
- bfcacheVersion: restorableClientState.currentBfcacheVersion,
628
- previousNextUrl: treeState.previousNextUrl,
629
- traversalIndex: currentHistoryTraversalIndex
630
- }), "", window.location.href);
575
+ previousNextUrl: treeState.previousNextUrl
576
+ });
631
577
  }, [
632
578
  treeState.bfcacheIds,
633
579
  treeState.previousNextUrl,
@@ -642,13 +588,17 @@ function BrowserRoot({ initialElements, initialNavigationSnapshot }) {
642
588
  const redirectedTree = createElement(AppRouterRedirectBridge, null, BfcacheIdMapContext ? createElement(BfcacheIdMapContext.Provider, { value: treeState.bfcacheIds }, stateKeyTree) : stateKeyTree);
643
589
  const innerTree = AppRouterContext ? createElement(AppRouterContext.Provider, { value: appRouterInstance }, redirectedTree) : redirectedTree;
644
590
  const committedTree = import.meta.env.DEV ? createElement(DevRecoveryBoundary, {
591
+ isImplicitRootErrorBoundary: true,
645
592
  resetKey: treeState.renderId,
646
593
  onCatch: handleDevRecoveryBoundaryCatch
647
594
  }, innerTree) : innerTree;
648
- const scrollScopedTree = createElement(AppRouterScrollCommitProvider, { commitId: treeState.renderId }, committedTree);
595
+ const rootErrorTree = createElement(GlobalErrorBoundary, {
596
+ fallback: DEFAULT_GLOBAL_ERROR_COMPONENT,
597
+ children: createElement(AppRouterScrollCommitProvider, { commitId: treeState.renderId }, committedTree)
598
+ });
649
599
  const ClientNavigationRenderContext = getClientNavigationRenderContext();
650
- if (!ClientNavigationRenderContext) return scrollScopedTree;
651
- return createElement(ClientNavigationRenderContext.Provider, { value: treeState.navigationSnapshot }, scrollScopedTree);
600
+ if (!ClientNavigationRenderContext) return rootErrorTree;
601
+ return createElement(ClientNavigationRenderContext.Provider, { value: treeState.navigationSnapshot }, rootErrorTree);
652
602
  }
653
603
  function restoreHydrationNavigationContext(pathname, searchParams, params) {
654
604
  setNavigationContext({
@@ -759,7 +709,7 @@ function registerServerActionCallback() {
759
709
  syncServerActionHttpFallbackHead(null);
760
710
  const temporaryReferences = createTemporaryReferenceSet();
761
711
  const actionInitiation = createActionInitiationSnapshot();
762
- syncCurrentHistoryStatePreviousNextUrl(actionInitiation.routerState.previousNextUrl, actionInitiation.routerState.bfcacheIds);
712
+ historyController.syncCurrentHistoryStatePreviousNextUrl(actionInitiation.routerState.previousNextUrl, actionInitiation.routerState.bfcacheIds);
763
713
  const body = await encodeReply(args, { temporaryReferences });
764
714
  const { headers } = resolveServerActionRequestState({
765
715
  actionId: id,
@@ -776,31 +726,23 @@ function registerServerActionCallback() {
776
726
  const hasActionRedirect = fetchResponse.headers.has(ACTION_REDIRECT_HEADER);
777
727
  const actionRedirectTarget = resolveActionRedirectTarget(fetchResponse);
778
728
  if (hasActionRedirect && !actionRedirectTarget) return;
779
- const actionRedirectCompatibilityHardNavigationTarget = resolveServerActionRedirectCompatibilityHardNavigationTarget({
729
+ const actionResultFacts = createServerActionResultFacts({
780
730
  actionRedirectHref: actionRedirectTarget?.href ?? null,
731
+ actionRedirectType: actionRedirectTarget?.type ?? null,
781
732
  clientCompatibilityId: CLIENT_RSC_COMPATIBILITY_ID,
782
- response: fetchResponse
783
- });
784
- if (actionRedirectCompatibilityHardNavigationTarget) {
785
- clearClientNavigationCaches();
786
- browserNavigationController.performHardNavigation(actionRedirectCompatibilityHardNavigationTarget, actionRedirectTarget?.type === "push" ? "assign" : "replace");
787
- return;
788
- }
789
- if (!actionRedirectTarget && shouldCheckRscCompatibilityForServerActionResponse(fetchResponse) && resolveRscCompatibilityNavigationDecision({
790
- clientCompatibilityId: CLIENT_RSC_COMPATIBILITY_ID,
733
+ compatibilityIdHeader: fetchResponse.headers.get(VINEXT_RSC_COMPATIBILITY_ID_HEADER),
734
+ contentTypeHeader: fetchResponse.headers.get("content-type"),
791
735
  currentHref: actionInitiation.href,
792
736
  origin: window.location.origin,
793
- responseCompatibilityId: fetchResponse.headers.get("X-Vinext-RSC-Compatibility-Id"),
794
737
  responseUrl: fetchResponse.url
795
- }).kind === "hard-navigate") {
796
- browserNavigationController.performHardNavigation(actionInitiation.href);
797
- return;
798
- }
738
+ });
739
+ const fetchResponseIsRsc = actionResultFacts.isRscContentType;
740
+ if (applyServerActionResultDecision(navigationPlanner.classifyServerActionResult(actionResultFacts), clearClientNavigationCaches, (url, historyMode) => browserNavigationController.performHardNavigation(url, historyMode))) return;
799
741
  const revalidation = parseServerActionRevalidationHeader(fetchResponse.headers);
800
742
  if (revalidation !== "none") clearClientNavigationCaches();
801
743
  const invalidResponseError = await readInvalidServerActionResponseError(fetchResponse.clone(), actionRedirectTarget !== null);
802
744
  if (invalidResponseError) throw invalidResponseError;
803
- if (actionRedirectTarget && !shouldCheckRscCompatibilityForServerActionResponse(fetchResponse)) {
745
+ if (actionRedirectTarget && !fetchResponseIsRsc) {
804
746
  browserNavigationController.performHardNavigation(actionRedirectTarget.href);
805
747
  return;
806
748
  }
@@ -843,12 +785,14 @@ function registerServerActionCallback() {
843
785
  return commitSameUrlNavigatePayload(Promise.resolve(AppElementsWire.decode(result)), actionInitiation, void 0, revalidation);
844
786
  };
845
787
  setServerCallback((id, args) => {
846
- const releaseCacheInvalidationGuard = restorableClientState.beginCacheInvalidationGuard();
788
+ const releaseCacheInvalidationGuard = historyController.beginCacheInvalidationGuard();
847
789
  return Promise.resolve().then(() => serverActionCallback(id, args)).finally(releaseCacheInvalidationGuard);
848
790
  });
849
791
  }
850
792
  async function main() {
793
+ if (!claimInitialAppRouterBootstrap()) return;
851
794
  registerServerActionCallback();
795
+ installAppNavigationFailureListeners();
852
796
  if (import.meta.env.DEV) {
853
797
  installDevErrorOverlay();
854
798
  installViteHmrErrorHandler(import.meta.hot);
@@ -861,34 +805,44 @@ async function main() {
861
805
  function bootstrapHydration(rscStream) {
862
806
  const root = decodeAppElementsPromise(createFromReadableStream(rscStream));
863
807
  const initialNavigationSnapshot = createClientNavigationRenderSnapshot(window.location.href, latestClientParams);
864
- replaceHistoryStateWithoutNotify(createHistoryStateWithNavigationMetadata(window.history.state, {
865
- previousNextUrl: null,
866
- traversalIndex: currentHistoryTraversalIndex
867
- }), "", window.location.href);
868
- const onUncaughtError = import.meta.env.DEV ? devOnUncaughtError : createOnUncaughtError(() => pendingNavigationRecoveryHref);
808
+ historyController.writeBootstrapHistoryMetadata();
809
+ const onUncaughtError = createOnUncaughtError();
869
810
  const formState = consumeInitialFormState(getVinextBrowserGlobal());
870
811
  const hydrateRootOptions = import.meta.env.DEV ? createVinextHydrateRootOptions({
871
812
  formState,
872
- onCaughtError: devOnCaughtError,
813
+ onCaughtError: createDevOnCaughtError(devOnCaughtError, onUncaughtError),
873
814
  onUncaughtError
874
815
  }) : createVinextHydrateRootOptions({
875
816
  formState,
817
+ onCaughtError: createProdOnCaughtError(onUncaughtError),
818
+ onRecoverableError: prodOnRecoverableError,
876
819
  onUncaughtError
877
820
  });
878
- window.__VINEXT_RSC_ROOT__ = hydrateRootInTransition({
879
- children: createElement(BrowserRoot, {
880
- initialElements: root,
881
- initialNavigationSnapshot
882
- }),
821
+ const children = createElement(BrowserRoot, {
822
+ initialElements: root,
823
+ initialNavigationSnapshot
824
+ });
825
+ const errorShellStyles = document.querySelectorAll("style[data-vinext-error-shell-style]");
826
+ if (document.documentElement.id === "__next_error__") {
827
+ const { formState: _inertFormState, ...createRootOptions } = hydrateRootOptions;
828
+ for (const style of errorShellStyles) style.remove();
829
+ startTransition(() => {
830
+ const clientRoot = createRoot(document, createRootOptions);
831
+ clientRoot.render(children);
832
+ window.__VINEXT_RSC_ROOT__ = clientRoot;
833
+ });
834
+ } else window.__VINEXT_RSC_ROOT__ = hydrateRootInTransition({
835
+ children,
883
836
  container: document,
884
837
  hydrateRoot,
885
838
  options: hydrateRootOptions,
886
839
  startTransition
887
840
  });
841
+ markInitialAppRouterBootstrapHydrated();
888
842
  registerNavigationRuntimeFunctions({
889
843
  clearNavigationCaches: clearClientNavigationCaches,
890
- commitHashNavigation: commitHashOnlyNavigation,
891
- navigate: async function navigateRsc(href, redirectDepth = 0, navigationKind = "navigate", historyUpdateMode, previousNextUrlOverride, programmaticTransition = false, traversalIntent, scrollIntent) {
844
+ commitHashNavigation: (href, historyUpdateMode, scroll) => historyController.commitHashOnlyNavigation(href, historyUpdateMode, scroll),
845
+ navigate: async function navigateRsc(href, redirectDepth = 0, navigationKind = "navigate", historyUpdateMode, previousNextUrlOverride, programmaticTransition = false, traversalIntent, scrollIntent, visibleCommitMode = "transition") {
892
846
  let pendingRouterState = null;
893
847
  const navId = browserNavigationController.beginNavigation();
894
848
  discardedServerActionRefreshScheduler.markNavigationStart();
@@ -897,16 +851,15 @@ function bootstrapHydration(rscStream) {
897
851
  let currentPrevNextUrl = previousNextUrlOverride;
898
852
  let redirectCount = redirectDepth;
899
853
  let detachedNavigationCommits = false;
900
- const activeTraversalIntent = navigationKind === "traverse" ? traversalIntent ?? resolveHistoryTraversalIntent({
901
- currentHistoryIndex: currentHistoryTraversalIndex,
902
- historyState: window.history.state
903
- }) : null;
854
+ const activeTraversalIntent = navigationKind === "traverse" ? traversalIntent ?? historyController.resolveTraversalIntent(window.history.state) : null;
904
855
  const performHardNavigationForScrollIntent = (targetHref) => {
905
856
  consumeAppRouterScrollIntent(scrollIntent ?? null);
906
- return browserNavigationController.performHardNavigation(targetHref);
857
+ const didNavigate = browserNavigationController.performHardNavigation(targetHref);
858
+ if (!didNavigate) clearAppNavigationFailureTarget(targetHref);
859
+ return didNavigate;
907
860
  };
908
- let restoredBfcacheIds = navigationKind === "traverse" ? restorableClientState.readCurrentBfcacheVersionHistoryIds(activeTraversalIntent?.historyState ?? window.history.state) : null;
909
- const reuseCurrentBfcacheIds = navigationKind !== "traverse" || !restorableClientState.isCacheInvalidationGuarded() && restorableClientState.isCurrentBfcacheVersion(activeTraversalIntent?.historyState ?? window.history.state);
861
+ let restoredBfcacheIds = navigationKind === "traverse" ? historyController.readCurrentBfcacheVersionHistoryIds(activeTraversalIntent?.historyState ?? window.history.state) : null;
862
+ const reuseCurrentBfcacheIds = navigationKind !== "traverse" || !historyController.isCacheInvalidationGuarded() && historyController.isCurrentBfcacheVersion(activeTraversalIntent?.historyState ?? window.history.state);
910
863
  try {
911
864
  const shouldUsePendingRouterState = programmaticTransition;
912
865
  if (shouldUsePendingRouterState && hasBrowserRouterState()) pendingRouterState = beginPendingBrowserRouterState();
@@ -920,50 +873,80 @@ function bootstrapHydration(rscStream) {
920
873
  const requestState = getRequestState(navigationKind, url.pathname, currentPrevNextUrl, activeTraversalIntent?.historyState);
921
874
  const requestInterceptionContext = requestState.interceptionContext;
922
875
  const requestPreviousNextUrl = requestState.previousNextUrl;
923
- if (navigationKind === "refresh") syncCurrentHistoryStatePreviousNextUrl(requestPreviousNextUrl, getBrowserRouterState().bfcacheIds);
876
+ if (navigationKind === "refresh") historyController.syncCurrentHistoryStatePreviousNextUrl(requestPreviousNextUrl, getBrowserRouterState().bfcacheIds);
924
877
  setPendingPathname(url.pathname, navId);
925
878
  const routerStateAtNavStart = getBrowserRouterState();
926
879
  const elementsAtNavStart = routerStateAtNavStart.elements;
927
880
  const mountedSlotsHeader = getMountedSlotIdsHeader(elementsAtNavStart);
928
- const shouldBypassNavigationCache = navigationKind === "navigate" && isSamePageSearchNavigation(routerStateAtNavStart.navigationSnapshot, url);
881
+ const earlyIntentDecision = navigationKind === "navigate" ? navigationPlanner.classifyEarlyNavigationIntent({
882
+ basePath: __basePath,
883
+ currentHref: clientNavigationSnapshotHref(routerStateAtNavStart.navigationSnapshot),
884
+ mode: "push",
885
+ scroll: false,
886
+ targetHref: url.href
887
+ }) : null;
888
+ const shouldBypassNavigationCache = earlyIntentDecision?.kind === "flightNavigation" && earlyIntentDecision.bypassNavigationCache;
929
889
  const requestHeaders = createRscRequestHeaders({
930
890
  interceptionContext: requestInterceptionContext,
931
891
  mountedSlotsHeader,
932
892
  renderMode: navigationKind === "refresh" ? APP_RSC_RENDER_MODE_REFRESH_PRESERVE_UI : void 0
933
893
  });
934
894
  const rscUrl = await createRscRequestUrl(url.pathname + url.search, requestHeaders);
935
- const cachedRoute = shouldBypassNavigationCache ? null : getVisitedResponse(rscUrl, requestInterceptionContext, mountedSlotsHeader, navigationKind);
936
- if (cachedRoute) {
937
- const compatibilityDecision = resolveRscCompatibilityNavigationDecision({
938
- clientCompatibilityId: CLIENT_RSC_COMPATIBILITY_ID,
939
- currentHref,
940
- origin: window.location.origin,
941
- responseCompatibilityId: cachedRoute.response.compatibilityIdHeader,
942
- responseUrl: cachedRoute.response.url
943
- });
944
- if (compatibilityDecision.kind === "hard-navigate") {
945
- performHardNavigationForScrollIntent(compatibilityDecision.hardNavigationTarget);
946
- return;
895
+ const visitedResponseCandidate = shouldBypassNavigationCache ? {
896
+ cacheKey: AppElementsWire.encodeCacheKey(rscUrl, requestInterceptionContext),
897
+ entry: null,
898
+ facts: {
899
+ candidate: "missing",
900
+ navigationKind
947
901
  }
948
- const cachedRedirectDecision = resolveRscRedirectLifecycleHop({
902
+ } : readVisitedResponseCacheCandidate(rscUrl, requestInterceptionContext, mountedSlotsHeader, navigationKind);
903
+ const cachedRoute = applyVisitedResponseCacheCandidateDecision(visitedResponseCandidate, navigationPlanner.classifyVisitedResponseCacheCandidate(visitedResponseCandidate.facts));
904
+ const visitedResponse = cachedRoute === null ? { status: "unavailable" } : { status: "available" };
905
+ const prefetchProbeDecision = navigationPlanner.classifyNavigationPrefetchProbe({
906
+ bypassNavigationCache: shouldBypassNavigationCache,
907
+ navigationKind,
908
+ visitedResponse
909
+ });
910
+ let routeManifest = navigationKind === "navigate" ? getBrowserRouteManifest() : null;
911
+ const hasPrefetchCandidate = prefetchProbeDecision.kind === "probe" && hasPrefetchCacheEntryForNavigation(rscUrl, requestInterceptionContext, mountedSlotsHeader, { notifyInvalidation: false });
912
+ const reuseDecision = navigationPlanner.classifyNavigationReuse({
913
+ bypassNavigationCache: shouldBypassNavigationCache,
914
+ navigationKind,
915
+ optimisticRouteShell: routeManifest === null ? {
916
+ reason: "routeManifestMissing",
917
+ status: "unavailable"
918
+ } : { status: "available" },
919
+ prefetch: hasPrefetchCandidate ? { status: "available" } : { status: "unavailable" },
920
+ targetHref: currentHref,
921
+ visitedResponse
922
+ });
923
+ if (reuseDecision.kind === "reuseVisitedResponse" && cachedRoute) {
924
+ const cachedFetchDecision = navigationPlanner.classifyRscFetchResult({
925
+ clientCompatibilityId: CLIENT_RSC_COMPATIBILITY_ID,
926
+ compatibilityIdHeader: cachedRoute.response.compatibilityIdHeader ?? null,
949
927
  currentHref,
950
- historyUpdateMode: currentHistoryMode ?? "replace",
928
+ effectiveHistoryUpdateMode: currentHistoryMode ?? "replace",
929
+ hasBody: true,
930
+ isRscContentType: true,
951
931
  origin: window.location.origin,
952
932
  redirectDepth: redirectCount,
953
933
  requestPreviousNextUrl,
954
- responseUrl: cachedRoute.response.url
934
+ responseOk: true,
935
+ responseUrl: cachedRoute.response.url,
936
+ source: "cached",
937
+ streamedRedirectTarget: null
955
938
  });
956
- if (cachedRedirectDecision.kind === "terminal-hard-navigation") {
957
- if (cachedRedirectDecision.reason === "maxRedirectsExceeded") console.error("[vinext] Too many RSC redirects — aborting navigation to prevent infinite loop.");
958
- performHardNavigationForScrollIntent(cachedRedirectDecision.href);
939
+ if (cachedFetchDecision.kind === "hardNavigate") {
940
+ if (cachedFetchDecision.reason === "redirectDepthExhausted") console.error("[vinext] Too many RSC redirects — aborting navigation to prevent infinite loop.");
941
+ performHardNavigationForScrollIntent(cachedFetchDecision.url);
959
942
  return;
960
943
  }
961
- if (cachedRedirectDecision.kind === "follow") {
944
+ if (cachedFetchDecision.kind === "followRedirect") {
962
945
  if (navigationKind === "traverse") restoredBfcacheIds = null;
963
- currentHref = cachedRedirectDecision.href;
964
- currentHistoryMode = cachedRedirectDecision.historyUpdateMode;
965
- currentPrevNextUrl = cachedRedirectDecision.previousNextUrl;
966
- redirectCount = cachedRedirectDecision.redirectDepth;
946
+ currentHref = cachedFetchDecision.redirect.href;
947
+ currentHistoryMode = cachedFetchDecision.redirect.historyUpdateMode;
948
+ currentPrevNextUrl = cachedFetchDecision.redirect.previousNextUrl;
949
+ redirectCount = cachedFetchDecision.redirect.redirectDepth;
967
950
  continue;
968
951
  }
969
952
  if (!browserNavigationController.isCurrentNavigation(navId)) return;
@@ -971,7 +954,7 @@ function bootstrapHydration(rscStream) {
971
954
  const cachedNavigationSnapshot = createClientNavigationRenderSnapshot(currentHref, cachedParams);
972
955
  const cachedPayload = decodeAppElementsPromise(createFromFetch(Promise.resolve(restoreRscResponse(cachedRoute.response))));
973
956
  if (!browserNavigationController.isCurrentNavigation(navId)) return;
974
- if (await renderNavigationPayload(cachedPayload, cachedNavigationSnapshot, currentHref, navId, currentHistoryMode, cachedParams, requestPreviousNextUrl, detachedNavigationCommits ? null : pendingRouterState, VISITED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN, toActionType(navigationKind), toOperationLane(navigationKind), activeTraversalIntent, scrollIntent, restoredBfcacheIds, reuseCurrentBfcacheIds) === "no-commit") {
957
+ if (await renderNavigationPayload(cachedPayload, cachedNavigationSnapshot, currentHref, navId, currentHistoryMode, cachedParams, requestPreviousNextUrl, detachedNavigationCommits ? null : pendingRouterState, VISITED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN, toActionType(navigationKind), toOperationLane(navigationKind), activeTraversalIntent, scrollIntent, restoredBfcacheIds, reuseCurrentBfcacheIds, visibleCommitMode) === "no-commit") {
975
958
  deleteVisitedResponse(rscUrl, requestInterceptionContext);
976
959
  continue;
977
960
  }
@@ -980,7 +963,8 @@ function bootstrapHydration(rscStream) {
980
963
  let navResponse;
981
964
  let navResponseExpiresAt;
982
965
  let navResponseUrl = null;
983
- if (navigationKind !== "refresh" && !shouldBypassNavigationCache) {
966
+ let fallbackReuseDecision = reuseDecision;
967
+ if (reuseDecision.kind === "consumePrefetch") {
984
968
  const prefetchedResponse = await consumePrefetchResponseForNavigation(rscUrl, requestInterceptionContext, mountedSlotsHeader, { shouldConsume: () => browserNavigationController.isCurrentNavigation(navId) });
985
969
  if (!browserNavigationController.isCurrentNavigation(navId)) return;
986
970
  if (prefetchedResponse) {
@@ -988,9 +972,22 @@ function bootstrapHydration(rscStream) {
988
972
  navResponseExpiresAt = prefetchedResponse.expiresAt;
989
973
  navResponseUrl = prefetchedResponse.url;
990
974
  }
975
+ if (!navResponse) {
976
+ routeManifest = navigationKind === "navigate" ? getBrowserRouteManifest() : null;
977
+ fallbackReuseDecision = navigationPlanner.classifyNavigationReuse({
978
+ bypassNavigationCache: shouldBypassNavigationCache,
979
+ navigationKind,
980
+ optimisticRouteShell: routeManifest === null ? {
981
+ reason: "routeManifestMissing",
982
+ status: "unavailable"
983
+ } : { status: "available" },
984
+ prefetch: { status: "unavailable" },
985
+ targetHref: currentHref,
986
+ visitedResponse: { status: "unavailable" }
987
+ });
988
+ }
991
989
  }
992
- if (!navResponse && navigationKind === "navigate") {
993
- const routeManifest = getBrowserRouteManifest();
990
+ if (!navResponse && fallbackReuseDecision.kind === "attemptOptimisticRouteShell") {
994
991
  await learnOptimisticRouteTemplatesFromPrefetchCache({
995
992
  interceptionContext: requestInterceptionContext,
996
993
  mountedSlotsHeader,
@@ -1009,7 +1006,7 @@ function bootstrapHydration(rscStream) {
1009
1006
  if (optimisticPayload !== null) {
1010
1007
  detachedNavigationCommits = true;
1011
1008
  const optimisticNavigationSnapshot = createClientNavigationRenderSnapshot(currentHref, optimisticPayload.params);
1012
- renderNavigationPayload(Promise.resolve(optimisticPayload.elements), optimisticNavigationSnapshot, currentHref, navId, currentHistoryMode, optimisticPayload.params, requestPreviousNextUrl, null, FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, toActionType(navigationKind), toOperationLane(navigationKind), activeTraversalIntent, scrollIntent, restoredBfcacheIds, reuseCurrentBfcacheIds).catch((error) => {
1009
+ renderNavigationPayload(Promise.resolve(optimisticPayload.elements), optimisticNavigationSnapshot, currentHref, navId, currentHistoryMode, optimisticPayload.params, requestPreviousNextUrl, null, FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, toActionType(navigationKind), toOperationLane(navigationKind), activeTraversalIntent, scrollIntent, restoredBfcacheIds, reuseCurrentBfcacheIds, visibleCommitMode).catch((error) => {
1013
1010
  if (browserNavigationController.isCurrentNavigation(navId)) console.error("[vinext] Optimistic RSC navigation error:", error);
1014
1011
  });
1015
1012
  }
@@ -1026,61 +1023,36 @@ function bootstrapHydration(rscStream) {
1026
1023
  });
1027
1024
  }
1028
1025
  if (!browserNavigationController.isCurrentNavigation(navId)) return;
1029
- const isRscResponse = (navResponse.headers.get("content-type") ?? "").startsWith("text/x-component");
1030
- if (!navResponse.ok || !isRscResponse || !navResponse.body) {
1031
- performHardNavigationForScrollIntent(resolveHardNavigationTargetFromRscResponse(navResponseUrl ?? navResponse.url, currentHref, window.location.origin));
1032
- return;
1033
- }
1034
- const compatibilityDecision = resolveRscCompatibilityNavigationDecision({
1026
+ const navContentType = navResponse.headers.get("content-type") ?? "";
1027
+ const liveFetchDecision = navigationPlanner.classifyRscFetchResult({
1035
1028
  clientCompatibilityId: CLIENT_RSC_COMPATIBILITY_ID,
1029
+ compatibilityIdHeader: navResponse.headers.get(VINEXT_RSC_COMPATIBILITY_ID_HEADER),
1036
1030
  currentHref,
1037
- origin: window.location.origin,
1038
- responseCompatibilityId: navResponse.headers.get(VINEXT_RSC_COMPATIBILITY_ID_HEADER),
1039
- responseUrl: navResponseUrl ?? navResponse.url
1040
- });
1041
- if (compatibilityDecision.kind === "hard-navigate") {
1042
- performHardNavigationForScrollIntent(compatibilityDecision.hardNavigationTarget);
1043
- return;
1044
- }
1045
- const redirectDecision = resolveRscRedirectLifecycleHop({
1046
- currentHref,
1047
- historyUpdateMode: currentHistoryMode ?? "replace",
1031
+ effectiveHistoryUpdateMode: currentHistoryMode ?? "replace",
1032
+ hasBody: navResponse.body !== null,
1033
+ isRscContentType: navContentType.startsWith(VINEXT_RSC_CONTENT_TYPE),
1048
1034
  origin: window.location.origin,
1049
1035
  redirectDepth: redirectCount,
1050
1036
  requestPreviousNextUrl,
1051
- responseUrl: navResponseUrl ?? navResponse.url
1037
+ responseOk: navResponse.ok,
1038
+ responseUrl: navResponseUrl ?? navResponse.url,
1039
+ source: "live",
1040
+ streamedRedirectTarget: navResponse.headers.get(VINEXT_RSC_REDIRECT_HEADER)
1052
1041
  });
1053
- if (redirectDecision.kind === "terminal-hard-navigation") {
1054
- if (redirectDecision.reason === "maxRedirectsExceeded") console.error("[vinext] Too many RSC redirects — aborting navigation to prevent infinite loop.");
1055
- performHardNavigationForScrollIntent(redirectDecision.href);
1042
+ if (liveFetchDecision.kind === "hardNavigate") {
1043
+ if (liveFetchDecision.discardBody) navResponse.body?.cancel().catch(() => {});
1044
+ if (liveFetchDecision.reason === "redirectDepthExhausted") console.error("[vinext] Too many RSC redirects — aborting navigation to prevent infinite loop.");
1045
+ if (liveFetchDecision.reason === "streamedRedirectLoop") console.error("[vinext] RSC streamed redirect resolved to the current URL — aborting navigation to prevent infinite loop.");
1046
+ performHardNavigationForScrollIntent(liveFetchDecision.url);
1056
1047
  return;
1057
1048
  }
1058
- if (redirectDecision.kind === "follow") {
1059
- if (navigationKind === "traverse") restoredBfcacheIds = null;
1060
- currentHref = redirectDecision.href;
1061
- currentHistoryMode = redirectDecision.historyUpdateMode;
1062
- currentPrevNextUrl = redirectDecision.previousNextUrl;
1063
- redirectCount = redirectDecision.redirectDepth;
1064
- continue;
1065
- }
1066
- const flightRedirectTarget = navResponse.headers.get(VINEXT_RSC_REDIRECT_HEADER);
1067
- if (flightRedirectTarget) {
1068
- navResponse.body?.cancel().catch(() => {});
1069
- const resolvedTarget = new URL(flightRedirectTarget, window.location.origin);
1070
- if (resolvedTarget.origin !== window.location.origin) {
1071
- performHardNavigationForScrollIntent(resolvedTarget.href);
1072
- return;
1073
- }
1074
- if (redirectCount >= 10) {
1075
- console.error("[vinext] Too many RSC redirects — aborting navigation to prevent infinite loop.");
1076
- performHardNavigationForScrollIntent(resolvedTarget.href);
1077
- return;
1078
- }
1049
+ if (liveFetchDecision.kind === "followRedirect") {
1050
+ if (liveFetchDecision.discardBody) navResponse.body?.cancel().catch(() => {});
1079
1051
  if (navigationKind === "traverse") restoredBfcacheIds = null;
1080
- currentHref = `${resolvedTarget.pathname}${resolvedTarget.search}${resolvedTarget.hash}`;
1081
- currentHistoryMode = currentHistoryMode ?? "replace";
1082
- currentPrevNextUrl = requestPreviousNextUrl;
1083
- redirectCount += 1;
1052
+ currentHref = liveFetchDecision.redirect.href;
1053
+ currentHistoryMode = liveFetchDecision.redirect.historyUpdateMode;
1054
+ currentPrevNextUrl = liveFetchDecision.redirect.previousNextUrl;
1055
+ redirectCount = liveFetchDecision.redirect.redirectDepth;
1084
1056
  continue;
1085
1057
  }
1086
1058
  const navParams = parseEncodedJsonHeader(navResponse.headers.get("X-Vinext-Params")) ?? {};
@@ -1096,7 +1068,7 @@ function bootstrapHydration(rscStream) {
1096
1068
  if (!browserNavigationController.isCurrentNavigation(navId)) return;
1097
1069
  const rscPayload = decodeAppElementsPromise(createFromFetch(Promise.resolve(reactResponse)));
1098
1070
  if (!browserNavigationController.isCurrentNavigation(navId)) return;
1099
- if (await renderNavigationPayload(rscPayload, navigationSnapshot, currentHref, navId, currentHistoryMode, navParams, requestPreviousNextUrl, detachedNavigationCommits ? null : pendingRouterState, FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, toActionType(navigationKind), toOperationLane(navigationKind), activeTraversalIntent, scrollIntent, restoredBfcacheIds, reuseCurrentBfcacheIds) !== "committed") return;
1071
+ if (await renderNavigationPayload(rscPayload, navigationSnapshot, currentHref, navId, currentHistoryMode, navParams, requestPreviousNextUrl, detachedNavigationCommits ? null : pendingRouterState, FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, toActionType(navigationKind), toOperationLane(navigationKind), activeTraversalIntent, scrollIntent, restoredBfcacheIds, reuseCurrentBfcacheIds, visibleCommitMode) !== "committed") return;
1100
1072
  if (!browserNavigationController.isCurrentNavigation(navId)) return;
1101
1073
  try {
1102
1074
  const renderedElements = await rscPayload;
@@ -1117,7 +1089,7 @@ function bootstrapHydration(rscStream) {
1117
1089
  } catch (error) {
1118
1090
  if (!browserNavigationController.isCurrentNavigation(navId)) return;
1119
1091
  if (!isPageUnloading) console.error("[vinext] RSC navigation error:", error);
1120
- performHardNavigationForScrollIntent(currentHref);
1092
+ performHardNavigationForScrollIntent(navigationPlanner.classifyRscNavigationError({ currentHref }).url);
1121
1093
  } finally {
1122
1094
  browserNavigationController.finalizeNavigation(navId, pendingRouterState);
1123
1095
  discardedServerActionRefreshScheduler.markNavigationSettled();
@@ -1142,7 +1114,7 @@ function bootstrapHydration(rscStream) {
1142
1114
  const href = window.location.href;
1143
1115
  if (isSameAppRoutePopstateTarget(href)) {
1144
1116
  notifyAppRouterTransitionStart(href, "traverse");
1145
- commitTraversalIndexFromHistoryState(event.state);
1117
+ historyController.commitTraversalIndexFromHistoryState(event.state);
1146
1118
  restorePopstateScrollPosition(event.state);
1147
1119
  return;
1148
1120
  }