vinext 0.1.2 → 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 (199) hide show
  1. package/dist/build/prerender.d.ts +9 -1
  2. package/dist/build/prerender.js +41 -12
  3. package/dist/build/run-prerender.d.ts +10 -2
  4. package/dist/build/run-prerender.js +15 -1
  5. package/dist/client/app-nav-failure-handler.d.ts +8 -0
  6. package/dist/client/app-nav-failure-handler.js +44 -0
  7. package/dist/client/vinext-next-data.d.ts +18 -1
  8. package/dist/client/window-next.d.ts +2 -1
  9. package/dist/client/window-next.js +12 -1
  10. package/dist/cloudflare/src/cache/cdn-adapter.runtime.js +6 -1
  11. package/dist/config/config-matchers.js +73 -14
  12. package/dist/config/next-config.d.ts +46 -4
  13. package/dist/config/next-config.js +147 -48
  14. package/dist/deploy.d.ts +30 -11
  15. package/dist/deploy.js +180 -99
  16. package/dist/entries/app-browser-entry.d.ts +9 -3
  17. package/dist/entries/app-browser-entry.js +21 -3
  18. package/dist/entries/app-rsc-entry.d.ts +2 -0
  19. package/dist/entries/app-rsc-entry.js +64 -5
  20. package/dist/entries/app-rsc-manifest.js +2 -0
  21. package/dist/entries/app-ssr-entry.js +1 -1
  22. package/dist/entries/pages-client-entry.js +53 -8
  23. package/dist/entries/pages-server-entry.js +41 -5
  24. package/dist/index.js +200 -62
  25. package/dist/plugins/extensionless-dynamic-import.d.ts +6 -0
  26. package/dist/plugins/extensionless-dynamic-import.js +152 -0
  27. package/dist/plugins/optimize-imports.d.ts +2 -1
  28. package/dist/plugins/optimize-imports.js +11 -9
  29. package/dist/plugins/postcss.js +7 -7
  30. package/dist/plugins/typeof-window.d.ts +14 -0
  31. package/dist/plugins/typeof-window.js +150 -0
  32. package/dist/routing/app-route-graph.d.ts +2 -1
  33. package/dist/routing/app-route-graph.js +44 -14
  34. package/dist/routing/file-matcher.d.ts +10 -1
  35. package/dist/routing/file-matcher.js +22 -1
  36. package/dist/routing/pages-router.js +3 -3
  37. package/dist/routing/utils.d.ts +35 -6
  38. package/dist/routing/utils.js +59 -7
  39. package/dist/server/api-handler.d.ts +6 -1
  40. package/dist/server/api-handler.js +21 -15
  41. package/dist/server/app-browser-action-result.d.ts +19 -6
  42. package/dist/server/app-browser-action-result.js +19 -10
  43. package/dist/server/app-browser-entry.js +167 -90
  44. package/dist/server/app-browser-error.d.ts +10 -6
  45. package/dist/server/app-browser-error.js +43 -8
  46. package/dist/server/app-browser-hydration.d.ts +2 -0
  47. package/dist/server/app-browser-hydration.js +1 -0
  48. package/dist/server/app-browser-navigation-controller.d.ts +4 -2
  49. package/dist/server/app-browser-navigation-controller.js +23 -2
  50. package/dist/server/app-browser-server-action-navigation.d.ts +6 -0
  51. package/dist/server/app-browser-server-action-navigation.js +9 -0
  52. package/dist/server/app-browser-stream.js +86 -43
  53. package/dist/server/app-elements-wire.d.ts +6 -1
  54. package/dist/server/app-elements-wire.js +14 -4
  55. package/dist/server/app-elements.d.ts +2 -2
  56. package/dist/server/app-elements.js +2 -2
  57. package/dist/server/app-fallback-renderer.d.ts +1 -0
  58. package/dist/server/app-fallback-renderer.js +3 -1
  59. package/dist/server/app-optimistic-routing.js +2 -2
  60. package/dist/server/app-page-boundary-render.d.ts +1 -0
  61. package/dist/server/app-page-boundary-render.js +27 -14
  62. package/dist/server/app-page-cache-render.d.ts +53 -0
  63. package/dist/server/app-page-cache-render.js +91 -0
  64. package/dist/server/app-page-cache.d.ts +16 -2
  65. package/dist/server/app-page-cache.js +62 -1
  66. package/dist/server/app-page-dispatch.d.ts +26 -0
  67. package/dist/server/app-page-dispatch.js +149 -92
  68. package/dist/server/app-page-element-builder.d.ts +1 -0
  69. package/dist/server/app-page-element-builder.js +5 -2
  70. package/dist/server/app-page-execution.d.ts +6 -1
  71. package/dist/server/app-page-execution.js +21 -1
  72. package/dist/server/app-page-probe.d.ts +1 -0
  73. package/dist/server/app-page-probe.js +4 -0
  74. package/dist/server/app-page-render-observation.d.ts +3 -1
  75. package/dist/server/app-page-render-observation.js +17 -1
  76. package/dist/server/app-page-render.d.ts +12 -1
  77. package/dist/server/app-page-render.js +42 -4
  78. package/dist/server/app-page-request.d.ts +2 -0
  79. package/dist/server/app-page-request.js +2 -1
  80. package/dist/server/app-page-route-wiring.d.ts +3 -1
  81. package/dist/server/app-page-route-wiring.js +14 -5
  82. package/dist/server/app-page-stream.d.ts +15 -3
  83. package/dist/server/app-page-stream.js +11 -5
  84. package/dist/server/app-pages-bridge.d.ts +18 -0
  85. package/dist/server/app-pages-bridge.js +22 -5
  86. package/dist/server/app-ppr-fallback-shell-render.d.ts +17 -0
  87. package/dist/server/app-ppr-fallback-shell-render.js +26 -0
  88. package/dist/server/app-ppr-fallback-shell.d.ts +13 -1
  89. package/dist/server/app-ppr-fallback-shell.js +8 -1
  90. package/dist/server/app-route-handler-dispatch.js +9 -2
  91. package/dist/server/app-route-handler-policy.d.ts +1 -0
  92. package/dist/server/app-router-entry.js +5 -0
  93. package/dist/server/app-rsc-cache-busting.js +2 -0
  94. package/dist/server/app-rsc-handler.d.ts +25 -0
  95. package/dist/server/app-rsc-handler.js +154 -54
  96. package/dist/server/app-rsc-route-matching.d.ts +3 -0
  97. package/dist/server/app-rsc-route-matching.js +2 -0
  98. package/dist/server/app-segment-config.d.ts +9 -1
  99. package/dist/server/app-segment-config.js +12 -3
  100. package/dist/server/app-server-action-execution.d.ts +1 -0
  101. package/dist/server/app-server-action-execution.js +42 -13
  102. package/dist/server/app-ssr-entry.d.ts +2 -0
  103. package/dist/server/app-ssr-entry.js +83 -10
  104. package/dist/server/cache-control.js +4 -0
  105. package/dist/server/dev-server.d.ts +2 -2
  106. package/dist/server/dev-server.js +244 -51
  107. package/dist/server/hybrid-route-priority.d.ts +22 -0
  108. package/dist/server/hybrid-route-priority.js +33 -0
  109. package/dist/server/image-optimization.d.ts +18 -9
  110. package/dist/server/image-optimization.js +37 -23
  111. package/dist/server/implicit-tags.d.ts +2 -1
  112. package/dist/server/implicit-tags.js +4 -1
  113. package/dist/server/navigation-planner.d.ts +133 -30
  114. package/dist/server/navigation-planner.js +114 -0
  115. package/dist/server/navigation-trace.d.ts +8 -1
  116. package/dist/server/navigation-trace.js +8 -1
  117. package/dist/server/pages-api-route.d.ts +6 -0
  118. package/dist/server/pages-api-route.js +13 -2
  119. package/dist/server/pages-asset-tags.d.ts +2 -1
  120. package/dist/server/pages-asset-tags.js +6 -2
  121. package/dist/server/pages-data-route.d.ts +8 -1
  122. package/dist/server/pages-data-route.js +11 -2
  123. package/dist/server/pages-get-initial-props.d.ts +54 -4
  124. package/dist/server/pages-get-initial-props.js +43 -1
  125. package/dist/server/pages-node-compat.js +2 -2
  126. package/dist/server/pages-page-data.d.ts +11 -2
  127. package/dist/server/pages-page-data.js +204 -33
  128. package/dist/server/pages-page-handler.d.ts +4 -2
  129. package/dist/server/pages-page-handler.js +59 -22
  130. package/dist/server/pages-page-response.d.ts +2 -1
  131. package/dist/server/pages-page-response.js +7 -4
  132. package/dist/server/pages-request-pipeline.d.ts +1 -0
  133. package/dist/server/pages-request-pipeline.js +73 -36
  134. package/dist/server/pregenerated-concrete-paths.d.ts +1 -17
  135. package/dist/server/pregenerated-concrete-paths.js +2 -19
  136. package/dist/server/prerender-manifest.d.ts +33 -0
  137. package/dist/server/prerender-manifest.js +54 -0
  138. package/dist/server/prerender-route-params.d.ts +1 -2
  139. package/dist/server/prod-server.js +9 -3
  140. package/dist/server/request-pipeline.d.ts +3 -15
  141. package/dist/server/request-pipeline.js +58 -47
  142. package/dist/server/rsc-stream-hints.d.ts +5 -1
  143. package/dist/server/rsc-stream-hints.js +6 -1
  144. package/dist/server/seed-cache.js +10 -18
  145. package/dist/shims/app-router-scroll-state.d.ts +3 -1
  146. package/dist/shims/app-router-scroll-state.js +14 -2
  147. package/dist/shims/app-router-scroll.d.ts +3 -0
  148. package/dist/shims/app-router-scroll.js +28 -18
  149. package/dist/shims/cache-runtime.js +3 -2
  150. package/dist/shims/cache.d.ts +1 -0
  151. package/dist/shims/cache.js +1 -1
  152. package/dist/shims/cdn-cache.d.ts +5 -5
  153. package/dist/shims/dynamic-preload-chunks.js +6 -4
  154. package/dist/shims/error-boundary.d.ts +2 -0
  155. package/dist/shims/error-boundary.js +7 -0
  156. package/dist/shims/error.js +3 -2
  157. package/dist/shims/error.react-server.d.ts +9 -0
  158. package/dist/shims/error.react-server.js +6 -0
  159. package/dist/shims/fetch-cache.d.ts +3 -1
  160. package/dist/shims/fetch-cache.js +45 -20
  161. package/dist/shims/hash-scroll.js +6 -1
  162. package/dist/shims/headers.js +29 -4
  163. package/dist/shims/internal/als-registry.js +28 -1
  164. package/dist/shims/internal/app-route-detection.js +8 -17
  165. package/dist/shims/internal/hybrid-client-route-owner.d.ts +31 -0
  166. package/dist/shims/internal/hybrid-client-route-owner.js +143 -0
  167. package/dist/shims/internal/navigation-untracked.d.ts +35 -0
  168. package/dist/shims/internal/navigation-untracked.js +55 -0
  169. package/dist/shims/internal/pages-data-target.d.ts +7 -2
  170. package/dist/shims/internal/pages-data-target.js +17 -8
  171. package/dist/shims/internal/pages-router-accessor.d.ts +19 -0
  172. package/dist/shims/internal/pages-router-accessor.js +13 -0
  173. package/dist/shims/internal/router-context.d.ts +2 -1
  174. package/dist/shims/internal/router-context.js +3 -1
  175. package/dist/shims/link.js +12 -5
  176. package/dist/shims/navigation.d.ts +8 -2
  177. package/dist/shims/navigation.js +61 -31
  178. package/dist/shims/ppr-fallback-shell.d.ts +5 -1
  179. package/dist/shims/ppr-fallback-shell.js +28 -7
  180. package/dist/shims/router.d.ts +13 -2
  181. package/dist/shims/router.js +419 -128
  182. package/dist/shims/server.d.ts +16 -1
  183. package/dist/shims/server.js +44 -12
  184. package/dist/shims/unified-request-context.js +1 -0
  185. package/dist/utils/built-asset-url.d.ts +4 -0
  186. package/dist/utils/built-asset-url.js +11 -0
  187. package/dist/utils/commonjs-loader.d.ts +16 -0
  188. package/dist/utils/commonjs-loader.js +100 -0
  189. package/dist/utils/deployment-id.d.ts +8 -0
  190. package/dist/utils/deployment-id.js +22 -0
  191. package/dist/utils/html-limited-bots.d.ts +18 -1
  192. package/dist/utils/html-limited-bots.js +23 -1
  193. package/dist/utils/parse-cookie.d.ts +13 -0
  194. package/dist/utils/parse-cookie.js +52 -0
  195. package/dist/utils/path.d.ts +7 -1
  196. package/dist/utils/path.js +9 -1
  197. package/package.json +2 -2
  198. package/dist/shims/internal/parse-cookie-header.d.ts +0 -14
  199. package/dist/shims/internal/parse-cookie-header.js +0 -30
