vinext 1.4.0 → 1.4.2

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 (156) hide show
  1. package/README.md +21 -21
  2. package/dist/build/action-owner-manifest.js +1 -0
  3. package/dist/build/prerender.js +3 -2
  4. package/dist/check.js +4 -7
  5. package/dist/client/dev-error-overlay-store.d.ts +1 -0
  6. package/dist/client/dev-error-overlay.d.ts +2 -0
  7. package/dist/client/dev-error-overlay.js +19 -3
  8. package/dist/config/config-matchers.js +4 -2
  9. package/dist/config/destination-params.d.ts +2 -1
  10. package/dist/config/destination-params.js +55 -2
  11. package/dist/config/next-config.d.ts +22 -1
  12. package/dist/config/next-config.js +49 -4
  13. package/dist/entries/app-rsc-entry.js +41 -19
  14. package/dist/entries/app-rsc-manifest.js +4 -0
  15. package/dist/entries/pages-server-entry.js +5 -1
  16. package/dist/index.js +44 -32
  17. package/dist/init-cloudflare.js +18 -2
  18. package/dist/plugins/css-target.d.ts +18 -0
  19. package/dist/plugins/css-target.js +93 -0
  20. package/dist/plugins/strip-server-exports.js +2 -1
  21. package/dist/routing/app-route-graph.d.ts +10 -0
  22. package/dist/routing/app-route-graph.js +15 -1
  23. package/dist/server/api-handler.d.ts +2 -0
  24. package/dist/server/api-handler.js +5 -6
  25. package/dist/server/app-action-forwarding.js +3 -1
  26. package/dist/server/app-browser-entry.js +28 -7
  27. package/dist/server/app-browser-rsc-redirect.js +3 -3
  28. package/dist/server/app-browser-server-action-client.js +2 -2
  29. package/dist/server/app-browser-visible-commit.js +2 -2
  30. package/dist/server/app-elements.d.ts +3 -0
  31. package/dist/server/app-elements.js +14 -1
  32. package/dist/server/app-fallback-renderer.js +2 -2
  33. package/dist/server/app-optimistic-routing.d.ts +12 -1
  34. package/dist/server/app-optimistic-routing.js +40 -19
  35. package/dist/server/app-page-boundary-render.js +7 -12
  36. package/dist/server/app-page-cache-render.js +1 -1
  37. package/dist/server/app-page-dispatch.d.ts +10 -2
  38. package/dist/server/app-page-dispatch.js +73 -31
  39. package/dist/server/app-page-element-builder.d.ts +9 -20
  40. package/dist/server/app-page-element-builder.js +40 -52
  41. package/dist/server/app-page-execution.js +9 -6
  42. package/dist/server/app-page-intercept-segment-config.d.ts +56 -0
  43. package/dist/server/app-page-intercept-segment-config.js +90 -0
  44. package/dist/server/app-page-navigation-params.d.ts +23 -0
  45. package/dist/server/app-page-navigation-params.js +49 -0
  46. package/dist/server/app-page-render.d.ts +5 -3
  47. package/dist/server/app-page-render.js +31 -17
  48. package/dist/server/app-page-request.d.ts +24 -2
  49. package/dist/server/app-page-request.js +10 -10
  50. package/dist/server/app-page-response.js +1 -1
  51. package/dist/server/app-page-route-wiring.d.ts +10 -0
  52. package/dist/server/app-page-route-wiring.js +34 -13
  53. package/dist/server/app-page-segment-plan.js +9 -1
  54. package/dist/server/app-page-segment-state.d.ts +9 -0
  55. package/dist/server/app-page-segment-state.js +54 -1
  56. package/dist/server/app-page-stream.d.ts +10 -8
  57. package/dist/server/app-page-stream.js +2 -1
  58. package/dist/server/app-request-stage-independent-entry.js +1 -1
  59. package/dist/server/app-response-stage-entry.js +1 -0
  60. package/dist/server/app-route-handler-execution.js +3 -2
  61. package/dist/server/app-route-handler-runtime.d.ts +1 -1
  62. package/dist/server/app-route-handler-runtime.js +11 -7
  63. package/dist/server/app-route-module-loader.d.ts +2 -0
  64. package/dist/server/app-route-module-loader.js +1 -0
  65. package/dist/server/app-router-entry.js +1 -1
  66. package/dist/server/app-rsc-cache-busting.d.ts +10 -10
  67. package/dist/server/app-rsc-cache-busting.js +27 -68
  68. package/dist/server/app-rsc-error-handler.js +1 -1
  69. package/dist/server/app-rsc-errors.js +4 -1
  70. package/dist/server/app-rsc-handler.d.ts +10 -1
  71. package/dist/server/app-rsc-handler.js +126 -103
  72. package/dist/server/app-rsc-request-normalization.d.ts +10 -12
  73. package/dist/server/app-rsc-request-normalization.js +11 -14
  74. package/dist/server/app-rsc-response-finalizer.d.ts +3 -0
  75. package/dist/server/app-rsc-response-finalizer.js +11 -1
  76. package/dist/server/app-rsc-response-stage.js +4 -12
  77. package/dist/server/app-rsc-route-matching.d.ts +14 -0
  78. package/dist/server/app-rsc-route-matching.js +42 -18
  79. package/dist/server/app-server-action-execution.js +24 -14
  80. package/dist/server/app-ssr-entry.d.ts +6 -0
  81. package/dist/server/app-ssr-entry.js +13 -8
  82. package/dist/server/app-worker-stages.d.ts +12 -3
  83. package/dist/server/app-worker-stages.js +37 -4
  84. package/dist/server/bfcache-identity.d.ts +7 -0
  85. package/dist/server/bfcache-identity.js +10 -1
  86. package/dist/server/cache-control.d.ts +2 -0
  87. package/dist/server/cache-control.js +3 -1
  88. package/dist/server/cacheability-manifest.js +1 -2
  89. package/dist/server/dev-origin-check.d.ts +2 -1
  90. package/dist/server/dev-origin-check.js +2 -1
  91. package/dist/server/dev-server.js +2 -1
  92. package/dist/server/image-local-patterns.d.ts +21 -0
  93. package/dist/server/image-local-patterns.js +59 -0
  94. package/dist/server/image-optimization.d.ts +28 -22
  95. package/dist/server/image-optimization.js +17 -2
  96. package/dist/server/isr-cache.js +4 -1
  97. package/dist/server/metadata-route-response.js +25 -7
  98. package/dist/server/middleware-matcher.js +19 -6
  99. package/dist/server/middleware-runtime.js +6 -2
  100. package/dist/server/multi-stage.d.ts +7 -3
  101. package/dist/server/nitro-public-files-plugin.js +20 -8
  102. package/dist/server/pages-data-route.d.ts +5 -1
  103. package/dist/server/pages-data-route.js +14 -6
  104. package/dist/server/pages-node-compat.d.ts +1 -1
  105. package/dist/server/pages-node-compat.js +2 -0
  106. package/dist/server/pages-page-data.js +2 -1
  107. package/dist/server/pages-page-handler.js +17 -6
  108. package/dist/server/pages-page-response.d.ts +9 -0
  109. package/dist/server/pages-page-response.js +18 -4
  110. package/dist/server/pages-request-pipeline.js +6 -5
  111. package/dist/server/pages-request-stage-entry.js +25 -4
  112. package/dist/server/pages-router-entry.js +3 -2
  113. package/dist/server/prod-server.d.ts +2 -2
  114. package/dist/server/prod-server.js +59 -17
  115. package/dist/server/request-error-log.d.ts +9 -0
  116. package/dist/server/request-error-log.js +13 -0
  117. package/dist/server/request-pipeline.d.ts +14 -4
  118. package/dist/server/request-pipeline.js +33 -15
  119. package/dist/server/response-stage-cacheability.d.ts +7 -0
  120. package/dist/server/response-stage-cacheability.js +6 -5
  121. package/dist/server/rsc-completion-metadata.js +3 -0
  122. package/dist/server/static-file-cache.d.ts +9 -0
  123. package/dist/server/static-file-cache.js +13 -2
  124. package/dist/server/worker-image-optimization.d.ts +2 -2
  125. package/dist/server/worker-image-optimization.js +18 -3
  126. package/dist/server/worker-utils.d.ts +8 -0
  127. package/dist/server/worker-utils.js +19 -2
  128. package/dist/shims/cache-request-state.d.ts +6 -6
  129. package/dist/shims/cache-request-state.js +6 -36
  130. package/dist/shims/cache-runtime.d.ts +3 -1
  131. package/dist/shims/cache-runtime.js +77 -47
  132. package/dist/shims/cache.d.ts +10 -5
  133. package/dist/shims/cache.js +35 -22
  134. package/dist/shims/client-hook-error.d.ts +2 -0
  135. package/dist/shims/client-hook-error.js +16 -1
  136. package/dist/shims/fetch-cache.js +6 -2
  137. package/dist/shims/headers.d.ts +2 -1
  138. package/dist/shims/headers.js +5 -3
  139. package/dist/shims/image-props.d.ts +6 -0
  140. package/dist/shims/image-props.js +39 -3
  141. package/dist/shims/image.js +3 -3
  142. package/dist/shims/internal/cache-context-accessor.d.ts +1 -1
  143. package/dist/shims/link.js +5 -10
  144. package/dist/shims/navigation.js +2 -3
  145. package/dist/shims/request-state-types.d.ts +2 -1
  146. package/dist/shims/slot.d.ts +9 -2
  147. package/dist/shims/slot.js +76 -11
  148. package/dist/shims/unified-request-context.d.ts +6 -0
  149. package/dist/shims/unified-request-context.js +1 -0
  150. package/dist/utils/base-path.d.ts +7 -0
  151. package/dist/utils/base-path.js +11 -1
  152. package/dist/utils/cache-life-profiles.d.ts +33 -0
  153. package/dist/utils/cache-life-profiles.js +111 -0
  154. package/dist/utils/middleware-request-headers.d.ts +14 -3
  155. package/dist/utils/middleware-request-headers.js +54 -7
  156. package/package.json +1 -1
