vinext 0.0.43 → 0.0.44
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.
- package/dist/client/vinext-next-data.d.ts +1 -3
- package/dist/deploy.js +21 -4
- package/dist/deploy.js.map +1 -1
- package/dist/entries/app-rsc-entry.js +10 -2
- package/dist/entries/app-rsc-entry.js.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/routing/app-router.d.ts +2 -1
- package/dist/routing/app-router.js +5 -2
- package/dist/routing/app-router.js.map +1 -1
- package/dist/server/app-browser-entry.js +150 -96
- package/dist/server/app-browser-entry.js.map +1 -1
- package/dist/server/app-page-route-wiring.d.ts +1 -0
- package/dist/server/app-page-route-wiring.js +12 -2
- package/dist/server/app-page-route-wiring.js.map +1 -1
- package/dist/server/app-router-entry.js +8 -1
- package/dist/server/app-router-entry.js.map +1 -1
- package/dist/server/app-ssr-entry.js +2 -1
- package/dist/server/app-ssr-entry.js.map +1 -1
- package/dist/server/prod-server.js +16 -13
- package/dist/server/prod-server.js.map +1 -1
- package/dist/server/request-pipeline.d.ts +33 -1
- package/dist/server/request-pipeline.js +44 -2
- package/dist/server/request-pipeline.js.map +1 -1
- package/dist/shims/navigation.js +17 -0
- package/dist/shims/navigation.js.map +1 -1
- package/package.json +1 -1
- package/dist/client/entry.d.ts +0 -1
- package/dist/client/entry.js +0 -60
- package/dist/client/entry.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-browser-entry.js","names":[],"sources":["../../src/server/app-browser-entry.ts"],"sourcesContent":["/// <reference types=\"vite/client\" />\n\nimport {\n createElement,\n startTransition,\n use,\n useLayoutEffect,\n useRef,\n useState,\n type Dispatch,\n type ReactNode,\n} from \"react\";\nimport {\n createFromFetch,\n createFromReadableStream,\n createTemporaryReferenceSet,\n encodeReply,\n setServerCallback,\n} from \"@vitejs/plugin-rsc/browser\";\nimport { hydrateRoot } from \"react-dom/client\";\nimport \"../client/instrumentation-client.js\";\nimport { notifyAppRouterTransitionStart } from \"../client/instrumentation-client-state.js\";\nimport {\n __basePath,\n activateNavigationSnapshot,\n clearPendingPathname,\n commitClientNavigationState,\n consumePrefetchResponse,\n createClientNavigationRenderSnapshot,\n getCurrentNextUrl,\n getCurrentInterceptionContext,\n getClientNavigationRenderContext,\n getClientNavigationState,\n getPrefetchCache,\n getPrefetchedUrls,\n pushHistoryStateWithoutNotify,\n replaceClientParamsWithoutNotify,\n replaceHistoryStateWithoutNotify,\n restoreRscResponse,\n setClientParams,\n setPendingPathname,\n snapshotRscResponse,\n setMountedSlotsHeader,\n setNavigationContext,\n toRscUrl,\n type CachedRscResponse,\n type ClientNavigationRenderSnapshot,\n} from \"../shims/navigation.js\";\nimport { stripBasePath } from \"../utils/base-path.js\";\nimport {\n chunksToReadableStream,\n createProgressiveRscStream,\n getVinextBrowserGlobal,\n} from \"./app-browser-stream.js\";\nimport {\n createAppPayloadCacheKey,\n getMountedSlotIdsHeader,\n normalizeAppElements,\n readAppElementsMetadata,\n resolveVisitedResponseInterceptionContext,\n type AppElements,\n type AppWireElements,\n type LayoutFlags,\n} from \"./app-elements.js\";\nimport {\n createHistoryStateWithPreviousNextUrl,\n createPendingNavigationCommit,\n readHistoryStatePreviousNextUrl,\n resolveAndClassifyNavigationCommit,\n resolveInterceptionContextFromPreviousNextUrl,\n resolvePendingNavigationCommitDisposition,\n resolveServerActionRequestState,\n routerReducer,\n type AppRouterAction,\n type AppRouterState,\n} from \"./app-browser-state.js\";\nimport { ElementsContext, Slot } from \"../shims/slot.js\";\nimport { devOnCaughtError } from \"./app-browser-error.js\";\n\ntype SearchParamInput = ConstructorParameters<typeof URLSearchParams>[0];\n\ntype ServerActionResult = {\n root: AppWireElements;\n returnValue?: {\n ok: boolean;\n data: unknown;\n };\n};\n\ntype NavigationKind = \"navigate\" | \"traverse\" | \"refresh\";\n\n// Maps NavigationKind to the AppRouterAction type used by the reducer.\n// \"refresh\" is intentionally treated as \"navigate\" (merge, preserve absent slots).\n// Both call sites must stay in sync — update here if NavigationKind gains new values.\nfunction toActionType(kind: NavigationKind): \"navigate\" | \"traverse\" {\n return kind === \"traverse\" ? \"traverse\" : \"navigate\";\n}\n\ntype HistoryUpdateMode = \"push\" | \"replace\";\ntype VisitedResponseCacheEntry = {\n params: Record<string, string | string[]>;\n expiresAt: number;\n response: CachedRscResponse;\n};\n\nconst MAX_VISITED_RESPONSE_CACHE_SIZE = 50;\nconst VISITED_RESPONSE_CACHE_TTL = 5 * 60_000;\nconst MAX_TRAVERSAL_CACHE_TTL = 30 * 60_000;\n\n// These are plain module-level variables, unlike ClientNavigationState in\n// navigation.ts which uses Symbol.for to survive multiple Vite module instances.\n// The browser entry is loaded exactly once (via the RSC plugin's generated\n// bootstrap), so module-level state is safe here. If that assumption ever\n// changes, these should be 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.\nlet nextNavigationRenderId = 0;\nlet activeNavigationId = 0;\nconst pendingNavigationCommits = new Map<number, () => void>();\nconst pendingNavigationPrePaintEffects = new Map<number, () => void>();\ntype PendingBrowserRouterState = {\n promise: Promise<AppRouterState>;\n resolve: (state: AppRouterState) => void;\n settled: boolean;\n};\n\nfunction isRouterStatePromise(\n value: AppRouterState | Promise<AppRouterState>,\n): value is Promise<AppRouterState> {\n return value instanceof Promise;\n}\n\nlet setBrowserRouterState: Dispatch<AppRouterState | Promise<AppRouterState>> | null = null;\nlet browserRouterStateRef: { current: AppRouterState } | null = null;\nlet activePendingBrowserRouterState: PendingBrowserRouterState | null = null;\nlet latestClientParams: Record<string, string | string[]> = {};\nconst visitedResponseCache = new Map<string, VisitedResponseCacheEntry>();\n\nfunction isServerActionResult(value: unknown): value is ServerActionResult {\n return !!value && typeof value === \"object\" && \"root\" in value;\n}\n\nfunction 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\nfunction getBrowserRouterState(): AppRouterState {\n if (!browserRouterStateRef) {\n throw new Error(\"[vinext] Browser router state is not initialized\");\n }\n return browserRouterStateRef.current;\n}\n\nfunction beginPendingBrowserRouterState(): PendingBrowserRouterState {\n const setter = getBrowserRouterStateSetter();\n\n if (activePendingBrowserRouterState && !activePendingBrowserRouterState.settled) {\n activePendingBrowserRouterState.settled = true;\n activePendingBrowserRouterState.resolve(getBrowserRouterState());\n }\n\n let resolve!: (state: AppRouterState) => void;\n const promise = new Promise<AppRouterState>((resolvePromise) => {\n resolve = resolvePromise;\n });\n\n const pending: PendingBrowserRouterState = {\n promise,\n resolve,\n settled: false,\n };\n\n activePendingBrowserRouterState = pending;\n setter(promise);\n\n return pending;\n}\n\nfunction 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\nfunction resolvePendingBrowserRouterState(\n pending: PendingBrowserRouterState | null | undefined,\n action: AppRouterAction,\n): void {\n if (!pending || pending.settled) return;\n\n pending.settled = true;\n pending.resolve(routerReducer(getBrowserRouterState(), action));\n\n if (activePendingBrowserRouterState === pending) {\n activePendingBrowserRouterState = null;\n }\n}\n\nfunction applyClientParams(params: Record<string, string | string[]>): void {\n latestClientParams = params;\n setClientParams(params);\n}\n\nfunction stageClientParams(params: Record<string, string | string[]>): void {\n // NB: latestClientParams diverges from ClientNavigationState.clientParams\n // between staging and commit. Server action snapshots (same-URL\n // commitSameUrlNavigatePayload() calls inside registerServerActionCallback)\n // read latestClientParams, so a\n // server action fired during this window would get the pending (not yet\n // committed) params. This is acceptable because the commit effect fires\n // before hooks observe the new URL state, keeping the window vanishingly small.\n latestClientParams = params;\n replaceClientParamsWithoutNotify(params);\n}\n\nfunction clearVisitedResponseCache(): void {\n visitedResponseCache.clear();\n}\n\nfunction clearPrefetchState(): void {\n getPrefetchCache().clear();\n getPrefetchedUrls().clear();\n}\n\nfunction clearClientNavigationCaches(): void {\n clearVisitedResponseCache();\n clearPrefetchState();\n}\n\nfunction 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 */\nfunction drainPrePaintEffects(upToRenderId: number): void {\n for (const [id, effect] of pendingNavigationPrePaintEffects) {\n if (id <= upToRenderId) {\n pendingNavigationPrePaintEffects.delete(id);\n if (id === upToRenderId) {\n // Winning navigation: run its actual pre-paint effect\n effect();\n } else {\n // Superseded navigation: balance its activateNavigationSnapshot().\n // Pass undefined navId intentionally so this cleanup cannot clear\n // pendingPathname owned by the current active navigation.\n commitClientNavigationState(undefined);\n }\n }\n }\n}\n\nfunction createNavigationCommitEffect(\n href: string,\n historyUpdateMode: HistoryUpdateMode | undefined,\n navId: number,\n params: Record<string, string | string[]>,\n previousNextUrl: string | null,\n): () => void {\n return () => {\n // Only update URL if this is still the active navigation.\n // A newer navigation would have incremented activeNavigationId.\n if (navId !== activeNavigationId) {\n // This transition was superseded before commit; balance the active\n // snapshot counter without clearing pendingPathname ownership.\n commitClientNavigationState(undefined);\n return;\n }\n\n const targetHref = new URL(href, window.location.origin).href;\n stageClientParams(params);\n const preserveExistingState = historyUpdateMode === \"replace\";\n const historyState = createHistoryStateWithPreviousNextUrl(\n preserveExistingState ? window.history.state : null,\n previousNextUrl,\n );\n\n if (historyUpdateMode === \"replace\" && window.location.href !== targetHref) {\n replaceHistoryStateWithoutNotify(historyState, \"\", href);\n } else if (historyUpdateMode === \"push\" && window.location.href !== targetHref) {\n pushHistoryStateWithoutNotify(historyState, \"\", href);\n }\n\n commitClientNavigationState(navId);\n };\n}\n\nfunction evictVisitedResponseCacheIfNeeded(): void {\n while (visitedResponseCache.size >= MAX_VISITED_RESPONSE_CACHE_SIZE) {\n const oldest = visitedResponseCache.keys().next().value;\n if (oldest === undefined) {\n return;\n }\n visitedResponseCache.delete(oldest);\n }\n}\n\nfunction getVisitedResponse(\n rscUrl: string,\n interceptionContext: string | null,\n mountedSlotsHeader: string | null,\n navigationKind: NavigationKind,\n): VisitedResponseCacheEntry | null {\n const cacheKey = createAppPayloadCacheKey(rscUrl, interceptionContext);\n const cached = visitedResponseCache.get(cacheKey);\n if (!cached) {\n return null;\n }\n\n if ((cached.response.mountedSlotsHeader ?? null) !== mountedSlotsHeader) {\n visitedResponseCache.delete(cacheKey);\n return null;\n }\n\n if (navigationKind === \"refresh\") {\n return null;\n }\n\n if (navigationKind === \"traverse\") {\n const createdAt = cached.expiresAt - VISITED_RESPONSE_CACHE_TTL;\n if (Date.now() - createdAt >= MAX_TRAVERSAL_CACHE_TTL) {\n visitedResponseCache.delete(cacheKey);\n return null;\n }\n // LRU: promote to most-recently-used (delete + re-insert moves to end of Map)\n visitedResponseCache.delete(cacheKey);\n visitedResponseCache.set(cacheKey, cached);\n return cached;\n }\n\n if (cached.expiresAt > Date.now()) {\n // LRU: promote to most-recently-used\n visitedResponseCache.delete(cacheKey);\n visitedResponseCache.set(cacheKey, cached);\n return cached;\n }\n\n visitedResponseCache.delete(cacheKey);\n return null;\n}\n\nfunction storeVisitedResponseSnapshot(\n rscUrl: string,\n interceptionContext: string | null,\n snapshot: CachedRscResponse,\n params: Record<string, string | string[]>,\n): void {\n const cacheKey = createAppPayloadCacheKey(rscUrl, interceptionContext);\n visitedResponseCache.delete(cacheKey);\n evictVisitedResponseCacheIfNeeded();\n const now = Date.now();\n visitedResponseCache.set(cacheKey, {\n params,\n expiresAt: now + VISITED_RESPONSE_CACHE_TTL,\n response: snapshot,\n });\n}\n\ntype NavigationRequestState = {\n interceptionContext: string | null;\n previousNextUrl: string | null;\n};\n\nfunction getRequestState(\n navigationKind: NavigationKind,\n previousNextUrlOverride?: string | null,\n): NavigationRequestState {\n if (previousNextUrlOverride !== undefined) {\n return {\n interceptionContext: resolveInterceptionContextFromPreviousNextUrl(\n previousNextUrlOverride,\n __basePath,\n ),\n previousNextUrl: previousNextUrlOverride,\n };\n }\n\n switch (navigationKind) {\n case \"navigate\":\n return {\n interceptionContext: getCurrentInterceptionContext(),\n previousNextUrl: getCurrentNextUrl(),\n };\n case \"traverse\": {\n const previousNextUrl = readHistoryStatePreviousNextUrl(window.history.state);\n return {\n interceptionContext: resolveInterceptionContextFromPreviousNextUrl(\n previousNextUrl,\n __basePath,\n ),\n previousNextUrl,\n };\n }\n case \"refresh\": {\n const currentPreviousNextUrl = getBrowserRouterState().previousNextUrl;\n return {\n interceptionContext: resolveInterceptionContextFromPreviousNextUrl(\n currentPreviousNextUrl,\n __basePath,\n ),\n previousNextUrl: currentPreviousNextUrl,\n };\n }\n default: {\n const _exhaustive: never = navigationKind;\n throw new Error(\"[vinext] Unknown navigation kind: \" + String(_exhaustive));\n }\n }\n}\n\nfunction createRscRequestHeaders(interceptionContext: string | null): Headers {\n const headers = new Headers({ Accept: \"text/x-component\" });\n if (interceptionContext !== null) {\n headers.set(\"X-Vinext-Interception-Context\", interceptionContext);\n }\n return headers;\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 */\nfunction resolveCommittedNavigations(renderId: number): void {\n for (const [pendingId, resolve] of pendingNavigationCommits) {\n if (pendingId <= renderId) {\n pendingNavigationCommits.delete(pendingId);\n resolve();\n }\n }\n}\n\nfunction NavigationCommitSignal({\n renderId,\n children,\n}: {\n renderId: number;\n children?: ReactNode;\n}) {\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\nfunction normalizeAppElementsPromise(payload: Promise<AppWireElements>): Promise<AppElements> {\n // Wrap in Promise.resolve() because createFromReadableStream() returns a\n // React Flight thenable whose .then() returns undefined (not a new Promise).\n // Without the wrap, chaining .then() produces undefined → use() crashes.\n return Promise.resolve(payload).then((elements) => normalizeAppElements(elements));\n}\n\nasync function commitSameUrlNavigatePayload(\n nextElements: Promise<AppElements>,\n returnValue?: ServerActionResult[\"returnValue\"],\n): Promise<unknown> {\n const navigationSnapshot = createClientNavigationRenderSnapshot(\n window.location.href,\n latestClientParams,\n );\n const currentState = getBrowserRouterState();\n const startedNavigationId = activeNavigationId;\n const { disposition, pending } = await resolveAndClassifyNavigationCommit({\n activeNavigationId,\n currentState,\n navigationSnapshot,\n nextElements,\n renderId: ++nextNavigationRenderId,\n startedNavigationId,\n type: \"navigate\",\n });\n\n // Known limitation: if a same-URL navigation fully commits while this\n // server action is awaiting createPendingNavigationCommit(), the action\n // can still dispatch its older payload afterward. The old pre-2c code had\n // the same race, and Next.js has similar behavior. Tightening this would\n // need a stronger commit-version gate than activeNavigationId alone.\n if (disposition === \"hard-navigate\") {\n window.location.assign(window.location.href);\n return undefined;\n }\n\n if (disposition === \"dispatch\") {\n dispatchBrowserTree(\n pending.action.elements,\n navigationSnapshot,\n pending.action.renderId,\n \"navigate\",\n pending.interceptionContext,\n pending.action.layoutFlags,\n pending.previousNextUrl,\n pending.routeId,\n pending.rootLayoutTreePath,\n null,\n false,\n );\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\nfunction BrowserRoot({\n initialElements,\n initialNavigationSnapshot,\n}: {\n initialElements: Promise<AppElements>;\n initialNavigationSnapshot: ClientNavigationRenderSnapshot;\n}) {\n const resolvedElements = use(initialElements);\n const initialMetadata = readAppElementsMetadata(resolvedElements);\n const [treeStateValue, setTreeStateValue] = useState<AppRouterState | Promise<AppRouterState>>({\n elements: resolvedElements,\n interceptionContext: initialMetadata.interceptionContext,\n layoutFlags: initialMetadata.layoutFlags,\n navigationSnapshot: initialNavigationSnapshot,\n previousNextUrl: null,\n renderId: 0,\n rootLayoutTreePath: initialMetadata.rootLayoutTreePath,\n routeId: initialMetadata.routeId,\n });\n const treeState = isRouterStatePromise(treeStateValue) ? use(treeStateValue) : treeStateValue;\n\n // Keep the latest router state in a ref so external callers (navigate(),\n // server actions, HMR) always read the current state. Safe: those readers\n // run from events/effects, never from React render itself.\n // Note: stateRef.current is written during render, not in an effect, to\n // avoid a stale-read window between commit and layout effects. This mirrors\n // the same render-phase ref update pattern used by Next.js's own router.\n const stateRef = useRef(treeState);\n stateRef.current = treeState;\n\n // Publish the stable ref object and dispatch during layout commit. This keeps\n // the module-level escape hatches aligned with React's committed tree without\n // performing module writes during render. __VINEXT_RSC_NAVIGATE__ is assigned\n // after hydrateRoot() returns; by then this layout effect has already run for\n // the hydration commit, so getBrowserRouterState() never observes a null ref.\n useLayoutEffect(() => {\n setBrowserRouterState = setTreeStateValue;\n browserRouterStateRef = stateRef;\n return () => {\n if (setBrowserRouterState === setTreeStateValue) {\n setBrowserRouterState = null;\n }\n if (browserRouterStateRef === stateRef) {\n browserRouterStateRef = null;\n }\n setMountedSlotsHeader(null);\n };\n }, [setTreeStateValue]);\n\n useLayoutEffect(() => {\n setMountedSlotsHeader(getMountedSlotIdsHeader(stateRef.current.elements));\n }, [treeState.elements]);\n\n useLayoutEffect(() => {\n if (treeState.renderId !== 0) {\n return;\n }\n\n replaceHistoryStateWithoutNotify(\n createHistoryStateWithPreviousNextUrl(window.history.state, treeState.previousNextUrl),\n \"\",\n window.location.href,\n );\n }, [treeState.previousNextUrl, treeState.renderId]);\n\n const committedTree = createElement(\n NavigationCommitSignal,\n { renderId: treeState.renderId },\n createElement(\n ElementsContext.Provider,\n { value: treeState.elements },\n createElement(Slot, { id: treeState.routeId }),\n ),\n );\n\n const ClientNavigationRenderContext = getClientNavigationRenderContext();\n if (!ClientNavigationRenderContext) {\n return committedTree;\n }\n\n return createElement(\n ClientNavigationRenderContext.Provider,\n { value: treeState.navigationSnapshot },\n committedTree,\n );\n}\n\nfunction dispatchBrowserTree(\n elements: AppElements,\n navigationSnapshot: ClientNavigationRenderSnapshot,\n renderId: number,\n actionType: \"navigate\" | \"replace\" | \"traverse\",\n interceptionContext: string | null,\n layoutFlags: LayoutFlags,\n previousNextUrl: string | null,\n routeId: string,\n rootLayoutTreePath: string | null,\n pendingRouterState: PendingBrowserRouterState | null,\n useTransitionMode: boolean,\n): void {\n const setter = getBrowserRouterStateSetter();\n const action: AppRouterAction = {\n elements,\n interceptionContext,\n layoutFlags,\n navigationSnapshot,\n previousNextUrl,\n renderId,\n rootLayoutTreePath,\n routeId,\n type: actionType,\n };\n\n const applyAction = () => {\n if (pendingRouterState) {\n // The programmatic navigation is already running inside React.startTransition\n // (from router.push/replace/refresh), so resolving the deferred promise is\n // sufficient — no additional startTransition wrapper is needed below.\n resolvePendingBrowserRouterState(pendingRouterState, action);\n return;\n }\n\n setter(routerReducer(getBrowserRouterState(), action));\n };\n\n if (useTransitionMode) {\n startTransition(applyAction);\n } else {\n applyAction();\n }\n}\n\nasync function renderNavigationPayload(\n payload: Promise<AppElements>,\n navigationSnapshot: ClientNavigationRenderSnapshot,\n targetHref: string,\n navId: number,\n historyUpdateMode: HistoryUpdateMode | undefined,\n params: Record<string, string | string[]>,\n previousNextUrl: string | null,\n pendingRouterState: PendingBrowserRouterState | null,\n useTransition = true,\n actionType: \"navigate\" | \"replace\" | \"traverse\" = \"navigate\",\n): Promise<void> {\n const renderId = ++nextNavigationRenderId;\n const committed = new Promise<void>((resolve) => {\n pendingNavigationCommits.set(renderId, resolve);\n });\n\n let snapshotActivated = false;\n try {\n const currentState = getBrowserRouterState();\n const pending = await createPendingNavigationCommit({\n currentState,\n nextElements: payload,\n navigationSnapshot,\n previousNextUrl,\n renderId,\n type: actionType,\n });\n\n const disposition = resolvePendingNavigationCommitDisposition({\n activeNavigationId,\n currentRootLayoutTreePath: currentState.rootLayoutTreePath,\n nextRootLayoutTreePath: pending.rootLayoutTreePath,\n startedNavigationId: navId,\n });\n\n if (disposition === \"skip\") {\n settlePendingBrowserRouterState(pendingRouterState);\n const resolve = pendingNavigationCommits.get(renderId);\n pendingNavigationCommits.delete(renderId);\n resolve?.();\n return;\n }\n\n if (disposition === \"hard-navigate\") {\n settlePendingBrowserRouterState(pendingRouterState);\n pendingNavigationCommits.delete(renderId);\n window.location.assign(targetHref);\n return;\n }\n\n queuePrePaintNavigationEffect(\n renderId,\n createNavigationCommitEffect(\n targetHref,\n historyUpdateMode,\n navId,\n params,\n pending.previousNextUrl,\n ),\n );\n activateNavigationSnapshot();\n snapshotActivated = true;\n dispatchBrowserTree(\n pending.action.elements,\n navigationSnapshot,\n renderId,\n actionType,\n pending.interceptionContext,\n pending.action.layoutFlags,\n pending.previousNextUrl,\n pending.routeId,\n pending.rootLayoutTreePath,\n pendingRouterState,\n useTransition,\n );\n } catch (error) {\n // Clean up pending state on error. Only decrement the snapshot counter\n // if activateNavigationSnapshot() was actually called — if\n // createPendingNavigationCommit() threw, the counter was never\n // incremented so decrementing would underflow it.\n pendingNavigationPrePaintEffects.delete(renderId);\n const resolve = pendingNavigationCommits.get(renderId);\n pendingNavigationCommits.delete(renderId);\n if (snapshotActivated) {\n commitClientNavigationState(navId);\n }\n settlePendingBrowserRouterState(pendingRouterState);\n resolve?.();\n throw error;\n }\n\n return committed;\n}\n\nfunction restoreHydrationNavigationContext(\n pathname: string,\n searchParams: SearchParamInput,\n params: Record<string, string | string[]>,\n): void {\n setNavigationContext({\n pathname,\n searchParams: new URLSearchParams(searchParams),\n params,\n });\n}\n\nfunction restorePopstateScrollPosition(state: unknown): void {\n if (!(state && typeof state === \"object\" && \"__vinext_scrollY\" in state)) {\n return;\n }\n\n const y = Number(state.__vinext_scrollY);\n const x = \"__vinext_scrollX\" in state ? Number(state.__vinext_scrollX) : 0;\n\n requestAnimationFrame(() => {\n window.scrollTo(x, y);\n });\n}\n\nasync function readInitialRscStream(): Promise<ReadableStream<Uint8Array>> {\n const vinext = getVinextBrowserGlobal();\n\n if (vinext.__VINEXT_RSC__ || vinext.__VINEXT_RSC_CHUNKS__ || vinext.__VINEXT_RSC_DONE__) {\n if (vinext.__VINEXT_RSC__) {\n const embedData = vinext.__VINEXT_RSC__;\n delete vinext.__VINEXT_RSC__;\n\n const params = embedData.params ?? {};\n if (embedData.params) {\n applyClientParams(embedData.params);\n }\n if (embedData.nav) {\n restoreHydrationNavigationContext(\n embedData.nav.pathname,\n embedData.nav.searchParams,\n params,\n );\n }\n\n return chunksToReadableStream(embedData.rsc);\n }\n\n const params = vinext.__VINEXT_RSC_PARAMS__ ?? {};\n if (vinext.__VINEXT_RSC_PARAMS__) {\n applyClientParams(vinext.__VINEXT_RSC_PARAMS__);\n }\n if (vinext.__VINEXT_RSC_NAV__) {\n restoreHydrationNavigationContext(\n vinext.__VINEXT_RSC_NAV__.pathname,\n vinext.__VINEXT_RSC_NAV__.searchParams,\n params,\n );\n }\n\n return createProgressiveRscStream();\n }\n\n const rscResponse = await fetch(toRscUrl(window.location.pathname + window.location.search));\n\n let params: Record<string, string | string[]> = {};\n const paramsHeader = rscResponse.headers.get(\"X-Vinext-Params\");\n if (paramsHeader) {\n try {\n params = JSON.parse(decodeURIComponent(paramsHeader)) as Record<string, string | string[]>;\n applyClientParams(params);\n } catch {\n // Ignore malformed param headers and continue with hydration.\n }\n }\n\n restoreHydrationNavigationContext(window.location.pathname, window.location.search, params);\n\n if (!rscResponse.body) {\n throw new Error(\"[vinext] Initial RSC response had no body\");\n }\n\n return rscResponse.body;\n}\n\nfunction registerServerActionCallback(): void {\n setServerCallback(async (id, args) => {\n const temporaryReferences = createTemporaryReferenceSet();\n const body = await encodeReply(args, { temporaryReferences });\n\n // Carry the interception context + mounted slots from the current router\n // state so the server-action re-render rebuilds the intercepted tree\n // instead of replacing it with the direct page. Parity with Next.js,\n // which sends `Next-URL` on action POSTs when the current tree contains\n // an interception route.\n const currentState = getBrowserRouterState();\n const { headers } = resolveServerActionRequestState({\n actionId: id,\n basePath: __basePath,\n elements: currentState.elements,\n previousNextUrl: currentState.previousNextUrl,\n });\n\n const fetchResponse = await fetch(toRscUrl(window.location.pathname + window.location.search), {\n method: \"POST\",\n headers,\n body,\n });\n\n const actionRedirect = fetchResponse.headers.get(\"x-action-redirect\");\n if (actionRedirect) {\n // Check for external URLs that need a hard redirect.\n try {\n const redirectUrl = new URL(actionRedirect, window.location.origin);\n if (redirectUrl.origin !== window.location.origin) {\n window.location.href = actionRedirect;\n return undefined;\n }\n } catch {\n // Fall through to hard redirect below if URL parsing fails.\n }\n\n // Use hard redirect for all action redirects because vinext's server\n // currently returns an empty body for redirect responses. RSC navigation\n // requires a valid RSC payload. This is a known parity gap with Next.js,\n // which pre-renders the redirect target's RSC payload.\n const redirectType = fetchResponse.headers.get(\"x-action-redirect-type\") ?? \"replace\";\n if (redirectType === \"push\") {\n window.location.assign(actionRedirect);\n } else {\n window.location.replace(actionRedirect);\n }\n return undefined;\n }\n\n clearClientNavigationCaches();\n\n const result = await createFromFetch<ServerActionResult | AppWireElements>(\n Promise.resolve(fetchResponse),\n { temporaryReferences },\n );\n\n // Server actions stay on the same URL and use commitSameUrlNavigatePayload()\n // for merge-based dispatch. This path does not call\n // activateNavigationSnapshot() because there is no URL change to commit, so\n // hooks continue reading the live external-store values directly. If server\n // actions ever trigger URL changes via RSC payload (instead of hard\n // redirects), this would need renderNavigationPayload().\n if (isServerActionResult(result)) {\n return commitSameUrlNavigatePayload(\n Promise.resolve(normalizeAppElements(result.root)),\n result.returnValue,\n );\n }\n\n return commitSameUrlNavigatePayload(Promise.resolve(normalizeAppElements(result)));\n });\n}\n\nasync function main(): Promise<void> {\n registerServerActionCallback();\n\n const rscStream = await readInitialRscStream();\n const root = normalizeAppElementsPromise(createFromReadableStream<AppWireElements>(rscStream));\n const initialNavigationSnapshot = createClientNavigationRenderSnapshot(\n window.location.href,\n latestClientParams,\n );\n replaceHistoryStateWithoutNotify(\n createHistoryStateWithPreviousNextUrl(window.history.state, null),\n \"\",\n window.location.href,\n );\n\n window.__VINEXT_RSC_ROOT__ = hydrateRoot(\n document,\n createElement(BrowserRoot, {\n initialElements: root,\n initialNavigationSnapshot,\n }),\n import.meta.env.DEV ? { onCaughtError: devOnCaughtError } : undefined,\n );\n window.__VINEXT_HYDRATED_AT = performance.now();\n\n window.__VINEXT_RSC_NAVIGATE__ = async function navigateRsc(\n href: string,\n redirectDepth = 0,\n navigationKind: NavigationKind = \"navigate\",\n historyUpdateMode?: HistoryUpdateMode,\n previousNextUrlOverride?: string | null,\n programmaticTransition = false,\n ): Promise<void> {\n if (redirectDepth > 10) {\n console.error(\n \"[vinext] Too many RSC redirects — aborting navigation to prevent infinite loop.\",\n );\n window.location.href = href;\n return;\n }\n\n let _snapshotPending = false;\n let pendingRouterState: PendingBrowserRouterState | null = null;\n // Hoist navId above try so the catch block can guard against hard-navigating\n // to a stale URL when this navigation has already been superseded.\n const navId = ++activeNavigationId;\n try {\n if (programmaticTransition) {\n pendingRouterState = beginPendingBrowserRouterState();\n }\n\n const url = new URL(href, window.location.origin);\n const rscUrl = toRscUrl(url.pathname + url.search);\n const requestState = getRequestState(navigationKind, previousNextUrlOverride);\n const requestInterceptionContext = requestState.interceptionContext;\n const requestPreviousNextUrl = requestState.previousNextUrl;\n\n // Compare against previous pending navigation first, then committed state.\n // This avoids isSameRoute misclassification during rapid back-to-back clicks.\n const navState = getClientNavigationState();\n const currentPath =\n navState?.pendingPathname ??\n navState?.cachedPathname ??\n stripBasePath(window.location.pathname, __basePath);\n\n const targetPath = stripBasePath(url.pathname, __basePath);\n const isSameRoute = targetPath === currentPath;\n\n // Set this navigation as the pending pathname, overwriting any previous.\n // Pass navId so only this navigation (or a newer one) can clear it later.\n setPendingPathname(url.pathname, navId);\n\n const elementsAtNavStart = getBrowserRouterState().elements;\n const mountedSlotsHeader = getMountedSlotIdsHeader(elementsAtNavStart);\n const cachedRoute = getVisitedResponse(\n rscUrl,\n requestInterceptionContext,\n mountedSlotsHeader,\n navigationKind,\n );\n if (cachedRoute) {\n // Check stale-navigation before and after createFromFetch. The pre-check\n // avoids wasted parse work; the post-check catches supersessions that\n // occur during the await. createFromFetch on a buffered response is fast\n // but still async, so the window exists. The non-cached path (below) places\n // its heavyweight async steps (fetch, snapshotRscResponse, createFromFetch)\n // between navId checks consistently; the cached path omits the check between\n // createClientNavigationRenderSnapshot (synchronous) and createFromFetch\n // because there is no await in that gap.\n if (navId !== activeNavigationId) {\n settlePendingBrowserRouterState(pendingRouterState);\n return;\n }\n const cachedParams = cachedRoute.params;\n // createClientNavigationRenderSnapshot is synchronous (URL parsing + param\n // wrapping only) — no stale-navigation recheck needed between here and the\n // next await.\n const cachedNavigationSnapshot = createClientNavigationRenderSnapshot(href, cachedParams);\n const cachedPayload = normalizeAppElementsPromise(\n createFromFetch<AppWireElements>(\n Promise.resolve(restoreRscResponse(cachedRoute.response)),\n ),\n );\n if (navId !== activeNavigationId) {\n settlePendingBrowserRouterState(pendingRouterState);\n return;\n }\n _snapshotPending = true; // Set before renderNavigationPayload\n try {\n await renderNavigationPayload(\n cachedPayload,\n cachedNavigationSnapshot,\n href,\n navId,\n historyUpdateMode,\n cachedParams,\n requestPreviousNextUrl,\n pendingRouterState,\n isSameRoute,\n toActionType(navigationKind),\n );\n } finally {\n // Always clear _snapshotPending so the outer catch does not\n // double-decrement if renderNavigationPayload throws.\n _snapshotPending = false;\n }\n return;\n }\n\n // Continue using the slot state captured at navigation start for fetches\n // and prefetch compatibility decisions.\n\n let navResponse: Response | undefined;\n let navResponseUrl: string | null = null;\n if (navigationKind !== \"refresh\") {\n const prefetchedResponse = consumePrefetchResponse(\n rscUrl,\n requestInterceptionContext,\n mountedSlotsHeader,\n );\n if (prefetchedResponse) {\n navResponse = restoreRscResponse(prefetchedResponse, false);\n navResponseUrl = prefetchedResponse.url;\n }\n }\n\n if (!navResponse) {\n const requestHeaders = createRscRequestHeaders(requestInterceptionContext);\n if (mountedSlotsHeader) {\n requestHeaders.set(\"X-Vinext-Mounted-Slots\", mountedSlotsHeader);\n }\n navResponse = await fetch(rscUrl, {\n headers: requestHeaders,\n credentials: \"include\",\n });\n }\n\n if (navId !== activeNavigationId) {\n settlePendingBrowserRouterState(pendingRouterState);\n return;\n }\n\n const finalUrl = new URL(navResponseUrl ?? navResponse.url, window.location.origin);\n const requestedUrl = new URL(rscUrl, window.location.origin);\n\n if (finalUrl.pathname !== requestedUrl.pathname) {\n const destinationPath = finalUrl.pathname.replace(/\\.rsc$/, \"\") + finalUrl.search;\n replaceHistoryStateWithoutNotify(\n createHistoryStateWithPreviousNextUrl(null, requestPreviousNextUrl),\n \"\",\n destinationPath,\n );\n\n const navigate = window.__VINEXT_RSC_NAVIGATE__;\n if (!navigate) {\n settlePendingBrowserRouterState(pendingRouterState);\n window.location.href = destinationPath;\n return;\n }\n\n // Hand ownership of the pending transition off before recursing. The\n // recursive call will not receive pendingRouterState (programmaticTransition=false),\n // so if we left it unsettled its promise would orphan in the useState slot\n // until the next programmatic push caught it via the !settled branch in\n // beginPendingBrowserRouterState. Settling here with the current committed\n // state makes isPending flip false mid-redirect — a deliberate tradeoff\n // over leaning on React's internal transition-completion heuristic.\n settlePendingBrowserRouterState(pendingRouterState);\n\n // The URL has already been updated via replaceHistoryStateWithoutNotify above,\n // so the recursive navigation should NOT push/replace again. Pass undefined\n // for historyUpdateMode to make the commit effect a no-op for history updates.\n return navigate(\n destinationPath,\n redirectDepth + 1,\n navigationKind,\n undefined,\n requestPreviousNextUrl,\n false,\n );\n }\n\n let navParams: Record<string, string | string[]> = {};\n const paramsHeader = navResponse.headers.get(\"X-Vinext-Params\");\n if (paramsHeader) {\n try {\n navParams = JSON.parse(decodeURIComponent(paramsHeader)) as Record<\n string,\n string | string[]\n >;\n } catch {\n // navParams stays as {}\n }\n }\n // Build snapshot from local params, not latestClientParams\n const navigationSnapshot = createClientNavigationRenderSnapshot(href, navParams);\n\n const responseSnapshot = await snapshotRscResponse(navResponse);\n\n if (navId !== activeNavigationId) {\n settlePendingBrowserRouterState(pendingRouterState);\n return;\n }\n\n const rscPayload = normalizeAppElementsPromise(\n createFromFetch<AppWireElements>(Promise.resolve(restoreRscResponse(responseSnapshot))),\n );\n\n if (navId !== activeNavigationId) {\n settlePendingBrowserRouterState(pendingRouterState);\n return;\n }\n\n _snapshotPending = true; // Set before renderNavigationPayload\n try {\n await renderNavigationPayload(\n rscPayload,\n navigationSnapshot,\n href,\n navId,\n historyUpdateMode,\n navParams,\n requestPreviousNextUrl,\n pendingRouterState,\n isSameRoute,\n toActionType(navigationKind),\n );\n } finally {\n // Always clear _snapshotPending after renderNavigationPayload returns or\n // throws. renderNavigationPayload's inner catch already calls\n // commitClientNavigationState() on synchronous errors and re-throws, so\n // the outer catch must not call it again. Clearing here prevents the outer\n // catch from double-decrementing navigationSnapshotActiveCount.\n _snapshotPending = false;\n }\n // Don't cache the response if this navigation was superseded during\n // renderNavigationPayload's await — the elements were never dispatched.\n if (navId !== activeNavigationId) {\n settlePendingBrowserRouterState(pendingRouterState);\n return;\n }\n // Store the visited response only after renderNavigationPayload succeeds.\n // If we stored it before and renderNavigationPayload threw, a future\n // back/forward navigation could replay a snapshot from a navigation that\n // never actually rendered successfully.\n const resolvedElements = await rscPayload;\n const metadata = readAppElementsMetadata(resolvedElements);\n storeVisitedResponseSnapshot(\n rscUrl,\n resolveVisitedResponseInterceptionContext(\n requestInterceptionContext,\n metadata.interceptionContext,\n ),\n responseSnapshot,\n navParams,\n );\n return;\n } catch (error) {\n // Only decrement counter if snapshot was activated but not yet committed.\n // renderNavigationPayload clears _snapshotPending (via its inner try-finally)\n // before re-throwing, so this guard correctly skips the double-decrement case.\n if (_snapshotPending) {\n _snapshotPending = false;\n commitClientNavigationState(navId);\n }\n settlePendingBrowserRouterState(pendingRouterState);\n // Clear pending pathname on error so subsequent navigations compare correctly.\n // Only clear if this is still the active navigation — a newer navigation\n // has already overwritten pendingPathname with its own target.\n if (navId === activeNavigationId) {\n clearPendingPathname(navId);\n }\n // Don't hard-navigate to a stale URL if this navigation was superseded by\n // a newer one — the newer navigation is already in flight and would be clobbered.\n if (navId !== activeNavigationId) {\n return;\n }\n console.error(\"[vinext] RSC navigation error:\", error);\n window.location.href = href;\n }\n };\n\n if (\"scrollRestoration\" in history) {\n history.scrollRestoration = \"manual\";\n }\n\n // Note: This popstate handler runs for App Router (RSC navigation available).\n // It coordinates scroll restoration with the pending RSC navigation.\n // Pages Router scroll restoration is handled in shims/navigation.ts:1289 with\n // microtask-based deferral for compatibility with non-RSC navigation.\n // See: https://github.com/vercel/next.js/discussions/41934#discussioncomment-4602607\n window.addEventListener(\"popstate\", (event) => {\n notifyAppRouterTransitionStart(window.location.href, \"traverse\");\n const pendingNavigation =\n window.__VINEXT_RSC_NAVIGATE__?.(window.location.href, 0, \"traverse\") ?? Promise.resolve();\n window.__VINEXT_RSC_PENDING__ = pendingNavigation;\n void pendingNavigation.finally(() => {\n restorePopstateScrollPosition(event.state);\n if (window.__VINEXT_RSC_PENDING__ === pendingNavigation) {\n window.__VINEXT_RSC_PENDING__ = null;\n }\n });\n });\n\n if (import.meta.hot) {\n import.meta.hot.on(\"rsc:update\", async () => {\n try {\n clearClientNavigationCaches();\n const navigationSnapshot = createClientNavigationRenderSnapshot(\n window.location.href,\n latestClientParams,\n );\n // Interception context on HMR re-renders is intentionally deferred:\n // preserving intercepted modal state across HMR reloads is out of scope\n // for the previousNextUrl mechanism.\n const pending = await createPendingNavigationCommit({\n currentState: getBrowserRouterState(),\n nextElements: normalizeAppElementsPromise(\n createFromFetch<AppWireElements>(\n fetch(toRscUrl(window.location.pathname + window.location.search)),\n ),\n ),\n navigationSnapshot,\n renderId: ++nextNavigationRenderId,\n type: \"replace\",\n });\n dispatchBrowserTree(\n pending.action.elements,\n navigationSnapshot,\n pending.action.renderId,\n \"replace\",\n pending.interceptionContext,\n pending.action.layoutFlags,\n pending.previousNextUrl,\n pending.routeId,\n pending.rootLayoutTreePath,\n null,\n false,\n );\n } catch (error) {\n console.error(\"[vinext] RSC HMR error:\", error);\n }\n });\n }\n}\n\nif (typeof document !== \"undefined\") {\n void main();\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"app-browser-entry.js","names":[],"sources":["../../src/server/app-browser-entry.ts"],"sourcesContent":["/// <reference types=\"vite/client\" />\n\nimport {\n createElement,\n startTransition,\n use,\n useLayoutEffect,\n useRef,\n useState,\n type Dispatch,\n type ReactNode,\n} from \"react\";\nimport {\n createFromFetch,\n createFromReadableStream,\n createTemporaryReferenceSet,\n encodeReply,\n setServerCallback,\n} from \"@vitejs/plugin-rsc/browser\";\nimport { hydrateRoot } from \"react-dom/client\";\nimport \"../client/instrumentation-client.js\";\nimport { notifyAppRouterTransitionStart } from \"../client/instrumentation-client-state.js\";\nimport {\n __basePath,\n activateNavigationSnapshot,\n clearPendingPathname,\n commitClientNavigationState,\n consumePrefetchResponse,\n createClientNavigationRenderSnapshot,\n getCurrentNextUrl,\n getCurrentInterceptionContext,\n getClientNavigationRenderContext,\n getClientNavigationState,\n getPrefetchCache,\n getPrefetchedUrls,\n pushHistoryStateWithoutNotify,\n replaceClientParamsWithoutNotify,\n replaceHistoryStateWithoutNotify,\n restoreRscResponse,\n setClientParams,\n setPendingPathname,\n snapshotRscResponse,\n setMountedSlotsHeader,\n setNavigationContext,\n toRscUrl,\n type CachedRscResponse,\n type ClientNavigationRenderSnapshot,\n} from \"../shims/navigation.js\";\nimport { stripBasePath } from \"../utils/base-path.js\";\nimport {\n chunksToReadableStream,\n createProgressiveRscStream,\n getVinextBrowserGlobal,\n} from \"./app-browser-stream.js\";\nimport {\n createAppPayloadCacheKey,\n getMountedSlotIdsHeader,\n normalizeAppElements,\n readAppElementsMetadata,\n resolveVisitedResponseInterceptionContext,\n type AppElements,\n type AppWireElements,\n type LayoutFlags,\n} from \"./app-elements.js\";\nimport {\n createHistoryStateWithPreviousNextUrl,\n createPendingNavigationCommit,\n readHistoryStatePreviousNextUrl,\n resolveAndClassifyNavigationCommit,\n resolveInterceptionContextFromPreviousNextUrl,\n resolvePendingNavigationCommitDisposition,\n resolveServerActionRequestState,\n routerReducer,\n type AppRouterAction,\n type AppRouterState,\n} from \"./app-browser-state.js\";\nimport { ElementsContext, Slot } from \"../shims/slot.js\";\nimport { devOnCaughtError } from \"./app-browser-error.js\";\n\ntype SearchParamInput = ConstructorParameters<typeof URLSearchParams>[0];\n\ntype ServerActionResult = {\n root: AppWireElements;\n returnValue?: {\n ok: boolean;\n data: unknown;\n };\n};\n\ntype NavigationKind = \"navigate\" | \"traverse\" | \"refresh\";\n\n// Maps NavigationKind to the AppRouterAction type used by the reducer.\n// \"refresh\" is intentionally treated as \"navigate\" (merge, preserve absent slots).\n// Both call sites must stay in sync — update here if NavigationKind gains new values.\nfunction toActionType(kind: NavigationKind): \"navigate\" | \"traverse\" {\n return kind === \"traverse\" ? \"traverse\" : \"navigate\";\n}\n\ntype HistoryUpdateMode = \"push\" | \"replace\";\ntype VisitedResponseCacheEntry = {\n params: Record<string, string | string[]>;\n expiresAt: number;\n response: CachedRscResponse;\n};\n\nconst MAX_VISITED_RESPONSE_CACHE_SIZE = 50;\nconst VISITED_RESPONSE_CACHE_TTL = 5 * 60_000;\nconst MAX_TRAVERSAL_CACHE_TTL = 30 * 60_000;\n\n// These are plain module-level variables, unlike ClientNavigationState in\n// navigation.ts which uses Symbol.for to survive multiple Vite module instances.\n// The browser entry is loaded exactly once (via the RSC plugin's generated\n// bootstrap), so module-level state is safe here. If that assumption ever\n// changes, these should be 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.\nlet nextNavigationRenderId = 0;\nlet activeNavigationId = 0;\nconst pendingNavigationCommits = new Map<number, () => void>();\nconst pendingNavigationPrePaintEffects = new Map<number, () => void>();\ntype PendingBrowserRouterState = {\n promise: Promise<AppRouterState>;\n resolve: (state: AppRouterState) => void;\n settled: boolean;\n};\n\nfunction isRouterStatePromise(\n value: AppRouterState | Promise<AppRouterState>,\n): value is Promise<AppRouterState> {\n return value instanceof Promise;\n}\n\nlet setBrowserRouterState: Dispatch<AppRouterState | Promise<AppRouterState>> | null = null;\nlet browserRouterStateRef: { current: AppRouterState } | null = null;\nlet activePendingBrowserRouterState: PendingBrowserRouterState | null = null;\nlet latestClientParams: Record<string, string | string[]> = {};\nconst visitedResponseCache = new Map<string, VisitedResponseCacheEntry>();\n\nfunction isServerActionResult(value: unknown): value is ServerActionResult {\n return !!value && typeof value === \"object\" && \"root\" in value;\n}\n\nfunction 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\nfunction getBrowserRouterState(): AppRouterState {\n if (!browserRouterStateRef) {\n throw new Error(\"[vinext] Browser router state is not initialized\");\n }\n return browserRouterStateRef.current;\n}\n\nfunction beginPendingBrowserRouterState(): PendingBrowserRouterState {\n const setter = getBrowserRouterStateSetter();\n\n if (activePendingBrowserRouterState && !activePendingBrowserRouterState.settled) {\n activePendingBrowserRouterState.settled = true;\n activePendingBrowserRouterState.resolve(getBrowserRouterState());\n }\n\n let resolve!: (state: AppRouterState) => void;\n const promise = new Promise<AppRouterState>((resolvePromise) => {\n resolve = resolvePromise;\n });\n\n const pending: PendingBrowserRouterState = {\n promise,\n resolve,\n settled: false,\n };\n\n activePendingBrowserRouterState = pending;\n setter(promise);\n\n return pending;\n}\n\nfunction 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\nfunction resolvePendingBrowserRouterState(\n pending: PendingBrowserRouterState | null | undefined,\n action: AppRouterAction,\n): void {\n if (!pending || pending.settled) return;\n\n pending.settled = true;\n pending.resolve(routerReducer(getBrowserRouterState(), action));\n\n if (activePendingBrowserRouterState === pending) {\n activePendingBrowserRouterState = null;\n }\n}\n\nfunction applyClientParams(params: Record<string, string | string[]>): void {\n latestClientParams = params;\n setClientParams(params);\n}\n\nfunction stageClientParams(params: Record<string, string | string[]>): void {\n // NB: latestClientParams diverges from ClientNavigationState.clientParams\n // between staging and commit. Server action snapshots (same-URL\n // commitSameUrlNavigatePayload() calls inside registerServerActionCallback)\n // read latestClientParams, so a\n // server action fired during this window would get the pending (not yet\n // committed) params. This is acceptable because the commit effect fires\n // before hooks observe the new URL state, keeping the window vanishingly small.\n latestClientParams = params;\n replaceClientParamsWithoutNotify(params);\n}\n\nfunction clearVisitedResponseCache(): void {\n visitedResponseCache.clear();\n}\n\nfunction clearPrefetchState(): void {\n getPrefetchCache().clear();\n getPrefetchedUrls().clear();\n}\n\nfunction clearClientNavigationCaches(): void {\n clearVisitedResponseCache();\n clearPrefetchState();\n}\n\nfunction 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 */\nfunction drainPrePaintEffects(upToRenderId: number): void {\n for (const [id, effect] of pendingNavigationPrePaintEffects) {\n if (id <= upToRenderId) {\n pendingNavigationPrePaintEffects.delete(id);\n if (id === upToRenderId) {\n // Winning navigation: run its actual pre-paint effect\n effect();\n } else {\n // Superseded navigation: balance its activateNavigationSnapshot().\n // Pass undefined navId intentionally so this cleanup cannot clear\n // pendingPathname owned by the current active navigation.\n commitClientNavigationState(undefined);\n }\n }\n }\n}\n\nfunction createNavigationCommitEffect(\n href: string,\n historyUpdateMode: HistoryUpdateMode | undefined,\n navId: number,\n params: Record<string, string | string[]>,\n previousNextUrl: string | null,\n): () => void {\n return () => {\n // Only update URL if this is still the active navigation.\n // A newer navigation would have incremented activeNavigationId.\n if (navId !== activeNavigationId) {\n // This transition was superseded before commit; balance the active\n // snapshot counter without clearing pendingPathname ownership.\n commitClientNavigationState(undefined);\n return;\n }\n\n const targetHref = new URL(href, window.location.origin).href;\n stageClientParams(params);\n const preserveExistingState = historyUpdateMode === \"replace\";\n const historyState = createHistoryStateWithPreviousNextUrl(\n preserveExistingState ? window.history.state : null,\n previousNextUrl,\n );\n\n if (historyUpdateMode === \"replace\" && window.location.href !== targetHref) {\n replaceHistoryStateWithoutNotify(historyState, \"\", href);\n } else if (historyUpdateMode === \"push\" && window.location.href !== targetHref) {\n pushHistoryStateWithoutNotify(historyState, \"\", href);\n }\n\n commitClientNavigationState(navId);\n };\n}\n\nfunction evictVisitedResponseCacheIfNeeded(): void {\n while (visitedResponseCache.size >= MAX_VISITED_RESPONSE_CACHE_SIZE) {\n const oldest = visitedResponseCache.keys().next().value;\n if (oldest === undefined) {\n return;\n }\n visitedResponseCache.delete(oldest);\n }\n}\n\nfunction getVisitedResponse(\n rscUrl: string,\n interceptionContext: string | null,\n mountedSlotsHeader: string | null,\n navigationKind: NavigationKind,\n): VisitedResponseCacheEntry | null {\n const cacheKey = createAppPayloadCacheKey(rscUrl, interceptionContext);\n const cached = visitedResponseCache.get(cacheKey);\n if (!cached) {\n return null;\n }\n\n if ((cached.response.mountedSlotsHeader ?? null) !== mountedSlotsHeader) {\n visitedResponseCache.delete(cacheKey);\n return null;\n }\n\n if (navigationKind === \"refresh\") {\n return null;\n }\n\n if (navigationKind === \"traverse\") {\n const createdAt = cached.expiresAt - VISITED_RESPONSE_CACHE_TTL;\n if (Date.now() - createdAt >= MAX_TRAVERSAL_CACHE_TTL) {\n visitedResponseCache.delete(cacheKey);\n return null;\n }\n // LRU: promote to most-recently-used (delete + re-insert moves to end of Map)\n visitedResponseCache.delete(cacheKey);\n visitedResponseCache.set(cacheKey, cached);\n return cached;\n }\n\n if (cached.expiresAt > Date.now()) {\n // LRU: promote to most-recently-used\n visitedResponseCache.delete(cacheKey);\n visitedResponseCache.set(cacheKey, cached);\n return cached;\n }\n\n visitedResponseCache.delete(cacheKey);\n return null;\n}\n\nfunction storeVisitedResponseSnapshot(\n rscUrl: string,\n interceptionContext: string | null,\n snapshot: CachedRscResponse,\n params: Record<string, string | string[]>,\n): void {\n const cacheKey = createAppPayloadCacheKey(rscUrl, interceptionContext);\n visitedResponseCache.delete(cacheKey);\n evictVisitedResponseCacheIfNeeded();\n const now = Date.now();\n visitedResponseCache.set(cacheKey, {\n params,\n expiresAt: now + VISITED_RESPONSE_CACHE_TTL,\n response: snapshot,\n });\n}\n\ntype NavigationRequestState = {\n interceptionContext: string | null;\n previousNextUrl: string | null;\n};\n\nfunction getRequestState(\n navigationKind: NavigationKind,\n previousNextUrlOverride?: string | null,\n): NavigationRequestState {\n if (previousNextUrlOverride !== undefined) {\n return {\n interceptionContext: resolveInterceptionContextFromPreviousNextUrl(\n previousNextUrlOverride,\n __basePath,\n ),\n previousNextUrl: previousNextUrlOverride,\n };\n }\n\n switch (navigationKind) {\n case \"navigate\":\n return {\n interceptionContext: getCurrentInterceptionContext(),\n previousNextUrl: getCurrentNextUrl(),\n };\n case \"traverse\": {\n const previousNextUrl = readHistoryStatePreviousNextUrl(window.history.state);\n return {\n interceptionContext: resolveInterceptionContextFromPreviousNextUrl(\n previousNextUrl,\n __basePath,\n ),\n previousNextUrl,\n };\n }\n case \"refresh\": {\n const currentPreviousNextUrl = getBrowserRouterState().previousNextUrl;\n return {\n interceptionContext: resolveInterceptionContextFromPreviousNextUrl(\n currentPreviousNextUrl,\n __basePath,\n ),\n previousNextUrl: currentPreviousNextUrl,\n };\n }\n default: {\n const _exhaustive: never = navigationKind;\n throw new Error(\"[vinext] Unknown navigation kind: \" + String(_exhaustive));\n }\n }\n}\n\nfunction createRscRequestHeaders(interceptionContext: string | null): Headers {\n const headers = new Headers({ Accept: \"text/x-component\" });\n if (interceptionContext !== null) {\n headers.set(\"X-Vinext-Interception-Context\", interceptionContext);\n }\n return headers;\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 */\nfunction resolveCommittedNavigations(renderId: number): void {\n for (const [pendingId, resolve] of pendingNavigationCommits) {\n if (pendingId <= renderId) {\n pendingNavigationCommits.delete(pendingId);\n resolve();\n }\n }\n}\n\nfunction NavigationCommitSignal({\n renderId,\n children,\n}: {\n renderId: number;\n children?: ReactNode;\n}) {\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\nfunction normalizeAppElementsPromise(payload: Promise<AppWireElements>): Promise<AppElements> {\n // Wrap in Promise.resolve() because createFromReadableStream() returns a\n // React Flight thenable whose .then() returns undefined (not a new Promise).\n // Without the wrap, chaining .then() produces undefined → use() crashes.\n return Promise.resolve(payload).then((elements) => normalizeAppElements(elements));\n}\n\nasync function commitSameUrlNavigatePayload(\n nextElements: Promise<AppElements>,\n returnValue?: ServerActionResult[\"returnValue\"],\n): Promise<unknown> {\n const navigationSnapshot = createClientNavigationRenderSnapshot(\n window.location.href,\n latestClientParams,\n );\n const currentState = getBrowserRouterState();\n const startedNavigationId = activeNavigationId;\n const { disposition, pending } = await resolveAndClassifyNavigationCommit({\n activeNavigationId,\n currentState,\n navigationSnapshot,\n nextElements,\n renderId: ++nextNavigationRenderId,\n startedNavigationId,\n type: \"navigate\",\n });\n\n // Known limitation: if a same-URL navigation fully commits while this\n // server action is awaiting createPendingNavigationCommit(), the action\n // can still dispatch its older payload afterward. The old pre-2c code had\n // the same race, and Next.js has similar behavior. Tightening this would\n // need a stronger commit-version gate than activeNavigationId alone.\n if (disposition === \"hard-navigate\") {\n window.location.assign(window.location.href);\n return undefined;\n }\n\n if (disposition === \"dispatch\") {\n dispatchBrowserTree(\n pending.action.elements,\n navigationSnapshot,\n pending.action.renderId,\n \"navigate\",\n pending.interceptionContext,\n pending.action.layoutFlags,\n pending.previousNextUrl,\n pending.routeId,\n pending.rootLayoutTreePath,\n null,\n false,\n );\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\nfunction BrowserRoot({\n initialElements,\n initialNavigationSnapshot,\n}: {\n initialElements: Promise<AppElements>;\n initialNavigationSnapshot: ClientNavigationRenderSnapshot;\n}) {\n const resolvedElements = use(initialElements);\n const initialMetadata = readAppElementsMetadata(resolvedElements);\n const [treeStateValue, setTreeStateValue] = useState<AppRouterState | Promise<AppRouterState>>({\n elements: resolvedElements,\n interceptionContext: initialMetadata.interceptionContext,\n layoutFlags: initialMetadata.layoutFlags,\n navigationSnapshot: initialNavigationSnapshot,\n previousNextUrl: null,\n renderId: 0,\n rootLayoutTreePath: initialMetadata.rootLayoutTreePath,\n routeId: initialMetadata.routeId,\n });\n const treeState = isRouterStatePromise(treeStateValue) ? use(treeStateValue) : treeStateValue;\n\n // Keep the latest router state in a ref so external callers (navigate(),\n // server actions, HMR) always read the current state. Safe: those readers\n // run from events/effects, never from React render itself.\n // Note: stateRef.current is written during render, not in an effect, to\n // avoid a stale-read window between commit and layout effects. This mirrors\n // the same render-phase ref update pattern used by Next.js's own router.\n const stateRef = useRef(treeState);\n stateRef.current = treeState;\n\n // Publish the stable ref object and dispatch during layout commit. This keeps\n // the module-level escape hatches aligned with React's committed tree without\n // performing module writes during render. __VINEXT_RSC_NAVIGATE__ is assigned\n // after hydrateRoot() returns; by then this layout effect has already run for\n // the hydration commit, so getBrowserRouterState() never observes a null ref.\n useLayoutEffect(() => {\n setBrowserRouterState = setTreeStateValue;\n browserRouterStateRef = stateRef;\n return () => {\n if (setBrowserRouterState === setTreeStateValue) {\n setBrowserRouterState = null;\n }\n if (browserRouterStateRef === stateRef) {\n browserRouterStateRef = null;\n }\n setMountedSlotsHeader(null);\n };\n }, [setTreeStateValue]);\n\n useLayoutEffect(() => {\n setMountedSlotsHeader(getMountedSlotIdsHeader(stateRef.current.elements));\n }, [treeState.elements]);\n\n useLayoutEffect(() => {\n if (treeState.renderId !== 0) {\n return;\n }\n\n replaceHistoryStateWithoutNotify(\n createHistoryStateWithPreviousNextUrl(window.history.state, treeState.previousNextUrl),\n \"\",\n window.location.href,\n );\n }, [treeState.previousNextUrl, treeState.renderId]);\n\n const committedTree = createElement(\n NavigationCommitSignal,\n { renderId: treeState.renderId },\n createElement(\n ElementsContext.Provider,\n { value: treeState.elements },\n createElement(Slot, { id: treeState.routeId }),\n ),\n );\n\n const ClientNavigationRenderContext = getClientNavigationRenderContext();\n if (!ClientNavigationRenderContext) {\n return committedTree;\n }\n\n return createElement(\n ClientNavigationRenderContext.Provider,\n { value: treeState.navigationSnapshot },\n committedTree,\n );\n}\n\nfunction dispatchBrowserTree(\n elements: AppElements,\n navigationSnapshot: ClientNavigationRenderSnapshot,\n renderId: number,\n actionType: \"navigate\" | \"replace\" | \"traverse\",\n interceptionContext: string | null,\n layoutFlags: LayoutFlags,\n previousNextUrl: string | null,\n routeId: string,\n rootLayoutTreePath: string | null,\n pendingRouterState: PendingBrowserRouterState | null,\n useTransitionMode: boolean,\n): void {\n const setter = getBrowserRouterStateSetter();\n const action: AppRouterAction = {\n elements,\n interceptionContext,\n layoutFlags,\n navigationSnapshot,\n previousNextUrl,\n renderId,\n rootLayoutTreePath,\n routeId,\n type: actionType,\n };\n\n const applyAction = () => {\n if (pendingRouterState) {\n // The programmatic navigation is already running inside React.startTransition\n // (from router.push/replace/refresh), so resolving the deferred promise is\n // sufficient — no additional startTransition wrapper is needed below.\n resolvePendingBrowserRouterState(pendingRouterState, action);\n return;\n }\n\n setter(routerReducer(getBrowserRouterState(), action));\n };\n\n if (useTransitionMode) {\n startTransition(applyAction);\n } else {\n applyAction();\n }\n}\n\nasync function renderNavigationPayload(\n payload: Promise<AppElements>,\n navigationSnapshot: ClientNavigationRenderSnapshot,\n targetHref: string,\n navId: number,\n historyUpdateMode: HistoryUpdateMode | undefined,\n params: Record<string, string | string[]>,\n previousNextUrl: string | null,\n pendingRouterState: PendingBrowserRouterState | null,\n useTransition = true,\n actionType: \"navigate\" | \"replace\" | \"traverse\" = \"navigate\",\n): Promise<void> {\n const renderId = ++nextNavigationRenderId;\n const committed = new Promise<void>((resolve) => {\n pendingNavigationCommits.set(renderId, resolve);\n });\n\n let snapshotActivated = false;\n try {\n const currentState = getBrowserRouterState();\n const pending = await createPendingNavigationCommit({\n currentState,\n nextElements: payload,\n navigationSnapshot,\n previousNextUrl,\n renderId,\n type: actionType,\n });\n\n const disposition = resolvePendingNavigationCommitDisposition({\n activeNavigationId,\n currentRootLayoutTreePath: currentState.rootLayoutTreePath,\n nextRootLayoutTreePath: pending.rootLayoutTreePath,\n startedNavigationId: navId,\n });\n\n if (disposition === \"skip\") {\n settlePendingBrowserRouterState(pendingRouterState);\n const resolve = pendingNavigationCommits.get(renderId);\n pendingNavigationCommits.delete(renderId);\n resolve?.();\n return;\n }\n\n if (disposition === \"hard-navigate\") {\n settlePendingBrowserRouterState(pendingRouterState);\n pendingNavigationCommits.delete(renderId);\n window.location.assign(targetHref);\n return;\n }\n\n queuePrePaintNavigationEffect(\n renderId,\n createNavigationCommitEffect(\n targetHref,\n historyUpdateMode,\n navId,\n params,\n pending.previousNextUrl,\n ),\n );\n activateNavigationSnapshot();\n snapshotActivated = true;\n dispatchBrowserTree(\n pending.action.elements,\n navigationSnapshot,\n renderId,\n actionType,\n pending.interceptionContext,\n pending.action.layoutFlags,\n pending.previousNextUrl,\n pending.routeId,\n pending.rootLayoutTreePath,\n pendingRouterState,\n useTransition,\n );\n } catch (error) {\n // Clean up pending state on error. Only decrement the snapshot counter\n // if activateNavigationSnapshot() was actually called — if\n // createPendingNavigationCommit() threw, the counter was never\n // incremented so decrementing would underflow it.\n pendingNavigationPrePaintEffects.delete(renderId);\n const resolve = pendingNavigationCommits.get(renderId);\n pendingNavigationCommits.delete(renderId);\n if (snapshotActivated) {\n commitClientNavigationState(navId);\n }\n settlePendingBrowserRouterState(pendingRouterState);\n resolve?.();\n throw error;\n }\n\n return committed;\n}\n\nfunction restoreHydrationNavigationContext(\n pathname: string,\n searchParams: SearchParamInput,\n params: Record<string, string | string[]>,\n): void {\n setNavigationContext({\n pathname,\n searchParams: new URLSearchParams(searchParams),\n params,\n });\n}\n\nfunction restorePopstateScrollPosition(state: unknown): void {\n if (!(state && typeof state === \"object\" && \"__vinext_scrollY\" in state)) {\n return;\n }\n\n const y = Number(state.__vinext_scrollY);\n const x = \"__vinext_scrollX\" in state ? Number(state.__vinext_scrollX) : 0;\n\n requestAnimationFrame(() => {\n window.scrollTo(x, y);\n });\n}\n\n// Set on pagehide so the RSC navigation catch block can distinguish expected\n// fetch aborts (triggered by the unload itself) from real errors worth logging.\nlet isPageUnloading = false;\n\nconst RSC_RELOAD_KEY = \"__vinext_rsc_initial_reload__\";\n\n// sessionStorage can throw SecurityError in strict-mode iframes, storage-\n// disabled browsers, and some Safari private-browsing configurations. Wrap\n// every access so a recovery path for one error does not crash hydration.\nfunction readReloadFlag(): string | null {\n try {\n return sessionStorage.getItem(RSC_RELOAD_KEY);\n } catch {\n return null;\n }\n}\nfunction writeReloadFlag(path: string): void {\n try {\n sessionStorage.setItem(RSC_RELOAD_KEY, path);\n } catch {}\n}\nfunction clearReloadFlag(): void {\n try {\n sessionStorage.removeItem(RSC_RELOAD_KEY);\n } catch {}\n}\n\n// A non-ok or wrong-content-type RSC response during initial hydration means\n// the server cannot deliver a valid RSC payload for this URL. Parsing the\n// response as RSC causes an opaque parse failure. On the first attempt,\n// reload once so the server has a chance to render the correct error page\n// as HTML. On the second attempt (detected via the sessionStorage flag), the\n// endpoint is persistently broken. Returns null so main() aborts the\n// hydration bootstrap without registering `__VINEXT_RSC_*` globals —\n// including during the brief window between reload() firing and the page\n// actually unloading — so external probes never see a half-hydrated page.\nfunction recoverFromBadInitialRscResponse(reason: string): null {\n const currentPath = window.location.pathname + window.location.search;\n if (readReloadFlag() === currentPath) {\n clearReloadFlag();\n console.error(\n `[vinext] Initial RSC fetch ${reason} after reload; aborting hydration. ` +\n \"Server-rendered HTML remains visible; client components will not hydrate.\",\n );\n return null;\n }\n writeReloadFlag(currentPath);\n // Verify the write persisted. In storage-denied environments (strict-mode\n // iframes, locked-down enterprise policies), every getItem returns null and\n // every setItem silently no-ops, so the reload-loop guard cannot survive\n // the reload — the page would loop forever. Abort instead so the user at\n // least sees the server-rendered HTML.\n if (readReloadFlag() !== currentPath) {\n console.error(\n `[vinext] Initial RSC fetch ${reason}; sessionStorage unavailable so the ` +\n \"reload-loop guard cannot persist — aborting hydration. \" +\n \"Server-rendered HTML remains visible; client components will not hydrate.\",\n );\n return null;\n }\n // One-shot diagnostic so a production reload is traceable. Only fires once\n // per broken path thanks to the sessionStorage flag above; not noisy.\n console.warn(\n `[vinext] Initial RSC fetch ${reason}; reloading once to let the server render the HTML error page`,\n );\n window.location.reload();\n return null;\n}\n\nasync function readInitialRscStream(): Promise<ReadableStream<Uint8Array> | null> {\n const vinext = getVinextBrowserGlobal();\n\n if (vinext.__VINEXT_RSC__ || vinext.__VINEXT_RSC_CHUNKS__ || vinext.__VINEXT_RSC_DONE__) {\n // Reaching the embedded-RSC branch means the server successfully rendered\n // the page — any prior reload flag for this path is stale and must be\n // cleared so a future failure gets its own fresh recovery attempt.\n clearReloadFlag();\n\n if (vinext.__VINEXT_RSC__) {\n const embedData = vinext.__VINEXT_RSC__;\n delete vinext.__VINEXT_RSC__;\n\n const params = embedData.params ?? {};\n if (embedData.params) {\n applyClientParams(embedData.params);\n }\n if (embedData.nav) {\n restoreHydrationNavigationContext(\n embedData.nav.pathname,\n embedData.nav.searchParams,\n params,\n );\n }\n\n return chunksToReadableStream(embedData.rsc);\n }\n\n const params = vinext.__VINEXT_RSC_PARAMS__ ?? {};\n if (vinext.__VINEXT_RSC_PARAMS__) {\n applyClientParams(vinext.__VINEXT_RSC_PARAMS__);\n }\n if (vinext.__VINEXT_RSC_NAV__) {\n restoreHydrationNavigationContext(\n vinext.__VINEXT_RSC_NAV__.pathname,\n vinext.__VINEXT_RSC_NAV__.searchParams,\n params,\n );\n }\n\n return createProgressiveRscStream();\n }\n\n const rscResponse = await fetch(toRscUrl(window.location.pathname + window.location.search));\n\n if (!rscResponse.ok) {\n return recoverFromBadInitialRscResponse(`returned ${rscResponse.status}`);\n }\n // Guard against proxies/CDNs that return 200 with a rewritten Content-Type\n // (e.g. text/html instead of text/x-component). Such responses cannot be\n // parsed as RSC and would throw the same opaque parse error this fallback\n // exists to prevent.\n const contentType = rscResponse.headers.get(\"content-type\") ?? \"\";\n if (!contentType.startsWith(\"text/x-component\")) {\n return recoverFromBadInitialRscResponse(\n `returned non-RSC content-type \"${contentType || \"(missing)\"}\"`,\n );\n }\n // Missing body (e.g. 204 No Content, or an edge worker that returned ok\n // headers without piping the stream) fails the same way downstream.\n // Matches Next.js' `!res.body` branch in fetch-server-response.ts.\n if (!rscResponse.body) {\n return recoverFromBadInitialRscResponse(\"returned empty body\");\n }\n // Successful RSC response clears the guard so a subsequent reload of the\n // same path after a transient failure still gets one recovery attempt.\n clearReloadFlag();\n\n let params: Record<string, string | string[]> = {};\n const paramsHeader = rscResponse.headers.get(\"X-Vinext-Params\");\n if (paramsHeader) {\n try {\n params = JSON.parse(decodeURIComponent(paramsHeader)) as Record<string, string | string[]>;\n applyClientParams(params);\n } catch {\n // Ignore malformed param headers and continue with hydration.\n }\n }\n\n restoreHydrationNavigationContext(window.location.pathname, window.location.search, params);\n\n return rscResponse.body;\n}\n\nfunction registerServerActionCallback(): void {\n setServerCallback(async (id, args) => {\n const temporaryReferences = createTemporaryReferenceSet();\n const body = await encodeReply(args, { temporaryReferences });\n\n // Carry the interception context + mounted slots from the current router\n // state so the server-action re-render rebuilds the intercepted tree\n // instead of replacing it with the direct page. Parity with Next.js,\n // which sends `Next-URL` on action POSTs when the current tree contains\n // an interception route.\n const currentState = getBrowserRouterState();\n const { headers } = resolveServerActionRequestState({\n actionId: id,\n basePath: __basePath,\n elements: currentState.elements,\n previousNextUrl: currentState.previousNextUrl,\n });\n\n const fetchResponse = await fetch(toRscUrl(window.location.pathname + window.location.search), {\n method: \"POST\",\n headers,\n body,\n });\n\n const actionRedirect = fetchResponse.headers.get(\"x-action-redirect\");\n if (actionRedirect) {\n // Check for external URLs that need a hard redirect.\n try {\n const redirectUrl = new URL(actionRedirect, window.location.origin);\n if (redirectUrl.origin !== window.location.origin) {\n window.location.href = actionRedirect;\n return undefined;\n }\n } catch {\n // Fall through to hard redirect below if URL parsing fails.\n }\n\n // Use hard redirect for all action redirects because vinext's server\n // currently returns an empty body for redirect responses. RSC navigation\n // requires a valid RSC payload. This is a known parity gap with Next.js,\n // which pre-renders the redirect target's RSC payload.\n const redirectType = fetchResponse.headers.get(\"x-action-redirect-type\") ?? \"replace\";\n if (redirectType === \"push\") {\n window.location.assign(actionRedirect);\n } else {\n window.location.replace(actionRedirect);\n }\n return undefined;\n }\n\n clearClientNavigationCaches();\n\n const result = await createFromFetch<ServerActionResult | AppWireElements>(\n Promise.resolve(fetchResponse),\n { temporaryReferences },\n );\n\n // Server actions stay on the same URL and use commitSameUrlNavigatePayload()\n // for merge-based dispatch. This path does not call\n // activateNavigationSnapshot() because there is no URL change to commit, so\n // hooks continue reading the live external-store values directly. If server\n // actions ever trigger URL changes via RSC payload (instead of hard\n // redirects), this would need renderNavigationPayload().\n if (isServerActionResult(result)) {\n return commitSameUrlNavigatePayload(\n Promise.resolve(normalizeAppElements(result.root)),\n result.returnValue,\n );\n }\n\n return commitSameUrlNavigatePayload(Promise.resolve(normalizeAppElements(result)));\n });\n}\n\nasync function main(): Promise<void> {\n registerServerActionCallback();\n\n const rscStream = await readInitialRscStream();\n // null signals that readInitialRscStream aborted hydration — either because\n // a reload is in flight (first-attempt recovery) or the endpoint is\n // persistently broken (post-reload). Bootstrap is a separate synchronous\n // helper so the null-branch structurally cannot reach any __VINEXT_RSC_*\n // global assignment, even if a future refactor interposes async work here.\n if (rscStream === null) return;\n bootstrapHydration(rscStream);\n}\n\nfunction bootstrapHydration(rscStream: ReadableStream<Uint8Array>): void {\n const root = normalizeAppElementsPromise(createFromReadableStream<AppWireElements>(rscStream));\n const initialNavigationSnapshot = createClientNavigationRenderSnapshot(\n window.location.href,\n latestClientParams,\n );\n replaceHistoryStateWithoutNotify(\n createHistoryStateWithPreviousNextUrl(window.history.state, null),\n \"\",\n window.location.href,\n );\n\n window.__VINEXT_RSC_ROOT__ = hydrateRoot(\n document,\n createElement(BrowserRoot, {\n initialElements: root,\n initialNavigationSnapshot,\n }),\n import.meta.env.DEV ? { onCaughtError: devOnCaughtError } : undefined,\n );\n window.__VINEXT_HYDRATED_AT = performance.now();\n\n window.__VINEXT_RSC_NAVIGATE__ = async function navigateRsc(\n href: string,\n redirectDepth = 0,\n navigationKind: NavigationKind = \"navigate\",\n historyUpdateMode?: HistoryUpdateMode,\n previousNextUrlOverride?: string | null,\n programmaticTransition = false,\n ): Promise<void> {\n let _snapshotPending = false;\n let pendingRouterState: PendingBrowserRouterState | null = null;\n // Hoist navId above try so the catch and finally blocks can reference it.\n const navId = ++activeNavigationId;\n\n // Loop variables for inline redirect following. On a redirect, these are\n // updated and the loop continues without returning or re-entering navigateRsc,\n // so a single pendingRouterState spans all hops and isPending never flashes.\n let currentHref = href;\n let currentHistoryMode = historyUpdateMode;\n let currentPrevNextUrl = previousNextUrlOverride;\n let redirectCount = redirectDepth;\n\n try {\n if (programmaticTransition) {\n pendingRouterState = beginPendingBrowserRouterState();\n }\n\n while (true) {\n if (redirectCount > 10) {\n console.error(\n \"[vinext] Too many RSC redirects — aborting navigation to prevent infinite loop.\",\n );\n window.location.href = currentHref;\n return;\n }\n\n const url = new URL(currentHref, window.location.origin);\n const rscUrl = toRscUrl(url.pathname + url.search);\n const requestState = getRequestState(navigationKind, currentPrevNextUrl);\n const requestInterceptionContext = requestState.interceptionContext;\n const requestPreviousNextUrl = requestState.previousNextUrl;\n\n // Compare against previous pending navigation first, then committed state.\n // This avoids isSameRoute misclassification during rapid back-to-back clicks.\n const navState = getClientNavigationState();\n const currentPath =\n navState?.pendingPathname ??\n navState?.cachedPathname ??\n stripBasePath(window.location.pathname, __basePath);\n\n const targetPath = stripBasePath(url.pathname, __basePath);\n const isSameRoute = targetPath === currentPath;\n\n // Set this navigation as the pending pathname, overwriting any previous.\n // Pass navId so only this navigation (or a newer one) can clear it later.\n setPendingPathname(url.pathname, navId);\n\n const elementsAtNavStart = getBrowserRouterState().elements;\n const mountedSlotsHeader = getMountedSlotIdsHeader(elementsAtNavStart);\n const cachedRoute = getVisitedResponse(\n rscUrl,\n requestInterceptionContext,\n mountedSlotsHeader,\n navigationKind,\n );\n if (cachedRoute) {\n // Check stale-navigation before and after createFromFetch. The pre-check\n // avoids wasted parse work; the post-check catches supersessions that\n // occur during the await. createFromFetch on a buffered response is fast\n // but still async, so the window exists. The non-cached path (below) places\n // its heavyweight async steps (fetch, snapshotRscResponse, createFromFetch)\n // between navId checks consistently; the cached path omits the check between\n // createClientNavigationRenderSnapshot (synchronous) and createFromFetch\n // because there is no await in that gap.\n if (navId !== activeNavigationId) return;\n const cachedParams = cachedRoute.params;\n // createClientNavigationRenderSnapshot is synchronous (URL parsing + param\n // wrapping only) — no stale-navigation recheck needed between here and the\n // next await.\n const cachedNavigationSnapshot = createClientNavigationRenderSnapshot(\n currentHref,\n cachedParams,\n );\n const cachedPayload = normalizeAppElementsPromise(\n createFromFetch<AppWireElements>(\n Promise.resolve(restoreRscResponse(cachedRoute.response)),\n ),\n );\n if (navId !== activeNavigationId) return;\n _snapshotPending = true; // Set before renderNavigationPayload\n try {\n await renderNavigationPayload(\n cachedPayload,\n cachedNavigationSnapshot,\n currentHref,\n navId,\n currentHistoryMode,\n cachedParams,\n requestPreviousNextUrl,\n pendingRouterState,\n isSameRoute,\n toActionType(navigationKind),\n );\n } finally {\n // Always clear _snapshotPending so the outer catch does not\n // double-decrement if renderNavigationPayload throws.\n _snapshotPending = false;\n }\n return;\n }\n\n // Continue using the slot state captured at navigation start for fetches\n // and prefetch compatibility decisions.\n\n let navResponse: Response | undefined;\n let navResponseUrl: string | null = null;\n if (navigationKind !== \"refresh\") {\n const prefetchedResponse = consumePrefetchResponse(\n rscUrl,\n requestInterceptionContext,\n mountedSlotsHeader,\n );\n if (prefetchedResponse) {\n navResponse = restoreRscResponse(prefetchedResponse, false);\n navResponseUrl = prefetchedResponse.url;\n }\n }\n\n if (!navResponse) {\n const requestHeaders = createRscRequestHeaders(requestInterceptionContext);\n if (mountedSlotsHeader) {\n requestHeaders.set(\"X-Vinext-Mounted-Slots\", mountedSlotsHeader);\n }\n navResponse = await fetch(rscUrl, {\n headers: requestHeaders,\n credentials: \"include\",\n });\n }\n\n if (navId !== activeNavigationId) return;\n\n // Any response that isn't a valid RSC payload (non-ok status,\n // missing/rewritten Content-Type, or missing body) means the server\n // returned something we cannot parse — typically an HTML error page\n // or a proxy-rewritten response. Parsing such a body as an RSC stream\n // throws a cryptic \"Connection closed\" error. Match Next.js behavior\n // (fetch-server-response.ts:211, `!isFlightResponse || !res.ok || !res.body`):\n // hard-navigate to the response URL so the server can render the correct\n // error page as HTML. The outer finally handles\n // settlePendingBrowserRouterState and clearPendingPathname on this\n // return path.\n //\n // Prefer the post-redirect response URL over `currentHref`: on a\n // redirect chain like `/old` → 307 → `/new` → 500, the browser's\n // fetch already followed the redirect, so `navResponse.url` is the\n // failing `/new` destination. Hard-navigating there directly avoids\n // bouncing off `/old` just to re-follow the same 307, which would\n // flash the wrong URL in the address bar and mis-key analytics.\n // Matches Next.js' `doMpaNavigation(responseUrl.toString())`. Falls\n // back to `currentHref` when no response URL is available.\n const navContentType = navResponse.headers.get(\"content-type\") ?? \"\";\n const isRscResponse = navContentType.startsWith(\"text/x-component\");\n if (!navResponse.ok || !isRscResponse || !navResponse.body) {\n const responseUrl = navResponseUrl ?? navResponse.url;\n let hardNavTarget = currentHref;\n if (responseUrl) {\n const parsed = new URL(responseUrl, window.location.origin);\n const origUrl = new URL(currentHref, window.location.origin);\n let pathname = parsed.pathname.replace(/\\.rsc$/, \"\");\n // toRscUrl strips trailing slash before appending .rsc, so the\n // response URL loses it on the round-trip. Restore it when the\n // original href had one so sites with trailingSlash:true don't\n // incur an extra 308 to the canonical form on the error path.\n if (\n origUrl.pathname.length > 1 &&\n origUrl.pathname.endsWith(\"/\") &&\n !pathname.endsWith(\"/\")\n ) {\n pathname += \"/\";\n }\n hardNavTarget = pathname + parsed.search;\n // Preserve the hash from the user's clicked href — a .rsc response\n // URL never carries a fragment, so dropping it would silently strip\n // `/foo#section` down to `/foo`.\n if (origUrl.hash) hardNavTarget += origUrl.hash;\n }\n window.location.href = hardNavTarget;\n return;\n }\n\n const finalUrl = new URL(navResponseUrl ?? navResponse.url, window.location.origin);\n const requestedUrl = new URL(rscUrl, window.location.origin);\n\n if (finalUrl.pathname !== requestedUrl.pathname) {\n // Server-side redirect: update the URL in history and loop to fetch\n // the destination without settling pendingRouterState. This keeps\n // isPending true across all redirect hops instead of flashing false.\n const destinationPath = finalUrl.pathname.replace(/\\.rsc$/, \"\") + finalUrl.search;\n replaceHistoryStateWithoutNotify(\n createHistoryStateWithPreviousNextUrl(null, requestPreviousNextUrl),\n \"\",\n destinationPath,\n );\n\n currentHref = destinationPath;\n // URL already written above; the commit effect must not push/replace again.\n currentHistoryMode = undefined;\n currentPrevNextUrl = requestPreviousNextUrl;\n redirectCount += 1;\n continue;\n }\n\n let navParams: Record<string, string | string[]> = {};\n const paramsHeader = navResponse.headers.get(\"X-Vinext-Params\");\n if (paramsHeader) {\n try {\n navParams = JSON.parse(decodeURIComponent(paramsHeader)) as Record<\n string,\n string | string[]\n >;\n } catch {\n // navParams stays as {}\n }\n }\n // Build snapshot from local params, not latestClientParams\n const navigationSnapshot = createClientNavigationRenderSnapshot(currentHref, navParams);\n\n const responseSnapshot = await snapshotRscResponse(navResponse);\n\n if (navId !== activeNavigationId) return;\n\n const rscPayload = normalizeAppElementsPromise(\n createFromFetch<AppWireElements>(Promise.resolve(restoreRscResponse(responseSnapshot))),\n );\n\n if (navId !== activeNavigationId) return;\n\n _snapshotPending = true; // Set before renderNavigationPayload\n try {\n await renderNavigationPayload(\n rscPayload,\n navigationSnapshot,\n currentHref,\n navId,\n currentHistoryMode,\n navParams,\n requestPreviousNextUrl,\n pendingRouterState,\n isSameRoute,\n toActionType(navigationKind),\n );\n } finally {\n // Always clear _snapshotPending after renderNavigationPayload returns or\n // throws. renderNavigationPayload's inner catch already calls\n // commitClientNavigationState() on synchronous errors and re-throws, so\n // the outer catch must not call it again. Clearing here prevents the outer\n // catch from double-decrementing navigationSnapshotActiveCount.\n _snapshotPending = false;\n }\n // Don't cache the response if this navigation was superseded during\n // renderNavigationPayload's await — the elements were never dispatched.\n if (navId !== activeNavigationId) return;\n // Store the visited response only after renderNavigationPayload succeeds.\n // If we stored it before and renderNavigationPayload threw, a future\n // back/forward navigation could replay a snapshot from a navigation that\n // never actually rendered successfully.\n const resolvedElements = await rscPayload;\n const metadata = readAppElementsMetadata(resolvedElements);\n storeVisitedResponseSnapshot(\n rscUrl,\n resolveVisitedResponseInterceptionContext(\n requestInterceptionContext,\n metadata.interceptionContext,\n ),\n responseSnapshot,\n navParams,\n );\n return;\n }\n } catch (error) {\n // Only decrement counter if snapshot was activated but not yet committed.\n // renderNavigationPayload clears _snapshotPending (via its inner try-finally)\n // before re-throwing, so this guard correctly skips the double-decrement case.\n if (_snapshotPending) {\n _snapshotPending = false;\n commitClientNavigationState(navId);\n }\n // Don't hard-navigate to a stale URL if this navigation was superseded by\n // a newer one — the newer navigation is already in flight and would be clobbered.\n if (navId !== activeNavigationId) return;\n // Suppress the diagnostic when the page is unloading: a hard-nav or anchor\n // click tears down the document and aborts any in-flight RSC fetch, which\n // surfaces here as an error. The page is already going away, so the log\n // is just noise. Mirrors Next.js' isPageUnloading pattern.\n if (!isPageUnloading) {\n console.error(\"[vinext] RSC navigation error:\", error);\n }\n window.location.href = currentHref;\n } finally {\n // Single settlement site: covers normal return, early returns on stale-id\n // checks, and error paths. The finally runs even when the catch returns.\n // settlePendingBrowserRouterState is idempotent via the settled flag.\n settlePendingBrowserRouterState(pendingRouterState);\n // Clear pendingPathname on all exit paths. On the success path this fires\n // before the RAF commit effect, but commitClientNavigationState() in the\n // commit effect clears it again — that double-clear is idempotent. Skipped\n // when superseded so a newer navigation's pendingPathname is not disturbed.\n if (navId === activeNavigationId) {\n clearPendingPathname(navId);\n }\n }\n };\n\n if (\"scrollRestoration\" in history) {\n history.scrollRestoration = \"manual\";\n }\n\n // Note: This popstate handler runs for App Router (RSC navigation available).\n // It coordinates scroll restoration with the pending RSC navigation.\n // Pages Router scroll restoration is handled in shims/navigation.ts:1289 with\n // microtask-based deferral for compatibility with non-RSC navigation.\n // See: https://github.com/vercel/next.js/discussions/41934#discussioncomment-4602607\n window.addEventListener(\"popstate\", (event) => {\n notifyAppRouterTransitionStart(window.location.href, \"traverse\");\n const pendingNavigation =\n window.__VINEXT_RSC_NAVIGATE__?.(window.location.href, 0, \"traverse\") ?? Promise.resolve();\n window.__VINEXT_RSC_PENDING__ = pendingNavigation;\n void pendingNavigation.finally(() => {\n restorePopstateScrollPosition(event.state);\n if (window.__VINEXT_RSC_PENDING__ === pendingNavigation) {\n window.__VINEXT_RSC_PENDING__ = null;\n }\n });\n });\n\n if (import.meta.hot) {\n import.meta.hot.on(\"rsc:update\", async () => {\n try {\n clearClientNavigationCaches();\n const navigationSnapshot = createClientNavigationRenderSnapshot(\n window.location.href,\n latestClientParams,\n );\n // Interception context on HMR re-renders is intentionally deferred:\n // preserving intercepted modal state across HMR reloads is out of scope\n // for the previousNextUrl mechanism.\n const pending = await createPendingNavigationCommit({\n currentState: getBrowserRouterState(),\n nextElements: normalizeAppElementsPromise(\n createFromFetch<AppWireElements>(\n fetch(toRscUrl(window.location.pathname + window.location.search)),\n ),\n ),\n navigationSnapshot,\n renderId: ++nextNavigationRenderId,\n type: \"replace\",\n });\n dispatchBrowserTree(\n pending.action.elements,\n navigationSnapshot,\n pending.action.renderId,\n \"replace\",\n pending.interceptionContext,\n pending.action.layoutFlags,\n pending.previousNextUrl,\n pending.routeId,\n pending.rootLayoutTreePath,\n null,\n false,\n );\n } catch (error) {\n console.error(\"[vinext] RSC HMR error:\", error);\n }\n });\n }\n}\n\nif (typeof document !== \"undefined\") {\n window.addEventListener(\"pagehide\", () => {\n isPageUnloading = true;\n });\n // Reset on pageshow so a bfcache-restored document does not resume with\n // the flag stuck at true, which would silently swallow every subsequent\n // RSC navigation error for the lifetime of that tab. Matches Next.js'\n // fetch-server-response.ts handler pair.\n window.addEventListener(\"pageshow\", () => {\n isPageUnloading = false;\n });\n void main();\n}\n"],"mappings":"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"}
|
|
@@ -48,6 +48,7 @@ type AppPageRouteWiringRoute<TModule extends AppPageModule = AppPageModule, TErr
|
|
|
48
48
|
templates?: readonly (TModule | null | undefined)[] | null;
|
|
49
49
|
};
|
|
50
50
|
type AppPageSlotOverride<TModule extends AppPageModule = AppPageModule> = {
|
|
51
|
+
layoutModules?: readonly (TModule | null | undefined)[] | null;
|
|
51
52
|
pageModule: TModule;
|
|
52
53
|
params?: AppPageParams;
|
|
53
54
|
props?: Readonly<Record<string, unknown>>;
|
|
@@ -206,12 +206,22 @@ function buildAppPageElements(options) {
|
|
|
206
206
|
elements[slotId] = APP_UNMATCHED_SLOT_WIRE_VALUE;
|
|
207
207
|
continue;
|
|
208
208
|
}
|
|
209
|
-
const
|
|
209
|
+
const slotThenableParams = options.makeThenableParams(slotParams);
|
|
210
|
+
const slotProps = { params: slotThenableParams };
|
|
210
211
|
if (slotOverride?.props) Object.assign(slotProps, slotOverride.props);
|
|
211
212
|
let slotElement = /* @__PURE__ */ jsx(slotComponent, { ...slotProps });
|
|
213
|
+
const interceptLayouts = slotOverride?.layoutModules ?? [];
|
|
214
|
+
for (let layoutIndex = interceptLayouts.length - 1; layoutIndex >= 0; layoutIndex--) {
|
|
215
|
+
const interceptLayoutComponent = getDefaultExport(interceptLayouts[layoutIndex]);
|
|
216
|
+
if (!interceptLayoutComponent) continue;
|
|
217
|
+
slotElement = /* @__PURE__ */ jsx(interceptLayoutComponent, {
|
|
218
|
+
params: slotThenableParams,
|
|
219
|
+
children: slotElement
|
|
220
|
+
});
|
|
221
|
+
}
|
|
212
222
|
const slotLayoutComponent = getDefaultExport(slot.layout);
|
|
213
223
|
if (slotLayoutComponent) slotElement = /* @__PURE__ */ jsx(slotLayoutComponent, {
|
|
214
|
-
params:
|
|
224
|
+
params: slotThenableParams,
|
|
215
225
|
children: slotElement
|
|
216
226
|
});
|
|
217
227
|
const slotLoadingComponent = getDefaultExport(slot.loading);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-page-route-wiring.js","names":["Children"],"sources":["../../src/server/app-page-route-wiring.tsx"],"sourcesContent":["import { Suspense, type ComponentType, type ReactNode } from \"react\";\nimport {\n APP_INTERCEPTION_CONTEXT_KEY,\n APP_ROOT_LAYOUT_KEY,\n APP_ROUTE_KEY,\n APP_UNMATCHED_SLOT_WIRE_VALUE,\n createAppPayloadPageId,\n createAppPayloadRouteId,\n type AppElements,\n} from \"./app-elements.js\";\nimport { ErrorBoundary, NotFoundBoundary } from \"../shims/error-boundary.js\";\nimport { LayoutSegmentProvider } from \"../shims/layout-segment-context.js\";\nimport { MetadataHead, ViewportHead, type Metadata, type Viewport } from \"../shims/metadata.js\";\nimport { Children, ParallelSlot, Slot } from \"../shims/slot.js\";\nimport type { AppPageParams } from \"./app-page-boundary.js\";\nimport {\n createAppRenderDependency,\n renderAfterAppDependencies,\n renderWithAppDependencyBarrier,\n type AppRenderDependency,\n} from \"./app-render-dependency.js\";\n\ntype AppPageComponentProps = {\n children?: ReactNode;\n error?: Error;\n params?: unknown;\n reset?: () => void;\n} & Record<string, unknown>;\n\ntype AppPageComponent = ComponentType<AppPageComponentProps>;\ntype AppPageErrorComponent = ComponentType<{ error: Error; reset: () => void }>;\n\nexport type AppPageModule = Record<string, unknown> & {\n default?: AppPageComponent | null | undefined;\n};\n\nexport type AppPageErrorModule = Record<string, unknown> & {\n default?: AppPageErrorComponent | null | undefined;\n};\n\nexport type AppPageRouteWiringSlot<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n> = {\n /** Slot prop name passed to the owning layout (e.g. \"modal\" from @modal). */\n name: string;\n default?: TModule | null;\n error?: TErrorModule | null;\n layout?: TModule | null;\n layoutIndex: number;\n loading?: TModule | null;\n page?: TModule | null;\n routeSegments?: readonly string[] | null;\n};\n\nexport type AppPageRouteWiringRoute<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n> = {\n error?: TErrorModule | null;\n errors?: readonly (TErrorModule | null | undefined)[] | null;\n layoutTreePositions?: readonly number[] | null;\n layouts: readonly (TModule | null | undefined)[];\n loading?: TModule | null;\n notFound?: TModule | null;\n notFounds?: readonly (TModule | null | undefined)[] | null;\n routeSegments?: readonly string[];\n /**\n * Keyed by stable slot id (name + owner path), not necessarily the slot prop name.\n */\n slots?: Readonly<Record<string, AppPageRouteWiringSlot<TModule, TErrorModule>>> | null;\n templateTreePositions?: readonly number[] | null;\n templates?: readonly (TModule | null | undefined)[] | null;\n};\n\nexport type AppPageSlotOverride<TModule extends AppPageModule = AppPageModule> = {\n pageModule: TModule;\n params?: AppPageParams;\n props?: Readonly<Record<string, unknown>>;\n};\n\nexport type AppPageLayoutEntry<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n> = {\n errorModule?: TErrorModule | null | undefined;\n id: string;\n layoutModule?: TModule | null | undefined;\n notFoundModule?: TModule | null | undefined;\n treePath: string;\n treePosition: number;\n};\n\nexport type BuildAppPageRouteElementOptions<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n> = {\n element: ReactNode;\n globalErrorModule?: TErrorModule | null;\n makeThenableParams: (params: AppPageParams) => unknown;\n matchedParams: AppPageParams;\n resolvedMetadata: Metadata | null;\n resolvedViewport: Viewport;\n rootNotFoundModule?: TModule | null;\n route: AppPageRouteWiringRoute<TModule, TErrorModule>;\n slotOverrides?: Readonly<Record<string, AppPageSlotOverride<TModule>>> | null;\n};\n\nexport type BuildAppPageElementsOptions<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n> = BuildAppPageRouteElementOptions<TModule, TErrorModule> & {\n interceptionContext?: string | null;\n isRscRequest?: boolean;\n mountedSlotIds?: ReadonlySet<string> | null;\n routePath: string;\n};\n\ntype AppPageTemplateEntry<TModule extends AppPageModule = AppPageModule> = {\n id: string;\n templateModule?: TModule | null | undefined;\n treePath: string;\n treePosition: number;\n};\n\nfunction getDefaultExport<TModule extends AppPageModule>(\n module: TModule | null | undefined,\n): AppPageComponent | null {\n return module?.default ?? null;\n}\n\nfunction getErrorBoundaryExport<TModule extends AppPageErrorModule>(\n module: TModule | null | undefined,\n): AppPageErrorComponent | null {\n return module?.default ?? null;\n}\n\nexport function createAppPageTreePath(\n routeSegments: readonly string[] | null | undefined,\n treePosition: number,\n): string {\n const treePathSegments = routeSegments?.slice(0, treePosition) ?? [];\n if (treePathSegments.length === 0) {\n return \"/\";\n }\n return `/${treePathSegments.join(\"/\")}`;\n}\n\nexport function createAppPageLayoutEntries<\n TModule extends AppPageModule,\n TErrorModule extends AppPageErrorModule,\n>(\n route: Pick<\n AppPageRouteWiringRoute<TModule, TErrorModule>,\n \"errors\" | \"layoutTreePositions\" | \"layouts\" | \"notFounds\" | \"routeSegments\"\n >,\n): AppPageLayoutEntry<TModule, TErrorModule>[] {\n return route.layouts.map((layoutModule, index) => {\n const treePosition = route.layoutTreePositions?.[index] ?? 0;\n const treePath = createAppPageTreePath(route.routeSegments, treePosition);\n return {\n errorModule: route.errors?.[index] ?? null,\n id: `layout:${treePath}`,\n layoutModule,\n notFoundModule: route.notFounds?.[index] ?? null,\n treePath,\n treePosition,\n };\n });\n}\n\nexport function createAppPageTemplateEntries<TModule extends AppPageModule>(\n route: Pick<\n AppPageRouteWiringRoute<TModule>,\n \"routeSegments\" | \"templateTreePositions\" | \"templates\"\n >,\n): AppPageTemplateEntry<TModule>[] {\n return (route.templates ?? []).map((templateModule, index) => {\n const treePosition = route.templateTreePositions?.[index] ?? 0;\n const treePath = createAppPageTreePath(route.routeSegments, treePosition);\n return {\n id: `template:${treePath}`,\n templateModule,\n treePath,\n treePosition,\n };\n });\n}\n\nexport function resolveAppPageChildSegments(\n routeSegments: readonly string[],\n treePosition: number,\n params: AppPageParams,\n): string[] {\n const rawSegments = routeSegments.slice(treePosition);\n const resolvedSegments: string[] = [];\n\n for (const segment of rawSegments) {\n if (\n segment.startsWith(\"[[...\") &&\n segment.endsWith(\"]]\") &&\n segment.length > \"[[...x]]\".length - 1\n ) {\n const paramName = segment.slice(5, -2);\n const paramValue = params[paramName];\n if (Array.isArray(paramValue) && paramValue.length === 0) {\n continue;\n }\n if (paramValue === undefined) {\n continue;\n }\n resolvedSegments.push(Array.isArray(paramValue) ? paramValue.join(\"/\") : paramValue);\n continue;\n }\n\n if (segment.startsWith(\"[...\") && segment.endsWith(\"]\")) {\n const paramName = segment.slice(4, -1);\n const paramValue = params[paramName];\n if (Array.isArray(paramValue)) {\n resolvedSegments.push(paramValue.join(\"/\"));\n continue;\n }\n resolvedSegments.push(paramValue ?? segment);\n continue;\n }\n\n if (segment.startsWith(\"[\") && segment.endsWith(\"]\") && !segment.includes(\".\")) {\n const paramName = segment.slice(1, -1);\n const paramValue = params[paramName];\n resolvedSegments.push(\n Array.isArray(paramValue) ? paramValue.join(\"/\") : (paramValue ?? segment),\n );\n continue;\n }\n\n resolvedSegments.push(segment);\n }\n\n return resolvedSegments;\n}\n\nfunction resolveAppPageVisibleSegments(\n routeSegments: readonly string[],\n params: AppPageParams,\n): string[] {\n const resolvedSegments = resolveAppPageChildSegments(routeSegments, 0, params);\n return resolvedSegments.filter((segment) => !(segment.startsWith(\"(\") && segment.endsWith(\")\")));\n}\n\nfunction resolveAppPageTemplateKey(\n routeSegments: readonly string[],\n treePosition: number,\n params: AppPageParams,\n): string {\n const visibleSegments = resolveAppPageVisibleSegments(routeSegments.slice(treePosition), params);\n return visibleSegments[0] ?? \"\";\n}\n\nfunction createAppPageParallelSlotEntries<\n TModule extends AppPageModule,\n TErrorModule extends AppPageErrorModule,\n>(\n layoutIndex: number,\n layoutEntries: readonly AppPageLayoutEntry<TModule, TErrorModule>[],\n route: AppPageRouteWiringRoute<TModule, TErrorModule>,\n getEffectiveSlotParams: (slotKey: string, slotName: string) => AppPageParams,\n): Readonly<Record<string, ReactNode>> | undefined {\n const parallelSlots: Record<string, ReactNode> = {};\n\n for (const [slotKey, slot] of Object.entries(route.slots ?? {})) {\n const slotName = slot.name;\n const targetIndex = slot.layoutIndex >= 0 ? slot.layoutIndex : layoutEntries.length - 1;\n if (targetIndex !== layoutIndex) {\n continue;\n }\n\n const layoutEntry = layoutEntries[targetIndex];\n const treePath = layoutEntry?.treePath ?? \"/\";\n const slotParams = getEffectiveSlotParams(slotKey, slotName);\n const slotSegments = slot.routeSegments\n ? resolveAppPageChildSegments(slot.routeSegments, 0, slotParams)\n : [];\n parallelSlots[slotName] = (\n <LayoutSegmentProvider segmentMap={{ children: slotSegments }}>\n <Slot id={`slot:${slotName}:${treePath}`} />\n </LayoutSegmentProvider>\n );\n }\n\n return Object.keys(parallelSlots).length > 0 ? parallelSlots : undefined;\n}\n\nfunction createAppPageRouteHead(metadata: Metadata | null, viewport: Viewport): ReactNode {\n return (\n <>\n <meta charSet=\"utf-8\" />\n {metadata ? <MetadataHead metadata={metadata} /> : null}\n <ViewportHead viewport={viewport} />\n </>\n );\n}\n\nexport function buildAppPageElements<\n TModule extends AppPageModule,\n TErrorModule extends AppPageErrorModule,\n>(options: BuildAppPageElementsOptions<TModule, TErrorModule>): AppElements {\n const elements: Record<string, ReactNode | string | null> = {};\n const interceptionContext = options.interceptionContext ?? null;\n const routeId = createAppPayloadRouteId(options.routePath, interceptionContext);\n const pageId = createAppPayloadPageId(options.routePath, interceptionContext);\n const layoutEntries = createAppPageLayoutEntries(options.route);\n const templateEntries = createAppPageTemplateEntries(options.route);\n const layoutEntriesByTreePosition = new Map<number, AppPageLayoutEntry<TModule, TErrorModule>>();\n const templateEntriesByTreePosition = new Map<number, AppPageTemplateEntry<TModule>>();\n for (const layoutEntry of layoutEntries) {\n layoutEntriesByTreePosition.set(layoutEntry.treePosition, layoutEntry);\n }\n for (const templateEntry of templateEntries) {\n templateEntriesByTreePosition.set(templateEntry.treePosition, templateEntry);\n }\n const layoutIndicesByTreePosition = new Map<number, number>();\n for (let index = 0; index < layoutEntries.length; index++) {\n layoutIndicesByTreePosition.set(layoutEntries[index].treePosition, index);\n }\n const layoutDependenciesByIndex = new Map<number, AppRenderDependency>();\n const layoutDependenciesBefore: AppRenderDependency[][] = [];\n const slotDependenciesByLayoutIndex: AppRenderDependency[][] = [];\n const templateDependenciesById = new Map<string, AppRenderDependency>();\n const templateDependenciesBeforeById = new Map<string, AppRenderDependency[]>();\n const pageDependencies: AppRenderDependency[] = [];\n const routeThenableParams = options.makeThenableParams(options.matchedParams);\n const rootLayoutTreePath = layoutEntries[0]?.treePath ?? null;\n const slotNameCounts = new Map<string, number>();\n for (const slot of Object.values(options.route.slots ?? {})) {\n const slotName = slot.name;\n slotNameCounts.set(slotName, (slotNameCounts.get(slotName) ?? 0) + 1);\n }\n const orderedTreePositions = Array.from(\n new Set<number>([\n ...layoutEntries.map((entry) => entry.treePosition),\n ...templateEntries.map((entry) => entry.treePosition),\n ]),\n ).sort((left, right) => left - right);\n const resolveSlotOverride = (slotKey: string, slotName: string) => {\n const overrideByKey = options.slotOverrides?.[slotKey];\n if (overrideByKey) {\n return overrideByKey;\n }\n\n // Legacy callers may still provide overrides by slot prop name.\n // Only allow that fallback when it is unambiguous.\n if (slotKey === slotName || (slotNameCounts.get(slotName) ?? 0) === 1) {\n return options.slotOverrides?.[slotName];\n }\n\n return undefined;\n };\n const getEffectiveSlotParams = (slotKey: string, slotName: string): AppPageParams =>\n resolveSlotOverride(slotKey, slotName)?.params ?? options.matchedParams;\n\n for (const treePosition of orderedTreePositions) {\n const layoutIndex = layoutIndicesByTreePosition.get(treePosition);\n if (layoutIndex !== undefined) {\n const layoutEntry = layoutEntries[layoutIndex];\n layoutDependenciesBefore[layoutIndex] = [...pageDependencies];\n if (getDefaultExport(layoutEntry.layoutModule)) {\n const layoutDependency = createAppRenderDependency();\n layoutDependenciesByIndex.set(layoutIndex, layoutDependency);\n pageDependencies.push(layoutDependency);\n }\n slotDependenciesByLayoutIndex[layoutIndex] = [...pageDependencies];\n }\n\n const templateEntry = templateEntriesByTreePosition.get(treePosition);\n if (!templateEntry || !getDefaultExport(templateEntry.templateModule)) {\n continue;\n }\n\n const templateDependency = createAppRenderDependency();\n templateDependenciesById.set(templateEntry.id, templateDependency);\n templateDependenciesBeforeById.set(templateEntry.id, [...pageDependencies]);\n pageDependencies.push(templateDependency);\n }\n\n elements[APP_ROUTE_KEY] = routeId;\n elements[APP_INTERCEPTION_CONTEXT_KEY] = interceptionContext;\n elements[APP_ROOT_LAYOUT_KEY] = rootLayoutTreePath;\n elements[pageId] = renderAfterAppDependencies(options.element, pageDependencies);\n\n for (const templateEntry of templateEntries) {\n const templateComponent = getDefaultExport(templateEntry.templateModule);\n if (!templateComponent) {\n continue;\n }\n const TemplateComponent = templateComponent;\n const templateDependency = templateDependenciesById.get(templateEntry.id);\n const templateElement = templateDependency ? (\n renderWithAppDependencyBarrier(\n <TemplateComponent params={options.matchedParams}>\n <Children />\n </TemplateComponent>,\n templateDependency,\n )\n ) : (\n <TemplateComponent params={options.matchedParams}>\n <Children />\n </TemplateComponent>\n );\n elements[templateEntry.id] = renderAfterAppDependencies(\n templateElement,\n templateDependenciesBeforeById.get(templateEntry.id) ?? [],\n );\n }\n\n for (let index = 0; index < layoutEntries.length; index++) {\n const layoutEntry = layoutEntries[index];\n const layoutComponent = getDefaultExport(layoutEntry.layoutModule);\n if (!layoutComponent) {\n continue;\n }\n\n const layoutProps: Record<string, unknown> = {\n params: routeThenableParams,\n };\n\n for (const slot of Object.values(options.route.slots ?? {})) {\n const slotName = slot.name;\n const targetIndex = slot.layoutIndex >= 0 ? slot.layoutIndex : layoutEntries.length - 1;\n if (targetIndex !== index) {\n continue;\n }\n layoutProps[slotName] = <ParallelSlot name={slotName} />;\n }\n\n const LayoutComponent = layoutComponent;\n const layoutDependency = layoutDependenciesByIndex.get(index);\n const layoutElement = layoutDependency ? (\n renderWithAppDependencyBarrier(\n <LayoutComponent {...layoutProps}>\n <Children />\n </LayoutComponent>,\n layoutDependency,\n )\n ) : (\n <LayoutComponent {...layoutProps}>\n <Children />\n </LayoutComponent>\n );\n elements[layoutEntry.id] = renderAfterAppDependencies(\n layoutElement,\n layoutDependenciesBefore[index] ?? [],\n );\n }\n\n for (const [slotKey, slot] of Object.entries(options.route.slots ?? {})) {\n const slotName = slot.name;\n const targetIndex = slot.layoutIndex >= 0 ? slot.layoutIndex : layoutEntries.length - 1;\n const treePath = layoutEntries[targetIndex]?.treePath ?? \"/\";\n const slotId = `slot:${slotName}:${treePath}`;\n const slotOverride = resolveSlotOverride(slotKey, slotName);\n const slotParams = getEffectiveSlotParams(slotKey, slotName);\n const overrideOrPageComponent =\n getDefaultExport(slotOverride?.pageModule) ?? getDefaultExport(slot.page);\n const defaultComponent = getDefaultExport(slot.default);\n\n // On soft nav (RSC): omit key when only default.tsx exists and the slot is\n // already mounted on the client. Absent key means the browser retains prior\n // slot content rather than replacing it. When the slot is not yet mounted\n // (first entry into this layout), include the key so default.tsx renders.\n if (\n !overrideOrPageComponent &&\n defaultComponent &&\n options.isRscRequest &&\n options.mountedSlotIds?.has(slotId)\n ) {\n continue;\n }\n\n const slotComponent = overrideOrPageComponent ?? defaultComponent;\n\n if (!slotComponent) {\n elements[slotId] = APP_UNMATCHED_SLOT_WIRE_VALUE;\n continue;\n }\n\n const slotProps: Record<string, unknown> = {\n params: options.makeThenableParams(slotParams),\n };\n if (slotOverride?.props) {\n Object.assign(slotProps, slotOverride.props);\n }\n\n const SlotComponent = slotComponent;\n let slotElement: ReactNode = <SlotComponent {...slotProps} />;\n\n const slotLayoutComponent = getDefaultExport(slot.layout);\n if (slotLayoutComponent) {\n const SlotLayoutComponent = slotLayoutComponent;\n slotElement = (\n <SlotLayoutComponent params={options.makeThenableParams(slotParams)}>\n {slotElement}\n </SlotLayoutComponent>\n );\n }\n\n const slotLoadingComponent = getDefaultExport(slot.loading);\n if (slotLoadingComponent) {\n const SlotLoadingComponent = slotLoadingComponent;\n slotElement = <Suspense fallback={<SlotLoadingComponent />}>{slotElement}</Suspense>;\n }\n\n const slotErrorComponent = getErrorBoundaryExport(slot.error);\n if (slotErrorComponent) {\n slotElement = <ErrorBoundary fallback={slotErrorComponent}>{slotElement}</ErrorBoundary>;\n }\n\n elements[slotId] = renderAfterAppDependencies(\n slotElement,\n targetIndex >= 0 ? (slotDependenciesByLayoutIndex[targetIndex] ?? []) : [],\n );\n }\n\n let routeChildren: ReactNode = (\n <LayoutSegmentProvider segmentMap={{ children: [] }}>\n <Slot id={pageId} />\n </LayoutSegmentProvider>\n );\n\n const routeLoadingComponent = getDefaultExport(options.route.loading);\n if (routeLoadingComponent) {\n const RouteLoadingComponent = routeLoadingComponent;\n routeChildren = <Suspense fallback={<RouteLoadingComponent />}>{routeChildren}</Suspense>;\n }\n\n const lastLayoutErrorModule =\n options.route.errors && options.route.errors.length > 0\n ? options.route.errors[options.route.errors.length - 1]\n : null;\n const pageErrorComponent = getErrorBoundaryExport(options.route.error);\n if (pageErrorComponent && options.route.error !== lastLayoutErrorModule) {\n routeChildren = <ErrorBoundary fallback={pageErrorComponent}>{routeChildren}</ErrorBoundary>;\n }\n\n const notFoundComponent =\n getDefaultExport(options.route.notFound) ?? getDefaultExport(options.rootNotFoundModule);\n if (notFoundComponent) {\n const NotFoundComponent = notFoundComponent;\n routeChildren = (\n <NotFoundBoundary fallback={<NotFoundComponent />}>{routeChildren}</NotFoundBoundary>\n );\n }\n\n for (let index = orderedTreePositions.length - 1; index >= 0; index--) {\n const treePosition = orderedTreePositions[index];\n let segmentChildren: ReactNode = routeChildren;\n const layoutEntry = layoutEntriesByTreePosition.get(treePosition);\n const templateEntry = templateEntriesByTreePosition.get(treePosition);\n\n // Next.js nesting per segment (outer to inner): Layout > Template > Error > NotFound > children.\n // Building bottom-up means NotFoundBoundary must wrap the leaf subtree first,\n // then ErrorBoundary, then Template, with the Layout slot outermost.\n if (layoutEntry) {\n const layoutNotFoundComponent = getDefaultExport(layoutEntry.notFoundModule);\n if (layoutNotFoundComponent) {\n const LayoutNotFoundComponent = layoutNotFoundComponent;\n segmentChildren = (\n <NotFoundBoundary fallback={<LayoutNotFoundComponent />}>\n {segmentChildren}\n </NotFoundBoundary>\n );\n }\n\n const layoutErrorComponent = getErrorBoundaryExport(layoutEntry.errorModule);\n if (layoutErrorComponent) {\n segmentChildren = (\n <ErrorBoundary fallback={layoutErrorComponent}>{segmentChildren}</ErrorBoundary>\n );\n }\n }\n\n if (templateEntry && getDefaultExport(templateEntry.templateModule)) {\n segmentChildren = (\n <Slot\n id={templateEntry.id}\n key={resolveAppPageTemplateKey(\n options.route.routeSegments ?? [],\n templateEntry.treePosition,\n options.matchedParams,\n )}\n >\n {segmentChildren}\n </Slot>\n );\n }\n\n if (!layoutEntry) {\n routeChildren = segmentChildren;\n continue;\n }\n const layoutHasElement = getDefaultExport(layoutEntry.layoutModule) !== null;\n const layoutIndex = layoutIndicesByTreePosition.get(treePosition) ?? -1;\n const segmentMap: { children: string[] } & Record<string, string[]> = {\n children: resolveAppPageChildSegments(\n options.route.routeSegments ?? [],\n layoutEntry.treePosition,\n options.matchedParams,\n ),\n };\n for (const [slotKey, slot] of Object.entries(options.route.slots ?? {})) {\n const slotName = slot.name;\n const targetIndex = slot.layoutIndex >= 0 ? slot.layoutIndex : layoutEntries.length - 1;\n if (targetIndex !== layoutIndex) {\n continue;\n }\n const slotParams = getEffectiveSlotParams(slotKey, slotName);\n segmentMap[slotName] = slot.routeSegments\n ? resolveAppPageChildSegments(slot.routeSegments, 0, slotParams)\n : [];\n }\n\n routeChildren = (\n <LayoutSegmentProvider segmentMap={segmentMap}>\n {layoutHasElement ? (\n <Slot\n id={layoutEntry.id}\n parallelSlots={createAppPageParallelSlotEntries(\n layoutIndex,\n layoutEntries,\n options.route,\n getEffectiveSlotParams,\n )}\n >\n {segmentChildren}\n </Slot>\n ) : (\n segmentChildren\n )}\n </LayoutSegmentProvider>\n );\n }\n\n const globalErrorComponent = getErrorBoundaryExport(options.globalErrorModule);\n if (globalErrorComponent) {\n routeChildren = <ErrorBoundary fallback={globalErrorComponent}>{routeChildren}</ErrorBoundary>;\n }\n\n elements[routeId] = (\n <>\n {createAppPageRouteHead(options.resolvedMetadata, options.resolvedViewport)}\n {routeChildren}\n </>\n );\n\n return elements;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"app-page-route-wiring.js","names":["Children"],"sources":["../../src/server/app-page-route-wiring.tsx"],"sourcesContent":["import { Suspense, type ComponentType, type ReactNode } from \"react\";\nimport {\n APP_INTERCEPTION_CONTEXT_KEY,\n APP_ROOT_LAYOUT_KEY,\n APP_ROUTE_KEY,\n APP_UNMATCHED_SLOT_WIRE_VALUE,\n createAppPayloadPageId,\n createAppPayloadRouteId,\n type AppElements,\n} from \"./app-elements.js\";\nimport { ErrorBoundary, NotFoundBoundary } from \"../shims/error-boundary.js\";\nimport { LayoutSegmentProvider } from \"../shims/layout-segment-context.js\";\nimport { MetadataHead, ViewportHead, type Metadata, type Viewport } from \"../shims/metadata.js\";\nimport { Children, ParallelSlot, Slot } from \"../shims/slot.js\";\nimport type { AppPageParams } from \"./app-page-boundary.js\";\nimport {\n createAppRenderDependency,\n renderAfterAppDependencies,\n renderWithAppDependencyBarrier,\n type AppRenderDependency,\n} from \"./app-render-dependency.js\";\n\ntype AppPageComponentProps = {\n children?: ReactNode;\n error?: Error;\n params?: unknown;\n reset?: () => void;\n} & Record<string, unknown>;\n\ntype AppPageComponent = ComponentType<AppPageComponentProps>;\ntype AppPageErrorComponent = ComponentType<{ error: Error; reset: () => void }>;\n\nexport type AppPageModule = Record<string, unknown> & {\n default?: AppPageComponent | null | undefined;\n};\n\nexport type AppPageErrorModule = Record<string, unknown> & {\n default?: AppPageErrorComponent | null | undefined;\n};\n\nexport type AppPageRouteWiringSlot<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n> = {\n /** Slot prop name passed to the owning layout (e.g. \"modal\" from @modal). */\n name: string;\n default?: TModule | null;\n error?: TErrorModule | null;\n layout?: TModule | null;\n layoutIndex: number;\n loading?: TModule | null;\n page?: TModule | null;\n routeSegments?: readonly string[] | null;\n};\n\nexport type AppPageRouteWiringRoute<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n> = {\n error?: TErrorModule | null;\n errors?: readonly (TErrorModule | null | undefined)[] | null;\n layoutTreePositions?: readonly number[] | null;\n layouts: readonly (TModule | null | undefined)[];\n loading?: TModule | null;\n notFound?: TModule | null;\n notFounds?: readonly (TModule | null | undefined)[] | null;\n routeSegments?: readonly string[];\n /**\n * Keyed by stable slot id (name + owner path), not necessarily the slot prop name.\n */\n slots?: Readonly<Record<string, AppPageRouteWiringSlot<TModule, TErrorModule>>> | null;\n templateTreePositions?: readonly number[] | null;\n templates?: readonly (TModule | null | undefined)[] | null;\n};\n\nexport type AppPageSlotOverride<TModule extends AppPageModule = AppPageModule> = {\n layoutModules?: readonly (TModule | null | undefined)[] | null;\n pageModule: TModule;\n params?: AppPageParams;\n props?: Readonly<Record<string, unknown>>;\n};\n\nexport type AppPageLayoutEntry<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n> = {\n errorModule?: TErrorModule | null | undefined;\n id: string;\n layoutModule?: TModule | null | undefined;\n notFoundModule?: TModule | null | undefined;\n treePath: string;\n treePosition: number;\n};\n\nexport type BuildAppPageRouteElementOptions<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n> = {\n element: ReactNode;\n globalErrorModule?: TErrorModule | null;\n makeThenableParams: (params: AppPageParams) => unknown;\n matchedParams: AppPageParams;\n resolvedMetadata: Metadata | null;\n resolvedViewport: Viewport;\n rootNotFoundModule?: TModule | null;\n route: AppPageRouteWiringRoute<TModule, TErrorModule>;\n slotOverrides?: Readonly<Record<string, AppPageSlotOverride<TModule>>> | null;\n};\n\nexport type BuildAppPageElementsOptions<\n TModule extends AppPageModule = AppPageModule,\n TErrorModule extends AppPageErrorModule = AppPageErrorModule,\n> = BuildAppPageRouteElementOptions<TModule, TErrorModule> & {\n interceptionContext?: string | null;\n isRscRequest?: boolean;\n mountedSlotIds?: ReadonlySet<string> | null;\n routePath: string;\n};\n\ntype AppPageTemplateEntry<TModule extends AppPageModule = AppPageModule> = {\n id: string;\n templateModule?: TModule | null | undefined;\n treePath: string;\n treePosition: number;\n};\n\nfunction getDefaultExport<TModule extends AppPageModule>(\n module: TModule | null | undefined,\n): AppPageComponent | null {\n return module?.default ?? null;\n}\n\nfunction getErrorBoundaryExport<TModule extends AppPageErrorModule>(\n module: TModule | null | undefined,\n): AppPageErrorComponent | null {\n return module?.default ?? null;\n}\n\nexport function createAppPageTreePath(\n routeSegments: readonly string[] | null | undefined,\n treePosition: number,\n): string {\n const treePathSegments = routeSegments?.slice(0, treePosition) ?? [];\n if (treePathSegments.length === 0) {\n return \"/\";\n }\n return `/${treePathSegments.join(\"/\")}`;\n}\n\nexport function createAppPageLayoutEntries<\n TModule extends AppPageModule,\n TErrorModule extends AppPageErrorModule,\n>(\n route: Pick<\n AppPageRouteWiringRoute<TModule, TErrorModule>,\n \"errors\" | \"layoutTreePositions\" | \"layouts\" | \"notFounds\" | \"routeSegments\"\n >,\n): AppPageLayoutEntry<TModule, TErrorModule>[] {\n return route.layouts.map((layoutModule, index) => {\n const treePosition = route.layoutTreePositions?.[index] ?? 0;\n const treePath = createAppPageTreePath(route.routeSegments, treePosition);\n return {\n errorModule: route.errors?.[index] ?? null,\n id: `layout:${treePath}`,\n layoutModule,\n notFoundModule: route.notFounds?.[index] ?? null,\n treePath,\n treePosition,\n };\n });\n}\n\nexport function createAppPageTemplateEntries<TModule extends AppPageModule>(\n route: Pick<\n AppPageRouteWiringRoute<TModule>,\n \"routeSegments\" | \"templateTreePositions\" | \"templates\"\n >,\n): AppPageTemplateEntry<TModule>[] {\n return (route.templates ?? []).map((templateModule, index) => {\n const treePosition = route.templateTreePositions?.[index] ?? 0;\n const treePath = createAppPageTreePath(route.routeSegments, treePosition);\n return {\n id: `template:${treePath}`,\n templateModule,\n treePath,\n treePosition,\n };\n });\n}\n\nexport function resolveAppPageChildSegments(\n routeSegments: readonly string[],\n treePosition: number,\n params: AppPageParams,\n): string[] {\n const rawSegments = routeSegments.slice(treePosition);\n const resolvedSegments: string[] = [];\n\n for (const segment of rawSegments) {\n if (\n segment.startsWith(\"[[...\") &&\n segment.endsWith(\"]]\") &&\n segment.length > \"[[...x]]\".length - 1\n ) {\n const paramName = segment.slice(5, -2);\n const paramValue = params[paramName];\n if (Array.isArray(paramValue) && paramValue.length === 0) {\n continue;\n }\n if (paramValue === undefined) {\n continue;\n }\n resolvedSegments.push(Array.isArray(paramValue) ? paramValue.join(\"/\") : paramValue);\n continue;\n }\n\n if (segment.startsWith(\"[...\") && segment.endsWith(\"]\")) {\n const paramName = segment.slice(4, -1);\n const paramValue = params[paramName];\n if (Array.isArray(paramValue)) {\n resolvedSegments.push(paramValue.join(\"/\"));\n continue;\n }\n resolvedSegments.push(paramValue ?? segment);\n continue;\n }\n\n if (segment.startsWith(\"[\") && segment.endsWith(\"]\") && !segment.includes(\".\")) {\n const paramName = segment.slice(1, -1);\n const paramValue = params[paramName];\n resolvedSegments.push(\n Array.isArray(paramValue) ? paramValue.join(\"/\") : (paramValue ?? segment),\n );\n continue;\n }\n\n resolvedSegments.push(segment);\n }\n\n return resolvedSegments;\n}\n\nfunction resolveAppPageVisibleSegments(\n routeSegments: readonly string[],\n params: AppPageParams,\n): string[] {\n const resolvedSegments = resolveAppPageChildSegments(routeSegments, 0, params);\n return resolvedSegments.filter((segment) => !(segment.startsWith(\"(\") && segment.endsWith(\")\")));\n}\n\nfunction resolveAppPageTemplateKey(\n routeSegments: readonly string[],\n treePosition: number,\n params: AppPageParams,\n): string {\n const visibleSegments = resolveAppPageVisibleSegments(routeSegments.slice(treePosition), params);\n return visibleSegments[0] ?? \"\";\n}\n\nfunction createAppPageParallelSlotEntries<\n TModule extends AppPageModule,\n TErrorModule extends AppPageErrorModule,\n>(\n layoutIndex: number,\n layoutEntries: readonly AppPageLayoutEntry<TModule, TErrorModule>[],\n route: AppPageRouteWiringRoute<TModule, TErrorModule>,\n getEffectiveSlotParams: (slotKey: string, slotName: string) => AppPageParams,\n): Readonly<Record<string, ReactNode>> | undefined {\n const parallelSlots: Record<string, ReactNode> = {};\n\n for (const [slotKey, slot] of Object.entries(route.slots ?? {})) {\n const slotName = slot.name;\n const targetIndex = slot.layoutIndex >= 0 ? slot.layoutIndex : layoutEntries.length - 1;\n if (targetIndex !== layoutIndex) {\n continue;\n }\n\n const layoutEntry = layoutEntries[targetIndex];\n const treePath = layoutEntry?.treePath ?? \"/\";\n const slotParams = getEffectiveSlotParams(slotKey, slotName);\n const slotSegments = slot.routeSegments\n ? resolveAppPageChildSegments(slot.routeSegments, 0, slotParams)\n : [];\n parallelSlots[slotName] = (\n <LayoutSegmentProvider segmentMap={{ children: slotSegments }}>\n <Slot id={`slot:${slotName}:${treePath}`} />\n </LayoutSegmentProvider>\n );\n }\n\n return Object.keys(parallelSlots).length > 0 ? parallelSlots : undefined;\n}\n\nfunction createAppPageRouteHead(metadata: Metadata | null, viewport: Viewport): ReactNode {\n return (\n <>\n <meta charSet=\"utf-8\" />\n {metadata ? <MetadataHead metadata={metadata} /> : null}\n <ViewportHead viewport={viewport} />\n </>\n );\n}\n\nexport function buildAppPageElements<\n TModule extends AppPageModule,\n TErrorModule extends AppPageErrorModule,\n>(options: BuildAppPageElementsOptions<TModule, TErrorModule>): AppElements {\n const elements: Record<string, ReactNode | string | null> = {};\n const interceptionContext = options.interceptionContext ?? null;\n const routeId = createAppPayloadRouteId(options.routePath, interceptionContext);\n const pageId = createAppPayloadPageId(options.routePath, interceptionContext);\n const layoutEntries = createAppPageLayoutEntries(options.route);\n const templateEntries = createAppPageTemplateEntries(options.route);\n const layoutEntriesByTreePosition = new Map<number, AppPageLayoutEntry<TModule, TErrorModule>>();\n const templateEntriesByTreePosition = new Map<number, AppPageTemplateEntry<TModule>>();\n for (const layoutEntry of layoutEntries) {\n layoutEntriesByTreePosition.set(layoutEntry.treePosition, layoutEntry);\n }\n for (const templateEntry of templateEntries) {\n templateEntriesByTreePosition.set(templateEntry.treePosition, templateEntry);\n }\n const layoutIndicesByTreePosition = new Map<number, number>();\n for (let index = 0; index < layoutEntries.length; index++) {\n layoutIndicesByTreePosition.set(layoutEntries[index].treePosition, index);\n }\n const layoutDependenciesByIndex = new Map<number, AppRenderDependency>();\n const layoutDependenciesBefore: AppRenderDependency[][] = [];\n const slotDependenciesByLayoutIndex: AppRenderDependency[][] = [];\n const templateDependenciesById = new Map<string, AppRenderDependency>();\n const templateDependenciesBeforeById = new Map<string, AppRenderDependency[]>();\n const pageDependencies: AppRenderDependency[] = [];\n const routeThenableParams = options.makeThenableParams(options.matchedParams);\n const rootLayoutTreePath = layoutEntries[0]?.treePath ?? null;\n const slotNameCounts = new Map<string, number>();\n for (const slot of Object.values(options.route.slots ?? {})) {\n const slotName = slot.name;\n slotNameCounts.set(slotName, (slotNameCounts.get(slotName) ?? 0) + 1);\n }\n const orderedTreePositions = Array.from(\n new Set<number>([\n ...layoutEntries.map((entry) => entry.treePosition),\n ...templateEntries.map((entry) => entry.treePosition),\n ]),\n ).sort((left, right) => left - right);\n const resolveSlotOverride = (slotKey: string, slotName: string) => {\n const overrideByKey = options.slotOverrides?.[slotKey];\n if (overrideByKey) {\n return overrideByKey;\n }\n\n // Legacy callers may still provide overrides by slot prop name.\n // Only allow that fallback when it is unambiguous.\n if (slotKey === slotName || (slotNameCounts.get(slotName) ?? 0) === 1) {\n return options.slotOverrides?.[slotName];\n }\n\n return undefined;\n };\n const getEffectiveSlotParams = (slotKey: string, slotName: string): AppPageParams =>\n resolveSlotOverride(slotKey, slotName)?.params ?? options.matchedParams;\n\n for (const treePosition of orderedTreePositions) {\n const layoutIndex = layoutIndicesByTreePosition.get(treePosition);\n if (layoutIndex !== undefined) {\n const layoutEntry = layoutEntries[layoutIndex];\n layoutDependenciesBefore[layoutIndex] = [...pageDependencies];\n if (getDefaultExport(layoutEntry.layoutModule)) {\n const layoutDependency = createAppRenderDependency();\n layoutDependenciesByIndex.set(layoutIndex, layoutDependency);\n pageDependencies.push(layoutDependency);\n }\n slotDependenciesByLayoutIndex[layoutIndex] = [...pageDependencies];\n }\n\n const templateEntry = templateEntriesByTreePosition.get(treePosition);\n if (!templateEntry || !getDefaultExport(templateEntry.templateModule)) {\n continue;\n }\n\n const templateDependency = createAppRenderDependency();\n templateDependenciesById.set(templateEntry.id, templateDependency);\n templateDependenciesBeforeById.set(templateEntry.id, [...pageDependencies]);\n pageDependencies.push(templateDependency);\n }\n\n elements[APP_ROUTE_KEY] = routeId;\n elements[APP_INTERCEPTION_CONTEXT_KEY] = interceptionContext;\n elements[APP_ROOT_LAYOUT_KEY] = rootLayoutTreePath;\n elements[pageId] = renderAfterAppDependencies(options.element, pageDependencies);\n\n for (const templateEntry of templateEntries) {\n const templateComponent = getDefaultExport(templateEntry.templateModule);\n if (!templateComponent) {\n continue;\n }\n const TemplateComponent = templateComponent;\n const templateDependency = templateDependenciesById.get(templateEntry.id);\n const templateElement = templateDependency ? (\n renderWithAppDependencyBarrier(\n <TemplateComponent params={options.matchedParams}>\n <Children />\n </TemplateComponent>,\n templateDependency,\n )\n ) : (\n <TemplateComponent params={options.matchedParams}>\n <Children />\n </TemplateComponent>\n );\n elements[templateEntry.id] = renderAfterAppDependencies(\n templateElement,\n templateDependenciesBeforeById.get(templateEntry.id) ?? [],\n );\n }\n\n for (let index = 0; index < layoutEntries.length; index++) {\n const layoutEntry = layoutEntries[index];\n const layoutComponent = getDefaultExport(layoutEntry.layoutModule);\n if (!layoutComponent) {\n continue;\n }\n\n const layoutProps: Record<string, unknown> = {\n params: routeThenableParams,\n };\n\n for (const slot of Object.values(options.route.slots ?? {})) {\n const slotName = slot.name;\n const targetIndex = slot.layoutIndex >= 0 ? slot.layoutIndex : layoutEntries.length - 1;\n if (targetIndex !== index) {\n continue;\n }\n layoutProps[slotName] = <ParallelSlot name={slotName} />;\n }\n\n const LayoutComponent = layoutComponent;\n const layoutDependency = layoutDependenciesByIndex.get(index);\n const layoutElement = layoutDependency ? (\n renderWithAppDependencyBarrier(\n <LayoutComponent {...layoutProps}>\n <Children />\n </LayoutComponent>,\n layoutDependency,\n )\n ) : (\n <LayoutComponent {...layoutProps}>\n <Children />\n </LayoutComponent>\n );\n elements[layoutEntry.id] = renderAfterAppDependencies(\n layoutElement,\n layoutDependenciesBefore[index] ?? [],\n );\n }\n\n for (const [slotKey, slot] of Object.entries(options.route.slots ?? {})) {\n const slotName = slot.name;\n const targetIndex = slot.layoutIndex >= 0 ? slot.layoutIndex : layoutEntries.length - 1;\n const treePath = layoutEntries[targetIndex]?.treePath ?? \"/\";\n const slotId = `slot:${slotName}:${treePath}`;\n const slotOverride = resolveSlotOverride(slotKey, slotName);\n const slotParams = getEffectiveSlotParams(slotKey, slotName);\n const overrideOrPageComponent =\n getDefaultExport(slotOverride?.pageModule) ?? getDefaultExport(slot.page);\n const defaultComponent = getDefaultExport(slot.default);\n\n // On soft nav (RSC): omit key when only default.tsx exists and the slot is\n // already mounted on the client. Absent key means the browser retains prior\n // slot content rather than replacing it. When the slot is not yet mounted\n // (first entry into this layout), include the key so default.tsx renders.\n if (\n !overrideOrPageComponent &&\n defaultComponent &&\n options.isRscRequest &&\n options.mountedSlotIds?.has(slotId)\n ) {\n continue;\n }\n\n const slotComponent = overrideOrPageComponent ?? defaultComponent;\n\n if (!slotComponent) {\n elements[slotId] = APP_UNMATCHED_SLOT_WIRE_VALUE;\n continue;\n }\n\n const slotThenableParams = options.makeThenableParams(slotParams);\n const slotProps: Record<string, unknown> = {\n params: slotThenableParams,\n };\n if (slotOverride?.props) {\n Object.assign(slotProps, slotOverride.props);\n }\n\n const SlotComponent = slotComponent;\n let slotElement: ReactNode = <SlotComponent {...slotProps} />;\n const interceptLayouts = slotOverride?.layoutModules ?? [];\n\n for (let layoutIndex = interceptLayouts.length - 1; layoutIndex >= 0; layoutIndex--) {\n const interceptLayoutComponent = getDefaultExport(interceptLayouts[layoutIndex]);\n if (!interceptLayoutComponent) {\n continue;\n }\n const InterceptLayoutComponent = interceptLayoutComponent;\n slotElement = (\n <InterceptLayoutComponent params={slotThenableParams}>\n {slotElement}\n </InterceptLayoutComponent>\n );\n }\n\n const slotLayoutComponent = getDefaultExport(slot.layout);\n if (slotLayoutComponent) {\n const SlotLayoutComponent = slotLayoutComponent;\n slotElement = (\n <SlotLayoutComponent params={slotThenableParams}>{slotElement}</SlotLayoutComponent>\n );\n }\n\n const slotLoadingComponent = getDefaultExport(slot.loading);\n if (slotLoadingComponent) {\n const SlotLoadingComponent = slotLoadingComponent;\n slotElement = <Suspense fallback={<SlotLoadingComponent />}>{slotElement}</Suspense>;\n }\n\n const slotErrorComponent = getErrorBoundaryExport(slot.error);\n if (slotErrorComponent) {\n slotElement = <ErrorBoundary fallback={slotErrorComponent}>{slotElement}</ErrorBoundary>;\n }\n\n elements[slotId] = renderAfterAppDependencies(\n slotElement,\n targetIndex >= 0 ? (slotDependenciesByLayoutIndex[targetIndex] ?? []) : [],\n );\n }\n\n let routeChildren: ReactNode = (\n <LayoutSegmentProvider segmentMap={{ children: [] }}>\n <Slot id={pageId} />\n </LayoutSegmentProvider>\n );\n\n const routeLoadingComponent = getDefaultExport(options.route.loading);\n if (routeLoadingComponent) {\n const RouteLoadingComponent = routeLoadingComponent;\n routeChildren = <Suspense fallback={<RouteLoadingComponent />}>{routeChildren}</Suspense>;\n }\n\n const lastLayoutErrorModule =\n options.route.errors && options.route.errors.length > 0\n ? options.route.errors[options.route.errors.length - 1]\n : null;\n const pageErrorComponent = getErrorBoundaryExport(options.route.error);\n if (pageErrorComponent && options.route.error !== lastLayoutErrorModule) {\n routeChildren = <ErrorBoundary fallback={pageErrorComponent}>{routeChildren}</ErrorBoundary>;\n }\n\n const notFoundComponent =\n getDefaultExport(options.route.notFound) ?? getDefaultExport(options.rootNotFoundModule);\n if (notFoundComponent) {\n const NotFoundComponent = notFoundComponent;\n routeChildren = (\n <NotFoundBoundary fallback={<NotFoundComponent />}>{routeChildren}</NotFoundBoundary>\n );\n }\n\n for (let index = orderedTreePositions.length - 1; index >= 0; index--) {\n const treePosition = orderedTreePositions[index];\n let segmentChildren: ReactNode = routeChildren;\n const layoutEntry = layoutEntriesByTreePosition.get(treePosition);\n const templateEntry = templateEntriesByTreePosition.get(treePosition);\n\n // Next.js nesting per segment (outer to inner): Layout > Template > Error > NotFound > children.\n // Building bottom-up means NotFoundBoundary must wrap the leaf subtree first,\n // then ErrorBoundary, then Template, with the Layout slot outermost.\n if (layoutEntry) {\n const layoutNotFoundComponent = getDefaultExport(layoutEntry.notFoundModule);\n if (layoutNotFoundComponent) {\n const LayoutNotFoundComponent = layoutNotFoundComponent;\n segmentChildren = (\n <NotFoundBoundary fallback={<LayoutNotFoundComponent />}>\n {segmentChildren}\n </NotFoundBoundary>\n );\n }\n\n const layoutErrorComponent = getErrorBoundaryExport(layoutEntry.errorModule);\n if (layoutErrorComponent) {\n segmentChildren = (\n <ErrorBoundary fallback={layoutErrorComponent}>{segmentChildren}</ErrorBoundary>\n );\n }\n }\n\n if (templateEntry && getDefaultExport(templateEntry.templateModule)) {\n segmentChildren = (\n <Slot\n id={templateEntry.id}\n key={resolveAppPageTemplateKey(\n options.route.routeSegments ?? [],\n templateEntry.treePosition,\n options.matchedParams,\n )}\n >\n {segmentChildren}\n </Slot>\n );\n }\n\n if (!layoutEntry) {\n routeChildren = segmentChildren;\n continue;\n }\n const layoutHasElement = getDefaultExport(layoutEntry.layoutModule) !== null;\n const layoutIndex = layoutIndicesByTreePosition.get(treePosition) ?? -1;\n const segmentMap: { children: string[] } & Record<string, string[]> = {\n children: resolveAppPageChildSegments(\n options.route.routeSegments ?? [],\n layoutEntry.treePosition,\n options.matchedParams,\n ),\n };\n for (const [slotKey, slot] of Object.entries(options.route.slots ?? {})) {\n const slotName = slot.name;\n const targetIndex = slot.layoutIndex >= 0 ? slot.layoutIndex : layoutEntries.length - 1;\n if (targetIndex !== layoutIndex) {\n continue;\n }\n const slotParams = getEffectiveSlotParams(slotKey, slotName);\n segmentMap[slotName] = slot.routeSegments\n ? resolveAppPageChildSegments(slot.routeSegments, 0, slotParams)\n : [];\n }\n\n routeChildren = (\n <LayoutSegmentProvider segmentMap={segmentMap}>\n {layoutHasElement ? (\n <Slot\n id={layoutEntry.id}\n parallelSlots={createAppPageParallelSlotEntries(\n layoutIndex,\n layoutEntries,\n options.route,\n getEffectiveSlotParams,\n )}\n >\n {segmentChildren}\n </Slot>\n ) : (\n segmentChildren\n )}\n </LayoutSegmentProvider>\n );\n }\n\n const globalErrorComponent = getErrorBoundaryExport(options.globalErrorModule);\n if (globalErrorComponent) {\n routeChildren = <ErrorBoundary fallback={globalErrorComponent}>{routeChildren}</ErrorBoundary>;\n }\n\n elements[routeId] = (\n <>\n {createAppPageRouteHead(options.resolvedMetadata, options.resolvedViewport)}\n {routeChildren}\n </>\n );\n\n return elements;\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { runWithExecutionContext } from "../shims/request-context.js";
|
|
2
|
+
import { isOpenRedirectShaped } from "./request-pipeline.js";
|
|
2
3
|
import { resolveStaticAssetSignal } from "./worker-utils.js";
|
|
3
4
|
import rscHandler from "virtual:vinext-rsc-entry";
|
|
4
5
|
//#region src/server/app-router-entry.ts
|
|
@@ -16,7 +17,13 @@ import rscHandler from "virtual:vinext-rsc-entry";
|
|
|
16
17
|
* cloudflare({ viteEnvironment: { name: "rsc", childEnvironments: ["ssr"] } })
|
|
17
18
|
*/
|
|
18
19
|
var app_router_entry_default = { async fetch(request, env, ctx) {
|
|
19
|
-
|
|
20
|
+
const url = new URL(request.url);
|
|
21
|
+
if (isOpenRedirectShaped(url.pathname)) return new Response("404 Not Found", { status: 404 });
|
|
22
|
+
try {
|
|
23
|
+
decodeURIComponent(url.pathname);
|
|
24
|
+
} catch {
|
|
25
|
+
return new Response("Bad Request", { status: 400 });
|
|
26
|
+
}
|
|
20
27
|
const handleFn = () => rscHandler(request, ctx);
|
|
21
28
|
const result = await (ctx ? runWithExecutionContext(ctx, handleFn) : handleFn());
|
|
22
29
|
if (result instanceof Response) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-router-entry.js","names":[],"sources":["../../src/server/app-router-entry.ts"],"sourcesContent":["/**\n * Default Cloudflare Worker entry point for vinext App Router.\n *\n * Use this directly in wrangler.jsonc:\n * \"main\": \"vinext/server/app-router-entry\"\n *\n * Or import and delegate to it from a custom worker:\n * import handler from \"vinext/server/app-router-entry\";\n * return handler.fetch(request, env, ctx);\n *\n * This file runs in the RSC environment. Configure the Cloudflare plugin with:\n * cloudflare({ viteEnvironment: { name: \"rsc\", childEnvironments: [\"ssr\"] } })\n */\n\n// @ts-expect-error — virtual module resolved by vinext\nimport rscHandler from \"virtual:vinext-rsc-entry\";\nimport { runWithExecutionContext, type ExecutionContextLike } from \"../shims/request-context.js\";\nimport { resolveStaticAssetSignal } from \"./worker-utils.js\";\n\ntype WorkerAssetEnv = {\n ASSETS?: {\n fetch(request: Request): Promise<Response> | Response;\n };\n};\n\nexport default {\n async fetch(\n request: Request,\n env?: WorkerAssetEnv,\n ctx?: ExecutionContextLike,\n ): Promise<Response> {\n const url = new URL(request.url);\n\n //
|
|
1
|
+
{"version":3,"file":"app-router-entry.js","names":[],"sources":["../../src/server/app-router-entry.ts"],"sourcesContent":["/**\n * Default Cloudflare Worker entry point for vinext App Router.\n *\n * Use this directly in wrangler.jsonc:\n * \"main\": \"vinext/server/app-router-entry\"\n *\n * Or import and delegate to it from a custom worker:\n * import handler from \"vinext/server/app-router-entry\";\n * return handler.fetch(request, env, ctx);\n *\n * This file runs in the RSC environment. Configure the Cloudflare plugin with:\n * cloudflare({ viteEnvironment: { name: \"rsc\", childEnvironments: [\"ssr\"] } })\n */\n\n// @ts-expect-error — virtual module resolved by vinext\nimport rscHandler from \"virtual:vinext-rsc-entry\";\nimport { runWithExecutionContext, type ExecutionContextLike } from \"../shims/request-context.js\";\nimport { resolveStaticAssetSignal } from \"./worker-utils.js\";\nimport { isOpenRedirectShaped } from \"./request-pipeline.js\";\n\ntype WorkerAssetEnv = {\n ASSETS?: {\n fetch(request: Request): Promise<Response> | Response;\n };\n};\n\nexport default {\n async fetch(\n request: Request,\n env?: WorkerAssetEnv,\n ctx?: ExecutionContextLike,\n ): Promise<Response> {\n const url = new URL(request.url);\n\n // Block protocol-relative URL open redirects (//evil.com/, /\\evil.com/,\n // /%5Cevil.com/, /%2F/evil.com/). Check BEFORE decode so both literal and\n // percent-encoded variants are caught — encoded forms survive segment-wise\n // decoding and would otherwise reach trailing-slash redirect emitters.\n if (isOpenRedirectShaped(url.pathname)) {\n return new Response(\"404 Not Found\", { status: 404 });\n }\n\n // Validate that percent-encoding is well-formed. The RSC handler performs\n // the actual decode + normalize; we only check here to return a clean 400\n // instead of letting a malformed sequence crash downstream.\n try {\n decodeURIComponent(url.pathname);\n } catch {\n // Malformed percent-encoding (e.g. /%E0%A4%A) — return 400 instead of throwing.\n return new Response(\"Bad Request\", { status: 400 });\n }\n\n // Do NOT decode/normalize the pathname here. The RSC handler\n // (virtual:vinext-rsc-entry) is the single point of decoding — it calls\n // decodeURIComponent + normalizePath on the incoming URL. Decoding here\n // AND in the handler would double-decode, causing inconsistent path\n // matching between middleware and routing.\n\n // Delegate to RSC handler (which decodes + normalizes the pathname itself),\n // wrapping in the ExecutionContext ALS scope so downstream code can reach\n // ctx.waitUntil() without having ctx threaded through every call site.\n const handleFn = () => rscHandler(request, ctx);\n const result = await (ctx ? runWithExecutionContext(ctx, handleFn) : handleFn());\n\n if (result instanceof Response) {\n if (env?.ASSETS) {\n const assetResponse = await resolveStaticAssetSignal(result, {\n fetchAsset: (path) =>\n Promise.resolve(env.ASSETS!.fetch(new Request(new URL(path, request.url)))),\n });\n if (assetResponse) return assetResponse;\n }\n return result;\n }\n\n if (result === null || result === undefined) {\n return new Response(\"Not Found\", { status: 404 });\n }\n\n return new Response(String(result), { status: 200 });\n },\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AA0BA,IAAA,2BAAe,EACb,MAAM,MACJ,SACA,KACA,KACmB;CACnB,MAAM,MAAM,IAAI,IAAI,QAAQ,IAAI;AAMhC,KAAI,qBAAqB,IAAI,SAAS,CACpC,QAAO,IAAI,SAAS,iBAAiB,EAAE,QAAQ,KAAK,CAAC;AAMvD,KAAI;AACF,qBAAmB,IAAI,SAAS;SAC1B;AAEN,SAAO,IAAI,SAAS,eAAe,EAAE,QAAQ,KAAK,CAAC;;CAYrD,MAAM,iBAAiB,WAAW,SAAS,IAAI;CAC/C,MAAM,SAAS,OAAO,MAAM,wBAAwB,KAAK,SAAS,GAAG,UAAU;AAE/E,KAAI,kBAAkB,UAAU;AAC9B,MAAI,KAAK,QAAQ;GACf,MAAM,gBAAgB,MAAM,yBAAyB,QAAQ,EAC3D,aAAa,SACX,QAAQ,QAAQ,IAAI,OAAQ,MAAM,IAAI,QAAQ,IAAI,IAAI,MAAM,QAAQ,IAAI,CAAC,CAAC,CAAC,EAC9E,CAAC;AACF,OAAI,cAAe,QAAO;;AAE5B,SAAO;;AAGT,KAAI,WAAW,QAAQ,WAAW,KAAA,EAChC,QAAO,IAAI,SAAS,aAAa,EAAE,QAAQ,KAAK,CAAC;AAGnD,QAAO,IAAI,SAAS,OAAO,OAAO,EAAE,EAAE,QAAQ,KAAK,CAAC;GAEvD"}
|
|
@@ -4,6 +4,7 @@ import { runWithNavigationContext } from "../shims/navigation-state.js";
|
|
|
4
4
|
import { withScriptNonce } from "../shims/script-nonce-context.js";
|
|
5
5
|
import { createInlineScriptTag, createNonceAttribute, escapeHtmlAttr, safeJsonStringify } from "./html.js";
|
|
6
6
|
import { ElementsContext, Slot } from "../shims/slot.js";
|
|
7
|
+
import { isOpenRedirectShaped } from "./request-pipeline.js";
|
|
7
8
|
import { createRscEmbedTransform, createTickBufferedTransform } from "./app-ssr-stream.js";
|
|
8
9
|
import { Fragment, createElement, use } from "react";
|
|
9
10
|
import { renderToReadableStream, renderToStaticMarkup } from "react-dom/server.edge";
|
|
@@ -97,7 +98,7 @@ async function handleSsr(rscStream, navContext, fontData, options) {
|
|
|
97
98
|
});
|
|
98
99
|
}
|
|
99
100
|
var app_ssr_entry_default = { async fetch(request) {
|
|
100
|
-
if (new URL(request.url).pathname
|
|
101
|
+
if (isOpenRedirectShaped(new URL(request.url).pathname)) return new Response("404 Not Found", { status: 404 });
|
|
101
102
|
const result = await (await import.meta.viteRsc.loadModule("rsc", "index")).default(request);
|
|
102
103
|
if (result instanceof Response) return result;
|
|
103
104
|
if (result == null) return new Response("Not Found", { status: 404 });
|