@@ -4,40 +4,43 @@ import { AppElementsWire } from "./app-elements-wire.js";
4
4
  import { APP_RSC_RENDER_MODE_REFRESH_PRESERVE_UI } from "./app-rsc-render-mode.js";
5
5
  import { getMountedSlotIdsHeader, resolveVisitedResponseInterceptionContext } from "./app-elements.js";
6
6
  import { AppRouterContext } from "../shims/internal/app-router-context.js";
7
- import { installWindowNext } from "../client/window-next.js";
7
+ import { installWindowNext, setWindowNextInternalSourcePage } from "../client/window-next.js";
8
8
  import { retryScrollTo, scrollToHashTargetOnNextFrame } from "../shims/hash-scroll.js";
9
9
  import { getNavigationRuntime, registerNavigationRuntimeBootstrap, registerNavigationRuntimeFunctions } from "../client/navigation-runtime.js";
10
10
  import { notifyAppRouterTransitionStart } from "../client/instrumentation-client-state.js";
11
+ import { clearAppNavigationFailureTarget, installAppNavigationFailureListeners } from "../client/app-nav-failure-handler.js";
11
12
  import { resolveManifestNavigationInterceptionContext, resolveMiddlewareRewriteNavigationInterceptionContext } from "./app-browser-interception-context.js";