@@ -23,11 +23,11 @@ import { navigationPlanner } from "./navigation-planner.js";
23
23
  import { decodeRedirectError, isRedirectError } from "../shims/navigation-errors.js";
24
24
  import { beginAppRouterScrollIntent, consumeAppRouterScrollIntent } from "../shims/app-router-scroll-state.js";
25
25
  import { getBfcacheIdMapContext, getNavigationContext, setNavigationContext } from "../shims/navigation-context-state.js";
26
- import { DYNAMIC_NAVIGATION_CACHE_TTL, PREFETCH_CACHE_TTL, __basePath, appRouterInstance, commitClientNavigationState, consumePrefetchResponse, consumePrefetchResponseForNavigation, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, createSnapshotPathAndSearch, deletePrefetchResponseSnapshot, disableNavigationResponsePrefetchCacheReuse, getClientNavigationRenderContext, getMountedSlotsHeader, getPrefetchCache, hasPrefetchCacheEntryForNavigation, invalidateDynamicPrefetchCache, invalidatePrefetchCache, invalidateVisitedResponsePrefetches, parseRenderedPathAndSearchHeader, preloadHybridClientRouteOwner, pushHistoryStateWithoutNotify, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, resolveLoadedHybridClientRewriteHref, resolvePrefetchCacheEntryMountedSlotsHeader, restoreRscResponse, saveScrollPosition, seedPrefetchResponseSnapshot, setClientParams, setMountedSlotsHeader, setPendingPathname, trackAppRouterNavigationInFlight, useRouter } from "../shims/navigation.js";
26
+ import { DYNAMIC_NAVIGATION_CACHE_TTL, PREFETCH_CACHE_TTL, __basePath, activateNavigationSnapshot, appRouterInstance, commitClientNavigationState, consumePrefetchResponse, consumePrefetchResponseForNavigation, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, createSnapshotPathAndSearch, deletePrefetchResponseSnapshot, disableNavigationResponsePrefetchCacheReuse, getClientNavigationRenderContext, getMountedSlotsHeader, getPrefetchCache, hasPrefetchCacheEntryForNavigation, invalidateDynamicPrefetchCache, invalidatePrefetchCache, invalidateVisitedResponsePrefetches, parseRenderedPathAndSearchHeader, preloadHybridClientRouteOwner, pushHistoryStateWithoutNotify, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, resolveLoadedHybridClientRewriteHref, resolvePrefetchCacheEntryMountedSlotsHeader, restoreRscResponse, saveScrollPosition, seedPrefetchResponseSnapshot, setClientParams, setMountedSlotsHeader, setPendingPathname, trackAppRouterNavigationInFlight, useRouter } from "../shims/navigation.js";
27
27
  import { AppRouterScrollCommitProvider } from "../shims/app-router-scroll.js";
