vinext 0.0.53 → 0.0.54

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 (188) hide show
  1. package/dist/build/inline-css.d.ts +7 -0
  2. package/dist/build/inline-css.js +50 -0
  3. package/dist/build/inline-css.js.map +1 -0
  4. package/dist/build/prerender.js +2 -1
  5. package/dist/build/prerender.js.map +1 -1
  6. package/dist/check.js +4 -0
  7. package/dist/check.js.map +1 -1
  8. package/dist/client/navigation-runtime.d.ts +2 -1
  9. package/dist/client/navigation-runtime.js.map +1 -1
  10. package/dist/client/window-next.d.ts +7 -0
  11. package/dist/client/window-next.js.map +1 -1
  12. package/dist/config/next-config.d.ts +83 -1
  13. package/dist/config/next-config.js +131 -2
  14. package/dist/config/next-config.js.map +1 -1
  15. package/dist/deploy.js +13 -0
  16. package/dist/deploy.js.map +1 -1
  17. package/dist/entries/app-browser-entry.d.ts +11 -1
  18. package/dist/entries/app-browser-entry.js +16 -6
  19. package/dist/entries/app-browser-entry.js.map +1 -1
  20. package/dist/entries/app-rsc-entry.d.ts +8 -1
  21. package/dist/entries/app-rsc-entry.js +18 -5
  22. package/dist/entries/app-rsc-entry.js.map +1 -1
  23. package/dist/entries/app-rsc-manifest.d.ts +21 -1
  24. package/dist/entries/app-rsc-manifest.js +6 -4
  25. package/dist/entries/app-rsc-manifest.js.map +1 -1
  26. package/dist/entries/pages-client-entry.d.ts +4 -1
  27. package/dist/entries/pages-client-entry.js +18 -2
  28. package/dist/entries/pages-client-entry.js.map +1 -1
  29. package/dist/entries/pages-server-entry.js +82 -4
  30. package/dist/entries/pages-server-entry.js.map +1 -1
  31. package/dist/entries/runtime-entry-module.d.ts +1 -10
  32. package/dist/entries/runtime-entry-module.js +2 -12
  33. package/dist/entries/runtime-entry-module.js.map +1 -1
  34. package/dist/index.js +63 -5
  35. package/dist/index.js.map +1 -1
  36. package/dist/plugins/remove-console.d.ts +16 -0
  37. package/dist/plugins/remove-console.js +176 -0
  38. package/dist/plugins/remove-console.js.map +1 -0
  39. package/dist/routing/app-route-graph.d.ts +24 -1
  40. package/dist/routing/app-route-graph.js +52 -4
  41. package/dist/routing/app-route-graph.js.map +1 -1
  42. package/dist/routing/app-router.d.ts +2 -2
  43. package/dist/routing/app-router.js +2 -2
  44. package/dist/routing/app-router.js.map +1 -1
  45. package/dist/routing/file-matcher.d.ts +21 -1
  46. package/dist/routing/file-matcher.js +39 -1
  47. package/dist/routing/file-matcher.js.map +1 -1
  48. package/dist/routing/pages-router.d.ts +1 -1
  49. package/dist/routing/pages-router.js +10 -3
  50. package/dist/routing/pages-router.js.map +1 -1
  51. package/dist/server/api-handler.js +1 -1
  52. package/dist/server/app-browser-entry.js +25 -16
  53. package/dist/server/app-browser-entry.js.map +1 -1
  54. package/dist/server/app-browser-navigation-controller.d.ts +2 -0
  55. package/dist/server/app-browser-navigation-controller.js +4 -0
  56. package/dist/server/app-browser-navigation-controller.js.map +1 -1
  57. package/dist/server/app-elements-wire.d.ts +13 -4
  58. package/dist/server/app-elements-wire.js +10 -1
  59. package/dist/server/app-elements-wire.js.map +1 -1
  60. package/dist/server/app-elements.d.ts +2 -2
  61. package/dist/server/app-elements.js +2 -2
  62. package/dist/server/app-elements.js.map +1 -1
  63. package/dist/server/app-fallback-renderer.d.ts +15 -5
  64. package/dist/server/app-fallback-renderer.js +10 -4
  65. package/dist/server/app-fallback-renderer.js.map +1 -1
  66. package/dist/server/app-inline-css-client.d.ts +7 -0
  67. package/dist/server/app-inline-css-client.js +37 -0
  68. package/dist/server/app-inline-css-client.js.map +1 -0
  69. package/dist/server/app-page-boundary.d.ts +21 -1
  70. package/dist/server/app-page-boundary.js +28 -3
  71. package/dist/server/app-page-boundary.js.map +1 -1
  72. package/dist/server/app-page-cache.d.ts +7 -3
  73. package/dist/server/app-page-cache.js +7 -7
  74. package/dist/server/app-page-cache.js.map +1 -1
  75. package/dist/server/app-page-dispatch.d.ts +10 -1
  76. package/dist/server/app-page-dispatch.js +126 -79
  77. package/dist/server/app-page-dispatch.js.map +1 -1
  78. package/dist/server/app-page-element-builder.js +12 -28
  79. package/dist/server/app-page-element-builder.js.map +1 -1
  80. package/dist/server/app-page-render-identity.d.ts +22 -0
  81. package/dist/server/app-page-render-identity.js +42 -0
  82. package/dist/server/app-page-render-identity.js.map +1 -0
  83. package/dist/server/app-page-render.d.ts +8 -1
  84. package/dist/server/app-page-render.js +4 -1
  85. package/dist/server/app-page-render.js.map +1 -1
  86. package/dist/server/app-page-request.d.ts +6 -3
  87. package/dist/server/app-page-request.js +5 -2
  88. package/dist/server/app-page-request.js.map +1 -1
  89. package/dist/server/app-page-response.js +2 -2
  90. package/dist/server/app-page-response.js.map +1 -1
  91. package/dist/server/app-page-route-wiring.d.ts +15 -0
  92. package/dist/server/app-page-route-wiring.js +7 -5
  93. package/dist/server/app-page-route-wiring.js.map +1 -1
  94. package/dist/server/app-page-stream.d.ts +11 -0
  95. package/dist/server/app-page-stream.js +1 -0
  96. package/dist/server/app-page-stream.js.map +1 -1
  97. package/dist/server/app-route-handler-response.js +37 -5
  98. package/dist/server/app-route-handler-response.js.map +1 -1
  99. package/dist/server/app-rsc-handler.d.ts +14 -3
  100. package/dist/server/app-rsc-handler.js +45 -5
  101. package/dist/server/app-rsc-handler.js.map +1 -1
  102. package/dist/server/app-rsc-request-normalization.d.ts +2 -1
  103. package/dist/server/app-rsc-request-normalization.js +3 -2
  104. package/dist/server/app-rsc-request-normalization.js.map +1 -1
  105. package/dist/server/app-server-action-execution.d.ts +21 -3
  106. package/dist/server/app-server-action-execution.js +42 -7
  107. package/dist/server/app-server-action-execution.js.map +1 -1
  108. package/dist/server/app-ssr-entry.d.ts +6 -0
  109. package/dist/server/app-ssr-entry.js +22 -7
  110. package/dist/server/app-ssr-entry.js.map +1 -1
  111. package/dist/server/app-ssr-error-meta.js +3 -3
  112. package/dist/server/app-ssr-error-meta.js.map +1 -1
  113. package/dist/server/app-ssr-stream.d.ts +2 -1
  114. package/dist/server/app-ssr-stream.js +176 -31
  115. package/dist/server/app-ssr-stream.js.map +1 -1
  116. package/dist/server/client-trace-metadata.d.ts +31 -0
  117. package/dist/server/client-trace-metadata.js +83 -0
  118. package/dist/server/client-trace-metadata.js.map +1 -0
  119. package/dist/server/cookie-utils.d.ts +13 -0
  120. package/dist/server/cookie-utils.js +20 -0
  121. package/dist/server/cookie-utils.js.map +1 -0
  122. package/dist/server/dev-server.d.ts +8 -1
  123. package/dist/server/dev-server.js +34 -5
  124. package/dist/server/dev-server.js.map +1 -1
  125. package/dist/server/html.d.ts +2 -1
  126. package/dist/server/html.js +6 -1
  127. package/dist/server/html.js.map +1 -1
  128. package/dist/server/isr-cache.d.ts +7 -5
  129. package/dist/server/isr-cache.js +17 -6
  130. package/dist/server/isr-cache.js.map +1 -1
  131. package/dist/server/middleware-runtime.js +1 -2
  132. package/dist/server/middleware-runtime.js.map +1 -1
  133. package/dist/server/pages-document-initial-props.d.ts +7 -0
  134. package/dist/server/pages-document-initial-props.js +14 -0
  135. package/dist/server/pages-document-initial-props.js.map +1 -0
  136. package/dist/server/pages-page-data.js +3 -0
  137. package/dist/server/pages-page-data.js.map +1 -1
  138. package/dist/server/pages-page-method.d.ts +48 -0
  139. package/dist/server/pages-page-method.js +19 -0
  140. package/dist/server/pages-page-method.js.map +1 -0
  141. package/dist/server/pages-page-response.d.ts +6 -0
  142. package/dist/server/pages-page-response.js +10 -3
  143. package/dist/server/pages-page-response.js.map +1 -1
  144. package/dist/server/pages-serializable-props.d.ts +25 -0
  145. package/dist/server/pages-serializable-props.js +69 -0
  146. package/dist/server/pages-serializable-props.js.map +1 -0
  147. package/dist/server/prod-server.js +3 -0
  148. package/dist/server/prod-server.js.map +1 -1
  149. package/dist/server/server-action-not-found.js +3 -2
  150. package/dist/server/server-action-not-found.js.map +1 -1
  151. package/dist/server/static-file-cache.js +2 -1
  152. package/dist/server/static-file-cache.js.map +1 -1
  153. package/dist/shims/app-router-scroll-state.d.ts +4 -2
  154. package/dist/shims/app-router-scroll-state.js +16 -3
  155. package/dist/shims/app-router-scroll-state.js.map +1 -1
  156. package/dist/shims/app-router-scroll.d.ts +16 -2
  157. package/dist/shims/app-router-scroll.js +18 -3
  158. package/dist/shims/app-router-scroll.js.map +1 -1
  159. package/dist/shims/cache.d.ts +6 -0
  160. package/dist/shims/cache.js +7 -0
  161. package/dist/shims/cache.js.map +1 -1
  162. package/dist/shims/error.js +3 -0
  163. package/dist/shims/error.js.map +1 -1
  164. package/dist/shims/headers.d.ts +7 -0
  165. package/dist/shims/headers.js +9 -1
  166. package/dist/shims/headers.js.map +1 -1
  167. package/dist/shims/internal/app-route-detection.d.ts +37 -0
  168. package/dist/shims/internal/app-route-detection.js +69 -0
  169. package/dist/shims/internal/app-route-detection.js.map +1 -0
  170. package/dist/shims/link.d.ts +18 -2
  171. package/dist/shims/link.js +70 -6
  172. package/dist/shims/link.js.map +1 -1
  173. package/dist/shims/metadata.d.ts +7 -6
  174. package/dist/shims/metadata.js +9 -5
  175. package/dist/shims/metadata.js.map +1 -1
  176. package/dist/shims/navigation.d.ts +1 -2
  177. package/dist/shims/navigation.js +63 -12
  178. package/dist/shims/navigation.js.map +1 -1
  179. package/dist/shims/router.d.ts +5 -0
  180. package/dist/shims/router.js +14 -4
  181. package/dist/shims/router.js.map +1 -1
  182. package/dist/shims/script.d.ts +11 -1
  183. package/dist/shims/script.js +75 -6
  184. package/dist/shims/script.js.map +1 -1
  185. package/dist/utils/path.d.ts +13 -0
  186. package/dist/utils/path.js +16 -0
  187. package/dist/utils/path.js.map +1 -0
  188. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"app-browser-navigation-controller.js","names":[],"sources":["../../src/server/app-browser-navigation-controller.ts"],"sourcesContent":["import { startTransition, useLayoutEffect, type Dispatch, type ReactNode } from \"react\";\nimport {\n activateNavigationSnapshot,\n clearPendingPathname,\n commitClientNavigationState,\n} from \"vinext/shims/navigation\";\nimport type { ClientNavigationRenderSnapshot } from \"vinext/shims/navigation\";\nimport type { RouteManifest } from \"../routing/app-route-graph.js\";\nimport {\n FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN,\n createPendingNavigationCommit,\n type AppNavigationPayloadOrigin,\n type AppRouterState,\n type OperationLane,\n} from \"./app-browser-state.js\";\nimport {\n applyApprovedVisibleCommit,\n approveHmrVisibleCommit,\n approvePendingNavigationCommit,\n resolveAndClassifyNavigationCommit,\n type ApprovedVisibleCommit,\n} from \"./app-browser-visible-commit.js\";\nimport {\n shouldScheduleRefreshForDiscardedServerAction,\n type ServerActionRevalidationKind,\n} from \"./app-browser-action-result.js\";\nimport type { AppElements } from \"./app-elements.js\";\n\nexport type HistoryUpdateMode = \"push\" | \"replace\";\n\nexport type PendingBrowserRouterState = {\n promise: Promise<AppRouterState>;\n resolve: (state: AppRouterState) => void;\n settled: boolean;\n};\nexport type NavigationPayloadOutcome = \"committed\" | \"no-commit\" | \"hard-navigate\";\ntype HardNavigationMode = \"assign\" | \"replace\";\n\ntype BrowserNavigationCommitEffectFactory = (options: {\n href: string;\n historyUpdateMode: HistoryUpdateMode | undefined;\n navId: number;\n params: Record<string, string | string[]>;\n previousNextUrl: string | null;\n targetHistoryIndex?: number | null;\n}) => () => void;\n\ntype BrowserRouterStateRef = {\n current: AppRouterState;\n};\n\ntype SameUrlServerActionLifecycleOptions = {\n onDiscardedRevalidation?: () => void;\n revalidation?: ServerActionRevalidationKind;\n startedNavigationId?: number;\n targetHref?: string;\n};\n\ntype BrowserNavigationControllerDeps = {\n commitClientNavigationState?: typeof commitClientNavigationState;\n performHardNavigation?: (href: string, mode?: HardNavigationMode) => boolean;\n getRouteManifest?: () => RouteManifest | null;\n syncHistoryStatePreviousNextUrl?: (previousNextUrl: string | null) => void;\n};\n\ntype BrowserNavigationController = {\n beginNavigation(): number;\n getActiveNavigationId(): number;\n hasBrowserRouterState(): boolean;\n getBrowserRouterState(): AppRouterState;\n isCurrentNavigation(navId: number): boolean;\n performHardNavigation(href: string, mode?: HardNavigationMode): boolean;\n waitForBrowserRouterStateReady(): Promise<void>;\n attachBrowserRouterState(\n setter: Dispatch<AppRouterState | Promise<AppRouterState>>,\n stateRef: BrowserRouterStateRef,\n ): () => void;\n beginPendingBrowserRouterState(): PendingBrowserRouterState;\n finalizeNavigation(navId: number, pending: PendingBrowserRouterState | null | undefined): void;\n renderNavigationPayload(options: {\n actionType: \"navigate\" | \"replace\" | \"traverse\";\n createNavigationCommitEffect: BrowserNavigationCommitEffectFactory;\n historyUpdateMode: HistoryUpdateMode | undefined;\n navigationSnapshot: ClientNavigationRenderSnapshot;\n nextElements: Promise<AppElements>;\n operationLane: OperationLane;\n payloadOrigin: AppNavigationPayloadOrigin;\n params: Record<string, string | string[]>;\n pendingRouterState: PendingBrowserRouterState | null;\n previousNextUrl: string | null;\n targetHistoryIndex?: number | null;\n targetHref: string;\n navId: number;\n }): Promise<NavigationPayloadOutcome>;\n commitSameUrlNavigatePayload(\n nextElements: Promise<AppElements>,\n navigationSnapshot: ClientNavigationRenderSnapshot,\n returnValue?: { ok: boolean; data: unknown },\n actionInitiationState?: AppRouterState,\n lifecycleOptions?: SameUrlServerActionLifecycleOptions,\n ): Promise<unknown>;\n hmrReplaceTree(\n nextElements: Promise<AppElements>,\n navigationSnapshot: ClientNavigationRenderSnapshot,\n ): Promise<void>;\n /**\n * Force-drain the queued pre-paint effect for the given renderId without\n * waiting for NavigationCommitSignal to commit. Used by the dev recovery\n * boundary in app-browser-entry.ts: when a render error replaces\n * NavigationCommitSignal with the boundary's null fallback, its\n * useLayoutEffect never fires, so the URL update for the in-flight\n * navigation would otherwise be lost.\n */\n drainPrePaintEffects(renderId: number): void;\n NavigationCommitSignal(\n this: void,\n {\n renderId,\n children,\n }: {\n renderId: number;\n children?: ReactNode;\n },\n ): ReactNode;\n};\n\nconst HARD_NAVIGATION_LOOP_GUARD_KEY = \"__vinext_hard_navigation_target__\";\n\nfunction normalizeBrowserHref(href: string): string {\n try {\n return new URL(href, window.location.href).href;\n } catch {\n return href;\n }\n}\n\nfunction readHardNavigationLoopGuard(): string | null {\n try {\n return window.sessionStorage.getItem(HARD_NAVIGATION_LOOP_GUARD_KEY);\n } catch {\n return null;\n }\n}\n\nfunction writeHardNavigationLoopGuard(targetHref: string): boolean {\n try {\n window.sessionStorage.setItem(HARD_NAVIGATION_LOOP_GUARD_KEY, targetHref);\n return window.sessionStorage.getItem(HARD_NAVIGATION_LOOP_GUARD_KEY) === targetHref;\n } catch {\n return false;\n }\n}\n\nexport function clearHardNavigationLoopGuard(): void {\n try {\n window.sessionStorage.removeItem(HARD_NAVIGATION_LOOP_GUARD_KEY);\n } catch {}\n}\n\nfunction performHardNavigationWithLoopGuard(\n href: string,\n mode: HardNavigationMode = \"assign\",\n): boolean {\n const targetHref = normalizeBrowserHref(href);\n const currentHref = normalizeBrowserHref(window.location.href);\n\n if (readHardNavigationLoopGuard() === targetHref && currentHref === targetHref) {\n clearHardNavigationLoopGuard();\n console.error(\n `[vinext] Prevented repeated hard navigation to ${targetHref}; ` +\n \"leaving the current document in place to avoid a reload loop.\",\n );\n return false;\n }\n\n const guardPersisted = writeHardNavigationLoopGuard(targetHref);\n if (!guardPersisted && currentHref === targetHref) {\n console.error(\n `[vinext] Hard navigation to ${targetHref} requires a reload-loop guard, ` +\n \"but sessionStorage is unavailable; leaving the current document in place.\",\n );\n return false;\n }\n // If storage is unavailable but the target is a different URL, the browser\n // can still make forward progress. Only same-target reloads need a persisted\n // guard because they can re-enter this exact recovery path indefinitely.\n\n if (mode === \"replace\") {\n window.location.replace(href);\n } else {\n window.location.assign(href);\n }\n return true;\n}\n\nexport function createAppBrowserNavigationController(\n deps: BrowserNavigationControllerDeps = {},\n): BrowserNavigationController {\n const commitClientNavigationStateImpl =\n deps.commitClientNavigationState ?? commitClientNavigationState;\n const performHardNavigation = deps.performHardNavigation ?? performHardNavigationWithLoopGuard;\n const getRouteManifest = deps.getRouteManifest ?? (() => null);\n const syncHistoryStatePreviousNextUrl = deps.syncHistoryStatePreviousNextUrl ?? (() => {});\n\n // These are plain module-level variables (inside the controller closure),\n // unlike ClientNavigationState which uses Symbol.for to survive multiple\n // Vite module instances. The browser entry is loaded exactly once (via the\n // RSC plugin's generated bootstrap), so the controller running in a single\n // module instance is safe. If that assumption ever changes, these should be\n // migrated to a Symbol.for-backed global.\n //\n // The most severe consequence of multiple instances would be Map fragmentation:\n // pendingNavigationCommits and pendingNavigationPrePaintEffects would split\n // across instances, so drainPrePaintEffects in one instance could never drain\n // effects queued by the other, permanently leaking navigationSnapshotActiveCount\n // and causing hooks to prefer stale snapshot values indefinitely.\n let nextNavigationRenderId = 0;\n let activeNavigationId = 0;\n const pendingNavigationCommits = new Map<number, () => void>();\n const pendingNavigationPrePaintEffects = new Map<number, () => void>();\n\n let setBrowserRouterState: Dispatch<AppRouterState | Promise<AppRouterState>> | null = null;\n let browserRouterStateRef: BrowserRouterStateRef | null = null;\n let activePendingBrowserRouterState: PendingBrowserRouterState | null = null;\n let resolveBrowserRouterStateReady: (() => void) | null = null;\n let browserRouterStateReadyPromise: Promise<void> | null = null;\n let browserRouterStateHasCommitted = false;\n\n function getBrowserRouterStateSetter(): Dispatch<AppRouterState | Promise<AppRouterState>> {\n if (!setBrowserRouterState) {\n throw new Error(\"[vinext] Browser router state setter is not initialized\");\n }\n return setBrowserRouterState;\n }\n\n function getBrowserRouterState(): AppRouterState {\n if (!browserRouterStateRef) {\n throw new Error(\"[vinext] Browser router state is not initialized\");\n }\n return browserRouterStateRef.current;\n }\n\n function waitForBrowserRouterStateReady(): Promise<void> {\n if (browserRouterStateRef || browserRouterStateHasCommitted) {\n return Promise.resolve();\n }\n\n if (!browserRouterStateReadyPromise) {\n browserRouterStateReadyPromise = new Promise((resolve) => {\n resolveBrowserRouterStateReady = resolve;\n });\n }\n\n return browserRouterStateReadyPromise;\n }\n\n function markBrowserRouterStateReady(): void {\n browserRouterStateHasCommitted = true;\n const resolveReady = resolveBrowserRouterStateReady;\n resolveBrowserRouterStateReady = null;\n browserRouterStateReadyPromise = null;\n resolveReady?.();\n }\n\n function beginNavigation(): number {\n activeNavigationId += 1;\n return activeNavigationId;\n }\n\n function getActiveNavigationId(): number {\n return activeNavigationId;\n }\n\n function allocateRenderId(): number {\n nextNavigationRenderId += 1;\n return nextNavigationRenderId;\n }\n\n function hasBrowserRouterState(): boolean {\n return browserRouterStateRef !== null;\n }\n\n function isCurrentNavigation(navId: number): boolean {\n return navId === activeNavigationId;\n }\n\n function beginPendingBrowserRouterState(): PendingBrowserRouterState {\n const setter = getBrowserRouterStateSetter();\n\n if (activePendingBrowserRouterState && !activePendingBrowserRouterState.settled) {\n activePendingBrowserRouterState.settled = true;\n activePendingBrowserRouterState.resolve(getBrowserRouterState());\n }\n\n let resolvePending: ((state: AppRouterState) => void) | undefined;\n const promise = new Promise<AppRouterState>((resolve) => {\n resolvePending = resolve;\n });\n\n if (!resolvePending) {\n throw new Error(\"[vinext] Failed to initialize browser router promise\");\n }\n\n const pending: PendingBrowserRouterState = {\n promise,\n resolve: resolvePending,\n settled: false,\n };\n\n activePendingBrowserRouterState = pending;\n setter(promise);\n\n return pending;\n }\n\n function settlePendingBrowserRouterState(\n pending: PendingBrowserRouterState | null | undefined,\n ): void {\n if (!pending || pending.settled) return;\n\n pending.settled = true;\n pending.resolve(getBrowserRouterState());\n\n if (activePendingBrowserRouterState === pending) {\n activePendingBrowserRouterState = null;\n }\n }\n\n function finalizeNavigation(\n navId: number,\n pending: PendingBrowserRouterState | null | undefined,\n ): void {\n settlePendingBrowserRouterState(pending);\n\n if (isCurrentNavigation(navId)) {\n clearPendingPathname(navId);\n }\n }\n\n function resolvePendingBrowserRouterState(\n pending: PendingBrowserRouterState | null | undefined,\n commit: ApprovedVisibleCommit,\n ): void {\n if (!pending || pending.settled) return;\n\n pending.settled = true;\n pending.resolve(applyApprovedVisibleCommit(getBrowserRouterState(), commit));\n\n if (activePendingBrowserRouterState === pending) {\n activePendingBrowserRouterState = null;\n }\n }\n\n function queuePrePaintNavigationEffect(renderId: number, effect: (() => void) | null): void {\n if (!effect) {\n return;\n }\n pendingNavigationPrePaintEffects.set(renderId, effect);\n }\n\n /**\n * Run all queued pre-paint effects for renderIds up to and including the\n * given renderId. When React supersedes a startTransition update (rapid\n * clicks on same-route links), the superseded NavigationCommitSignal never\n * mounts, so its pre-paint effect never fires. By draining all effects\n * <= the committed renderId here, the winning transition cleans up after\n * any superseded ones, keeping the counter balanced.\n *\n * Invariant: each superseded navigation gets a commitClientNavigationState()\n * to balance the activateNavigationSnapshot() from its renderNavigationPayload call.\n */\n function drainPrePaintEffects(upToRenderId: number): void {\n for (const [id, effect] of pendingNavigationPrePaintEffects) {\n if (id > upToRenderId) {\n continue;\n }\n\n pendingNavigationPrePaintEffects.delete(id);\n if (id === upToRenderId) {\n effect();\n } else {\n // Superseded navigations still need to balance the snapshot counter.\n commitClientNavigationStateImpl(undefined, { releaseSnapshot: true });\n }\n }\n }\n\n /**\n * Resolve all pending navigation commits with renderId <= the committed renderId.\n * Note: Map iteration handles concurrent deletion safely — entries are visited in\n * insertion order and deletion doesn't affect the iterator's view of remaining entries.\n * This pattern is also used in drainPrePaintEffects with the same semantics.\n */\n function resolveCommittedNavigations(renderId: number): void {\n for (const [pendingId, resolve] of pendingNavigationCommits) {\n if (pendingId > renderId) {\n continue;\n }\n\n pendingNavigationCommits.delete(pendingId);\n resolve();\n }\n }\n\n async function hmrReplaceTree(\n nextElements: Promise<AppElements>,\n navigationSnapshot: ClientNavigationRenderSnapshot,\n ): Promise<void> {\n if (!hasBrowserRouterState()) return;\n\n const currentState = getBrowserRouterState();\n const renderId = allocateRenderId();\n const pending = await createPendingNavigationCommit({\n currentState,\n nextElements,\n navigationSnapshot,\n operationLane: \"hmr\",\n payloadOrigin: FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN,\n renderId,\n type: \"replace\",\n });\n\n // createPendingNavigationCommit awaits the new RSC payload. While\n // suspended, the prior broken render can unmount BrowserRoot. Re-check\n // before dispatching so a racing unmount doesn't surface as an\n // initialized-setter error.\n if (!hasBrowserRouterState()) return;\n\n dispatchSynchronousVisibleCommit(approveHmrVisibleCommit(pending));\n }\n\n function NavigationCommitSignal(\n this: void,\n {\n renderId,\n children,\n }: {\n renderId: number;\n children?: ReactNode;\n },\n ): ReactNode {\n useLayoutEffect(() => {\n drainPrePaintEffects(renderId);\n\n const frame = requestAnimationFrame(() => {\n resolveCommittedNavigations(renderId);\n });\n\n return () => {\n cancelAnimationFrame(frame);\n // Resolve pending commits to prevent callers from hanging if React\n // unmounts this component without committing (e.g., error boundary).\n resolveCommittedNavigations(renderId);\n };\n }, [renderId]);\n\n return children;\n }\n\n function dispatchApprovedVisibleCommit(\n commit: ApprovedVisibleCommit,\n pendingRouterState: PendingBrowserRouterState | null,\n ): void {\n const setter = getBrowserRouterStateSetter();\n\n if (pendingRouterState) {\n // The programmatic navigation is already running inside React.startTransition\n // (from router.push/replace/refresh/Link), so resolving the deferred promise\n // is sufficient.\n resolvePendingBrowserRouterState(pendingRouterState, commit);\n return;\n }\n\n startTransition(() => {\n setter(applyApprovedVisibleCommit(getBrowserRouterState(), commit));\n });\n }\n\n function dispatchSynchronousVisibleCommit(commit: ApprovedVisibleCommit): void {\n const setter = getBrowserRouterStateSetter();\n setter(applyApprovedVisibleCommit(getBrowserRouterState(), commit));\n }\n\n function notifyDiscardedServerActionRevalidation(\n lifecycleOptions: SameUrlServerActionLifecycleOptions | undefined,\n ): void {\n const revalidation = lifecycleOptions?.revalidation ?? \"none\";\n if (!shouldScheduleRefreshForDiscardedServerAction(revalidation)) return;\n\n lifecycleOptions?.onDiscardedRevalidation?.();\n }\n\n async function renderNavigationPayload(options: {\n actionType: \"navigate\" | \"replace\" | \"traverse\";\n createNavigationCommitEffect: BrowserNavigationCommitEffectFactory;\n historyUpdateMode: HistoryUpdateMode | undefined;\n navigationSnapshot: ClientNavigationRenderSnapshot;\n nextElements: Promise<AppElements>;\n operationLane: OperationLane;\n payloadOrigin: AppNavigationPayloadOrigin;\n params: Record<string, string | string[]>;\n pendingRouterState: PendingBrowserRouterState | null;\n previousNextUrl: string | null;\n targetHistoryIndex?: number | null;\n targetHref: string;\n navId: number;\n }): Promise<NavigationPayloadOutcome> {\n const renderId = allocateRenderId();\n let resolveCommitted: (() => void) | undefined;\n const committed = new Promise<void>((resolve) => {\n resolveCommitted = resolve;\n pendingNavigationCommits.set(renderId, resolve);\n });\n\n let snapshotActivated = false;\n try {\n const startedState = getBrowserRouterState();\n const pending = await createPendingNavigationCommit({\n currentState: startedState,\n nextElements: options.nextElements,\n navigationSnapshot: options.navigationSnapshot,\n operationLane: options.operationLane,\n payloadOrigin: options.payloadOrigin,\n previousNextUrl: options.previousNextUrl,\n renderId,\n type: options.actionType,\n });\n\n const approval = approvePendingNavigationCommit({\n activeNavigationId,\n currentState: getBrowserRouterState(),\n pending,\n routeManifest: getRouteManifest(),\n startedNavigationId: options.navId,\n targetHref: options.targetHref,\n });\n\n if (approval.decision.disposition === \"no-commit\") {\n settlePendingBrowserRouterState(options.pendingRouterState);\n pendingNavigationCommits.delete(renderId);\n resolveCommitted?.();\n return \"no-commit\";\n }\n\n if (approval.decision.disposition === \"hard-navigate\") {\n settlePendingBrowserRouterState(options.pendingRouterState);\n pendingNavigationCommits.delete(renderId);\n return performHardNavigation(options.targetHref) ? \"hard-navigate\" : \"no-commit\";\n }\n\n const approvedCommit = approval.approvedCommit;\n if (approvedCommit === null) {\n throw new Error(\"[vinext] Commit decision did not approve a visible commit\");\n }\n\n queuePrePaintNavigationEffect(\n renderId,\n options.createNavigationCommitEffect({\n href: options.targetHref,\n historyUpdateMode: options.historyUpdateMode,\n navId: options.navId,\n params: options.params,\n previousNextUrl: approvedCommit.previousNextUrl,\n targetHistoryIndex: options.targetHistoryIndex,\n }),\n );\n activateNavigationSnapshot();\n snapshotActivated = true;\n dispatchApprovedVisibleCommit(approvedCommit, options.pendingRouterState);\n } catch (error) {\n pendingNavigationPrePaintEffects.delete(renderId);\n pendingNavigationCommits.delete(renderId);\n if (snapshotActivated) {\n commitClientNavigationStateImpl(options.navId);\n }\n settlePendingBrowserRouterState(options.pendingRouterState);\n resolveCommitted?.();\n throw error;\n }\n\n return committed.then(() => \"committed\");\n }\n\n async function commitSameUrlNavigatePayload(\n nextElements: Promise<AppElements>,\n navigationSnapshot: ClientNavigationRenderSnapshot,\n returnValue?: { ok: boolean; data: unknown },\n actionInitiationState?: AppRouterState,\n lifecycleOptions?: SameUrlServerActionLifecycleOptions,\n ): Promise<unknown> {\n const currentState = actionInitiationState ?? getBrowserRouterState();\n const startedNavigationId = lifecycleOptions?.startedNavigationId ?? activeNavigationId;\n const targetHref = lifecycleOptions?.targetHref ?? window.location.href;\n const {\n approvedCommit,\n decision,\n pending,\n // Intentionally retained as #726-OPS-01 trace-shell scaffolding. The\n // same-URL action path can consume this trace once later lifecycle gates\n // need an observable commit explanation.\n trace: _navigationTrace,\n } = await resolveAndClassifyNavigationCommit({\n activeNavigationId,\n currentState,\n getActiveNavigationId: () => activeNavigationId,\n getCurrentStateForApproval: getBrowserRouterState,\n navigationSnapshot,\n nextElements,\n renderId: allocateRenderId(),\n operationLane: \"server-action\",\n payloadOrigin: FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN,\n startedNavigationId,\n routeManifest: getRouteManifest(),\n targetHref,\n type: \"navigate\",\n });\n\n if (decision.disposition === \"hard-navigate\") {\n // Same-URL action hard navigations do not expose a navigation outcome to\n // callers. If the loop guard blocks, the degraded state is still the\n // existing return contract: no visible commit and no action value.\n performHardNavigation(targetHref);\n return undefined;\n }\n\n if (approvedCommit) {\n // The helper approval and this continuation are separated by a microtask\n // boundary, so re-check lifecycle authority before mutating visible UI.\n const latestApproval = approvePendingNavigationCommit({\n activeNavigationId,\n currentState: getBrowserRouterState(),\n pending,\n routeManifest: getRouteManifest(),\n startedNavigationId,\n targetHref,\n });\n\n if (latestApproval.decision.disposition === \"hard-navigate\") {\n // See the same-URL hard-navigation note above. The guard result is\n // deliberately not surfaced through the server-action return channel.\n performHardNavigation(targetHref);\n return undefined;\n }\n\n if (latestApproval.approvedCommit) {\n dispatchSynchronousVisibleCommit(latestApproval.approvedCommit);\n syncHistoryStatePreviousNextUrl(latestApproval.approvedCommit.previousNextUrl);\n } else {\n notifyDiscardedServerActionRevalidation(lifecycleOptions);\n }\n } else if (decision.disposition === \"no-commit\") {\n notifyDiscardedServerActionRevalidation(lifecycleOptions);\n }\n\n // Same-URL server actions still return their action value even if the UI\n // update was skipped due to a superseding navigation. That preserves the\n // existing caller contract; a future Phase 2 router state model could make\n // skipped UI updates observable to the caller without conflating them here.\n if (returnValue) {\n if (!returnValue.ok) {\n throw returnValue.data;\n }\n return returnValue.data;\n }\n\n return undefined;\n }\n\n function attachBrowserRouterState(\n setter: Dispatch<AppRouterState | Promise<AppRouterState>>,\n stateRef: BrowserRouterStateRef,\n ): () => void {\n setBrowserRouterState = setter;\n browserRouterStateRef = stateRef;\n markBrowserRouterStateReady();\n\n return () => {\n if (setBrowserRouterState === setter) {\n setBrowserRouterState = null;\n }\n if (browserRouterStateRef === stateRef) {\n browserRouterStateRef = null;\n browserRouterStateHasCommitted = false;\n }\n };\n }\n\n return {\n beginNavigation,\n getActiveNavigationId,\n hasBrowserRouterState,\n getBrowserRouterState,\n isCurrentNavigation,\n performHardNavigation,\n waitForBrowserRouterStateReady,\n attachBrowserRouterState,\n beginPendingBrowserRouterState,\n finalizeNavigation,\n renderNavigationPayload,\n commitSameUrlNavigatePayload,\n hmrReplaceTree,\n drainPrePaintEffects,\n NavigationCommitSignal,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"app-browser-navigation-controller.js","names":[],"sources":["../../src/server/app-browser-navigation-controller.ts"],"sourcesContent":["import { startTransition, useLayoutEffect, type Dispatch, type ReactNode } from \"react\";\nimport {\n activateNavigationSnapshot,\n clearPendingPathname,\n commitClientNavigationState,\n} from \"vinext/shims/navigation\";\nimport type { ClientNavigationRenderSnapshot } from \"vinext/shims/navigation\";\nimport {\n claimAppRouterScrollIntentForCommit,\n consumeAppRouterScrollIntent,\n type AppRouterScrollIntent,\n} from \"vinext/shims/app-router-scroll-state\";\nimport type { RouteManifest } from \"../routing/app-route-graph.js\";\nimport {\n FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN,\n createPendingNavigationCommit,\n type AppNavigationPayloadOrigin,\n type AppRouterState,\n type OperationLane,\n} from \"./app-browser-state.js\";\nimport {\n applyApprovedVisibleCommit,\n approveHmrVisibleCommit,\n approvePendingNavigationCommit,\n resolveAndClassifyNavigationCommit,\n type ApprovedVisibleCommit,\n} from \"./app-browser-visible-commit.js\";\nimport {\n shouldScheduleRefreshForDiscardedServerAction,\n type ServerActionRevalidationKind,\n} from \"./app-browser-action-result.js\";\nimport type { AppElements } from \"./app-elements.js\";\n\nexport type HistoryUpdateMode = \"push\" | \"replace\";\n\nexport type PendingBrowserRouterState = {\n promise: Promise<AppRouterState>;\n resolve: (state: AppRouterState) => void;\n settled: boolean;\n};\nexport type NavigationPayloadOutcome = \"committed\" | \"no-commit\" | \"hard-navigate\";\ntype HardNavigationMode = \"assign\" | \"replace\";\n\ntype BrowserNavigationCommitEffectFactory = (options: {\n href: string;\n historyUpdateMode: HistoryUpdateMode | undefined;\n navId: number;\n params: Record<string, string | string[]>;\n previousNextUrl: string | null;\n targetHistoryIndex?: number | null;\n}) => () => void;\n\ntype BrowserRouterStateRef = {\n current: AppRouterState;\n};\n\ntype SameUrlServerActionLifecycleOptions = {\n onDiscardedRevalidation?: () => void;\n revalidation?: ServerActionRevalidationKind;\n startedNavigationId?: number;\n targetHref?: string;\n};\n\ntype BrowserNavigationControllerDeps = {\n commitClientNavigationState?: typeof commitClientNavigationState;\n performHardNavigation?: (href: string, mode?: HardNavigationMode) => boolean;\n getRouteManifest?: () => RouteManifest | null;\n syncHistoryStatePreviousNextUrl?: (previousNextUrl: string | null) => void;\n};\n\ntype BrowserNavigationController = {\n beginNavigation(): number;\n getActiveNavigationId(): number;\n hasBrowserRouterState(): boolean;\n getBrowserRouterState(): AppRouterState;\n isCurrentNavigation(navId: number): boolean;\n performHardNavigation(href: string, mode?: HardNavigationMode): boolean;\n waitForBrowserRouterStateReady(): Promise<void>;\n attachBrowserRouterState(\n setter: Dispatch<AppRouterState | Promise<AppRouterState>>,\n stateRef: BrowserRouterStateRef,\n ): () => void;\n beginPendingBrowserRouterState(): PendingBrowserRouterState;\n finalizeNavigation(navId: number, pending: PendingBrowserRouterState | null | undefined): void;\n renderNavigationPayload(options: {\n actionType: \"navigate\" | \"replace\" | \"traverse\";\n createNavigationCommitEffect: BrowserNavigationCommitEffectFactory;\n historyUpdateMode: HistoryUpdateMode | undefined;\n navigationSnapshot: ClientNavigationRenderSnapshot;\n nextElements: Promise<AppElements>;\n operationLane: OperationLane;\n payloadOrigin: AppNavigationPayloadOrigin;\n params: Record<string, string | string[]>;\n pendingRouterState: PendingBrowserRouterState | null;\n previousNextUrl: string | null;\n scrollIntent?: AppRouterScrollIntent | null;\n targetHistoryIndex?: number | null;\n targetHref: string;\n navId: number;\n }): Promise<NavigationPayloadOutcome>;\n commitSameUrlNavigatePayload(\n nextElements: Promise<AppElements>,\n navigationSnapshot: ClientNavigationRenderSnapshot,\n returnValue?: { ok: boolean; data: unknown },\n actionInitiationState?: AppRouterState,\n lifecycleOptions?: SameUrlServerActionLifecycleOptions,\n ): Promise<unknown>;\n hmrReplaceTree(\n nextElements: Promise<AppElements>,\n navigationSnapshot: ClientNavigationRenderSnapshot,\n ): Promise<void>;\n /**\n * Force-drain the queued pre-paint effect for the given renderId without\n * waiting for NavigationCommitSignal to commit. Used by the dev recovery\n * boundary in app-browser-entry.ts: when a render error replaces\n * NavigationCommitSignal with the boundary's null fallback, its\n * useLayoutEffect never fires, so the URL update for the in-flight\n * navigation would otherwise be lost.\n */\n drainPrePaintEffects(renderId: number): void;\n NavigationCommitSignal(\n this: void,\n {\n renderId,\n children,\n }: {\n renderId: number;\n children?: ReactNode;\n },\n ): ReactNode;\n};\n\nconst HARD_NAVIGATION_LOOP_GUARD_KEY = \"__vinext_hard_navigation_target__\";\n\nfunction normalizeBrowserHref(href: string): string {\n try {\n return new URL(href, window.location.href).href;\n } catch {\n return href;\n }\n}\n\nfunction readHardNavigationLoopGuard(): string | null {\n try {\n return window.sessionStorage.getItem(HARD_NAVIGATION_LOOP_GUARD_KEY);\n } catch {\n return null;\n }\n}\n\nfunction writeHardNavigationLoopGuard(targetHref: string): boolean {\n try {\n window.sessionStorage.setItem(HARD_NAVIGATION_LOOP_GUARD_KEY, targetHref);\n return window.sessionStorage.getItem(HARD_NAVIGATION_LOOP_GUARD_KEY) === targetHref;\n } catch {\n return false;\n }\n}\n\nexport function clearHardNavigationLoopGuard(): void {\n try {\n window.sessionStorage.removeItem(HARD_NAVIGATION_LOOP_GUARD_KEY);\n } catch {}\n}\n\nfunction performHardNavigationWithLoopGuard(\n href: string,\n mode: HardNavigationMode = \"assign\",\n): boolean {\n const targetHref = normalizeBrowserHref(href);\n const currentHref = normalizeBrowserHref(window.location.href);\n\n if (readHardNavigationLoopGuard() === targetHref && currentHref === targetHref) {\n clearHardNavigationLoopGuard();\n console.error(\n `[vinext] Prevented repeated hard navigation to ${targetHref}; ` +\n \"leaving the current document in place to avoid a reload loop.\",\n );\n return false;\n }\n\n const guardPersisted = writeHardNavigationLoopGuard(targetHref);\n if (!guardPersisted && currentHref === targetHref) {\n console.error(\n `[vinext] Hard navigation to ${targetHref} requires a reload-loop guard, ` +\n \"but sessionStorage is unavailable; leaving the current document in place.\",\n );\n return false;\n }\n // If storage is unavailable but the target is a different URL, the browser\n // can still make forward progress. Only same-target reloads need a persisted\n // guard because they can re-enter this exact recovery path indefinitely.\n\n if (mode === \"replace\") {\n window.location.replace(href);\n } else {\n window.location.assign(href);\n }\n return true;\n}\n\nexport function createAppBrowserNavigationController(\n deps: BrowserNavigationControllerDeps = {},\n): BrowserNavigationController {\n const commitClientNavigationStateImpl =\n deps.commitClientNavigationState ?? commitClientNavigationState;\n const performHardNavigation = deps.performHardNavigation ?? performHardNavigationWithLoopGuard;\n const getRouteManifest = deps.getRouteManifest ?? (() => null);\n const syncHistoryStatePreviousNextUrl = deps.syncHistoryStatePreviousNextUrl ?? (() => {});\n\n // These are plain module-level variables (inside the controller closure),\n // unlike ClientNavigationState which uses Symbol.for to survive multiple\n // Vite module instances. The browser entry is loaded exactly once (via the\n // RSC plugin's generated bootstrap), so the controller running in a single\n // module instance is safe. If that assumption ever changes, these should be\n // migrated to a Symbol.for-backed global.\n //\n // The most severe consequence of multiple instances would be Map fragmentation:\n // pendingNavigationCommits and pendingNavigationPrePaintEffects would split\n // across instances, so drainPrePaintEffects in one instance could never drain\n // effects queued by the other, permanently leaking navigationSnapshotActiveCount\n // and causing hooks to prefer stale snapshot values indefinitely.\n let nextNavigationRenderId = 0;\n let activeNavigationId = 0;\n const pendingNavigationCommits = new Map<number, () => void>();\n const pendingNavigationPrePaintEffects = new Map<number, () => void>();\n\n let setBrowserRouterState: Dispatch<AppRouterState | Promise<AppRouterState>> | null = null;\n let browserRouterStateRef: BrowserRouterStateRef | null = null;\n let activePendingBrowserRouterState: PendingBrowserRouterState | null = null;\n let resolveBrowserRouterStateReady: (() => void) | null = null;\n let browserRouterStateReadyPromise: Promise<void> | null = null;\n let browserRouterStateHasCommitted = false;\n\n function getBrowserRouterStateSetter(): Dispatch<AppRouterState | Promise<AppRouterState>> {\n if (!setBrowserRouterState) {\n throw new Error(\"[vinext] Browser router state setter is not initialized\");\n }\n return setBrowserRouterState;\n }\n\n function getBrowserRouterState(): AppRouterState {\n if (!browserRouterStateRef) {\n throw new Error(\"[vinext] Browser router state is not initialized\");\n }\n return browserRouterStateRef.current;\n }\n\n function waitForBrowserRouterStateReady(): Promise<void> {\n if (browserRouterStateRef || browserRouterStateHasCommitted) {\n return Promise.resolve();\n }\n\n if (!browserRouterStateReadyPromise) {\n browserRouterStateReadyPromise = new Promise((resolve) => {\n resolveBrowserRouterStateReady = resolve;\n });\n }\n\n return browserRouterStateReadyPromise;\n }\n\n function markBrowserRouterStateReady(): void {\n browserRouterStateHasCommitted = true;\n const resolveReady = resolveBrowserRouterStateReady;\n resolveBrowserRouterStateReady = null;\n browserRouterStateReadyPromise = null;\n resolveReady?.();\n }\n\n function beginNavigation(): number {\n activeNavigationId += 1;\n return activeNavigationId;\n }\n\n function getActiveNavigationId(): number {\n return activeNavigationId;\n }\n\n function allocateRenderId(): number {\n nextNavigationRenderId += 1;\n return nextNavigationRenderId;\n }\n\n function hasBrowserRouterState(): boolean {\n return browserRouterStateRef !== null;\n }\n\n function isCurrentNavigation(navId: number): boolean {\n return navId === activeNavigationId;\n }\n\n function beginPendingBrowserRouterState(): PendingBrowserRouterState {\n const setter = getBrowserRouterStateSetter();\n\n if (activePendingBrowserRouterState && !activePendingBrowserRouterState.settled) {\n activePendingBrowserRouterState.settled = true;\n activePendingBrowserRouterState.resolve(getBrowserRouterState());\n }\n\n let resolvePending: ((state: AppRouterState) => void) | undefined;\n const promise = new Promise<AppRouterState>((resolve) => {\n resolvePending = resolve;\n });\n\n if (!resolvePending) {\n throw new Error(\"[vinext] Failed to initialize browser router promise\");\n }\n\n const pending: PendingBrowserRouterState = {\n promise,\n resolve: resolvePending,\n settled: false,\n };\n\n activePendingBrowserRouterState = pending;\n setter(promise);\n\n return pending;\n }\n\n function settlePendingBrowserRouterState(\n pending: PendingBrowserRouterState | null | undefined,\n ): void {\n if (!pending || pending.settled) return;\n\n pending.settled = true;\n pending.resolve(getBrowserRouterState());\n\n if (activePendingBrowserRouterState === pending) {\n activePendingBrowserRouterState = null;\n }\n }\n\n function finalizeNavigation(\n navId: number,\n pending: PendingBrowserRouterState | null | undefined,\n ): void {\n settlePendingBrowserRouterState(pending);\n\n if (isCurrentNavigation(navId)) {\n clearPendingPathname(navId);\n }\n }\n\n function resolvePendingBrowserRouterState(\n pending: PendingBrowserRouterState | null | undefined,\n commit: ApprovedVisibleCommit,\n ): void {\n if (!pending || pending.settled) return;\n\n pending.settled = true;\n pending.resolve(applyApprovedVisibleCommit(getBrowserRouterState(), commit));\n\n if (activePendingBrowserRouterState === pending) {\n activePendingBrowserRouterState = null;\n }\n }\n\n function queuePrePaintNavigationEffect(renderId: number, effect: (() => void) | null): void {\n if (!effect) {\n return;\n }\n pendingNavigationPrePaintEffects.set(renderId, effect);\n }\n\n /**\n * Run all queued pre-paint effects for renderIds up to and including the\n * given renderId. When React supersedes a startTransition update (rapid\n * clicks on same-route links), the superseded NavigationCommitSignal never\n * mounts, so its pre-paint effect never fires. By draining all effects\n * <= the committed renderId here, the winning transition cleans up after\n * any superseded ones, keeping the counter balanced.\n *\n * Invariant: each superseded navigation gets a commitClientNavigationState()\n * to balance the activateNavigationSnapshot() from its renderNavigationPayload call.\n */\n function drainPrePaintEffects(upToRenderId: number): void {\n for (const [id, effect] of pendingNavigationPrePaintEffects) {\n if (id > upToRenderId) {\n continue;\n }\n\n pendingNavigationPrePaintEffects.delete(id);\n if (id === upToRenderId) {\n effect();\n } else {\n // Superseded navigations still need to balance the snapshot counter.\n commitClientNavigationStateImpl(undefined, { releaseSnapshot: true });\n }\n }\n }\n\n /**\n * Resolve all pending navigation commits with renderId <= the committed renderId.\n * Note: Map iteration handles concurrent deletion safely — entries are visited in\n * insertion order and deletion doesn't affect the iterator's view of remaining entries.\n * This pattern is also used in drainPrePaintEffects with the same semantics.\n */\n function resolveCommittedNavigations(renderId: number): void {\n for (const [pendingId, resolve] of pendingNavigationCommits) {\n if (pendingId > renderId) {\n continue;\n }\n\n pendingNavigationCommits.delete(pendingId);\n resolve();\n }\n }\n\n async function hmrReplaceTree(\n nextElements: Promise<AppElements>,\n navigationSnapshot: ClientNavigationRenderSnapshot,\n ): Promise<void> {\n if (!hasBrowserRouterState()) return;\n\n const currentState = getBrowserRouterState();\n const renderId = allocateRenderId();\n const pending = await createPendingNavigationCommit({\n currentState,\n nextElements,\n navigationSnapshot,\n operationLane: \"hmr\",\n payloadOrigin: FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN,\n renderId,\n type: \"replace\",\n });\n\n // createPendingNavigationCommit awaits the new RSC payload. While\n // suspended, the prior broken render can unmount BrowserRoot. Re-check\n // before dispatching so a racing unmount doesn't surface as an\n // initialized-setter error.\n if (!hasBrowserRouterState()) return;\n\n dispatchSynchronousVisibleCommit(approveHmrVisibleCommit(pending));\n }\n\n function NavigationCommitSignal(\n this: void,\n {\n renderId,\n children,\n }: {\n renderId: number;\n children?: ReactNode;\n },\n ): ReactNode {\n useLayoutEffect(() => {\n drainPrePaintEffects(renderId);\n\n const frame = requestAnimationFrame(() => {\n resolveCommittedNavigations(renderId);\n });\n\n return () => {\n cancelAnimationFrame(frame);\n // Resolve pending commits to prevent callers from hanging if React\n // unmounts this component without committing (e.g., error boundary).\n resolveCommittedNavigations(renderId);\n };\n }, [renderId]);\n\n return children;\n }\n\n function dispatchApprovedVisibleCommit(\n commit: ApprovedVisibleCommit,\n pendingRouterState: PendingBrowserRouterState | null,\n ): void {\n const setter = getBrowserRouterStateSetter();\n\n if (pendingRouterState) {\n // The programmatic navigation is already running inside React.startTransition\n // (from router.push/replace/refresh/Link), so resolving the deferred promise\n // is sufficient.\n resolvePendingBrowserRouterState(pendingRouterState, commit);\n return;\n }\n\n startTransition(() => {\n setter(applyApprovedVisibleCommit(getBrowserRouterState(), commit));\n });\n }\n\n function dispatchSynchronousVisibleCommit(commit: ApprovedVisibleCommit): void {\n const setter = getBrowserRouterStateSetter();\n setter(applyApprovedVisibleCommit(getBrowserRouterState(), commit));\n }\n\n function notifyDiscardedServerActionRevalidation(\n lifecycleOptions: SameUrlServerActionLifecycleOptions | undefined,\n ): void {\n const revalidation = lifecycleOptions?.revalidation ?? \"none\";\n if (!shouldScheduleRefreshForDiscardedServerAction(revalidation)) return;\n\n lifecycleOptions?.onDiscardedRevalidation?.();\n }\n\n async function renderNavigationPayload(options: {\n actionType: \"navigate\" | \"replace\" | \"traverse\";\n createNavigationCommitEffect: BrowserNavigationCommitEffectFactory;\n historyUpdateMode: HistoryUpdateMode | undefined;\n navigationSnapshot: ClientNavigationRenderSnapshot;\n nextElements: Promise<AppElements>;\n operationLane: OperationLane;\n payloadOrigin: AppNavigationPayloadOrigin;\n params: Record<string, string | string[]>;\n pendingRouterState: PendingBrowserRouterState | null;\n previousNextUrl: string | null;\n scrollIntent?: AppRouterScrollIntent | null;\n targetHistoryIndex?: number | null;\n targetHref: string;\n navId: number;\n }): Promise<NavigationPayloadOutcome> {\n const renderId = allocateRenderId();\n let resolveCommitted: (() => void) | undefined;\n const committed = new Promise<void>((resolve) => {\n resolveCommitted = resolve;\n pendingNavigationCommits.set(renderId, resolve);\n });\n\n let snapshotActivated = false;\n try {\n const startedState = getBrowserRouterState();\n const pending = await createPendingNavigationCommit({\n currentState: startedState,\n nextElements: options.nextElements,\n navigationSnapshot: options.navigationSnapshot,\n operationLane: options.operationLane,\n payloadOrigin: options.payloadOrigin,\n previousNextUrl: options.previousNextUrl,\n renderId,\n type: options.actionType,\n });\n\n const approval = approvePendingNavigationCommit({\n activeNavigationId,\n currentState: getBrowserRouterState(),\n pending,\n routeManifest: getRouteManifest(),\n startedNavigationId: options.navId,\n targetHref: options.targetHref,\n });\n\n if (approval.decision.disposition === \"no-commit\") {\n settlePendingBrowserRouterState(options.pendingRouterState);\n pendingNavigationCommits.delete(renderId);\n resolveCommitted?.();\n consumeAppRouterScrollIntent(options.scrollIntent ?? null);\n return \"no-commit\";\n }\n\n if (approval.decision.disposition === \"hard-navigate\") {\n settlePendingBrowserRouterState(options.pendingRouterState);\n pendingNavigationCommits.delete(renderId);\n consumeAppRouterScrollIntent(options.scrollIntent ?? null);\n return performHardNavigation(options.targetHref) ? \"hard-navigate\" : \"no-commit\";\n }\n\n const approvedCommit = approval.approvedCommit;\n if (approvedCommit === null) {\n throw new Error(\"[vinext] Commit decision did not approve a visible commit\");\n }\n\n queuePrePaintNavigationEffect(\n renderId,\n options.createNavigationCommitEffect({\n href: options.targetHref,\n historyUpdateMode: options.historyUpdateMode,\n navId: options.navId,\n params: options.params,\n previousNextUrl: approvedCommit.previousNextUrl,\n targetHistoryIndex: options.targetHistoryIndex,\n }),\n );\n claimAppRouterScrollIntentForCommit(options.scrollIntent, renderId);\n activateNavigationSnapshot();\n snapshotActivated = true;\n dispatchApprovedVisibleCommit(approvedCommit, options.pendingRouterState);\n } catch (error) {\n pendingNavigationPrePaintEffects.delete(renderId);\n pendingNavigationCommits.delete(renderId);\n if (snapshotActivated) {\n commitClientNavigationStateImpl(options.navId);\n }\n settlePendingBrowserRouterState(options.pendingRouterState);\n resolveCommitted?.();\n throw error;\n }\n\n return committed.then(() => \"committed\");\n }\n\n async function commitSameUrlNavigatePayload(\n nextElements: Promise<AppElements>,\n navigationSnapshot: ClientNavigationRenderSnapshot,\n returnValue?: { ok: boolean; data: unknown },\n actionInitiationState?: AppRouterState,\n lifecycleOptions?: SameUrlServerActionLifecycleOptions,\n ): Promise<unknown> {\n const currentState = actionInitiationState ?? getBrowserRouterState();\n const startedNavigationId = lifecycleOptions?.startedNavigationId ?? activeNavigationId;\n const targetHref = lifecycleOptions?.targetHref ?? window.location.href;\n const {\n approvedCommit,\n decision,\n pending,\n // Intentionally retained as #726-OPS-01 trace-shell scaffolding. The\n // same-URL action path can consume this trace once later lifecycle gates\n // need an observable commit explanation.\n trace: _navigationTrace,\n } = await resolveAndClassifyNavigationCommit({\n activeNavigationId,\n currentState,\n getActiveNavigationId: () => activeNavigationId,\n getCurrentStateForApproval: getBrowserRouterState,\n navigationSnapshot,\n nextElements,\n renderId: allocateRenderId(),\n operationLane: \"server-action\",\n payloadOrigin: FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN,\n startedNavigationId,\n routeManifest: getRouteManifest(),\n targetHref,\n type: \"navigate\",\n });\n\n if (decision.disposition === \"hard-navigate\") {\n // Same-URL action hard navigations do not expose a navigation outcome to\n // callers. If the loop guard blocks, the degraded state is still the\n // existing return contract: no visible commit and no action value.\n performHardNavigation(targetHref);\n return undefined;\n }\n\n if (approvedCommit) {\n // The helper approval and this continuation are separated by a microtask\n // boundary, so re-check lifecycle authority before mutating visible UI.\n const latestApproval = approvePendingNavigationCommit({\n activeNavigationId,\n currentState: getBrowserRouterState(),\n pending,\n routeManifest: getRouteManifest(),\n startedNavigationId,\n targetHref,\n });\n\n if (latestApproval.decision.disposition === \"hard-navigate\") {\n // See the same-URL hard-navigation note above. The guard result is\n // deliberately not surfaced through the server-action return channel.\n performHardNavigation(targetHref);\n return undefined;\n }\n\n if (latestApproval.approvedCommit) {\n dispatchSynchronousVisibleCommit(latestApproval.approvedCommit);\n syncHistoryStatePreviousNextUrl(latestApproval.approvedCommit.previousNextUrl);\n } else {\n notifyDiscardedServerActionRevalidation(lifecycleOptions);\n }\n } else if (decision.disposition === \"no-commit\") {\n notifyDiscardedServerActionRevalidation(lifecycleOptions);\n }\n\n // Same-URL server actions still return their action value even if the UI\n // update was skipped due to a superseding navigation. That preserves the\n // existing caller contract; a future Phase 2 router state model could make\n // skipped UI updates observable to the caller without conflating them here.\n if (returnValue) {\n if (!returnValue.ok) {\n throw returnValue.data;\n }\n return returnValue.data;\n }\n\n return undefined;\n }\n\n function attachBrowserRouterState(\n setter: Dispatch<AppRouterState | Promise<AppRouterState>>,\n stateRef: BrowserRouterStateRef,\n ): () => void {\n setBrowserRouterState = setter;\n browserRouterStateRef = stateRef;\n markBrowserRouterStateReady();\n\n return () => {\n if (setBrowserRouterState === setter) {\n setBrowserRouterState = null;\n }\n if (browserRouterStateRef === stateRef) {\n browserRouterStateRef = null;\n browserRouterStateHasCommitted = false;\n }\n };\n }\n\n return {\n beginNavigation,\n getActiveNavigationId,\n hasBrowserRouterState,\n getBrowserRouterState,\n isCurrentNavigation,\n performHardNavigation,\n waitForBrowserRouterStateReady,\n attachBrowserRouterState,\n beginPendingBrowserRouterState,\n finalizeNavigation,\n renderNavigationPayload,\n commitSameUrlNavigatePayload,\n hmrReplaceTree,\n drainPrePaintEffects,\n NavigationCommitSignal,\n };\n}\n"],"mappings":"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"}