12
13
  import { readHistoryStatePreviousNextUrl } from "./app-history-state.js";
13
- import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, createRscRequestHeaders, createRscRequestUrl, createServerActionRequestUrl, getVinextRscCompatibilityId, resolveRscCompatibilityNavigationDecision } from "./app-rsc-cache-busting.js";
14
+ import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, createRscRequestHeaders, createRscRequestUrl, createServerActionRequestUrl, getVinextRscCompatibilityId } from "./app-rsc-cache-busting.js";
14
15
  import { AppBrowserMpaNavigationScheduler } from "./app-browser-mpa-navigation.js";
15
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, createSnapshotPathAndSearch, 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
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";
28
31
  import { AppBrowserHistoryController } from "./app-browser-history-controller.js";
29
32
  import { createVisitedResponseCacheEntry, isVisitedResponseCacheEntryFresh } from "./app-visited-response-cache.js";
30
33
  import { createPopstateRestoreHandler, restoreSynchronousPopstateScrollPosition } from "./app-browser-popstate.js";
31
- import { createOnUncaughtError, prodOnCaughtError } from "./app-browser-error.js";
34
+ import { createDevOnCaughtError, createOnUncaughtError, createProdOnCaughtError, prodOnRecoverableError } from "./app-browser-error.js";
32
35
  import { dismissOverlay } from "./dev-error-overlay-store.js";