28
28
  import { chunksToReadableStream, createProgressiveRscStream, getVinextBrowserGlobal } from "./app-browser-stream.js";
29
29
  import { createMountedLayoutsHeader, holdsSkippedLayouts } from "./app-mounted-layouts.js";
30
- import { BfcacheIdentityMapContext, bindAppElementsRenderedSearch, setAppElementsRenderedSearch } from "../shims/slot.js";
30
+ import { BfcacheIdentityMapContext, bindAppElementsRenderedSearch, isBfcacheIdentityRetained, setAppElementsRenderedSearch } from "../shims/slot.js";
31
31
  import { COMMITTED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN, FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, VISITED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN, isCacheRestorableAppPayloadMetadata, isCompleteAppPayloadMetadata, resolveInterceptionContextFromPreviousNextUrl } from "./app-browser-state.js";
32
32
  import { clearHardNavigationLoopGuard, createAppBrowserNavigationController, createBasePathStrippedPathAndSearch, navigateDocumentDirectly } from "./app-browser-navigation-controller.js";
33
33
  import { createAppRouteTree } from "./app-route-tree.js";
@@ -45,7 +45,7 @@ import { createHydrationCachePublication } from "./app-hydration-cache-publicati
45
45
  import { peekSettledPrefetchResponseForNavigation, prepareConsumedPrefetchResponseForPublication, preserveCommittedPrefetchExpiry, resolvePrefetchNavigationResponseUrl } from "./app-browser-prefetch-response.js";
46
46
  import { canCommitOptimisticRouteTemplate, createOptimisticRouteTemplate, createOptimisticRouteTemplateStore, getOptimisticPrefetchSourceKey, getOptimisticRouteTemplateKey, keepOptimisticStreamingMetadata, resolveOptimisticNavigationParamsForHref, resolveOptimisticNavigationPayload } from "./app-optimistic-routing.js";
47
47
  import { removeStylesheetLinksCoveredByInlineCss } from "./app-inline-css-client.js";