@@ -13,6 +13,15 @@ declare const APP_RENDER_OBSERVATION_KEY = "__renderObservation";
13
13
  declare const APP_ROUTE_KEY = "__route";
14
14
  declare const APP_ROOT_LAYOUT_KEY = "__rootLayout";
15
15
  declare const APP_SLOT_BINDINGS_KEY = "__slotBindings";
16
+ /**
17
+ * Static sibling segment names for the matched route, surfaced so the client
18
+ * router can determine if a cached prefetch of a dynamic route can be reused
19
+ * when navigating to a static sibling URL.
20
+ *
21
+ * Mirrors Next.js's `staticSiblings` tuple element on the loader-tree dynamic
22
+ * segments (issue cloudflare/vinext#1525).
23
+ */
24
+ declare const APP_STATIC_SIBLINGS_KEY = "__staticSiblings";
16
25
  declare const APP_UNMATCHED_SLOT_WIRE_VALUE = "__VINEXT_UNMATCHED_SLOT__";
17
26
  declare const UNMATCHED_SLOT: unique symbol;
18
27
  type AppElementsSlotBindingState = "active" | "default" | "unmatched";
@@ -106,7 +115,7 @@ type AppElementsWireMetadataEntries = Readonly<{
106
115
  * known keys (e.g. __layoutFlags). Distinct from AppElements / AppWireElements
107
116
  * which only carry render-time values.
108
117
  */
109
- type AppOutgoingElements = Readonly<Record<string, ReactNode | LayoutFlags | ArtifactCompatibilityEnvelope | CacheEntryReuseProof | AppElementsInterception | RenderObservation | readonly AppElementsSlotBinding[]>>;
118
+ type AppOutgoingElements = Readonly<Record<string, ReactNode | LayoutFlags | ArtifactCompatibilityEnvelope | CacheEntryReuseProof | AppElementsInterception | RenderObservation | readonly AppElementsSlotBinding[] | readonly string[]>>;
110
119
  type AppElementsWireKeys = {
111
120
  readonly artifactCompatibility: typeof APP_ARTIFACT_COMPATIBILITY_KEY;
112
121
  readonly cacheEntryReuseProof: typeof APP_CACHE_ENTRY_REUSE_PROOF_KEY;
@@ -127,7 +136,7 @@ type AppElementsWireCodec = {
127
136
  encodeCacheKey(rscUrl: string, interceptionContext: string | null): string;
128
137
  encodeLayoutId(treePath: string): string;
129
138
  encodeOutgoingPayload(input: {
130
- element: ReactNode | Readonly<Record<string, ReactNode | AppElementsInterception | readonly AppElementsSlotBinding[]>>;
139
+ element: ReactNode | Readonly<Record<string, ReactNode | AppElementsInterception | readonly AppElementsSlotBinding[] | readonly string[]>>;
131
140
  artifactCompatibility?: ArtifactCompatibilityEnvelope;
132
141
  cacheEntryReuseProof?: CacheEntryReuseProof;
133
142
  layoutFlags: LayoutFlags;
@@ -159,7 +168,7 @@ declare function withLayoutFlags<T extends Record<string, unknown>>(elements: T,
159
168
  [APP_LAYOUT_FLAGS_KEY]: LayoutFlags;
160
169
  };
161
170
  declare function buildOutgoingAppPayload(input: {
162
- element: ReactNode | Readonly<Record<string, ReactNode | AppElementsInterception | readonly AppElementsSlotBinding[]>>;
171
+ element: ReactNode | Readonly<Record<string, ReactNode | AppElementsInterception | readonly AppElementsSlotBinding[] | readonly string[]>>;
163
172
  artifactCompatibility?: ArtifactCompatibilityEnvelope;
164
173
  cacheEntryReuseProof?: CacheEntryReuseProof;
165
174
  layoutFlags: LayoutFlags;
@@ -168,5 +177,5 @@ declare function buildOutgoingAppPayload(input: {
168
177
  declare function readAppElementsMetadata(elements: Readonly<Record<string, unknown>>): AppElementsMetadata;
169
178
  declare const AppElementsWire: AppElementsWireCodec;
170
179
  //#endregion
171
- export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SLOT_BINDINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementValue, AppElements, AppElementsInterception, AppElementsSlotBinding, AppElementsSlotBindingState, AppElementsWire, AppOutgoingElements, AppWireElements, LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags };
180
+ export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SLOT_BINDINGS_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementValue, AppElements, AppElementsInterception, AppElementsSlotBinding, AppElementsSlotBindingState, AppElementsWire, AppOutgoingElements, AppWireElements, LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags };
172
181
  //# sourceMappingURL=app-elements-wire.d.ts.map
@@ -13,6 +13,15 @@ const APP_RENDER_OBSERVATION_KEY = "__renderObservation";
13
13
  const APP_ROUTE_KEY = "__route";
14
14
  const APP_ROOT_LAYOUT_KEY = "__rootLayout";
15
15
  const APP_SLOT_BINDINGS_KEY = "__slotBindings";
16
+ /**
17
+ * Static sibling segment names for the matched route, surfaced so the client
18
+ * router can determine if a cached prefetch of a dynamic route can be reused
19
+ * when navigating to a static sibling URL.
20
+ *
21
+ * Mirrors Next.js's `staticSiblings` tuple element on the loader-tree dynamic
22
+ * segments (issue cloudflare/vinext#1525).
23
+ */
24
+ const APP_STATIC_SIBLINGS_KEY = "__staticSiblings";
16
25
  const APP_UNMATCHED_SLOT_WIRE_VALUE = "__VINEXT_UNMATCHED_SLOT__";
17
26
  const UNMATCHED_SLOT = Symbol.for("vinext.unmatchedSlot");
18
27
  function createCacheProofRejectionCodeSet(codes) {
@@ -398,6 +407,6 @@ const AppElementsWire = {
398
407
  withLayoutFlags
399
408
  };
400
409
  //#endregion
401
- export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SLOT_BINDINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags };
410
+ export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SLOT_BINDINGS_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags };
402
411
 
403
412
  //# sourceMappingURL=app-elements-wire.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"app-elements-wire.js","names":[],"sources":["../../src/server/app-elements-wire.ts"],"sourcesContent":["import { isValidElement, type ReactNode } from \"react\";\nimport {\n createArtifactCompatibilityEnvelope,\n parseArtifactCompatibilityEnvelope,\n type ArtifactCompatibilityEnvelope,\n} from \"./artifact-compatibility.js\";\nimport type {\n CacheEntryReuseProof,\n CacheProofBreakerFallbackMode,\n CacheProofFallbackScope,\n CacheProofRejectionCode,\n RenderObservation,\n} from \"./cache-proof.js\";\nimport { isInterceptionMatchedUrlPath } from \"./normalize-path.js\";\n\nconst APP_INTERCEPTION_SEPARATOR = \"\\0\";\n\nexport const APP_ARTIFACT_COMPATIBILITY_KEY = \"__artifactCompatibility\";\nexport const APP_CACHE_ENTRY_REUSE_PROOF_KEY = \"__cacheEntryReuseProof\";\nexport const APP_INTERCEPTION_KEY = \"__interception\";\nexport const APP_INTERCEPTION_CONTEXT_KEY = \"__interceptionContext\";\nexport const APP_LAYOUT_IDS_KEY = \"__layoutIds\";\nexport const APP_LAYOUT_FLAGS_KEY = \"__layoutFlags\";\nexport const APP_RENDER_OBSERVATION_KEY = \"__renderObservation\";\nexport const APP_ROUTE_KEY = \"__route\";\nexport const APP_ROOT_LAYOUT_KEY = \"__rootLayout\";\nexport const APP_SLOT_BINDINGS_KEY = \"__slotBindings\";\nexport const APP_UNMATCHED_SLOT_WIRE_VALUE = \"__VINEXT_UNMATCHED_SLOT__\";\n\nexport const UNMATCHED_SLOT = Symbol.for(\"vinext.unmatchedSlot\");\n\nfunction createCacheProofRejectionCodeSet<const T extends readonly CacheProofRejectionCode[]>(\n codes: T &\n ([CacheProofRejectionCode] extends [T[number]]\n ? unknown\n : readonly [\n \"Missing cache proof rejection codes\",\n Exclude<CacheProofRejectionCode, T[number]>,\n ]),\n): ReadonlySet<string> {\n return new Set(codes);\n}\n\nconst CACHE_PROOF_REJECTION_CODES = createCacheProofRejectionCodeSet([\n \"CP_CACHE_ENTRY_PROOF_MISSING\",\n \"CP_MODEL_DISABLED\",\n \"CP_ARTIFACT_COMPATIBILITY_INCOMPATIBLE\",\n \"CP_ARTIFACT_COMPATIBILITY_UNKNOWN\",\n \"CP_DIMENSION_COUNT_EXCEEDED\",\n \"CP_DIMENSION_NAME_MISSING\",\n \"CP_DIMENSION_NAME_TOO_LONG\",\n \"CP_DIMENSION_VALUE_COUNT_EXCEEDED\",\n \"CP_DIMENSION_VALUE_TOO_LONG\",\n \"CP_DIMENSION_VALUES_MISSING\",\n \"CP_ENCODED_VARIANT_TOO_LONG\",\n \"CP_INVALID_VARIANT_BUDGET\",\n \"CP_ROUTE_VARIANT_BUDGET_ROUTE_MISMATCH\",\n \"CP_ROUTE_VARIANT_CEILING_EXCEEDED\",\n \"CP_UNSAFE_PUBLIC_DIMENSION\",\n \"CP_BOUNDARY_OUTCOME_MISMATCH\",\n \"CP_BOUNDARY_OUTCOME_UNKNOWN\",\n \"CP_PRIVATE_DYNAMIC_DOWNGRADE\",\n \"CP_STATIC_LAYOUT_CANDIDATE_OUTPUT_KIND\",\n \"CP_STATIC_LAYOUT_CURRENT_OUTPUT_KIND\",\n \"CP_STATIC_LAYOUT_ID_MISMATCH\",\n \"CP_STATIC_LAYOUT_OBSERVATION_OUTPUT_KIND\",\n \"CP_STATIC_LAYOUT_OBSERVATION_OUTPUT_MISMATCH\",\n \"CP_STATIC_LAYOUT_PRIVATE_DYNAMIC_DOWNGRADE\",\n \"CP_STATIC_LAYOUT_REQUEST_API_OBSERVED\",\n \"CP_STATIC_LAYOUT_REQUEST_API_UNKNOWN\",\n \"CP_STATIC_LAYOUT_ROOT_BOUNDARY_MISMATCH\",\n \"CP_STATIC_LAYOUT_ROOT_BOUNDARY_UNKNOWN\",\n \"CP_STATIC_LAYOUT_VARIANT_DIMENSION_UNPROVEN\",\n]);\n\nexport type AppElementsSlotBindingState = \"active\" | \"default\" | \"unmatched\";\n\nexport type AppElementsSlotBinding = Readonly<{\n ownerLayoutId: string | null;\n slotId: string;\n state: AppElementsSlotBindingState;\n}>;\n\nexport type AppElementsInterception = Readonly<{\n sourceMatchedUrl: string;\n sourceRouteId: string;\n slotId: string;\n targetMatchedUrl: string;\n targetRouteId: string;\n}>;\n\nexport function compareAppElementsSlotIds(left: string, right: string): number {\n if (left < right) return -1;\n if (left > right) return 1;\n return 0;\n}\n\nfunction compareAppElementsSlotBindingsBySlotId(\n left: Pick<AppElementsSlotBinding, \"slotId\">,\n right: Pick<AppElementsSlotBinding, \"slotId\">,\n): number {\n return compareAppElementsSlotIds(left.slotId, right.slotId);\n}\n\nexport function normalizeAppElementsSlotBindings(\n slotBindings: readonly AppElementsSlotBinding[],\n options: { layoutIds?: readonly string[] } = {},\n): readonly AppElementsSlotBinding[] {\n const ownerLayoutIds = options.layoutIds ? new Set(options.layoutIds) : null;\n const seenSlotIds = new Set<string>();\n const normalized: AppElementsSlotBinding[] = [];\n\n for (const binding of slotBindings) {\n if (seenSlotIds.has(binding.slotId)) {\n throw new Error(\"[vinext] Invalid __slotBindings in App Router payload: duplicate slot id\");\n }\n seenSlotIds.add(binding.slotId);\n\n if (\n ownerLayoutIds &&\n binding.ownerLayoutId !== null &&\n !ownerLayoutIds.has(binding.ownerLayoutId)\n ) {\n throw new Error(\n \"[vinext] Invalid __slotBindings in App Router payload: owner layout id missing from __layoutIds\",\n );\n }\n\n normalized.push({ ...binding });\n }\n\n return normalized.sort(compareAppElementsSlotBindingsBySlotId);\n}\n\nexport type AppElementValue =\n | ReactNode\n | typeof UNMATCHED_SLOT\n | string\n | null\n | LayoutFlags\n | ArtifactCompatibilityEnvelope\n | CacheEntryReuseProof\n | AppElementsInterception\n | readonly AppElementsSlotBinding[];\ntype AppWireElementValue =\n | ReactNode\n | string\n | null\n | LayoutFlags\n | ArtifactCompatibilityEnvelope\n | CacheEntryReuseProof\n | AppElementsInterception\n | readonly AppElementsSlotBinding[];\n\nexport type AppElements = Readonly<Record<string, AppElementValue>>;\nexport type AppWireElements = Readonly<Record<string, AppWireElementValue>>;\n\n/**\n * Per-layout static/dynamic flags. `\"s\"` = static (skippable on next nav);\n * `\"d\"` = dynamic (must always render).\n *\n * Lifecycle (partial — later PRs extend this):\n *\n * 1. PROBE — probeAppPageLayouts (server/app-page-execution.ts) returns\n * LayoutFlags for every layout in the route at render time.\n *\n * 2. ATTACH — AppElementsWire.encodeOutgoingPayload writes `__layoutFlags`\n * into the outgoing App Router payload record.\n *\n * 3. WIRE — renderToReadableStream serializes the record as RSC row 0.\n *\n * 4. PARSE — AppElementsWire.readMetadata extracts layoutFlags from the\n * wire payload on the client side.\n */\nexport type LayoutFlags = Readonly<Record<string, \"s\" | \"d\">>;\n\ntype AppElementsMetadata = {\n artifactCompatibility: ArtifactCompatibilityEnvelope;\n cacheEntryReuseProof?: CacheEntryReuseProof;\n interception: AppElementsInterception | null;\n interceptionContext: string | null;\n layoutIds: readonly string[];\n layoutFlags: LayoutFlags;\n routeId: string;\n rootLayoutTreePath: string | null;\n slotBindings: readonly AppElementsSlotBinding[];\n};\n\ntype AppElementsWireElementKey =\n | { kind: \"layout\"; treePath: string }\n | { interceptionContext: string | null; kind: \"page\"; path: string }\n | { interceptionContext: string | null; kind: \"route\"; path: string }\n | { kind: \"slot\"; name: string; treePath: string }\n | { kind: \"template\"; treePath: string };\n\ntype AppElementsWireMetadataInput = {\n interception?: AppElementsInterception | null;\n interceptionContext: string | null;\n layoutIds?: readonly string[];\n routeId: string;\n rootLayoutTreePath: string | null;\n slotBindings?: readonly AppElementsSlotBinding[];\n};\n\ntype AppElementsWireMetadataEntries = Readonly<{\n [APP_ROUTE_KEY]: string;\n [APP_INTERCEPTION_KEY]?: AppElementsInterception;\n [APP_INTERCEPTION_CONTEXT_KEY]: string | null;\n [APP_LAYOUT_IDS_KEY]: readonly string[];\n [APP_ROOT_LAYOUT_KEY]: string | null;\n [APP_SLOT_BINDINGS_KEY]?: readonly AppElementsSlotBinding[];\n}>;\n\n/**\n * The outgoing wire payload shape. Includes ReactNode values for the\n * rendered tree plus metadata values like LayoutFlags attached under\n * known keys (e.g. __layoutFlags). Distinct from AppElements / AppWireElements\n * which only carry render-time values.\n */\nexport type AppOutgoingElements = Readonly<\n Record<\n string,\n | ReactNode\n | LayoutFlags\n | ArtifactCompatibilityEnvelope\n | CacheEntryReuseProof\n | AppElementsInterception\n | RenderObservation\n | readonly AppElementsSlotBinding[]\n >\n>;\n\ntype AppElementsWireKeys = {\n readonly artifactCompatibility: typeof APP_ARTIFACT_COMPATIBILITY_KEY;\n readonly cacheEntryReuseProof: typeof APP_CACHE_ENTRY_REUSE_PROOF_KEY;\n readonly interception: typeof APP_INTERCEPTION_KEY;\n readonly interceptionContext: typeof APP_INTERCEPTION_CONTEXT_KEY;\n readonly layoutIds: typeof APP_LAYOUT_IDS_KEY;\n readonly layoutFlags: typeof APP_LAYOUT_FLAGS_KEY;\n readonly renderObservation: typeof APP_RENDER_OBSERVATION_KEY;\n readonly rootLayout: typeof APP_ROOT_LAYOUT_KEY;\n readonly route: typeof APP_ROUTE_KEY;\n readonly slotBindings: typeof APP_SLOT_BINDINGS_KEY;\n};\n\ntype AppElementsWireCodec = {\n readonly keys: AppElementsWireKeys;\n readonly unmatchedSlotValue: typeof APP_UNMATCHED_SLOT_WIRE_VALUE;\n createMetadataEntries(input: AppElementsWireMetadataInput): AppElementsWireMetadataEntries;\n decode(elements: AppWireElements): AppElements;\n encodeCacheKey(rscUrl: string, interceptionContext: string | null): string;\n encodeLayoutId(treePath: string): string;\n encodeOutgoingPayload(input: {\n element:\n | ReactNode\n | Readonly<\n Record<string, ReactNode | AppElementsInterception | readonly AppElementsSlotBinding[]>\n >;\n artifactCompatibility?: ArtifactCompatibilityEnvelope;\n cacheEntryReuseProof?: CacheEntryReuseProof;\n layoutFlags: LayoutFlags;\n renderObservation?: RenderObservation;\n }): ReactNode | AppOutgoingElements;\n encodePageId(routePath: string, interceptionContext: string | null): string;\n encodeRouteId(routePath: string, interceptionContext: string | null): string;\n encodeSlotId(slotName: string, treePath: string): string;\n encodeTemplateId(treePath: string): string;\n isSlotId(key: string): boolean;\n parseElementKey(key: string): AppElementsWireElementKey | null;\n readMetadata(elements: Readonly<Record<string, unknown>>): AppElementsMetadata;\n withLayoutFlags<T extends Record<string, unknown>>(\n elements: T,\n layoutFlags: LayoutFlags,\n ): T & { [APP_LAYOUT_FLAGS_KEY]: LayoutFlags };\n};\n\nfunction appendInterceptionContext(identity: string, interceptionContext: string | null): string {\n return interceptionContext === null\n ? identity\n : `${identity}${APP_INTERCEPTION_SEPARATOR}${interceptionContext}`;\n}\n\nfunction createAppPayloadRouteId(routePath: string, interceptionContext: string | null): string {\n return appendInterceptionContext(`route:${routePath}`, interceptionContext);\n}\n\nfunction createAppPayloadPageId(routePath: string, interceptionContext: string | null): string {\n return appendInterceptionContext(`page:${routePath}`, interceptionContext);\n}\n\nfunction createAppPayloadLayoutId(treePath: string): string {\n return `layout:${treePath}`;\n}\n\nfunction createAppPayloadTemplateId(treePath: string): string {\n return `template:${treePath}`;\n}\n\nfunction createAppPayloadSlotId(slotName: string, treePath: string): string {\n return `slot:${slotName}:${treePath}`;\n}\n\nfunction createAppPayloadCacheKey(rscUrl: string, interceptionContext: string | null): string {\n return appendInterceptionContext(rscUrl, interceptionContext);\n}\n\nfunction parsePathWithInterception(input: string): {\n interceptionContext: string | null;\n path: string;\n} | null {\n const separatorIndex = input.indexOf(APP_INTERCEPTION_SEPARATOR);\n const path = separatorIndex === -1 ? input : input.slice(0, separatorIndex);\n if (!path.startsWith(\"/\")) return null;\n\n return {\n interceptionContext: separatorIndex === -1 ? null : input.slice(separatorIndex + 1),\n path,\n };\n}\n\n/**\n * AppElements tree paths are absolute route-tree paths on the wire.\n * Bare segment names are not valid layout/template/slot tree identities.\n */\nfunction parseTreePath(input: string): string | null {\n return input.startsWith(\"/\") ? input : null;\n}\n\nfunction parseAppElementsWireElementKey(key: string): AppElementsWireElementKey | null {\n if (key.startsWith(\"route:\")) {\n const parsed = parsePathWithInterception(key.slice(\"route:\".length));\n if (!parsed) return null;\n return { interceptionContext: parsed.interceptionContext, kind: \"route\", path: parsed.path };\n }\n\n if (key.startsWith(\"page:\")) {\n const parsed = parsePathWithInterception(key.slice(\"page:\".length));\n if (!parsed) return null;\n return { interceptionContext: parsed.interceptionContext, kind: \"page\", path: parsed.path };\n }\n\n if (key.startsWith(\"layout:\")) {\n const treePath = parseTreePath(key.slice(\"layout:\".length));\n return treePath ? { kind: \"layout\", treePath } : null;\n }\n\n if (key.startsWith(\"template:\")) {\n const treePath = parseTreePath(key.slice(\"template:\".length));\n return treePath ? { kind: \"template\", treePath } : null;\n }\n\n if (key.startsWith(\"slot:\")) {\n const body = key.slice(\"slot:\".length);\n const separatorIndex = body.indexOf(\":\");\n if (separatorIndex <= 0) return null;\n const name = body.slice(0, separatorIndex);\n const treePath = parseTreePath(body.slice(separatorIndex + 1));\n return treePath ? { kind: \"slot\", name, treePath } : null;\n }\n\n return null;\n}\n\nfunction isAppElementsWireSlotId(key: string): boolean {\n if (!key.startsWith(\"slot:\")) return false;\n const body = key.slice(\"slot:\".length);\n const separatorIndex = body.indexOf(\":\");\n return separatorIndex > 0 && body.charCodeAt(separatorIndex + 1) === 0x2f;\n}\n\nfunction createAppElementsWireMetadataEntries(\n input: AppElementsWireMetadataInput,\n): AppElementsWireMetadataEntries {\n const layoutIds = [...(input.layoutIds ?? [])];\n const entries: AppElementsWireMetadataEntries = {\n [APP_ROUTE_KEY]: input.routeId,\n [APP_INTERCEPTION_CONTEXT_KEY]: input.interceptionContext,\n [APP_LAYOUT_IDS_KEY]: layoutIds,\n [APP_ROOT_LAYOUT_KEY]: input.rootLayoutTreePath,\n };\n // Empty slot binding metadata is intentionally omitted. Missing\n // __slotBindings round-trips as [] and means \"no route-state proof\", so\n // default/unmatched slot preservation is not promoted for that payload.\n const entriesWithInterception = input.interception\n ? { ...entries, [APP_INTERCEPTION_KEY]: input.interception }\n : entries;\n if (input.slotBindings && input.slotBindings.length > 0) {\n return {\n ...entriesWithInterception,\n [APP_SLOT_BINDINGS_KEY]: normalizeAppElementsSlotBindings(input.slotBindings, { layoutIds }),\n };\n }\n return entriesWithInterception;\n}\n\nexport function normalizeAppElements(elements: AppWireElements): AppElements {\n let needsNormalization = false;\n for (const [key, value] of Object.entries(elements)) {\n if (isAppElementsWireSlotId(key) && value === APP_UNMATCHED_SLOT_WIRE_VALUE) {\n needsNormalization = true;\n break;\n }\n }\n\n if (!needsNormalization) {\n return elements;\n }\n\n const normalized: Record<string, AppElementValue> = {};\n for (const [key, value] of Object.entries(elements)) {\n normalized[key] =\n isAppElementsWireSlotId(key) && value === APP_UNMATCHED_SLOT_WIRE_VALUE\n ? UNMATCHED_SLOT\n : value;\n }\n\n return normalized;\n}\n\nfunction isLayoutFlagsRecord(value: unknown): value is LayoutFlags {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return false;\n for (const v of Object.values(value)) {\n if (v !== \"s\" && v !== \"d\") return false;\n }\n return true;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction parseLayoutFlags(value: unknown): LayoutFlags {\n if (isLayoutFlagsRecord(value)) return value;\n return {};\n}\n\nfunction parseLayoutIds(value: unknown): readonly string[] {\n if (value === undefined) return [];\n if (!Array.isArray(value)) {\n throw new Error(\n \"[vinext] Invalid __layoutIds in App Router payload: expected layout id string[]\",\n );\n }\n\n const layoutIds: string[] = [];\n for (const entry of value) {\n if (typeof entry !== \"string\") {\n throw new Error(\n \"[vinext] Invalid __layoutIds in App Router payload: expected layout id string[]\",\n );\n }\n\n const parsed = parseAppElementsWireElementKey(entry);\n if (parsed?.kind !== \"layout\") {\n throw new Error(\"[vinext] Invalid __layoutIds in App Router payload: expected layout ids\");\n }\n\n layoutIds.push(entry);\n }\n return layoutIds;\n}\n\nfunction isSlotBindingState(value: unknown): value is AppElementsSlotBindingState {\n return value === \"active\" || value === \"default\" || value === \"unmatched\";\n}\n\nfunction parseSlotBindings(\n value: unknown,\n options: { layoutIds?: readonly string[] } = {},\n): readonly AppElementsSlotBinding[] {\n // Missing metadata is compatibility-safe but not semantic proof: callers see\n // an empty binding list, so promoted default/unmatched slot preservation is\n // denied instead of inferred from legacy transport shape.\n if (value === undefined) return [];\n if (!Array.isArray(value)) {\n throw new Error(\"[vinext] Invalid __slotBindings in App Router payload: expected array\");\n }\n\n const slotBindings: AppElementsSlotBinding[] = [];\n for (const entry of value) {\n if (!isRecord(entry)) {\n throw new Error(\"[vinext] Invalid __slotBindings in App Router payload: expected objects\");\n }\n\n const slotId = entry.slotId;\n if (typeof slotId !== \"string\" || parseAppElementsWireElementKey(slotId)?.kind !== \"slot\") {\n throw new Error(\"[vinext] Invalid __slotBindings in App Router payload: expected slot ids\");\n }\n\n const ownerLayoutId = entry.ownerLayoutId;\n if (\n ownerLayoutId !== null &&\n (typeof ownerLayoutId !== \"string\" ||\n parseAppElementsWireElementKey(ownerLayoutId)?.kind !== \"layout\")\n ) {\n throw new Error(\n \"[vinext] Invalid __slotBindings in App Router payload: expected owner layout ids\",\n );\n }\n\n const state = entry.state;\n if (!isSlotBindingState(state)) {\n throw new Error(\"[vinext] Invalid __slotBindings in App Router payload: expected state\");\n }\n\n slotBindings.push({ ownerLayoutId, slotId, state });\n }\n return normalizeAppElementsSlotBindings(slotBindings, options);\n}\n\nfunction readRequiredInterceptionString(\n entry: Record<string, unknown>,\n fieldName: keyof AppElementsInterception,\n): string {\n const value = entry[fieldName];\n if (typeof value !== \"string\") {\n throw new Error(\"[vinext] Invalid __interception in App Router payload: expected strings\");\n }\n return value;\n}\n\nfunction parseInterceptionMatchedUrl(value: string): string {\n if (!isInterceptionMatchedUrlPath(value)) {\n throw new Error(\"[vinext] Invalid __interception in App Router payload: expected path URLs\");\n }\n return value;\n}\n\nfunction parseInterceptionRouteId(value: string, matchedUrl: string): string {\n const parsed = parseAppElementsWireElementKey(value);\n if (\n parsed?.kind !== \"route\" ||\n parsed.path !== matchedUrl ||\n parsed.interceptionContext !== null\n ) {\n throw new Error(\"[vinext] Invalid __interception in App Router payload: expected route ids\");\n }\n return value;\n}\n\nfunction parseInterceptionSlotId(value: string): string {\n if (parseAppElementsWireElementKey(value)?.kind !== \"slot\") {\n throw new Error(\"[vinext] Invalid __interception in App Router payload: expected slot id\");\n }\n return value;\n}\n\nfunction parseInterceptionMetadata(value: unknown): AppElementsInterception | null {\n if (value === undefined || value === null) return null;\n if (!isRecord(value)) {\n throw new Error(\"[vinext] Invalid __interception in App Router payload: expected object\");\n }\n\n const sourceMatchedUrl = parseInterceptionMatchedUrl(\n readRequiredInterceptionString(value, \"sourceMatchedUrl\"),\n );\n const targetMatchedUrl = parseInterceptionMatchedUrl(\n readRequiredInterceptionString(value, \"targetMatchedUrl\"),\n );\n return {\n sourceMatchedUrl,\n sourceRouteId: parseInterceptionRouteId(\n readRequiredInterceptionString(value, \"sourceRouteId\"),\n sourceMatchedUrl,\n ),\n slotId: parseInterceptionSlotId(readRequiredInterceptionString(value, \"slotId\")),\n targetMatchedUrl,\n targetRouteId: parseInterceptionRouteId(\n readRequiredInterceptionString(value, \"targetRouteId\"),\n targetMatchedUrl,\n ),\n };\n}\n\n/**\n * Type predicate for a plain (non-null, non-array) record of app payload values.\n * Used to distinguish the App Router payload object from bare React elements at\n * the render boundary. Narrows to `Readonly<Record<string, unknown>>` because\n * the outgoing payload carries heterogeneous values (ReactNodes for the rendered\n * tree, plus metadata like `__layoutFlags` which is a plain object). Delegates\n * to React's canonical `isValidElement` so we don't depend on React's internal\n * `$$typeof` marker scheme.\n */\nexport function isAppElementsRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n if (typeof value !== \"object\" || value === null) return false;\n if (Array.isArray(value)) return false;\n if (isValidElement(value)) return false;\n return true;\n}\n\nexport function withLayoutFlags<T extends Record<string, unknown>>(\n elements: T,\n layoutFlags: LayoutFlags,\n): T & { [APP_LAYOUT_FLAGS_KEY]: LayoutFlags } {\n return { ...elements, [APP_LAYOUT_FLAGS_KEY]: layoutFlags };\n}\n\nexport function buildOutgoingAppPayload(input: {\n element:\n | ReactNode\n | Readonly<\n Record<string, ReactNode | AppElementsInterception | readonly AppElementsSlotBinding[]>\n >;\n artifactCompatibility?: ArtifactCompatibilityEnvelope;\n cacheEntryReuseProof?: CacheEntryReuseProof;\n layoutFlags: LayoutFlags;\n renderObservation?: RenderObservation;\n}): ReactNode | AppOutgoingElements {\n if (!isAppElementsRecord(input.element)) {\n return input.element;\n }\n const payload: Record<\n string,\n | ReactNode\n | LayoutFlags\n | ArtifactCompatibilityEnvelope\n | CacheEntryReuseProof\n | AppElementsInterception\n | RenderObservation\n | readonly AppElementsSlotBinding[]\n > = {\n ...input.element,\n [APP_LAYOUT_FLAGS_KEY]: input.layoutFlags,\n [APP_ARTIFACT_COMPATIBILITY_KEY]:\n input.artifactCompatibility ?? createArtifactCompatibilityEnvelope(),\n };\n if (input.cacheEntryReuseProof) {\n payload[APP_CACHE_ENTRY_REUSE_PROOF_KEY] = input.cacheEntryReuseProof;\n }\n if (input.renderObservation) {\n payload[APP_RENDER_OBSERVATION_KEY] = input.renderObservation;\n }\n return payload;\n}\n\nfunction readArtifactCompatibilityMetadata(value: unknown): ArtifactCompatibilityEnvelope {\n if (value === undefined) return createArtifactCompatibilityEnvelope();\n\n const artifactCompatibility = parseArtifactCompatibilityEnvelope(value);\n // TODO(#726-COMPAT-04): hard-fail malformed compatibility metadata once\n // cache/skip consumers depend on this proof. During Wave01 the field is\n // emitted as scaffolding, so bad or future-version values degrade like\n // missing __layoutFlags instead of crashing render paths that do not read it.\n return artifactCompatibility ?? createArtifactCompatibilityEnvelope();\n}\n\nfunction createMissingCacheEntryReuseProof(): CacheEntryReuseProof {\n return {\n kind: \"runtime-cache-entry\",\n decision: null,\n };\n}\n\nfunction isCacheProofRejectionCode(value: unknown): value is CacheProofRejectionCode {\n return typeof value === \"string\" && CACHE_PROOF_REJECTION_CODES.has(value);\n}\n\nfunction isCacheProofFallbackMode(value: unknown): value is CacheProofBreakerFallbackMode {\n return value === \"renderFresh\" || value === \"privateUncacheable\";\n}\n\nfunction isCacheProofFallbackScope(value: unknown): value is CacheProofFallbackScope {\n return value === \"affectedOutput\" || value === \"route\";\n}\n\n// Three-way wire semantics are intentional:\n// - null means the proof field was absent and no cache authority was claimed.\n// - { decision: null } means a present proof was malformed or unusable.\n// - { decision: ... } means the proof parsed into an explicit reuse decision.\nfunction parseCacheEntryReuseProofMetadata(value: unknown): CacheEntryReuseProof | null {\n if (value === undefined) return null;\n if (!isRecord(value) || value.kind !== \"runtime-cache-entry\") {\n return createMissingCacheEntryReuseProof();\n }\n\n const decision = value.decision;\n if (decision === null) return createMissingCacheEntryReuseProof();\n if (!isRecord(decision)) return createMissingCacheEntryReuseProof();\n\n if (\n decision.kind === \"reuse\" &&\n decision.canReuse === true &&\n decision.code === \"CP_STATIC_LAYOUT_REUSE_PROVEN\" &&\n // Static layout proofs are the only runtime cache-entry reuse class today.\n // Extend this parser alongside any new reuse class before it can restore\n // visited cache entries as commit-capable payloads.\n decision.reuseClass === \"static-layout\"\n ) {\n return {\n kind: \"runtime-cache-entry\",\n decision: {\n canReuse: true,\n code: decision.code,\n kind: \"reuse\",\n reuseClass: decision.reuseClass,\n },\n };\n }\n\n if (\n decision.kind === \"reject\" &&\n decision.canReuse === false &&\n isCacheProofRejectionCode(decision.code) &&\n isCacheProofFallbackMode(decision.mode) &&\n isCacheProofFallbackScope(decision.scope)\n ) {\n return {\n kind: \"runtime-cache-entry\",\n decision: {\n canReuse: false,\n code: decision.code,\n kind: \"reject\",\n mode: decision.mode,\n scope: decision.scope,\n },\n };\n }\n\n return createMissingCacheEntryReuseProof();\n}\n\nexport function readAppElementsMetadata(\n elements: Readonly<Record<string, unknown>>,\n): AppElementsMetadata {\n const routeId = elements[APP_ROUTE_KEY];\n if (typeof routeId !== \"string\") {\n throw new Error(\"[vinext] Missing __route string in App Router payload\");\n }\n\n const interceptionContext = elements[APP_INTERCEPTION_CONTEXT_KEY];\n if (\n interceptionContext !== undefined &&\n interceptionContext !== null &&\n typeof interceptionContext !== \"string\"\n ) {\n throw new Error(\"[vinext] Invalid __interceptionContext in App Router payload\");\n }\n\n const rootLayoutTreePath = elements[APP_ROOT_LAYOUT_KEY];\n if (rootLayoutTreePath === undefined) {\n throw new Error(\"[vinext] Missing __rootLayout key in App Router payload\");\n }\n if (rootLayoutTreePath !== null && typeof rootLayoutTreePath !== \"string\") {\n throw new Error(\"[vinext] Invalid __rootLayout in App Router payload: expected string or null\");\n }\n\n const layoutFlags = parseLayoutFlags(elements[APP_LAYOUT_FLAGS_KEY]);\n const layoutIds = parseLayoutIds(elements[APP_LAYOUT_IDS_KEY]);\n const slotBindings = parseSlotBindings(elements[APP_SLOT_BINDINGS_KEY], { layoutIds });\n const interception = parseInterceptionMetadata(elements[APP_INTERCEPTION_KEY]);\n const artifactCompatibility = readArtifactCompatibilityMetadata(\n elements[APP_ARTIFACT_COMPATIBILITY_KEY],\n );\n const cacheEntryReuseProof = parseCacheEntryReuseProofMetadata(\n elements[APP_CACHE_ENTRY_REUSE_PROOF_KEY],\n );\n\n return {\n artifactCompatibility,\n ...(cacheEntryReuseProof ? { cacheEntryReuseProof } : {}),\n interception,\n interceptionContext: interceptionContext ?? null,\n layoutIds,\n layoutFlags,\n routeId,\n rootLayoutTreePath,\n slotBindings,\n };\n}\n\nexport const AppElementsWire: AppElementsWireCodec = {\n // WIRE follow-ups use these stable key names when moving payload readers and writers\n // behind the codec boundary.\n keys: {\n artifactCompatibility: APP_ARTIFACT_COMPATIBILITY_KEY,\n cacheEntryReuseProof: APP_CACHE_ENTRY_REUSE_PROOF_KEY,\n interception: APP_INTERCEPTION_KEY,\n interceptionContext: APP_INTERCEPTION_CONTEXT_KEY,\n layoutIds: APP_LAYOUT_IDS_KEY,\n layoutFlags: APP_LAYOUT_FLAGS_KEY,\n renderObservation: APP_RENDER_OBSERVATION_KEY,\n rootLayout: APP_ROOT_LAYOUT_KEY,\n route: APP_ROUTE_KEY,\n slotBindings: APP_SLOT_BINDINGS_KEY,\n },\n unmatchedSlotValue: APP_UNMATCHED_SLOT_WIRE_VALUE,\n createMetadataEntries: createAppElementsWireMetadataEntries,\n decode: normalizeAppElements,\n encodeCacheKey: createAppPayloadCacheKey,\n encodeLayoutId: createAppPayloadLayoutId,\n encodeOutgoingPayload: buildOutgoingAppPayload,\n encodePageId: createAppPayloadPageId,\n encodeRouteId: createAppPayloadRouteId,\n encodeSlotId: createAppPayloadSlotId,\n encodeTemplateId: createAppPayloadTemplateId,\n isSlotId: isAppElementsWireSlotId,\n parseElementKey: parseAppElementsWireElementKey,\n readMetadata: readAppElementsMetadata,\n withLayoutFlags,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"app-elements-wire.js","names":[],"sources":["../../src/server/app-elements-wire.ts"],"sourcesContent":["import { isValidElement, type ReactNode } from \"react\";\nimport {\n createArtifactCompatibilityEnvelope,\n parseArtifactCompatibilityEnvelope,\n type ArtifactCompatibilityEnvelope,\n} from \"./artifact-compatibility.js\";\nimport type {\n CacheEntryReuseProof,\n CacheProofBreakerFallbackMode,\n CacheProofFallbackScope,\n CacheProofRejectionCode,\n RenderObservation,\n} from \"./cache-proof.js\";\nimport { isInterceptionMatchedUrlPath } from \"./normalize-path.js\";\n\nconst APP_INTERCEPTION_SEPARATOR = \"\\0\";\n\nexport const APP_ARTIFACT_COMPATIBILITY_KEY = \"__artifactCompatibility\";\nexport const APP_CACHE_ENTRY_REUSE_PROOF_KEY = \"__cacheEntryReuseProof\";\nexport const APP_INTERCEPTION_KEY = \"__interception\";\nexport const APP_INTERCEPTION_CONTEXT_KEY = \"__interceptionContext\";\nexport const APP_LAYOUT_IDS_KEY = \"__layoutIds\";\nexport const APP_LAYOUT_FLAGS_KEY = \"__layoutFlags\";\nexport const APP_RENDER_OBSERVATION_KEY = \"__renderObservation\";\nexport const APP_ROUTE_KEY = \"__route\";\nexport const APP_ROOT_LAYOUT_KEY = \"__rootLayout\";\nexport const APP_SLOT_BINDINGS_KEY = \"__slotBindings\";\n/**\n * Static sibling segment names for the matched route, surfaced so the client\n * router can determine if a cached prefetch of a dynamic route can be reused\n * when navigating to a static sibling URL.\n *\n * Mirrors Next.js's `staticSiblings` tuple element on the loader-tree dynamic\n * segments (issue cloudflare/vinext#1525).\n */\nexport const APP_STATIC_SIBLINGS_KEY = \"__staticSiblings\";\nexport const APP_UNMATCHED_SLOT_WIRE_VALUE = \"__VINEXT_UNMATCHED_SLOT__\";\n\nexport const UNMATCHED_SLOT = Symbol.for(\"vinext.unmatchedSlot\");\n\nfunction createCacheProofRejectionCodeSet<const T extends readonly CacheProofRejectionCode[]>(\n codes: T &\n ([CacheProofRejectionCode] extends [T[number]]\n ? unknown\n : readonly [\n \"Missing cache proof rejection codes\",\n Exclude<CacheProofRejectionCode, T[number]>,\n ]),\n): ReadonlySet<string> {\n return new Set(codes);\n}\n\nconst CACHE_PROOF_REJECTION_CODES = createCacheProofRejectionCodeSet([\n \"CP_CACHE_ENTRY_PROOF_MISSING\",\n \"CP_MODEL_DISABLED\",\n \"CP_ARTIFACT_COMPATIBILITY_INCOMPATIBLE\",\n \"CP_ARTIFACT_COMPATIBILITY_UNKNOWN\",\n \"CP_DIMENSION_COUNT_EXCEEDED\",\n \"CP_DIMENSION_NAME_MISSING\",\n \"CP_DIMENSION_NAME_TOO_LONG\",\n \"CP_DIMENSION_VALUE_COUNT_EXCEEDED\",\n \"CP_DIMENSION_VALUE_TOO_LONG\",\n \"CP_DIMENSION_VALUES_MISSING\",\n \"CP_ENCODED_VARIANT_TOO_LONG\",\n \"CP_INVALID_VARIANT_BUDGET\",\n \"CP_ROUTE_VARIANT_BUDGET_ROUTE_MISMATCH\",\n \"CP_ROUTE_VARIANT_CEILING_EXCEEDED\",\n \"CP_UNSAFE_PUBLIC_DIMENSION\",\n \"CP_BOUNDARY_OUTCOME_MISMATCH\",\n \"CP_BOUNDARY_OUTCOME_UNKNOWN\",\n \"CP_PRIVATE_DYNAMIC_DOWNGRADE\",\n \"CP_STATIC_LAYOUT_CANDIDATE_OUTPUT_KIND\",\n \"CP_STATIC_LAYOUT_CURRENT_OUTPUT_KIND\",\n \"CP_STATIC_LAYOUT_ID_MISMATCH\",\n \"CP_STATIC_LAYOUT_OBSERVATION_OUTPUT_KIND\",\n \"CP_STATIC_LAYOUT_OBSERVATION_OUTPUT_MISMATCH\",\n \"CP_STATIC_LAYOUT_PRIVATE_DYNAMIC_DOWNGRADE\",\n \"CP_STATIC_LAYOUT_REQUEST_API_OBSERVED\",\n \"CP_STATIC_LAYOUT_REQUEST_API_UNKNOWN\",\n \"CP_STATIC_LAYOUT_ROOT_BOUNDARY_MISMATCH\",\n \"CP_STATIC_LAYOUT_ROOT_BOUNDARY_UNKNOWN\",\n \"CP_STATIC_LAYOUT_VARIANT_DIMENSION_UNPROVEN\",\n]);\n\nexport type AppElementsSlotBindingState = \"active\" | \"default\" | \"unmatched\";\n\nexport type AppElementsSlotBinding = Readonly<{\n ownerLayoutId: string | null;\n slotId: string;\n state: AppElementsSlotBindingState;\n}>;\n\nexport type AppElementsInterception = Readonly<{\n sourceMatchedUrl: string;\n sourceRouteId: string;\n slotId: string;\n targetMatchedUrl: string;\n targetRouteId: string;\n}>;\n\nexport function compareAppElementsSlotIds(left: string, right: string): number {\n if (left < right) return -1;\n if (left > right) return 1;\n return 0;\n}\n\nfunction compareAppElementsSlotBindingsBySlotId(\n left: Pick<AppElementsSlotBinding, \"slotId\">,\n right: Pick<AppElementsSlotBinding, \"slotId\">,\n): number {\n return compareAppElementsSlotIds(left.slotId, right.slotId);\n}\n\nexport function normalizeAppElementsSlotBindings(\n slotBindings: readonly AppElementsSlotBinding[],\n options: { layoutIds?: readonly string[] } = {},\n): readonly AppElementsSlotBinding[] {\n const ownerLayoutIds = options.layoutIds ? new Set(options.layoutIds) : null;\n const seenSlotIds = new Set<string>();\n const normalized: AppElementsSlotBinding[] = [];\n\n for (const binding of slotBindings) {\n if (seenSlotIds.has(binding.slotId)) {\n throw new Error(\"[vinext] Invalid __slotBindings in App Router payload: duplicate slot id\");\n }\n seenSlotIds.add(binding.slotId);\n\n if (\n ownerLayoutIds &&\n binding.ownerLayoutId !== null &&\n !ownerLayoutIds.has(binding.ownerLayoutId)\n ) {\n throw new Error(\n \"[vinext] Invalid __slotBindings in App Router payload: owner layout id missing from __layoutIds\",\n );\n }\n\n normalized.push({ ...binding });\n }\n\n return normalized.sort(compareAppElementsSlotBindingsBySlotId);\n}\n\nexport type AppElementValue =\n | ReactNode\n | typeof UNMATCHED_SLOT\n | string\n | null\n | LayoutFlags\n | ArtifactCompatibilityEnvelope\n | CacheEntryReuseProof\n | AppElementsInterception\n | readonly AppElementsSlotBinding[];\ntype AppWireElementValue =\n | ReactNode\n | string\n | null\n | LayoutFlags\n | ArtifactCompatibilityEnvelope\n | CacheEntryReuseProof\n | AppElementsInterception\n | readonly AppElementsSlotBinding[];\n\nexport type AppElements = Readonly<Record<string, AppElementValue>>;\nexport type AppWireElements = Readonly<Record<string, AppWireElementValue>>;\n\n/**\n * Per-layout static/dynamic flags. `\"s\"` = static (skippable on next nav);\n * `\"d\"` = dynamic (must always render).\n *\n * Lifecycle (partial — later PRs extend this):\n *\n * 1. PROBE — probeAppPageLayouts (server/app-page-execution.ts) returns\n * LayoutFlags for every layout in the route at render time.\n *\n * 2. ATTACH — AppElementsWire.encodeOutgoingPayload writes `__layoutFlags`\n * into the outgoing App Router payload record.\n *\n * 3. WIRE — renderToReadableStream serializes the record as RSC row 0.\n *\n * 4. PARSE — AppElementsWire.readMetadata extracts layoutFlags from the\n * wire payload on the client side.\n */\nexport type LayoutFlags = Readonly<Record<string, \"s\" | \"d\">>;\n\ntype AppElementsMetadata = {\n artifactCompatibility: ArtifactCompatibilityEnvelope;\n cacheEntryReuseProof?: CacheEntryReuseProof;\n interception: AppElementsInterception | null;\n interceptionContext: string | null;\n layoutIds: readonly string[];\n layoutFlags: LayoutFlags;\n routeId: string;\n rootLayoutTreePath: string | null;\n slotBindings: readonly AppElementsSlotBinding[];\n};\n\ntype AppElementsWireElementKey =\n | { kind: \"layout\"; treePath: string }\n | { interceptionContext: string | null; kind: \"page\"; path: string }\n | { interceptionContext: string | null; kind: \"route\"; path: string }\n | { kind: \"slot\"; name: string; treePath: string }\n | { kind: \"template\"; treePath: string };\n\ntype AppElementsWireMetadataInput = {\n interception?: AppElementsInterception | null;\n interceptionContext: string | null;\n layoutIds?: readonly string[];\n routeId: string;\n rootLayoutTreePath: string | null;\n slotBindings?: readonly AppElementsSlotBinding[];\n};\n\ntype AppElementsWireMetadataEntries = Readonly<{\n [APP_ROUTE_KEY]: string;\n [APP_INTERCEPTION_KEY]?: AppElementsInterception;\n [APP_INTERCEPTION_CONTEXT_KEY]: string | null;\n [APP_LAYOUT_IDS_KEY]: readonly string[];\n [APP_ROOT_LAYOUT_KEY]: string | null;\n [APP_SLOT_BINDINGS_KEY]?: readonly AppElementsSlotBinding[];\n}>;\n\n/**\n * The outgoing wire payload shape. Includes ReactNode values for the\n * rendered tree plus metadata values like LayoutFlags attached under\n * known keys (e.g. __layoutFlags). Distinct from AppElements / AppWireElements\n * which only carry render-time values.\n */\nexport type AppOutgoingElements = Readonly<\n Record<\n string,\n | ReactNode\n | LayoutFlags\n | ArtifactCompatibilityEnvelope\n | CacheEntryReuseProof\n | AppElementsInterception\n | RenderObservation\n | readonly AppElementsSlotBinding[]\n | readonly string[]\n >\n>;\n\ntype AppElementsWireKeys = {\n readonly artifactCompatibility: typeof APP_ARTIFACT_COMPATIBILITY_KEY;\n readonly cacheEntryReuseProof: typeof APP_CACHE_ENTRY_REUSE_PROOF_KEY;\n readonly interception: typeof APP_INTERCEPTION_KEY;\n readonly interceptionContext: typeof APP_INTERCEPTION_CONTEXT_KEY;\n readonly layoutIds: typeof APP_LAYOUT_IDS_KEY;\n readonly layoutFlags: typeof APP_LAYOUT_FLAGS_KEY;\n readonly renderObservation: typeof APP_RENDER_OBSERVATION_KEY;\n readonly rootLayout: typeof APP_ROOT_LAYOUT_KEY;\n readonly route: typeof APP_ROUTE_KEY;\n readonly slotBindings: typeof APP_SLOT_BINDINGS_KEY;\n};\n\ntype AppElementsWireCodec = {\n readonly keys: AppElementsWireKeys;\n readonly unmatchedSlotValue: typeof APP_UNMATCHED_SLOT_WIRE_VALUE;\n createMetadataEntries(input: AppElementsWireMetadataInput): AppElementsWireMetadataEntries;\n decode(elements: AppWireElements): AppElements;\n encodeCacheKey(rscUrl: string, interceptionContext: string | null): string;\n encodeLayoutId(treePath: string): string;\n encodeOutgoingPayload(input: {\n element:\n | ReactNode\n | Readonly<\n Record<\n string,\n | ReactNode\n | AppElementsInterception\n | readonly AppElementsSlotBinding[]\n | readonly string[]\n >\n >;\n artifactCompatibility?: ArtifactCompatibilityEnvelope;\n cacheEntryReuseProof?: CacheEntryReuseProof;\n layoutFlags: LayoutFlags;\n renderObservation?: RenderObservation;\n }): ReactNode | AppOutgoingElements;\n encodePageId(routePath: string, interceptionContext: string | null): string;\n encodeRouteId(routePath: string, interceptionContext: string | null): string;\n encodeSlotId(slotName: string, treePath: string): string;\n encodeTemplateId(treePath: string): string;\n isSlotId(key: string): boolean;\n parseElementKey(key: string): AppElementsWireElementKey | null;\n readMetadata(elements: Readonly<Record<string, unknown>>): AppElementsMetadata;\n withLayoutFlags<T extends Record<string, unknown>>(\n elements: T,\n layoutFlags: LayoutFlags,\n ): T & { [APP_LAYOUT_FLAGS_KEY]: LayoutFlags };\n};\n\nfunction appendInterceptionContext(identity: string, interceptionContext: string | null): string {\n return interceptionContext === null\n ? identity\n : `${identity}${APP_INTERCEPTION_SEPARATOR}${interceptionContext}`;\n}\n\nfunction createAppPayloadRouteId(routePath: string, interceptionContext: string | null): string {\n return appendInterceptionContext(`route:${routePath}`, interceptionContext);\n}\n\nfunction createAppPayloadPageId(routePath: string, interceptionContext: string | null): string {\n return appendInterceptionContext(`page:${routePath}`, interceptionContext);\n}\n\nfunction createAppPayloadLayoutId(treePath: string): string {\n return `layout:${treePath}`;\n}\n\nfunction createAppPayloadTemplateId(treePath: string): string {\n return `template:${treePath}`;\n}\n\nfunction createAppPayloadSlotId(slotName: string, treePath: string): string {\n return `slot:${slotName}:${treePath}`;\n}\n\nfunction createAppPayloadCacheKey(rscUrl: string, interceptionContext: string | null): string {\n return appendInterceptionContext(rscUrl, interceptionContext);\n}\n\nfunction parsePathWithInterception(input: string): {\n interceptionContext: string | null;\n path: string;\n} | null {\n const separatorIndex = input.indexOf(APP_INTERCEPTION_SEPARATOR);\n const path = separatorIndex === -1 ? input : input.slice(0, separatorIndex);\n if (!path.startsWith(\"/\")) return null;\n\n return {\n interceptionContext: separatorIndex === -1 ? null : input.slice(separatorIndex + 1),\n path,\n };\n}\n\n/**\n * AppElements tree paths are absolute route-tree paths on the wire.\n * Bare segment names are not valid layout/template/slot tree identities.\n */\nfunction parseTreePath(input: string): string | null {\n return input.startsWith(\"/\") ? input : null;\n}\n\nfunction parseAppElementsWireElementKey(key: string): AppElementsWireElementKey | null {\n if (key.startsWith(\"route:\")) {\n const parsed = parsePathWithInterception(key.slice(\"route:\".length));\n if (!parsed) return null;\n return { interceptionContext: parsed.interceptionContext, kind: \"route\", path: parsed.path };\n }\n\n if (key.startsWith(\"page:\")) {\n const parsed = parsePathWithInterception(key.slice(\"page:\".length));\n if (!parsed) return null;\n return { interceptionContext: parsed.interceptionContext, kind: \"page\", path: parsed.path };\n }\n\n if (key.startsWith(\"layout:\")) {\n const treePath = parseTreePath(key.slice(\"layout:\".length));\n return treePath ? { kind: \"layout\", treePath } : null;\n }\n\n if (key.startsWith(\"template:\")) {\n const treePath = parseTreePath(key.slice(\"template:\".length));\n return treePath ? { kind: \"template\", treePath } : null;\n }\n\n if (key.startsWith(\"slot:\")) {\n const body = key.slice(\"slot:\".length);\n const separatorIndex = body.indexOf(\":\");\n if (separatorIndex <= 0) return null;\n const name = body.slice(0, separatorIndex);\n const treePath = parseTreePath(body.slice(separatorIndex + 1));\n return treePath ? { kind: \"slot\", name, treePath } : null;\n }\n\n return null;\n}\n\nfunction isAppElementsWireSlotId(key: string): boolean {\n if (!key.startsWith(\"slot:\")) return false;\n const body = key.slice(\"slot:\".length);\n const separatorIndex = body.indexOf(\":\");\n return separatorIndex > 0 && body.charCodeAt(separatorIndex + 1) === 0x2f;\n}\n\nfunction createAppElementsWireMetadataEntries(\n input: AppElementsWireMetadataInput,\n): AppElementsWireMetadataEntries {\n const layoutIds = [...(input.layoutIds ?? [])];\n const entries: AppElementsWireMetadataEntries = {\n [APP_ROUTE_KEY]: input.routeId,\n [APP_INTERCEPTION_CONTEXT_KEY]: input.interceptionContext,\n [APP_LAYOUT_IDS_KEY]: layoutIds,\n [APP_ROOT_LAYOUT_KEY]: input.rootLayoutTreePath,\n };\n // Empty slot binding metadata is intentionally omitted. Missing\n // __slotBindings round-trips as [] and means \"no route-state proof\", so\n // default/unmatched slot preservation is not promoted for that payload.\n const entriesWithInterception = input.interception\n ? { ...entries, [APP_INTERCEPTION_KEY]: input.interception }\n : entries;\n if (input.slotBindings && input.slotBindings.length > 0) {\n return {\n ...entriesWithInterception,\n [APP_SLOT_BINDINGS_KEY]: normalizeAppElementsSlotBindings(input.slotBindings, { layoutIds }),\n };\n }\n return entriesWithInterception;\n}\n\nexport function normalizeAppElements(elements: AppWireElements): AppElements {\n let needsNormalization = false;\n for (const [key, value] of Object.entries(elements)) {\n if (isAppElementsWireSlotId(key) && value === APP_UNMATCHED_SLOT_WIRE_VALUE) {\n needsNormalization = true;\n break;\n }\n }\n\n if (!needsNormalization) {\n return elements;\n }\n\n const normalized: Record<string, AppElementValue> = {};\n for (const [key, value] of Object.entries(elements)) {\n normalized[key] =\n isAppElementsWireSlotId(key) && value === APP_UNMATCHED_SLOT_WIRE_VALUE\n ? UNMATCHED_SLOT\n : value;\n }\n\n return normalized;\n}\n\nfunction isLayoutFlagsRecord(value: unknown): value is LayoutFlags {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return false;\n for (const v of Object.values(value)) {\n if (v !== \"s\" && v !== \"d\") return false;\n }\n return true;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction parseLayoutFlags(value: unknown): LayoutFlags {\n if (isLayoutFlagsRecord(value)) return value;\n return {};\n}\n\nfunction parseLayoutIds(value: unknown): readonly string[] {\n if (value === undefined) return [];\n if (!Array.isArray(value)) {\n throw new Error(\n \"[vinext] Invalid __layoutIds in App Router payload: expected layout id string[]\",\n );\n }\n\n const layoutIds: string[] = [];\n for (const entry of value) {\n if (typeof entry !== \"string\") {\n throw new Error(\n \"[vinext] Invalid __layoutIds in App Router payload: expected layout id string[]\",\n );\n }\n\n const parsed = parseAppElementsWireElementKey(entry);\n if (parsed?.kind !== \"layout\") {\n throw new Error(\"[vinext] Invalid __layoutIds in App Router payload: expected layout ids\");\n }\n\n layoutIds.push(entry);\n }\n return layoutIds;\n}\n\nfunction isSlotBindingState(value: unknown): value is AppElementsSlotBindingState {\n return value === \"active\" || value === \"default\" || value === \"unmatched\";\n}\n\nfunction parseSlotBindings(\n value: unknown,\n options: { layoutIds?: readonly string[] } = {},\n): readonly AppElementsSlotBinding[] {\n // Missing metadata is compatibility-safe but not semantic proof: callers see\n // an empty binding list, so promoted default/unmatched slot preservation is\n // denied instead of inferred from legacy transport shape.\n if (value === undefined) return [];\n if (!Array.isArray(value)) {\n throw new Error(\"[vinext] Invalid __slotBindings in App Router payload: expected array\");\n }\n\n const slotBindings: AppElementsSlotBinding[] = [];\n for (const entry of value) {\n if (!isRecord(entry)) {\n throw new Error(\"[vinext] Invalid __slotBindings in App Router payload: expected objects\");\n }\n\n const slotId = entry.slotId;\n if (typeof slotId !== \"string\" || parseAppElementsWireElementKey(slotId)?.kind !== \"slot\") {\n throw new Error(\"[vinext] Invalid __slotBindings in App Router payload: expected slot ids\");\n }\n\n const ownerLayoutId = entry.ownerLayoutId;\n if (\n ownerLayoutId !== null &&\n (typeof ownerLayoutId !== \"string\" ||\n parseAppElementsWireElementKey(ownerLayoutId)?.kind !== \"layout\")\n ) {\n throw new Error(\n \"[vinext] Invalid __slotBindings in App Router payload: expected owner layout ids\",\n );\n }\n\n const state = entry.state;\n if (!isSlotBindingState(state)) {\n throw new Error(\"[vinext] Invalid __slotBindings in App Router payload: expected state\");\n }\n\n slotBindings.push({ ownerLayoutId, slotId, state });\n }\n return normalizeAppElementsSlotBindings(slotBindings, options);\n}\n\nfunction readRequiredInterceptionString(\n entry: Record<string, unknown>,\n fieldName: keyof AppElementsInterception,\n): string {\n const value = entry[fieldName];\n if (typeof value !== \"string\") {\n throw new Error(\"[vinext] Invalid __interception in App Router payload: expected strings\");\n }\n return value;\n}\n\nfunction parseInterceptionMatchedUrl(value: string): string {\n if (!isInterceptionMatchedUrlPath(value)) {\n throw new Error(\"[vinext] Invalid __interception in App Router payload: expected path URLs\");\n }\n return value;\n}\n\nfunction parseInterceptionRouteId(value: string, matchedUrl: string): string {\n const parsed = parseAppElementsWireElementKey(value);\n if (\n parsed?.kind !== \"route\" ||\n parsed.path !== matchedUrl ||\n parsed.interceptionContext !== null\n ) {\n throw new Error(\"[vinext] Invalid __interception in App Router payload: expected route ids\");\n }\n return value;\n}\n\nfunction parseInterceptionSlotId(value: string): string {\n if (parseAppElementsWireElementKey(value)?.kind !== \"slot\") {\n throw new Error(\"[vinext] Invalid __interception in App Router payload: expected slot id\");\n }\n return value;\n}\n\nfunction parseInterceptionMetadata(value: unknown): AppElementsInterception | null {\n if (value === undefined || value === null) return null;\n if (!isRecord(value)) {\n throw new Error(\"[vinext] Invalid __interception in App Router payload: expected object\");\n }\n\n const sourceMatchedUrl = parseInterceptionMatchedUrl(\n readRequiredInterceptionString(value, \"sourceMatchedUrl\"),\n );\n const targetMatchedUrl = parseInterceptionMatchedUrl(\n readRequiredInterceptionString(value, \"targetMatchedUrl\"),\n );\n return {\n sourceMatchedUrl,\n sourceRouteId: parseInterceptionRouteId(\n readRequiredInterceptionString(value, \"sourceRouteId\"),\n sourceMatchedUrl,\n ),\n slotId: parseInterceptionSlotId(readRequiredInterceptionString(value, \"slotId\")),\n targetMatchedUrl,\n targetRouteId: parseInterceptionRouteId(\n readRequiredInterceptionString(value, \"targetRouteId\"),\n targetMatchedUrl,\n ),\n };\n}\n\n/**\n * Type predicate for a plain (non-null, non-array) record of app payload values.\n * Used to distinguish the App Router payload object from bare React elements at\n * the render boundary. Narrows to `Readonly<Record<string, unknown>>` because\n * the outgoing payload carries heterogeneous values (ReactNodes for the rendered\n * tree, plus metadata like `__layoutFlags` which is a plain object). Delegates\n * to React's canonical `isValidElement` so we don't depend on React's internal\n * `$$typeof` marker scheme.\n */\nexport function isAppElementsRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n if (typeof value !== \"object\" || value === null) return false;\n if (Array.isArray(value)) return false;\n if (isValidElement(value)) return false;\n return true;\n}\n\nexport function withLayoutFlags<T extends Record<string, unknown>>(\n elements: T,\n layoutFlags: LayoutFlags,\n): T & { [APP_LAYOUT_FLAGS_KEY]: LayoutFlags } {\n return { ...elements, [APP_LAYOUT_FLAGS_KEY]: layoutFlags };\n}\n\nexport function buildOutgoingAppPayload(input: {\n element:\n | ReactNode\n | Readonly<\n Record<\n string,\n | ReactNode\n | AppElementsInterception\n | readonly AppElementsSlotBinding[]\n | readonly string[]\n >\n >;\n artifactCompatibility?: ArtifactCompatibilityEnvelope;\n cacheEntryReuseProof?: CacheEntryReuseProof;\n layoutFlags: LayoutFlags;\n renderObservation?: RenderObservation;\n}): ReactNode | AppOutgoingElements {\n if (!isAppElementsRecord(input.element)) {\n return input.element;\n }\n const payload: Record<\n string,\n | ReactNode\n | LayoutFlags\n | ArtifactCompatibilityEnvelope\n | CacheEntryReuseProof\n | AppElementsInterception\n | RenderObservation\n | readonly AppElementsSlotBinding[]\n | readonly string[]\n > = {\n ...input.element,\n [APP_LAYOUT_FLAGS_KEY]: input.layoutFlags,\n [APP_ARTIFACT_COMPATIBILITY_KEY]:\n input.artifactCompatibility ?? createArtifactCompatibilityEnvelope(),\n };\n if (input.cacheEntryReuseProof) {\n payload[APP_CACHE_ENTRY_REUSE_PROOF_KEY] = input.cacheEntryReuseProof;\n }\n if (input.renderObservation) {\n payload[APP_RENDER_OBSERVATION_KEY] = input.renderObservation;\n }\n return payload;\n}\n\nfunction readArtifactCompatibilityMetadata(value: unknown): ArtifactCompatibilityEnvelope {\n if (value === undefined) return createArtifactCompatibilityEnvelope();\n\n const artifactCompatibility = parseArtifactCompatibilityEnvelope(value);\n // TODO(#726-COMPAT-04): hard-fail malformed compatibility metadata once\n // cache/skip consumers depend on this proof. During Wave01 the field is\n // emitted as scaffolding, so bad or future-version values degrade like\n // missing __layoutFlags instead of crashing render paths that do not read it.\n return artifactCompatibility ?? createArtifactCompatibilityEnvelope();\n}\n\nfunction createMissingCacheEntryReuseProof(): CacheEntryReuseProof {\n return {\n kind: \"runtime-cache-entry\",\n decision: null,\n };\n}\n\nfunction isCacheProofRejectionCode(value: unknown): value is CacheProofRejectionCode {\n return typeof value === \"string\" && CACHE_PROOF_REJECTION_CODES.has(value);\n}\n\nfunction isCacheProofFallbackMode(value: unknown): value is CacheProofBreakerFallbackMode {\n return value === \"renderFresh\" || value === \"privateUncacheable\";\n}\n\nfunction isCacheProofFallbackScope(value: unknown): value is CacheProofFallbackScope {\n return value === \"affectedOutput\" || value === \"route\";\n}\n\n// Three-way wire semantics are intentional:\n// - null means the proof field was absent and no cache authority was claimed.\n// - { decision: null } means a present proof was malformed or unusable.\n// - { decision: ... } means the proof parsed into an explicit reuse decision.\nfunction parseCacheEntryReuseProofMetadata(value: unknown): CacheEntryReuseProof | null {\n if (value === undefined) return null;\n if (!isRecord(value) || value.kind !== \"runtime-cache-entry\") {\n return createMissingCacheEntryReuseProof();\n }\n\n const decision = value.decision;\n if (decision === null) return createMissingCacheEntryReuseProof();\n if (!isRecord(decision)) return createMissingCacheEntryReuseProof();\n\n if (\n decision.kind === \"reuse\" &&\n decision.canReuse === true &&\n decision.code === \"CP_STATIC_LAYOUT_REUSE_PROVEN\" &&\n // Static layout proofs are the only runtime cache-entry reuse class today.\n // Extend this parser alongside any new reuse class before it can restore\n // visited cache entries as commit-capable payloads.\n decision.reuseClass === \"static-layout\"\n ) {\n return {\n kind: \"runtime-cache-entry\",\n decision: {\n canReuse: true,\n code: decision.code,\n kind: \"reuse\",\n reuseClass: decision.reuseClass,\n },\n };\n }\n\n if (\n decision.kind === \"reject\" &&\n decision.canReuse === false &&\n isCacheProofRejectionCode(decision.code) &&\n isCacheProofFallbackMode(decision.mode) &&\n isCacheProofFallbackScope(decision.scope)\n ) {\n return {\n kind: \"runtime-cache-entry\",\n decision: {\n canReuse: false,\n code: decision.code,\n kind: \"reject\",\n mode: decision.mode,\n scope: decision.scope,\n },\n };\n }\n\n return createMissingCacheEntryReuseProof();\n}\n\nexport function readAppElementsMetadata(\n elements: Readonly<Record<string, unknown>>,\n): AppElementsMetadata {\n const routeId = elements[APP_ROUTE_KEY];\n if (typeof routeId !== \"string\") {\n throw new Error(\"[vinext] Missing __route string in App Router payload\");\n }\n\n const interceptionContext = elements[APP_INTERCEPTION_CONTEXT_KEY];\n if (\n interceptionContext !== undefined &&\n interceptionContext !== null &&\n typeof interceptionContext !== \"string\"\n ) {\n throw new Error(\"[vinext] Invalid __interceptionContext in App Router payload\");\n }\n\n const rootLayoutTreePath = elements[APP_ROOT_LAYOUT_KEY];\n if (rootLayoutTreePath === undefined) {\n throw new Error(\"[vinext] Missing __rootLayout key in App Router payload\");\n }\n if (rootLayoutTreePath !== null && typeof rootLayoutTreePath !== \"string\") {\n throw new Error(\"[vinext] Invalid __rootLayout in App Router payload: expected string or null\");\n }\n\n const layoutFlags = parseLayoutFlags(elements[APP_LAYOUT_FLAGS_KEY]);\n const layoutIds = parseLayoutIds(elements[APP_LAYOUT_IDS_KEY]);\n const slotBindings = parseSlotBindings(elements[APP_SLOT_BINDINGS_KEY], { layoutIds });\n const interception = parseInterceptionMetadata(elements[APP_INTERCEPTION_KEY]);\n const artifactCompatibility = readArtifactCompatibilityMetadata(\n elements[APP_ARTIFACT_COMPATIBILITY_KEY],\n );\n const cacheEntryReuseProof = parseCacheEntryReuseProofMetadata(\n elements[APP_CACHE_ENTRY_REUSE_PROOF_KEY],\n );\n\n return {\n artifactCompatibility,\n ...(cacheEntryReuseProof ? { cacheEntryReuseProof } : {}),\n interception,\n interceptionContext: interceptionContext ?? null,\n layoutIds,\n layoutFlags,\n routeId,\n rootLayoutTreePath,\n slotBindings,\n };\n}\n\nexport const AppElementsWire: AppElementsWireCodec = {\n // WIRE follow-ups use these stable key names when moving payload readers and writers\n // behind the codec boundary.\n keys: {\n artifactCompatibility: APP_ARTIFACT_COMPATIBILITY_KEY,\n cacheEntryReuseProof: APP_CACHE_ENTRY_REUSE_PROOF_KEY,\n interception: APP_INTERCEPTION_KEY,\n interceptionContext: APP_INTERCEPTION_CONTEXT_KEY,\n layoutIds: APP_LAYOUT_IDS_KEY,\n layoutFlags: APP_LAYOUT_FLAGS_KEY,\n renderObservation: APP_RENDER_OBSERVATION_KEY,\n rootLayout: APP_ROOT_LAYOUT_KEY,\n route: APP_ROUTE_KEY,\n slotBindings: APP_SLOT_BINDINGS_KEY,\n },\n unmatchedSlotValue: APP_UNMATCHED_SLOT_WIRE_VALUE,\n createMetadataEntries: createAppElementsWireMetadataEntries,\n decode: normalizeAppElements,\n encodeCacheKey: createAppPayloadCacheKey,\n encodeLayoutId: createAppPayloadLayoutId,\n encodeOutgoingPayload: buildOutgoingAppPayload,\n encodePageId: createAppPayloadPageId,\n encodeRouteId: createAppPayloadRouteId,\n encodeSlotId: createAppPayloadSlotId,\n encodeTemplateId: createAppPayloadTemplateId,\n isSlotId: isAppElementsWireSlotId,\n parseElementKey: parseAppElementsWireElementKey,\n readMetadata: readAppElementsMetadata,\n withLayoutFlags,\n};\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SLOT_BINDINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementValue, AppElements, AppElementsInterception, AppElementsSlotBinding, AppElementsWire, AppOutgoingElements, AppWireElements, LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags } from "./app-elements-wire.js";
1
+ import { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SLOT_BINDINGS_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementValue, AppElements, AppElementsInterception, AppElementsSlotBinding, AppElementsWire, AppOutgoingElements, AppWireElements, LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags } from "./app-elements-wire.js";
2
2
 
3
3
  //#region src/server/app-elements.d.ts
4
4
  declare const APP_PREFETCH_LOADING_SHELL_MARKER_KEY = "__prefetchLoadingShell";
@@ -6,5 +6,5 @@ declare function getMountedSlotIds(elements: AppElements): string[];
6
6
  declare function getMountedSlotIdsHeader(elements: AppElements): string | null;
7
7
  declare function resolveVisitedResponseInterceptionContext(requestInterceptionContext: string | null, payloadInterceptionContext: string | null): string | null;
8
8
  //#endregion
9
- export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_PREFETCH_LOADING_SHELL_MARKER_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SLOT_BINDINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, type AppElementValue, type AppElements, type AppElementsInterception, type AppElementsSlotBinding, AppElementsWire, type AppOutgoingElements, type AppWireElements, type LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, getMountedSlotIds, getMountedSlotIdsHeader, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, resolveVisitedResponseInterceptionContext, withLayoutFlags };
9
+ export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_PREFETCH_LOADING_SHELL_MARKER_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SLOT_BINDINGS_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, type AppElementValue, type AppElements, type AppElementsInterception, type AppElementsSlotBinding, AppElementsWire, type AppOutgoingElements, type AppWireElements, type LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, getMountedSlotIds, getMountedSlotIdsHeader, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, resolveVisitedResponseInterceptionContext, withLayoutFlags };
10
10
  //# sourceMappingURL=app-elements.d.ts.map
@@ -1,4 +1,4 @@
1
- import { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SLOT_BINDINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags } from "./app-elements-wire.js";
1
+ import { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SLOT_BINDINGS_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags } from "./app-elements-wire.js";
2
2
  import { normalizeMountedSlotsHeader } from "./app-mounted-slots-header.js";
3
3
  //#region src/server/app-elements.ts
4
4
  const APP_PREFETCH_LOADING_SHELL_MARKER_KEY = "__prefetchLoadingShell";
@@ -15,6 +15,6 @@ function resolveVisitedResponseInterceptionContext(requestInterceptionContext, p
15
15
  return payloadInterceptionContext ?? requestInterceptionContext;
16
16
  }
17
17
  //#endregion
18
- export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_PREFETCH_LOADING_SHELL_MARKER_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SLOT_BINDINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, getMountedSlotIds, getMountedSlotIdsHeader, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, resolveVisitedResponseInterceptionContext, withLayoutFlags };
18
+ export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_PREFETCH_LOADING_SHELL_MARKER_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SLOT_BINDINGS_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, getMountedSlotIds, getMountedSlotIdsHeader, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, resolveVisitedResponseInterceptionContext, withLayoutFlags };
19
19
 
20
20
  //# sourceMappingURL=app-elements.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"app-elements.js","names":[],"sources":["../../src/server/app-elements.ts"],"sourcesContent":["import { normalizeMountedSlotsHeader } from \"./app-mounted-slots-header.js\";\nimport { AppElementsWire, UNMATCHED_SLOT, type AppElements } from \"./app-elements-wire.js\";\n\nexport const APP_PREFETCH_LOADING_SHELL_MARKER_KEY = \"__prefetchLoadingShell\";\n\nexport {\n AppElementsWire,\n APP_ARTIFACT_COMPATIBILITY_KEY,\n APP_CACHE_ENTRY_REUSE_PROOF_KEY,\n APP_INTERCEPTION_KEY,\n APP_INTERCEPTION_CONTEXT_KEY,\n APP_LAYOUT_IDS_KEY,\n APP_LAYOUT_FLAGS_KEY,\n APP_RENDER_OBSERVATION_KEY,\n APP_ROOT_LAYOUT_KEY,\n APP_ROUTE_KEY,\n APP_SLOT_BINDINGS_KEY,\n APP_UNMATCHED_SLOT_WIRE_VALUE,\n UNMATCHED_SLOT,\n buildOutgoingAppPayload,\n compareAppElementsSlotIds,\n isAppElementsRecord,\n normalizeAppElementsSlotBindings,\n normalizeAppElements,\n readAppElementsMetadata,\n withLayoutFlags,\n type AppElementValue,\n type AppElementsInterception,\n type AppElementsSlotBinding,\n type AppElements,\n type AppOutgoingElements,\n type AppWireElements,\n type LayoutFlags,\n} from \"./app-elements-wire.js\";\n\n// Raw constructor helpers stay private because callers use AppElementsWire codecs.\n\nexport function getMountedSlotIds(elements: AppElements): string[] {\n return Object.keys(elements)\n .filter((key) => {\n const value = elements[key];\n return (\n AppElementsWire.isSlotId(key) &&\n value !== null &&\n value !== undefined &&\n value !== UNMATCHED_SLOT\n );\n })\n .sort();\n}\n\nexport function getMountedSlotIdsHeader(elements: AppElements): string | null {\n return normalizeMountedSlotsHeader(getMountedSlotIds(elements).join(\" \"));\n}\n\nexport function resolveVisitedResponseInterceptionContext(\n requestInterceptionContext: string | null,\n payloadInterceptionContext: string | null,\n): string | null {\n return payloadInterceptionContext ?? requestInterceptionContext;\n}\n"],"mappings":";;;AAGA,MAAa,wCAAwC;AAkCrD,SAAgB,kBAAkB,UAAiC;CACjE,OAAO,OAAO,KAAK,SAAS,CACzB,QAAQ,QAAQ;EACf,MAAM,QAAQ,SAAS;EACvB,OACE,gBAAgB,SAAS,IAAI,IAC7B,UAAU,QACV,UAAU,KAAA,KACV,UAAU;GAEZ,CACD,MAAM;;AAGX,SAAgB,wBAAwB,UAAsC;CAC5E,OAAO,4BAA4B,kBAAkB,SAAS,CAAC,KAAK,IAAI,CAAC;;AAG3E,SAAgB,0CACd,4BACA,4BACe;CACf,OAAO,8BAA8B"}
1
+ {"version":3,"file":"app-elements.js","names":[],"sources":["../../src/server/app-elements.ts"],"sourcesContent":["import { normalizeMountedSlotsHeader } from \"./app-mounted-slots-header.js\";\nimport { AppElementsWire, UNMATCHED_SLOT, type AppElements } from \"./app-elements-wire.js\";\n\nexport const APP_PREFETCH_LOADING_SHELL_MARKER_KEY = \"__prefetchLoadingShell\";\n\nexport {\n AppElementsWire,\n APP_ARTIFACT_COMPATIBILITY_KEY,\n APP_CACHE_ENTRY_REUSE_PROOF_KEY,\n APP_INTERCEPTION_KEY,\n APP_INTERCEPTION_CONTEXT_KEY,\n APP_LAYOUT_IDS_KEY,\n APP_LAYOUT_FLAGS_KEY,\n APP_RENDER_OBSERVATION_KEY,\n APP_ROOT_LAYOUT_KEY,\n APP_ROUTE_KEY,\n APP_SLOT_BINDINGS_KEY,\n APP_STATIC_SIBLINGS_KEY,\n APP_UNMATCHED_SLOT_WIRE_VALUE,\n UNMATCHED_SLOT,\n buildOutgoingAppPayload,\n compareAppElementsSlotIds,\n isAppElementsRecord,\n normalizeAppElementsSlotBindings,\n normalizeAppElements,\n readAppElementsMetadata,\n withLayoutFlags,\n type AppElementValue,\n type AppElementsInterception,\n type AppElementsSlotBinding,\n type AppElements,\n type AppOutgoingElements,\n type AppWireElements,\n type LayoutFlags,\n} from \"./app-elements-wire.js\";\n\n// Raw constructor helpers stay private because callers use AppElementsWire codecs.\n\nexport function getMountedSlotIds(elements: AppElements): string[] {\n return Object.keys(elements)\n .filter((key) => {\n const value = elements[key];\n return (\n AppElementsWire.isSlotId(key) &&\n value !== null &&\n value !== undefined &&\n value !== UNMATCHED_SLOT\n );\n })\n .sort();\n}\n\nexport function getMountedSlotIdsHeader(elements: AppElements): string | null {\n return normalizeMountedSlotsHeader(getMountedSlotIds(elements).join(\" \"));\n}\n\nexport function resolveVisitedResponseInterceptionContext(\n requestInterceptionContext: string | null,\n payloadInterceptionContext: string | null,\n): string | null {\n return payloadInterceptionContext ?? requestInterceptionContext;\n}\n"],"mappings":";;;AAGA,MAAa,wCAAwC;AAmCrD,SAAgB,kBAAkB,UAAiC;CACjE,OAAO,OAAO,KAAK,SAAS,CACzB,QAAQ,QAAQ;EACf,MAAM,QAAQ,SAAS;EACvB,OACE,gBAAgB,SAAS,IAAI,IAC7B,UAAU,QACV,UAAU,KAAA,KACV,UAAU;GAEZ,CACD,MAAM;;AAGX,SAAgB,wBAAwB,UAAsC;CAC5E,OAAO,4BAA4B,kBAAkB,SAAS,CAAC,KAAK,IAAI,CAAC;;AAG3E,SAAgB,0CACd,4BACA,4BACe;CACf,OAAO,8BAA8B"}
@@ -33,13 +33,23 @@ type AppFallbackRendererOptions<TModule extends AppPageModule = AppPageModule> =
33
33
  getNavigationContext: () => unknown;
34
34
  globalErrorModule?: TModule | null;
35
35
  /**
36
- * Optional `app/global-not-found.tsx` module. When provided, route-miss 404s
37
- * render this module as a standalone document (skipping the root layout)
38
- * because it ships its own `<html>` and `<body>`. Page-triggered `notFound()`
39
- * calls continue to use the regular `not-found.tsx` boundary inside layouts.
36
+ * Loader for the user's `app/global-not-found.tsx` module. When provided,
37
+ * route-miss 404s render this module as a standalone document (skipping the
38
+ * root layout) because it ships its own `<html>` and `<body>`. Page-triggered
39
+ * `notFound()` calls continue to use the regular `not-found.tsx` boundary
40
+ * inside layouts.
41
+ *
42
+ * Passed as a deferred loader (rather than the resolved module) so the
43
+ * generated RSC entry can use `() => import(...)` for chunk isolation.
44
+ * Without that isolation, the bundler co-locates global-not-found's CSS
45
+ * with the root layout's CSS in a single chunk and the CSS minifier
46
+ * (lightningcss) drops overlapping declarations as dead code — breaking
47
+ * the cascade for route-miss 404s where only global-not-found is rendered.
48
+ *
40
49
  * @see https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/app-render.tsx
50
+ * @see Next.js test: test/e2e/app-dir/initial-css-order/initial-css-order.test.ts
41
51
  */
42
- globalNotFoundModule?: TModule | null;
52
+ loadGlobalNotFoundModule?: (() => Promise<TModule | null | undefined>) | null;
43
53
  makeThenableParams: (params: AppPageParams) => unknown;
44
54
  metadataRoutes: MetadataFileRoute[]; /** Configured next.config `basePath`, threaded into file-based metadata href emission. */
45
55
  basePath?: string;
@@ -7,14 +7,20 @@ const EMPTY_MW_CTX = {
7
7
  status: null
8
8
  };
9
9
  function createAppFallbackRenderer(options) {
10
- const { basePath = "", clearRequestContext, createRscOnErrorHandler: buildRscOnErrorHandler, fontProviders, getNavigationContext, globalErrorModule, globalNotFoundModule, makeThenableParams, metadataRoutes, resolveChildSegments, rootBoundaries, rscRenderer, sanitizer, ssrLoader } = options;
10
+ const { basePath = "", clearRequestContext, createRscOnErrorHandler: buildRscOnErrorHandler, fontProviders, getNavigationContext, globalErrorModule, loadGlobalNotFoundModule, makeThenableParams, metadataRoutes, resolveChildSegments, rootBoundaries, rscRenderer, sanitizer, ssrLoader } = options;
11
11
  const { rootForbiddenModule, rootLayouts, rootNotFoundModule, rootUnauthorizedModule } = rootBoundaries;
12
12
  const effectiveGlobalErrorModule = globalErrorModule ?? DEFAULT_GLOBAL_ERROR_MODULE;
13
13
  const effectiveRootNotFoundModule = rootNotFoundModule ?? DEFAULT_NOT_FOUND_MODULE;
14
+ let globalNotFoundModulePromise = null;
15
+ function resolveGlobalNotFoundModule() {
16
+ if (!loadGlobalNotFoundModule) return null;
17
+ if (globalNotFoundModulePromise === null) globalNotFoundModulePromise = Promise.resolve().then(loadGlobalNotFoundModule);
18
+ return globalNotFoundModulePromise;
19
+ }
14
20
  return {
15
- renderHttpAccessFallback(route, statusCode, isRscRequest, request, opts, scriptNonce, middlewareContext, callContext) {
16
- if (statusCode === 404 && !!globalNotFoundModule && !route && !opts?.boundaryComponent) {
17
- const globalNotFoundComponent = globalNotFoundModule?.default ?? null;
21
+ async renderHttpAccessFallback(route, statusCode, isRscRequest, request, opts, scriptNonce, middlewareContext, callContext) {
22
+ if (statusCode === 404 && !!loadGlobalNotFoundModule && !route && !opts?.boundaryComponent) {
23
+ const globalNotFoundComponent = (await resolveGlobalNotFoundModule())?.default ?? null;
18
24
  if (globalNotFoundComponent) return renderAppPageHttpAccessFallback({
19
25
  boundaryComponent: globalNotFoundComponent,
20
26
  buildFontLinkHeader: fontProviders.buildFontLinkHeader,