33
- import { devOnCaughtError, devOnUncaughtError, installDevErrorOverlay, installViteHmrErrorHandler, reportInitialDevServerErrors } from "./dev-error-overlay.js";
36
+ import { devOnCaughtError, installDevErrorOverlay, installViteHmrErrorHandler, reportInitialDevServerErrors } from "./dev-error-overlay.js";
34
37
  import { throwOnServerActionNotFound } from "./server-action-not-found.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,6 +58,14 @@ 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
  }
@@ -109,10 +120,10 @@ function isRouterStatePromise(value) {
109
120
  let latestClientParams = {};
110
121
  const visitedResponseCache = /* @__PURE__ */ new Map();
111
122
  let browserRouterStateHasEverCommitted = false;
112
- let pendingNavigationRecoveryHref = null;
113
123
  const mpaNavigationScheduler = new AppBrowserMpaNavigationScheduler();
114
124
  const unresolvedMpaNavigation = new Promise(() => {});
115
125
  const RSC_HMR_SETTLE_DELAY_MS = 150;
126
+ const DEFAULT_GLOBAL_ERROR_COMPONENT = DefaultGlobalError;
116
127
  let latestRscHmrUpdateId = 0;
117
128
  let synchronousPopstateScrollRestoreNavigationId = null;
118
129
  function waitForRscHmrSettle(delayMs = RSC_HMR_SETTLE_DELAY_MS) {
@@ -262,39 +273,31 @@ function createNavigationCommitEffect(options) {
262
273
  stageClientParams: () => stageClientParams(params),
263
274
  targetHistoryIndex
264
275
  });
265
- pendingNavigationRecoveryHref = null;
276
+ clearAppNavigationFailureTarget(href);
266
277
  commitClientNavigationState(navId);
267
278
  };
268
279
  }
269
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") {
270
281
  syncServerActionHttpFallbackHead(null);
271
- try {
272
- return await browserNavigationController.renderNavigationPayload({
273
- actionType,
274
- createNavigationCommitEffect: (options) => {
275
- pendingNavigationRecoveryHref = options.href;
276
- return createNavigationCommitEffect(options);
277
- },
278
- historyUpdateMode,
279
- navigationSnapshot,
280
- nextElements: payload,
281
- operationLane,
282
- payloadOrigin,
283
- params,
284
- pendingRouterState,
285
- previousNextUrl,
286
- scrollIntent,
287
- restoredBfcacheIds,
288
- reuseCurrentBfcacheIds,
289
- targetHistoryIndex: traversalIntent === null ? void 0 : traversalIntent.targetHistoryIndex,
290
- targetHref,
291
- navId,
292
- visibleCommitMode
293
- });
294
- } catch (error) {
295
- pendingNavigationRecoveryHref = null;
296
- throw error;
297
- }
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
+ });
298
301
  }
299
302
  function resolveActionRedirectTarget(response) {
300
303
  const actionRedirect = response.headers.get(ACTION_REDIRECT_HEADER);
@@ -360,23 +363,39 @@ function evictVisitedResponseCacheIfNeeded() {
360
363
  visitedResponseCache.delete(oldest);
361
364
  }
362
365
  }
363
- function getVisitedResponse(rscUrl, interceptionContext, mountedSlotsHeader, navigationKind) {
366
+ function readVisitedResponseCacheCandidate(rscUrl, interceptionContext, mountedSlotsHeader, navigationKind) {
364
367
  const cacheKey = AppElementsWire.encodeCacheKey(rscUrl, interceptionContext);
365
368
  const cached = visitedResponseCache.get(cacheKey);
366
- if (!cached) return null;
367
- if ((cached.response.mountedSlotsHeader ?? null) !== mountedSlotsHeader) {
368
- visitedResponseCache.delete(cacheKey);
369
- return null;
370
- }
371
- if (isVisitedResponseCacheEntryFresh(cached, {
372
- navigationKind,
373
- now: Date.now()
374
- })) {
375
- visitedResponseCache.delete(cacheKey);
376
- visitedResponseCache.set(cacheKey, cached);
377
- 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;
378
397
  }
379
- visitedResponseCache.delete(cacheKey);
398
+ visitedResponseCache.delete(candidate.cacheKey);
380
399
  return null;
381
400
  }
382
401
  function deleteVisitedResponse(rscUrl, interceptionContext) {
@@ -525,20 +544,25 @@ function BrowserRoot({ initialElements, initialNavigationSnapshot }) {
525
544
  return new Promise(() => {});
526
545
  } });
527
546
  browserRouterStateHasEverCommitted = true;
528
- const hydratedAt = performance.now();
529
- window.__VINEXT_HYDRATED_AT = hydratedAt;
530
- window.__NEXT_HYDRATED = true;
531
- window.__NEXT_HYDRATED_AT = hydratedAt;
532
- window.__NEXT_HYDRATED_CB?.();
533
547
  return () => {
534
548
  registerNavigationRuntimeFunctions({ navigateExternal: void 0 });
535
549
  detach();
536
550
  setMountedSlotsHeader(null);
537
551
  };