48
- import { createElement, startTransition, use, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
48
+ import { Fragment, createElement, startTransition, use, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
49
49
  import { createRoot, hydrateRoot } from "react-dom/client";
50
50
  import { createFromFetch, createFromReadableStream, setServerCallback } from "@vitejs/plugin-rsc/browser";
51
51
  import { flushSync } from "react-dom";
@@ -195,6 +195,12 @@ const RSC_HMR_SETTLE_DELAY_MS = 150;
195
195
  const DEFAULT_GLOBAL_ERROR_COMPONENT = DefaultGlobalError;
196
196
  let latestRscHmrUpdateId = 0;
197
197
  let synchronousPopstateScrollRestoreNavigationId = null;
198
+ let pendingHistoryRestoreCommit = null;
199
+ function flushPendingHistoryRestoreCommit() {
200
+ const commit = pendingHistoryRestoreCommit;
201
+ pendingHistoryRestoreCommit = null;
202
+ commit?.();
203
+ }
198
204
  function waitForRscHmrSettle(delayMs = RSC_HMR_SETTLE_DELAY_MS) {
199
205
  return new Promise((resolve) => {
200
206
  window.setTimeout(resolve, delayMs);
@@ -212,6 +218,10 @@ function restoreHistoryStateSnapshot(historyState, navId, onApprovedBeforeCommit
212
218
  beforeCommit: () => {
213
219
  onApprovedBeforeCommit?.();
214
220
  beforeCommit();
221
+ if (!restoreCopiedExternalHistoryEntry) {
222
+ activateNavigationSnapshot();
223
+ pendingHistoryRestoreCommit = () => commitClientNavigationState(navId);
224
+ }
215
225
  },
216
226
  navId,
217
227
  state,
@@ -223,7 +233,8 @@ function restoreHistoryStateSnapshot(historyState, navId, onApprovedBeforeCommit
223
233
  clientNavigationCacheGeneration += 1;
224
234
  revokeHistoryRestoreNavigationReuse(visitedResponseCache);
225
235
  disableNavigationResponsePrefetchCacheReuse();
226
- commitClientNavigationState(navId, { releaseSnapshot: false });
236
+ if (restoreCopiedExternalHistoryEntry) commitClientNavigationState(navId, { releaseSnapshot: false });
237
+ else flushPendingHistoryRestoreCommit();
227
238
  return true;
228
239
  }
229
240
  function getBrowserRouterState() {
@@ -1000,6 +1011,10 @@ function registerServerActionCallback() {
1000
1011
  })).finally(releaseCacheInvalidationGuard);
1001
1012
  });
1002
1013
  }
1014
+ function ReplayInitialDevServerErrors({ report }) {
1015
+ useEffect(report, [report]);
1016
+ return null;
1017
+ }
1003
1018
  async function main() {
1004
1019
  if (!claimInitialAppRouterBootstrap()) return;
1005
1020
  loadNavigationRuntimeRouteManifest();
@@ -1011,7 +1026,7 @@ async function main() {
1011
1026
  devErrorOverlay = await import("../client/dev-error-overlay.js");
1012
1027
  devErrorOverlay.installDevErrorOverlay();
1013
1028
  devErrorOverlay.installViteHmrErrorHandler(import.meta.hot);
1014
- devErrorOverlay.reportInitialDevServerErrors();
1029
+ if (document.documentElement.id !== "__next_error__") devErrorOverlay.reportInitialDevServerErrors();
1015
1030
  }
1016
1031
  const initialRscBootstrap = getNavigationRuntime()?.bootstrap.rsc;
1017
1032
  const rscStream = await readInitialRscStream();
@@ -1098,7 +1113,7 @@ function bootstrapHydration(rscStream, devErrorOverlay, initialRscBootstrap) {
1098
1113
  for (const style of errorShellStyles) style.remove();
1099
1114
  startTransition(() => {
1100
1115
  const clientRoot = createRoot(document, createRootOptions);
1101
- clientRoot.render(children);
1116
+ clientRoot.render(import.meta.env.DEV && devErrorOverlay ? createElement(Fragment, null, children, createElement(ReplayInitialDevServerErrors, { report: devErrorOverlay.reportInitialDevServerErrors })) : children);
1102
1117
  window.__VINEXT_RSC_ROOT__ = clientRoot;
1103
1118
  });
1104
1119
  } else window.__VINEXT_RSC_ROOT__ = hydrateRootInTransition({
@@ -1389,7 +1404,10 @@ function bootstrapHydration(rscStream, devErrorOverlay, initialRscBootstrap) {
1389
1404
  currentElements: navigationInitiationState.elements,
1390
1405
  currentLayoutIds: navigationInitiationState.layoutIds,
1391
1406
  currentParams: navigationInitiationState.navigationSnapshot.params,
1407
+ isBfcacheIdentityRetained,
1392
1408
  routeManifest,
1409
+ shownElements: getBrowserRouterState().elements,
1410
+ targetElements: optimisticPayload.elements,
1393
1411
  targetRouteParams: optimisticPayload.routeParams,
1394
1412
  targetUrlParts: optimisticPayload.urlParts,
1395
1413
  template: optimisticPayload.template
@@ -1631,7 +1649,10 @@ function bootstrapHydration(rscStream, devErrorOverlay, initialRscBootstrap) {
1631
1649
  discardPendingNavigation: () => {
1632
1650
  if (browserNavigationController.discardPendingNavigation(historyController.readCurrentTreeSnapshot())) navigationAbortCoordinator.abortActive();
1633
1651
  },
1634
- flushCommittingNavigationUrl: () => browserNavigationController.flushCommittingNavigationUrl()
1652
+ flushCommittingNavigationUrl: () => {
1653
+ flushPendingHistoryRestoreCommit();
1654
+ browserNavigationController.flushCommittingNavigationUrl();
1655
+ }
1635
1656
  });
1636
1657
  const handlePopstate = createPopstateRestoreHandler({
1637
1658
  getActiveNavigationId: browserNavigationController.getActiveNavigationId.bind(browserNavigationController),
@@ -1,5 +1,5 @@
1
1
  import { isDangerousScheme, reportBlockedDangerousNavigation } from "../shims/url-safety.js";
2
- import { resolveHardNavigationTargetFromRscResponse, stripRscCacheBustingSearchParam, stripRscSuffix } from "./app-rsc-cache-busting.js";
2
+ import { resolveHardNavigationTargetFromRscResponse, stripRscCacheBustingSearchParam, toPathAbsolutePathname } from "./app-rsc-cache-busting.js";
3
3
  //#region src/server/app-browser-rsc-redirect.ts
4
4
  const MAX_RSC_REDIRECT_DEPTH = 10;
5
5
  function blockDangerousStreamedRscRedirect(response, streamedRedirectTarget) {
@@ -11,10 +11,10 @@ function blockDangerousStreamedRscRedirect(response, streamedRedirectTarget) {
11
11
  function toVisibleAppHref(href, origin) {
12
12
  const url = new URL(href, origin);
13
13
  stripRscCacheBustingSearchParam(url);
14
- return `${stripRscSuffix(url.pathname)}${url.search}${url.hash}`;
14
+ return `${toPathAbsolutePathname(url.pathname)}${url.search}${url.hash}`;
15
15
  }
16
16
  function toStreamedRedirectVisibleAppHref(url) {
17
- return `${url.pathname}${url.search}${url.hash}`;
17
+ return `${toPathAbsolutePathname(url.pathname)}${url.search}${url.hash}`;
18
18
  }
19
19
  function resolveRedirectLifecycleHopFromTarget(options) {
20
20
  if (options.targetUrl.origin !== options.origin) return {
@@ -1,7 +1,7 @@
1
1
  import { hasBasePath } from "../utils/base-path.js";
2
2
  import { ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER } from "./headers.js";
3
3
  import { DANGEROUS_URL_BLOCK_MESSAGE, isDangerousScheme } from "../shims/url-safety.js";
4
- import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, createServerActionRequestUrl } from "./app-rsc-cache-busting.js";
4
+ import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, createServerActionRequestUrl, toPathAbsolutePathname } from "./app-rsc-cache-busting.js";
5
5
  import { throwOnServerActionNotFound } from "./server-action-not-found.js";
6
6
  import { AppElementsWire } from "./app-elements-wire.js";
7
7
  import "./app-elements.js";
@@ -49,7 +49,7 @@ var ServerActionRedirectError = class extends Error {
49
49
  constructor(target) {
50
50
  super("NEXT_REDIRECT");
51
51
  const redirectUrl = new URL(target.href, window.location.href);
52
- const redirectHref = redirectUrl.pathname + redirectUrl.search + redirectUrl.hash;
52
+ const redirectHref = toPathAbsolutePathname(redirectUrl.pathname) + redirectUrl.search + redirectUrl.hash;
53
53
  const redirectType = target.type === "push" ? "push" : "replace";
54
54
  this.digest = `NEXT_REDIRECT;${redirectType};${redirectHref};${target.status};`;
55
55
  }
@@ -87,11 +87,11 @@ function reduceApprovedVisibleCommitState(state, commit) {
87
87
  const hmrUniquePreserveElementIds = hmrPreserveElementIds.length > 1 ? [...new Set(hmrPreserveElementIds)] : hmrPreserveElementIds;
88
88
  const preserveElementIds = action.operation.lane === "hmr" ? hmrUniquePreserveElementIds : bfcacheCompatiblePreserveElementIds;
89
89
  const preserveTemplateIds = action.reuseCurrentBfcacheIds && (action.operation.lane === "navigation" || action.operation.lane === "traverse" || action.operation.lane === "server-action") ? Object.keys(state.elements).filter((id) => Object.hasOwn(action.elements, id) && hasSameServerTemplateSeedIdentity(id, state.navigationSnapshot, action.navigationSnapshot)) : [];
90
- const mergedPreserveElementIds = preserveTemplateIds.length === 0 ? preserveElementIds : [.../* @__PURE__ */ new Set([...preserveElementIds, ...preserveTemplateIds])];
91
90
  const mergedElements = mergeElements(state.elements, action.elements, {
92
91
  clearAbsentSlots: action.type === "traverse" || !action.reuseCurrentBfcacheIds,
93
92
  preserveAbsentSlots: action.reuseCurrentBfcacheIds && commit.decision.preserveAbsentSlots,
94
- preserveElementIds: mergedPreserveElementIds,
93
+ preserveElementIds,
94
+ preserveElementSeedIds: preserveTemplateIds,
95
95
  preservePreviousSlotIds: effectivePreservePreviousSlotIds
96
96
  });
97
97
  return commitVisibleRouterState(state, {
@@ -1,6 +1,9 @@
1
1
  import { APP_ARTIFACT_COMPATIBILITY_KEY, APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_IDS_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_SEGMENTS_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementValue, AppElements, AppElementsBfcacheSegmentIdentities, AppElementsInterception, AppElementsSlotBinding, AppElementsWire, AppOutgoingElements, AppWireElements, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata } from "./app-elements-wire.js";
2
2
  //#region src/server/app-elements.d.ts
3
3
  export declare const APP_PREFETCH_LOADING_SHELL_MARKER_KEY = "__prefetchLoadingShell";
4
+ type AppElementsStateKeyRebinder = (stateKey: string) => string;
5
+ export declare function setOptimisticStateKeyRebinder(elements: Record<string, unknown>, rebind: AppElementsStateKeyRebinder): void;
6
+ export declare function readOptimisticStateKeyRebinder(elements: AppElements): AppElementsStateKeyRebinder | null;
4
7
  /** Prefix of the element that streams a route's generateMetadata() tags in the body. */
5
8
  export declare const APP_STREAMING_METADATA_BODY_ID_PREFIX = "__vinext_streaming_metadata_body:";
6
9
  export declare function getMountedSlotIds(elements: AppElements): string[];
@@ -2,6 +2,19 @@ import { normalizeMountedSlotsHeader } from "./app-mounted-slots-header.js";
2
2
  import { APP_ARTIFACT_COMPATIBILITY_KEY, APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_IDS_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_SEGMENTS_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata } from "./app-elements-wire.js";
3
3
  //#region src/server/app-elements.ts
4
4
  const APP_PREFETCH_LOADING_SHELL_MARKER_KEY = "__prefetchLoadingShell";
5
+ /**
6
+ * An optimistic shell's rebinder from the learned URL's segment state keys to
7
+ * the target's. Only the browser sets it, on the elements it builds a shell
8
+ * from, so it never reaches the wire.
9
+ */
10
+ const APP_OPTIMISTIC_STATE_KEY_REBINDER_KEY = "__optimisticStateKeyRebinder";
11
+ function setOptimisticStateKeyRebinder(elements, rebind) {
12
+ elements[APP_OPTIMISTIC_STATE_KEY_REBINDER_KEY] = rebind;
13
+ }
14
+ function readOptimisticStateKeyRebinder(elements) {
15
+ const rebind = Reflect.get(elements, APP_OPTIMISTIC_STATE_KEY_REBINDER_KEY);
16
+ return typeof rebind === "function" ? rebind : null;
17
+ }
5
18
  /** Prefix of the element that streams a route's generateMetadata() tags in the body. */
6
19
  const APP_STREAMING_METADATA_BODY_ID_PREFIX = "__vinext_streaming_metadata_body:";
7
20
  function getMountedSlotIds(elements) {
@@ -18,4 +31,4 @@ function resolveVisitedResponseInterceptionContext(requestInterceptionContext, p
18
31
  return payloadInterceptionContext ?? requestInterceptionContext;
19
32
  }
20
33
  //#endregion
21
- export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_IDS_KEY, APP_PREFETCH_LOADING_SHELL_MARKER_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_SEGMENTS_KEY, APP_STATIC_SIBLINGS_KEY, APP_STREAMING_METADATA_BODY_ID_PREFIX, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, getMountedSlotIds, getMountedSlotIdsHeader, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, resolveVisitedResponseInterceptionContext };
34
+ export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_IDS_KEY, APP_PREFETCH_LOADING_SHELL_MARKER_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_SEGMENTS_KEY, APP_STATIC_SIBLINGS_KEY, APP_STREAMING_METADATA_BODY_ID_PREFIX, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, getMountedSlotIds, getMountedSlotIdsHeader, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, readOptimisticStateKeyRebinder, resolveVisitedResponseInterceptionContext, setOptimisticStateKeyRebinder };
@@ -1,10 +1,10 @@
1
1
  import { runOutsideRequestScopes } from "../shims/internal/als-registry.js";
2
2
  import { shareIsolatePromise } from "./isolate-shared-promise.js";
3
- import { DEFAULT_GLOBAL_ERROR_MODULE } from "./default-global-error-module.js";
4
- import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
5
3
  import { renderAppPageErrorBoundary, renderAppPageHttpAccessFallback } from "./app-page-boundary-render.js";
4
+ import { DEFAULT_GLOBAL_ERROR_MODULE } from "./default-global-error-module.js";
6
5
  import { DEFAULT_GLOBAL_NOT_FOUND_MODULE } from "./default-global-not-found-module.js";
7
6
  import { DEFAULT_NOT_FOUND_MODULE } from "./default-http-access-fallback-modules.js";
7
+ import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
8
8
  //#region src/server/app-fallback-renderer.ts
9
9
  const EMPTY_MW_CTX = {
10
10
  headers: null,
@@ -10,6 +10,8 @@ export type OptimisticRouteTemplate = {
10
10
  omittedBfcacheSegmentIds: readonly string[];
11
11
  omittedLayoutIds: readonly string[];
12
12
  pageElementIds: readonly string[];
13
+ /** The navigation params of the URL the template was learned from. */
14
+ params: Readonly<Record<string, string | string[]>>;
13
15
  routeId: string;
14
16
  };
15
17
  type OptimisticNavigationPayload = {
@@ -48,7 +50,7 @@ export declare function createOptimisticRouteTemplate(options: {
48
50
  mountedSlotsHeader: string | null;
49
51
  routeManifest: BrowserRouteManifest;
50
52
  }): OptimisticRouteTemplate | null;
51
- export declare function createOptimisticRouteElements(template: OptimisticRouteTemplate): AppElements;
53
+ export declare function createOptimisticRouteElements(template: OptimisticRouteTemplate, params?: Readonly<Record<string, string | string[]>>): AppElements;
52
54
  /**
53
55
  * The optimistic shell reveals the prefetch's streamed metadata, such as its
54
56
  * title. React won't hide revealed content again in a transition, so while the
@@ -77,7 +79,16 @@ export declare function canCommitOptimisticRouteTemplate(options: {
77
79
  currentElements: AppElements;
78
80
  currentLayoutIds: readonly string[];
79
81
  currentParams: Readonly<Record<string, string | string[]>>;
82
+ /** Whether a hidden BFCache entry retains a segment identity. */
83
+ isBfcacheIdentityRetained?: (identity: string) => boolean;
80
84
  routeManifest: BrowserRouteManifest;
85
+ /**
86
+ * The elements on screen, when a shell earlier in this navigation replaced
87
+ * the current ones. Defaults to `currentElements`.
88
+ */
89
+ shownElements?: AppElements;
90
+ /** The shell's elements for the target. */
91
+ targetElements?: AppElements;
81
92
  targetRouteParams: Readonly<Record<string, string | string[]>>;
82
93
  targetUrlParts: readonly string[];
83
94
  template: OptimisticRouteTemplate;
@@ -3,11 +3,11 @@ import { stripBasePath } from "../utils/base-path.js";
3
3
  import { decodeMatchedParams, splitPathnameForRouteMatch } from "../routing/utils.js";
4
4
  import { extractRawRoutePatternParams, matchRoutePattern } from "../routing/route-pattern.js";
5
5
  import { buildOptimisticRouteTrie, matchOptimisticRouteTrie } from "../routing/optimistic-route-trie.js";
6
- import { stripRscCacheBustingSearchParam, stripRscSuffix } from "./app-rsc-cache-busting.js";
7
- import { AppElementsWire } from "./app-elements-wire.js";
8
- import "./app-elements.js";
6
+ import { stripRscCacheBustingSearchParam } from "./app-rsc-cache-busting.js";
7
+ import { APP_BFCACHE_SEGMENT_IDENTITIES_KEY, AppElementsWire } from "./app-elements-wire.js";
8
+ import { setOptimisticStateKeyRebinder } from "./app-elements.js";
9
9
  import { createNestedBfcacheSlotSegmentId, deriveBfcacheSegmentIdentity, isNestedBfcacheSlotSegmentId } from "./bfcache-identity.js";
10
- import { canonicalizeAppPageParams, resolveAppPagePatternStateKey, resolveAppPageSemanticSegmentStateKey } from "./app-page-segment-state.js";
10
+ import { APP_PAGE_DEFAULT_SEGMENT_KEY, APP_PAGE_SEGMENT_KEY, canonicalizeAppPageParams, createAppPageSegmentStateKeyRebinder, resolveAppPagePatternStateKey, resolveAppPageSemanticSegmentStateKey } from "./app-page-segment-state.js";
11
11
  import { Suspense, createElement, isValidElement } from "react";
12
12
  //#region src/server/app-optimistic-routing.ts
13
13
  const routeTrieCache = /* @__PURE__ */ new WeakMap();
@@ -36,8 +36,7 @@ function hrefToRouteParts(href, basePath) {
36
36
  return null;
37
37
  }
38
38
  stripRscCacheBustingSearchParam(url);
39
- const withoutRscSuffix = stripRscSuffix(url.pathname);
40
- const appPathname = stripBasePath(withoutRscSuffix, basePath);
39
+ const appPathname = stripBasePath(url.pathname, basePath);
41
40
  const pathname = appPathname === "" ? "/" : appPathname;
42
41
  return {
43
42
  normalized: splitPathnameForRouteMatch(pathname),
@@ -115,6 +114,18 @@ function resolveTargetBfcacheSegmentIdentity(options) {
115
114
  const segmentParams = binding.state === "active" && binding.slotPatternParts !== void 0 && binding.slotPatternParts.length > 0 && !binding.slotParamNames?.every((name) => routeParamNames.has(name)) ? matchRoutePattern(options.targetUrlParts, binding.slotPatternParts) ?? options.targetRouteParams : options.targetRouteParams;
116
115
  const ownerLayout = binding.ownerLayoutId ? options.routeManifest.segmentGraph.layouts.get(binding.ownerLayoutId) : void 0;
117
116
  const ownerStateKey = ownerLayout ? resolveAppPagePatternStateKey(ownerLayout.patternParts, options.targetRouteParams) : "";
117
+ const deriveLevelIdentity = (segmentKeys) => {
118
+ const identityKey = JSON.stringify(segmentKeys);
119
+ return deriveBfcacheSegmentIdentity({
120
+ activeRouteGraphId: null,
121
+ boundSegmentKey: ownerStateKey ? JSON.stringify([ownerStateKey, identityKey]) : identityKey,
122
+ interceptionTargetRouteGraphId: null,
123
+ kind: "slot",
124
+ ownerLayoutGraphId: binding.ownerLayoutId,
125
+ slotGraphId: binding.slotId,
126
+ state: binding.state
127
+ });
128
+ };
118
129
  const boundSegmentKeys = [];
119
130
  let level = 0;
120
131
  for (const segment of binding.routeSegments ?? []) {
@@ -126,17 +137,9 @@ function resolveTargetBfcacheSegmentIdentity(options) {
126
137
  segment
127
138
  }, segmentParams));
128
139
  if (createNestedBfcacheSlotSegmentId(binding.slotId, level) !== options.segmentId) continue;
129
- const identityKey = JSON.stringify(boundSegmentKeys);
130
- return deriveBfcacheSegmentIdentity({
131
- activeRouteGraphId: null,
132
- boundSegmentKey: ownerStateKey ? JSON.stringify([ownerStateKey, identityKey]) : identityKey,
133
- interceptionTargetRouteGraphId: null,
134
- kind: "slot",
135
- ownerLayoutGraphId: binding.ownerLayoutId,
136
- slotGraphId: binding.slotId,
137
- state: binding.state
138
- });
140
+ return deriveLevelIdentity(boundSegmentKeys);
139
141
  }
142
+ if (level > 0 && createNestedBfcacheSlotSegmentId(binding.slotId, level + 1) === options.segmentId) return deriveLevelIdentity([...boundSegmentKeys, binding.state === "default" ? APP_PAGE_DEFAULT_SEGMENT_KEY : APP_PAGE_SEGMENT_KEY]);
140
143
  if (level === 0 && createNestedBfcacheSlotSegmentId(binding.slotId, 1) === options.segmentId) return deriveBfcacheSegmentIdentity({
141
144
  activeRouteGraphId: null,
142
145
  boundSegmentKey: ownerStateKey ? JSON.stringify([ownerStateKey, ""]) : "",
@@ -189,18 +192,31 @@ function createOptimisticRouteTemplate(options) {
189
192
  if (options.allowLoadingShell && (routeElement === void 0 || routeElement === null)) return null;
190
193
  const pageElementIds = getPageElementIds(options.elements, match.route);
191
194
  if (pageElementIds.length === 0) return null;
195
+ const urlParts = hrefToRouteParts(options.href, options.basePath);
196
+ if (urlParts === null) return null;
192
197
  return {
193
198
  elements: options.elements,
194
199
  mountedSlotsHeader: options.mountedSlotsHeader,
195
200
  omittedBfcacheSegmentIds: options.elements["__prefetchLoadingShell"] === "LoadingBoundary" ? getOmittedBfcacheSegmentIds(options.elements) : [],
196
201
  omittedLayoutIds: options.elements["__prefetchLoadingShell"] === "LoadingBoundary" ? metadata.layoutIds.filter((layoutId) => !Object.hasOwn(options.elements, layoutId)) : [],
197
202
  pageElementIds,
203
+ params: resolveOptimisticNavigationParams({
204
+ match,
205
+ rawUrlParts: urlParts.raw,
206
+ routeManifest: options.routeManifest,
207
+ urlParts: urlParts.normalized
208
+ }).navigationParams,
198
209
  routeId: match.route.id
199
210
  };
200
211
  }
201
- function createOptimisticRouteElements(template) {
212
+ function createOptimisticRouteElements(template, params = template.params) {
202
213
  const elements = { ...template.elements };
203
214
  for (const pageElementId of template.pageElementIds) elements[pageElementId] = createElement(OptimisticRouteSegment);
215
+ const reify = createAppPageSegmentStateKeyRebinder(template.params, params);
216
+ if (reify === null) return elements;
217
+ setOptimisticStateKeyRebinder(elements, reify);
218
+ const identities = AppElementsWire.readMetadata(template.elements).bfcacheSegmentIdentities;
219
+ if (Object.keys(identities).length > 0) elements[APP_BFCACHE_SEGMENT_IDENTITIES_KEY] = Object.fromEntries(Object.entries(identities).map(([id, identity]) => [id, reify(identity)]));
204
220
  return elements;
205
221
  }
206
222
  function findStreamingMetadataBody(elements) {
@@ -245,9 +261,14 @@ function keepOptimisticStreamingMetadata(elements, optimisticElements, navigatio
245
261
  * loading boundary does not re-trigger.
246
262
  */
247
263
  function canCommitOptimisticRouteTemplate(options) {
264
+ const currentIdentities = AppElementsWire.readMetadata(options.currentElements).bfcacheSegmentIdentities;
265
+ const { isBfcacheIdentityRetained, targetElements } = options;
266
+ if (isBfcacheIdentityRetained && targetElements) {
267
+ const shownIdentities = new Set(Object.values(options.shownElements ? AppElementsWire.readMetadata(options.shownElements).bfcacheSegmentIdentities : currentIdentities));
268
+ for (const identity of Object.values(AppElementsWire.readMetadata(targetElements).bfcacheSegmentIdentities)) if (!shownIdentities.has(identity) && isBfcacheIdentityRetained(identity)) return false;
269
+ }
248
270
  if (options.template.omittedLayoutIds.length === 0 && options.template.omittedBfcacheSegmentIds.length === 0) return true;
249
271
  const currentLayoutIds = new Set(options.currentLayoutIds);
250
- const currentIdentities = AppElementsWire.readMetadata(options.currentElements).bfcacheSegmentIdentities;
251
272
  for (const layoutId of options.template.omittedLayoutIds) {
252
273
  if (!currentLayoutIds.has(layoutId)) continue;
253
274
  if (!Object.hasOwn(options.currentElements, layoutId)) continue;
@@ -303,7 +324,7 @@ function resolveOptimisticNavigationPayload(options) {
303
324
  urlParts: urlParts.normalized
304
325
  });
305
326
  return {
306
- elements: createOptimisticRouteElements(template),
327
+ elements: createOptimisticRouteElements(template, navigationParams),
307
328
  params: navigationParams,
308
329
  routeParams,
309
330
  template,
@@ -3,13 +3,12 @@ import { isNavigationSignalError } from "../utils/navigation-signal.js";
3
3
  import { NEVER_CACHE_CONTROL, applyCdnResponseHeaders } from "./cache-control.js";
4
4
  import { isRenderDynamicLatched, isStaticGenerationAccessError } from "../shims/internal/headers-state.js";
5
5
  import { copyLinkHeaderProvenance } from "./app-response-header-provenance.js";
6
- import { stripRscSuffix } from "./app-rsc-cache-busting.js";
7
6
  import { createArtifactCompatibilityEnvelope } from "./artifact-compatibility.js";
8
7
  import { AppElementsWire } from "./app-elements-wire.js";
9
8
  import "./app-elements.js";
10
9
  import DefaultGlobalError from "../shims/default-global-error.js";
11
10
  import { ErrorBoundary, GlobalErrorBoundary, SerializedErrorBoundary } from "../shims/error-boundary.js";
12
- import { buildClientHookErrorMessage } from "../shims/client-hook-error.js";
11
+ import { rewriteClientHookError } from "../shims/client-hook-error.js";
13
12
  import { LayoutSegmentProvider } from "../shims/layout-segment-context.js";
14
13
  import { withUseCacheLayoutMarker } from "../shims/internal/app-page-props-cache-key.js";
15
14
  import { MetadataHead, ViewportHead } from "../shims/metadata.js";
@@ -21,9 +20,9 @@ import { hasAppPageDynamicMetadata, prepareAppPageHead, resolveActiveParallelRou
21
20
  import { renderAppPageBoundaryResponse, resolveAppPageErrorBoundary, resolveAppPageHttpAccessBoundaryModule, wrapAppPageBoundaryElement } from "./app-page-boundary.js";
22
21
  import { createRouteNotFoundHeadPlanOptions, recoverAppPageRouteHead, resolveHttpAccessFallbackMetadata, resolveHttpAccessFallbackViewport } from "./app-page-http-access-fallback-metadata.js";
23
22
  import "./app-rsc-route-matching.js";
24
- import { createAppPageLayoutEntries, createAppPageRouteBodyMetadata, createAppPageSourcePage } from "./app-page-route-wiring.js";
25
- import { resolveSlotParamOverrides } from "./app-page-element-builder.js";
23
+ import { resolveSlotParamOverrides } from "./app-page-navigation-params.js";
26
24
  import { createAppPageFontData, createAppPageRscErrorTracker, createAppPageSsrErrorHandler, renderAppPageHtmlResponse } from "./app-page-stream.js";
25
+ import { createAppPageLayoutEntries, createAppPageRouteBodyMetadata, createAppPageSourcePage } from "./app-page-route-wiring.js";
27
26
  import { Fragment, Suspense, createElement } from "react";
28
27
  //#region src/server/app-page-boundary-render.ts
29
28
  async function AppPageBoundaryStreamedMetadata(props) {
@@ -258,7 +257,7 @@ async function renderAppPageHttpAccessFallback(options) {
258
257
  if (!boundaryComponent) return null;
259
258
  const layoutModules = options.layoutModules ?? options.route?.layouts ?? options.rootLayouts;
260
259
  const pathname = new URL(options.requestUrl).pathname;
261
- const routePathname = options.routePathname ?? stripRscSuffix(stripBasePath(pathname, options.basePath ?? ""));
260
+ const routePathname = options.routePathname ?? stripBasePath(pathname, options.basePath ?? "");
262
261
  const headBoundaryModule = options.headBoundaryModule ?? boundaryModule;
263
262
  const headLayoutModules = options.headLayoutModules ?? layoutModules;
264
263
  const routeSegments = resolveHttpAccessFallbackHeadRouteSegments(options.route, headLayoutModules);
@@ -612,6 +611,7 @@ async function renderAppPageErrorBoundary(options) {
612
611
  skipLayoutWrapping: errorBoundary.isGlobalError
613
612
  });
614
613
  };
614
+ const isErrorStatus = errorBoundary.isGlobalError || !options.isRscRequest;
615
615
  const renderWith = async (BoundaryComponent) => {
616
616
  const response = await renderAppPageBoundaryElementResponse({
617
617
  ...options,
@@ -621,9 +621,9 @@ async function renderAppPageErrorBoundary(options) {
621
621
  navigationParams: matchedParams,
622
622
  route: options.route,
623
623
  routePattern: options.route?.pattern,
624
- status: errorBoundary.isGlobalError ? 500 : 200
624
+ status: isErrorStatus ? 500 : 200
625
625
  });
626
- if (errorBoundary.isGlobalError) applyCdnResponseHeaders(response.headers, { cacheControl: NEVER_CACHE_CONTROL });
626
+ if (isErrorStatus) applyCdnResponseHeaders(response.headers, { cacheControl: NEVER_CACHE_CONTROL });
627
627
  return response;
628
628
  };
629
629
  try {
@@ -636,10 +636,5 @@ async function renderAppPageErrorBoundary(options) {
636
636
  throw renderError;
637
637
  }
638
638
  }
639
- const _clientHookPattern = /\b(useState|useEffect|useReducer|useRef|useContext|useLayoutEffect|useInsertionEffect|useSyncExternalStore|useTransition|useImperativeHandle|useDeferredValue|useActionState|useOptimistic|useEffectEvent)\b.*is not a function/;
640
- function rewriteClientHookError(error) {
641
- const match = error.message.match(_clientHookPattern);
642
- if (match) error.message = buildClientHookErrorMessage(`${match[1]}()`);
643
- }
644
639
  //#endregion
645
640
  export { renderAppPageErrorBoundary, renderAppPageHttpAccessFallback };
@@ -4,8 +4,8 @@ import { _consumeRequestScopedCacheLife } from "../shims/cache-request-state.js"
4
4
  import { getCollectedFetchTags } from "../shims/fetch-cache.js";
5
5
  import { readStreamAsText } from "../utils/text-stream.js";
6
6
  import { buildAppPageFontLinkHeader, teeAppPageRscStreamForCapture } from "./app-page-execution.js";
7
- import { recordAppPageRenderError, traceAppPageRender } from "./app-page-tracing.js";
8
7
  import { buildAppPageLinkHeader, createAppPageSsrErrorHandler, isAppSsrRenderResult } from "./app-page-stream.js";
8
+ import { recordAppPageRenderError, traceAppPageRender } from "./app-page-tracing.js";
9
9
  import { consumeAppPageRenderObservationState, createAppPageHtmlOutputScope, createAppPageRenderObservation, createAppPageRscOutputScope } from "./app-page-render-observation.js";
10
10
  import { buildAppPageTags } from "./implicit-tags.js";
11
11
  //#region src/server/app-page-cache-render.ts
@@ -15,7 +15,7 @@ import { FetchCacheMode } from "../shims/fetch-cache-state.js";
15
15
  import "../shims/fetch-cache.js";
16
16
  import { AppPagePprFallbackCacheShell } from "./app-ppr-fallback-shell.js";
17
17
  import { WarmPprFallbackShellCachesOptions } from "./app-ppr-fallback-shell-render.js";
18
- import { ValidateAppPageDynamicParamsOptions } from "./app-page-request.js";
18
+ import { AppPageInterceptState, ValidateAppPageDynamicParamsOptions } from "./app-page-request.js";
19
19
  import { ReactNode } from "react";
20
20
  import { ReactFormState } from "react-dom/client";
21
21
  //#region src/server/app-page-dispatch.d.ts
@@ -96,10 +96,17 @@ type AppPageModule = {
96
96
  revalidate?: unknown;
97
97
  };
98
98
  type AppPageDispatchSlot = {
99
+ configLayouts?: readonly (AppPageModule | null | undefined)[] | null;
100
+ configLayoutTreePositions?: readonly number[] | null;
99
101
  default?: AppPageModule | null;
102
+ layout?: AppPageModule | null;
103
+ layoutIndex?: number;
100
104
  loading?: AppPageModule | null;
101
105
  loadings?: readonly (AppPageModule | null | undefined)[] | null;
106
+ name?: string;
107
+ ownerTreePosition?: number | null;
102
108
  page?: AppPageModule | null;
109
+ routeSegments?: readonly string[] | null;
103
110
  slotPatternParts?: readonly string[] | null;
104
111
  slotParamNames?: readonly string[] | null;
105
112
  };
@@ -184,6 +191,8 @@ export type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
184
191
  ensureRouteLoaded?: (route: TRoute) => unknown;
185
192
  fetchCache?: FetchCacheMode | null;
186
193
  findIntercept: (pathname: string) => AppPageDispatchIntercept | null;
194
+ /** This request's intercept, which dispatch resolves once before rendering. */
195
+ interceptState?: AppPageInterceptState<TRoute, unknown>;
187
196
  formState?: ReactFormState | null;
188
197
  actionError?: unknown;
189
198
  actionFailed?: boolean;
@@ -200,7 +209,6 @@ export type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
200
209
  hasGenerateStaticParams: boolean;
201
210
  /** Whether any segment of the route exports `generateStaticParams`. */
202
211
  hasAnyGenerateStaticParams: boolean;
203
- hasCustomGlobalError?: boolean;
204
212
  hasPageDefaultExport: boolean;
205
213
  hasPageModule: boolean;
206
214
  handlerStart: number;