538
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
+ }, []);
539
560
  useLayoutEffect(() => {
540
561
  historyController.rememberHistoryStateSnapshot(treeState);
541
562
  }, [treeState]);
563
+ useEffect(() => {
564
+ setWindowNextInternalSourcePage(AppElementsWire.readMetadata(treeState.elements).sourcePage);
565
+ }, [treeState.elements]);
542
566
  useLayoutEffect(() => {
543
567
  setMountedSlotsHeader(getMountedSlotIdsHeader(stateRef.current.elements));
544
568
  removeStylesheetLinksCoveredByInlineCss();
@@ -564,13 +588,17 @@ function BrowserRoot({ initialElements, initialNavigationSnapshot }) {
564
588
  const redirectedTree = createElement(AppRouterRedirectBridge, null, BfcacheIdMapContext ? createElement(BfcacheIdMapContext.Provider, { value: treeState.bfcacheIds }, stateKeyTree) : stateKeyTree);
565
589
  const innerTree = AppRouterContext ? createElement(AppRouterContext.Provider, { value: appRouterInstance }, redirectedTree) : redirectedTree;
566
590
  const committedTree = import.meta.env.DEV ? createElement(DevRecoveryBoundary, {
591
+ isImplicitRootErrorBoundary: true,
567
592
  resetKey: treeState.renderId,
568
593
  onCatch: handleDevRecoveryBoundaryCatch
569
594
  }, innerTree) : innerTree;
570
- 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
+ });
571
599
  const ClientNavigationRenderContext = getClientNavigationRenderContext();
572
- if (!ClientNavigationRenderContext) return scrollScopedTree;
573
- return createElement(ClientNavigationRenderContext.Provider, { value: treeState.navigationSnapshot }, scrollScopedTree);
600
+ if (!ClientNavigationRenderContext) return rootErrorTree;
601
+ return createElement(ClientNavigationRenderContext.Provider, { value: treeState.navigationSnapshot }, rootErrorTree);
574
602
  }
575
603
  function restoreHydrationNavigationContext(pathname, searchParams, params) {
576
604
  setNavigationContext({
@@ -698,31 +726,23 @@ function registerServerActionCallback() {
698
726
  const hasActionRedirect = fetchResponse.headers.has(ACTION_REDIRECT_HEADER);
699
727
  const actionRedirectTarget = resolveActionRedirectTarget(fetchResponse);
700
728
  if (hasActionRedirect && !actionRedirectTarget) return;
701
- const actionRedirectCompatibilityHardNavigationTarget = resolveServerActionRedirectCompatibilityHardNavigationTarget({
729
+ const actionResultFacts = createServerActionResultFacts({
702
730
  actionRedirectHref: actionRedirectTarget?.href ?? null,
731
+ actionRedirectType: actionRedirectTarget?.type ?? null,
703
732
  clientCompatibilityId: CLIENT_RSC_COMPATIBILITY_ID,
704
- response: fetchResponse
705
- });
706
- if (actionRedirectCompatibilityHardNavigationTarget) {
707
- clearClientNavigationCaches();
708
- browserNavigationController.performHardNavigation(actionRedirectCompatibilityHardNavigationTarget, actionRedirectTarget?.type === "push" ? "assign" : "replace");
709
- return;
710
- }
711
- if (!actionRedirectTarget && shouldCheckRscCompatibilityForServerActionResponse(fetchResponse) && resolveRscCompatibilityNavigationDecision({
712
- clientCompatibilityId: CLIENT_RSC_COMPATIBILITY_ID,
733
+ compatibilityIdHeader: fetchResponse.headers.get(VINEXT_RSC_COMPATIBILITY_ID_HEADER),
734
+ contentTypeHeader: fetchResponse.headers.get("content-type"),
713
735
  currentHref: actionInitiation.href,
714
736
  origin: window.location.origin,
715
- responseCompatibilityId: fetchResponse.headers.get("X-Vinext-RSC-Compatibility-Id"),
716
737
  responseUrl: fetchResponse.url
717
- }).kind === "hard-navigate") {
718
- browserNavigationController.performHardNavigation(actionInitiation.href);
719
- return;
720
- }
738
+ });
739
+ const fetchResponseIsRsc = actionResultFacts.isRscContentType;
740
+ if (applyServerActionResultDecision(navigationPlanner.classifyServerActionResult(actionResultFacts), clearClientNavigationCaches, (url, historyMode) => browserNavigationController.performHardNavigation(url, historyMode))) return;
721
741
  const revalidation = parseServerActionRevalidationHeader(fetchResponse.headers);
722
742
  if (revalidation !== "none") clearClientNavigationCaches();
723
743
  const invalidResponseError = await readInvalidServerActionResponseError(fetchResponse.clone(), actionRedirectTarget !== null);
724
744
  if (invalidResponseError) throw invalidResponseError;
725
- if (actionRedirectTarget && !shouldCheckRscCompatibilityForServerActionResponse(fetchResponse)) {
745
+ if (actionRedirectTarget && !fetchResponseIsRsc) {
726
746
  browserNavigationController.performHardNavigation(actionRedirectTarget.href);
727
747
  return;
728
748
  }
@@ -770,7 +790,9 @@ function registerServerActionCallback() {
770
790
  });
771
791
  }
772
792
  async function main() {
793
+ if (!claimInitialAppRouterBootstrap()) return;
773
794
  registerServerActionCallback();
795
+ installAppNavigationFailureListeners();
774
796
  if (import.meta.env.DEV) {
775
797
  installDevErrorOverlay();
776
798
  installViteHmrErrorHandler(import.meta.hot);
@@ -784,27 +806,39 @@ function bootstrapHydration(rscStream) {
784
806
  const root = decodeAppElementsPromise(createFromReadableStream(rscStream));
785
807
  const initialNavigationSnapshot = createClientNavigationRenderSnapshot(window.location.href, latestClientParams);
786
808
  historyController.writeBootstrapHistoryMetadata();
787
- const onUncaughtError = import.meta.env.DEV ? devOnUncaughtError : createOnUncaughtError(() => pendingNavigationRecoveryHref);
809
+ const onUncaughtError = createOnUncaughtError();
788
810
  const formState = consumeInitialFormState(getVinextBrowserGlobal());
789
811
  const hydrateRootOptions = import.meta.env.DEV ? createVinextHydrateRootOptions({
790
812
  formState,
791
- onCaughtError: devOnCaughtError,
813
+ onCaughtError: createDevOnCaughtError(devOnCaughtError, onUncaughtError),
792
814
  onUncaughtError
793
815
  }) : createVinextHydrateRootOptions({
794
816
  formState,
795
- onCaughtError: prodOnCaughtError,
817
+ onCaughtError: createProdOnCaughtError(onUncaughtError),
818
+ onRecoverableError: prodOnRecoverableError,
796
819
  onUncaughtError
797
820
  });
798
- window.__VINEXT_RSC_ROOT__ = hydrateRootInTransition({
799
- children: createElement(BrowserRoot, {
800
- initialElements: root,
801
- initialNavigationSnapshot
802
- }),
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,
803
836
  container: document,
804
837
  hydrateRoot,
805
838
  options: hydrateRootOptions,
806
839
  startTransition
807
840
  });
841
+ markInitialAppRouterBootstrapHydrated();
808
842
  registerNavigationRuntimeFunctions({
809
843
  clearNavigationCaches: clearClientNavigationCaches,
810
844
  commitHashNavigation: (href, historyUpdateMode, scroll) => historyController.commitHashOnlyNavigation(href, historyUpdateMode, scroll),
@@ -820,7 +854,9 @@ function bootstrapHydration(rscStream) {
820
854
  const activeTraversalIntent = navigationKind === "traverse" ? traversalIntent ?? historyController.resolveTraversalIntent(window.history.state) : null;
821
855
  const performHardNavigationForScrollIntent = (targetHref) => {
822
856
  consumeAppRouterScrollIntent(scrollIntent ?? null);
823
- return browserNavigationController.performHardNavigation(targetHref);
857
+ const didNavigate = browserNavigationController.performHardNavigation(targetHref);
858
+ if (!didNavigate) clearAppNavigationFailureTarget(targetHref);
859
+ return didNavigate;
824
860
  };
825
861
  let restoredBfcacheIds = navigationKind === "traverse" ? historyController.readCurrentBfcacheVersionHistoryIds(activeTraversalIntent?.historyState ?? window.history.state) : null;
826
862
  const reuseCurrentBfcacheIds = navigationKind !== "traverse" || !historyController.isCacheInvalidationGuarded() && historyController.isCurrentBfcacheVersion(activeTraversalIntent?.historyState ?? window.history.state);
@@ -856,8 +892,35 @@ function bootstrapHydration(rscStream) {
856
892
  renderMode: navigationKind === "refresh" ? APP_RSC_RENDER_MODE_REFRESH_PRESERVE_UI : void 0
857
893
  });
858
894
  const rscUrl = await createRscRequestUrl(url.pathname + url.search, requestHeaders);
859
- const cachedRoute = shouldBypassNavigationCache ? null : getVisitedResponse(rscUrl, requestInterceptionContext, mountedSlotsHeader, navigationKind);
860
- if (cachedRoute) {
895
+ const visitedResponseCandidate = shouldBypassNavigationCache ? {
896
+ cacheKey: AppElementsWire.encodeCacheKey(rscUrl, requestInterceptionContext),
897
+ entry: null,
898
+ facts: {
899
+ candidate: "missing",
900
+ navigationKind
901
+ }
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) {
861
924
  const cachedFetchDecision = navigationPlanner.classifyRscFetchResult({
862
925
  clientCompatibilityId: CLIENT_RSC_COMPATIBILITY_ID,
863
926
  compatibilityIdHeader: cachedRoute.response.compatibilityIdHeader ?? null,
@@ -900,7 +963,8 @@ function bootstrapHydration(rscStream) {
900
963
  let navResponse;
901
964
  let navResponseExpiresAt;
902
965
  let navResponseUrl = null;
903
- if (navigationKind !== "refresh" && !shouldBypassNavigationCache) {
966
+ let fallbackReuseDecision = reuseDecision;
967
+ if (reuseDecision.kind === "consumePrefetch") {
904
968
  const prefetchedResponse = await consumePrefetchResponseForNavigation(rscUrl, requestInterceptionContext, mountedSlotsHeader, { shouldConsume: () => browserNavigationController.isCurrentNavigation(navId) });
905
969
  if (!browserNavigationController.isCurrentNavigation(navId)) return;
906
970
  if (prefetchedResponse) {
@@ -908,9 +972,22 @@ function bootstrapHydration(rscStream) {
908
972
  navResponseExpiresAt = prefetchedResponse.expiresAt;
909
973
  navResponseUrl = prefetchedResponse.url;
910
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
+ }
911
989
  }
912
- if (!navResponse && navigationKind === "navigate") {
913
- const routeManifest = getBrowserRouteManifest();
990
+ if (!navResponse && fallbackReuseDecision.kind === "attemptOptimisticRouteShell") {
914
991
  await learnOptimisticRouteTemplatesFromPrefetchCache({
915
992
  interceptionContext: requestInterceptionContext,
916
993
  mountedSlotsHeader,
@@ -1012,7 +1089,7 @@ function bootstrapHydration(rscStream) {
1012
1089
  } catch (error) {
1013
1090
  if (!browserNavigationController.isCurrentNavigation(navId)) return;
1014
1091
  if (!isPageUnloading) console.error("[vinext] RSC navigation error:", error);
1015
- performHardNavigationForScrollIntent(currentHref);
1092
+ performHardNavigationForScrollIntent(navigationPlanner.classifyRscNavigationError({ currentHref }).url);
1016
1093
  } finally {
1017
1094
  browserNavigationController.finalizeNavigation(navId, pendingRouterState);
1018
1095
  discardedServerActionRefreshScheduler.markNavigationSettled();
@@ -1,9 +1,13 @@
1
1
  //#region src/server/app-browser-error.d.ts
2
- declare function createOnUncaughtError(getRecoveryHref: () => string | null): (error: unknown, errorInfo: {
2
+ type VinextHydrateRootErrorInfo = {
3
3
  componentStack?: string;
4
- }) => void;
5
- declare function prodOnCaughtError(error: unknown, errorInfo: {
6
- componentStack?: string;
7
- }): void;
4
+ errorBoundary?: unknown;
5
+ };
6
+ type HydrateRootErrorHandler = (error: unknown, errorInfo: VinextHydrateRootErrorInfo) => void;
7
+ declare function createOnUncaughtError(): HydrateRootErrorHandler;
8
+ declare function createProdOnCaughtError(onImplicitRootError: HydrateRootErrorHandler): HydrateRootErrorHandler;
9
+ declare function createDevOnCaughtError(onCaughtError: HydrateRootErrorHandler, onImplicitRootError: HydrateRootErrorHandler): HydrateRootErrorHandler;
10
+ declare function prodOnCaughtError(error: unknown, errorInfo: VinextHydrateRootErrorInfo): void;
11
+ declare function prodOnRecoverableError(error: unknown): void;
8
12
  //#endregion
9
- export { createOnUncaughtError, prodOnCaughtError };
13
+ export { createDevOnCaughtError, createOnUncaughtError, createProdOnCaughtError, prodOnCaughtError, prodOnRecoverableError };
@@ -1,17 +1,52 @@
1
+ import { isUnknownRecord } from "../utils/record.js";
1
2
  import { isNavigationSignalError } from "../utils/navigation-signal.js";
2
3
  //#region src/server/app-browser-error.ts
3
- function createOnUncaughtError(getRecoveryHref) {
4
+ function isImplicitRootErrorBoundary(errorInfo) {
5
+ if (!isUnknownRecord(errorInfo.errorBoundary)) return false;
6
+ const props = errorInfo.errorBoundary.props;
7
+ return isUnknownRecord(props) && props.isImplicitRootErrorBoundary === true;
8
+ }
9
+ function logCaughtError(error, errorInfo) {
10
+ console.error(error);
11
+ if (errorInfo?.componentStack) console.error("The above error occurred in a React component:\n" + errorInfo.componentStack);
12
+ }
13
+ function reportGlobalError(error) {
14
+ if (typeof globalThis.reportError === "function") {
15
+ globalThis.reportError(error);
16
+ return;
17
+ }
18
+ console.error(error);
19
+ }
20
+ function createOnUncaughtError() {
21
+ return (error) => {
22
+ reportGlobalError(error);
23
+ };
24
+ }
25
+ function createProdOnCaughtError(onImplicitRootError) {
26
+ return (error, errorInfo) => {
27
+ if (isNavigationSignalError(error)) return;
28
+ if (isImplicitRootErrorBoundary(errorInfo)) {
29
+ onImplicitRootError(error, errorInfo);
30
+ return;
31
+ }
32
+ logCaughtError(error, errorInfo);
33
+ };
34
+ }
35
+ function createDevOnCaughtError(onCaughtError, onImplicitRootError) {
4
36
  return (error, errorInfo) => {
5
- console.error(error);
6
- if (errorInfo?.componentStack) console.error("The above error occurred in a React component:\n" + errorInfo.componentStack);
7
- const recoveryHref = getRecoveryHref();
8
- if (recoveryHref !== null) window.location.assign(recoveryHref);
37
+ if (isImplicitRootErrorBoundary(errorInfo)) {
38
+ onImplicitRootError(error, errorInfo);
39
+ return;
40
+ }
41
+ onCaughtError(error, errorInfo);
9
42
  };
10
43
  }
11
44
  function prodOnCaughtError(error, errorInfo) {
12
45
  if (isNavigationSignalError(error)) return;
13
- console.error(error);
14
- if (errorInfo?.componentStack) console.error("The above error occurred in a React component:\n" + errorInfo.componentStack);
46
+ logCaughtError(error, errorInfo);
47
+ }
48
+ function prodOnRecoverableError(error) {
49
+ reportGlobalError(error instanceof Error && error.cause !== void 0 ? error.cause : error);
15
50
  }
16
51
  //#endregion
17
- export { createOnUncaughtError, prodOnCaughtError };
52
+ export { createDevOnCaughtError, createOnUncaughtError, createProdOnCaughtError, prodOnCaughtError, prodOnRecoverableError };
@@ -8,6 +8,7 @@ type HydrateRootChildren = Parameters<HydrateRoot>[1];
8
8
  type HydrateRootReturn = ReturnType<HydrateRoot>;
9
9
  type HydrateRootCaughtErrorHandler = NonNullable<HydrateRootOptions["onCaughtError"]>;
10
10
  type HydrateRootUncaughtErrorHandler = NonNullable<HydrateRootOptions["onUncaughtError"]>;
11
+ type HydrateRootRecoverableErrorHandler = NonNullable<HydrateRootOptions["onRecoverableError"]>;
11
12
  type StartTransition = (action: () => void) => void;
12
13
  declare const RSC_FORM_STATE_GLOBAL = "__VINEXT_RSC_FORM_STATE__";
13
14
  type FormStateGlobal = {
@@ -17,6 +18,7 @@ declare function consumeInitialFormState(global: FormStateGlobal): ReactFormStat
17
18
  declare function createVinextHydrateRootOptions(options: {
18
19
  formState: ReactFormState | null;
19
20
  onCaughtError?: HydrateRootCaughtErrorHandler;
21
+ onRecoverableError?: HydrateRootRecoverableErrorHandler;
20
22
  onUncaughtError: HydrateRootUncaughtErrorHandler;
21
23
  }): HydrateRootOptions;
22
24
  declare function hydrateRootInTransition(options: {
@@ -8,6 +8,7 @@ function consumeInitialFormState(global) {
8
8
  function createVinextHydrateRootOptions(options) {
9
9
  const hydrateOptions = {
10
10
  formState: options.formState,
11
+ ...options.onRecoverableError ? { onRecoverableError: options.onRecoverableError } : {},
11
12
  onUncaughtError: options.onUncaughtError
12
13
  };
13
14
  if (options.onCaughtError) return {
@@ -1,9 +1,9 @@
1
1
  import { RouteManifest } from "../routing/app-route-graph.js";
2
2
  import { AppRouterScrollIntent } from "../shims/app-router-scroll-state.js";
3
3
  import { NavigationRuntimeVisibleCommitMode } from "../client/navigation-runtime.js";
4
- import { ServerActionRevalidationKind } from "./app-browser-action-result.js";
5
4
  import { AppElements } from "./app-elements-wire.js";
6
5
  import { OperationLane } from "./navigation-planner.js";
6
+ import { ServerActionRevalidationKind } from "./app-browser-action-result.js";
7
7
  import { ClientNavigationRenderSnapshot, commitClientNavigationState, createSnapshotPathAndSearch } from "../shims/navigation.js";
8
8
  import { AppNavigationPayloadOrigin, AppRouterState } from "./app-browser-state.js";
9
9
  import { Dispatch, ReactNode } from "react";
@@ -17,6 +17,7 @@ type PendingBrowserRouterState = {
17
17
  };
18
18
  type NavigationPayloadOutcome = "committed" | "no-commit" | "hard-navigate";
19
19
  type HardNavigationMode = "assign" | "replace";
20
+ type BrowserNavigationCommitEffect = () => void;
20
21
  type BrowserNavigationCommitEffectFactory = (options: {
21
22
  bfcacheIds: Readonly<Record<string, string>>;
22
23
  href: string;
@@ -25,7 +26,7 @@ type BrowserNavigationCommitEffectFactory = (options: {
25
26
  params: Record<string, string | string[]>;
26
27
  previousNextUrl: string | null;
27
28
  targetHistoryIndex?: number | null;
28
- }) => () => void;
29
+ }) => BrowserNavigationCommitEffect;
29
30
  type BrowserRouterStateRef = {
30
31
  current: AppRouterState;
31
32
  };
@@ -92,6 +93,7 @@ type BrowserNavigationController = {
92
93
  * navigation would otherwise be lost.
93
94
  */
94
95
  drainPrePaintEffects(renderId: number): void;
96
+ clearCommittedNavigationFailureTargets(renderId: number): void;
95
97
  NavigationCommitSignal(this: void, {
96
98
  renderId,
97
99
  children