@rsc-kit/core 0.22.5 → 0.22.6

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.
@@ -44,8 +44,22 @@ const addTransitionType = React.addTransitionType ??
44
44
  React
45
45
  .unstable_addTransitionType;
46
46
  import { RedirectBoundary } from "./RedirectBoundary";
47
+ import { retentionKey } from "../routing";
47
48
  import { navigationCommitted } from "./perf";
48
49
  import { getSegmentState, replaceActive, navigatedOnce, seedSegment, subscribeToSegment, } from "./segmentStore";
50
+ /**
51
+ * The key the page this document arrived with is filed under: the url's,
52
+ * query included, when the url is that page - which is always, in an app,
53
+ * because the server keys a page by the document's own pathname. Anything
54
+ * else keeps the server's key rather than guess.
55
+ */
56
+ function seedKey(pageKey) {
57
+ if (typeof window === "undefined")
58
+ return pageKey;
59
+ return retentionKey(window.location.pathname, null) === retentionKey(pageKey, null)
60
+ ? retentionKey(window.location.pathname + window.location.search, null)
61
+ : pageKey;
62
+ }
49
63
  export function SegmentBoundary({ depth, pageKey, children, }) {
50
64
  // The store still addresses the boundary; the render reads React state, so
51
65
  // the update can be a transition. Initialised from the store on the client
@@ -76,8 +90,13 @@ export function SegmentBoundary({ depth, pageKey, children, }) {
76
90
  useEffect(() => {
77
91
  if (getSegmentState(depth))
78
92
  replaceActive(depth, children);
93
+ // Filed under the url's key, path and query, which is what every
94
+ // navigation and refresh looks it up by; mounted under the server's, the
95
+ // pathname the shell was frozen with. Seeded under the server's alone,
96
+ // the first refresh of a page loaded at ?c=25 found nothing, mounted a
97
+ // second copy, and showed every fallback in it.
79
98
  else if (pageKey)
80
- seedSegment(depth, pageKey, children);
99
+ seedSegment(depth, seedKey(pageKey), children, pageKey);
81
100
  }, [depth, pageKey, children]);
82
101
  // Wrapped here rather than around the whole app because this is the closest
83
102
  // client component above a page: a redirect thrown inside the page's own
@@ -109,6 +128,6 @@ export function SegmentBoundary({ depth, pageKey, children, }) {
109
128
  if (!state) {
110
129
  return (_jsx(Activity, { mode: "visible", children: _jsx(RedirectBoundary, { children: children }) }, pageKey));
111
130
  }
112
- return (_jsx(_Fragment, { children: state.entries.map((entry) => (_jsx(Activity, { mode: entry.key === state.activeKey ? "visible" : "hidden", children: _jsx(RedirectBoundary, { active: entry.key === state.activeKey, children: entry.tree }) }, entry.key))) }));
131
+ return (_jsx(_Fragment, { children: state.entries.map((entry) => (_jsx(Activity, { mode: entry.key === state.activeKey ? "visible" : "hidden", children: _jsx(RedirectBoundary, { active: entry.key === state.activeKey, children: entry.tree }) }, entry.identity ?? entry.key))) }));
113
132
  }
114
133
  //# sourceMappingURL=SegmentBoundary.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SegmentBoundary.js","sourceRoot":"","sources":["../../src/js/SegmentBoundary.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\n/**\n * The point in the tree a navigation can replace on its own.\n *\n * Sits between a layout and its children, so showing a different segment\n * re-renders from here down and leaves the layouts above it mounted. Server\n * components cannot be re-rendered on the client, which is why the seam has to\n * be a client component reading from a store rather than the layout itself.\n *\n * Pages it has already shown stay mounted behind <Activity mode=\"hidden\">.\n * Hidden is not unmounted: effects are torn down but state survives, so\n * returning to a page brings back the form you were filling in. Rendering only\n * the current one would throw that away, which is what replacing the root did.\n */\n\nimport * as React from \"react\";\nimport { Activity, startTransition, useEffect, useState } from \"react\";\n\n/**\n * The transition type a navigation carries.\n *\n * The engine does not animate a navigation itself; React's own\n * <ViewTransition> does, wherever an app puts one. What the app cannot do\n * from outside is tell a navigation from the seed after hydration - the\n * boundary taking over its own server-rendered children, which animated\n * would be the page fading into itself on every load. So a navigation's\n * update carries this type, and the seed's does not: a boundary keyed on it,\n * `default={{ \"rsc-navigation\": \"page\", default: \"none\" }}`, animates\n * navigations and nothing else.\n *\n * An earlier shape wrapped the segment in a boundary of the engine's own,\n * behind a flag. React names every top-level element under a boundary and\n * morphs each from where it was to where it is, so the stylesheet pulled\n * them back into one root fade - and fought React over the root, which it\n * cancels when nothing outside a boundary changed: a captured root with a\n * hidden group, a dark viewport on the first navigation. One wrapper element\n * under the app's own boundary is one snapshot pair, which is the dissolve\n * wanted, with nothing to fight.\n */\nexport const NAVIGATION_TRANSITION_TYPE = \"rsc-navigation\";\n\n// Exported by React 19.3; `unstable_` before it. Read at call time from the\n// namespace rather than imported by name, so a React that lacks it still\n// loads this module and simply does not mark the type.\nconst addTransitionType: ((type: string) => void) | undefined =\n (React as { addTransitionType?: (type: string) => void }).addTransitionType ??\n (React as { unstable_addTransitionType?: (type: string) => void })\n .unstable_addTransitionType;\nimport type { ReactNode } from \"react\";\nimport { RedirectBoundary } from \"./RedirectBoundary\";\nimport { navigationCommitted } from \"./perf\";\nimport {\n getSegmentState,\n replaceActive,\n navigatedOnce,\n seedSegment,\n subscribeToSegment,\n} from \"./segmentStore\";\n\nexport function SegmentBoundary({\n depth,\n pageKey,\n children,\n}: {\n depth: number;\n /** The page these server-rendered children belong to. */\n pageKey?: string;\n children: ReactNode;\n}) {\n // The store still addresses the boundary; the render reads React state, so\n // the update can be a transition. Initialised from the store on the client\n // and null on the server — exactly what getServerSnapshot did.\n const [state, setState] = useState<ReturnType<typeof getSegmentState>>(() =>\n typeof window === \"undefined\" ? null : getSegmentState(depth),\n );\n\n useEffect(\n () =>\n subscribeToSegment(depth, () => {\n startTransition(() => {\n // A navigation, not the seed: the seed is the page taking over\n // its own server-rendered children, and fading that is the page\n // fading into itself.\n if (navigatedOnce()) addTransitionType?.(NAVIGATION_TRANSITION_TYPE);\n\n setState(getSegmentState(depth));\n });\n }),\n [depth],\n );\n\n // The commit that put a navigated segment on screen: the end of the\n // navigation's measure, see perf.ts. Not on the first render, which is the\n // seed.\n useEffect(() => {\n if (state !== null) navigationCommitted();\n }, [state]);\n\n // Record the page we arrived on, so a later navigation away and back can\n // return to it. Without this the first page is the one page you cannot keep.\n // New children while the store already holds this depth is the document\n // rendered again in place - revalidate(\"all\") - and the page on screen\n // takes them under the key it has; see replaceActive.\n useEffect(() => {\n if (getSegmentState(depth)) replaceActive(depth, children);\n else if (pageKey) seedSegment(depth, pageKey, children);\n }, [depth, pageKey, children]);\n\n // Wrapped here rather than around the whole app because this is the closest\n // client component above a page: a redirect thrown inside the page's own\n // Suspense boundary surfaces at the nearest error boundary, and catching it\n // here leaves the layouts above mounted while the navigation runs. One\n // boundary per page, inside its Activity, not one around them all: a\n // boundary that catches renders its fallback in place of everything it\n // wraps, and one around them all unmounted every page being kept alive\n // behind the one redirecting - the destination among them, when it was\n // held - and then kept showing the fallback over the destination once it\n // arrived. The port's report was a sidebar and a breadcrumb over an empty\n // main.\n // The same shape before and after the seed. The server's render and the\n // first client render already place the children inside the retention\n // wrapper, keyed by the page, so when the store takes over after hydration\n // the tree changes state but not shape - and React keeps the DOM instead of\n // remounting the page, which was blank, then content, on every load.\n //\n // The Activity is there whether or not there is a page key to hang it on.\n // A parameterised route's PPR shell is rendered for every url it matches\n // and so carries no key - and the boundary used to leave the Activity out\n // then, so the shell had no <!--&--> markers where the client, hydrating\n // from the payload for the real url, rendered one. React 19.2 does not\n // recover from a hydration mismatch at an Activity: the boundary retries\n // hydrating, mismatches again, and the main thread never returns. A port\n // found /agent/tools/3 freezing the tab on every document load. The\n // markup of an Activity does not depend on its key, so the shell and the\n // client agree whenever both render one.\n if (!state) {\n return (\n <Activity key={pageKey} mode=\"visible\">\n <RedirectBoundary>{children}</RedirectBoundary>\n </Activity>\n );\n }\n\n return (\n <>\n {state.entries.map((entry) => (\n <Activity\n key={entry.key}\n mode={entry.key === state.activeKey ? \"visible\" : \"hidden\"}\n >\n <RedirectBoundary active={entry.key === state.activeKey}>\n {entry.tree as ReactNode}\n </RedirectBoundary>\n </Activity>\n ))}\n </>\n );\n}\n"]}
1
+ {"version":3,"file":"SegmentBoundary.js","sourceRoot":"","sources":["../../src/js/SegmentBoundary.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\n/**\n * The point in the tree a navigation can replace on its own.\n *\n * Sits between a layout and its children, so showing a different segment\n * re-renders from here down and leaves the layouts above it mounted. Server\n * components cannot be re-rendered on the client, which is why the seam has to\n * be a client component reading from a store rather than the layout itself.\n *\n * Pages it has already shown stay mounted behind <Activity mode=\"hidden\">.\n * Hidden is not unmounted: effects are torn down but state survives, so\n * returning to a page brings back the form you were filling in. Rendering only\n * the current one would throw that away, which is what replacing the root did.\n */\n\nimport * as React from \"react\";\nimport { Activity, startTransition, useEffect, useState } from \"react\";\n\n/**\n * The transition type a navigation carries.\n *\n * The engine does not animate a navigation itself; React's own\n * <ViewTransition> does, wherever an app puts one. What the app cannot do\n * from outside is tell a navigation from the seed after hydration - the\n * boundary taking over its own server-rendered children, which animated\n * would be the page fading into itself on every load. So a navigation's\n * update carries this type, and the seed's does not: a boundary keyed on it,\n * `default={{ \"rsc-navigation\": \"page\", default: \"none\" }}`, animates\n * navigations and nothing else.\n *\n * An earlier shape wrapped the segment in a boundary of the engine's own,\n * behind a flag. React names every top-level element under a boundary and\n * morphs each from where it was to where it is, so the stylesheet pulled\n * them back into one root fade - and fought React over the root, which it\n * cancels when nothing outside a boundary changed: a captured root with a\n * hidden group, a dark viewport on the first navigation. One wrapper element\n * under the app's own boundary is one snapshot pair, which is the dissolve\n * wanted, with nothing to fight.\n */\nexport const NAVIGATION_TRANSITION_TYPE = \"rsc-navigation\";\n\n// Exported by React 19.3; `unstable_` before it. Read at call time from the\n// namespace rather than imported by name, so a React that lacks it still\n// loads this module and simply does not mark the type.\nconst addTransitionType: ((type: string) => void) | undefined =\n (React as { addTransitionType?: (type: string) => void }).addTransitionType ??\n (React as { unstable_addTransitionType?: (type: string) => void })\n .unstable_addTransitionType;\nimport type { ReactNode } from \"react\";\nimport { RedirectBoundary } from \"./RedirectBoundary\";\nimport { retentionKey } from \"../routing\";\nimport { navigationCommitted } from \"./perf\";\nimport {\n getSegmentState,\n replaceActive,\n navigatedOnce,\n seedSegment,\n subscribeToSegment,\n} from \"./segmentStore\";\n\n/**\n * The key the page this document arrived with is filed under: the url's,\n * query included, when the url is that page - which is always, in an app,\n * because the server keys a page by the document's own pathname. Anything\n * else keeps the server's key rather than guess.\n */\nfunction seedKey(pageKey: string): string {\n if (typeof window === \"undefined\") return pageKey;\n\n return retentionKey(window.location.pathname, null) === retentionKey(pageKey, null)\n ? retentionKey(window.location.pathname + window.location.search, null)\n : pageKey;\n}\n\nexport function SegmentBoundary({\n depth,\n pageKey,\n children,\n}: {\n depth: number;\n /** The page these server-rendered children belong to. */\n pageKey?: string;\n children: ReactNode;\n}) {\n // The store still addresses the boundary; the render reads React state, so\n // the update can be a transition. Initialised from the store on the client\n // and null on the server — exactly what getServerSnapshot did.\n const [state, setState] = useState<ReturnType<typeof getSegmentState>>(() =>\n typeof window === \"undefined\" ? null : getSegmentState(depth),\n );\n\n useEffect(\n () =>\n subscribeToSegment(depth, () => {\n startTransition(() => {\n // A navigation, not the seed: the seed is the page taking over\n // its own server-rendered children, and fading that is the page\n // fading into itself.\n if (navigatedOnce()) addTransitionType?.(NAVIGATION_TRANSITION_TYPE);\n\n setState(getSegmentState(depth));\n });\n }),\n [depth],\n );\n\n // The commit that put a navigated segment on screen: the end of the\n // navigation's measure, see perf.ts. Not on the first render, which is the\n // seed.\n useEffect(() => {\n if (state !== null) navigationCommitted();\n }, [state]);\n\n // Record the page we arrived on, so a later navigation away and back can\n // return to it. Without this the first page is the one page you cannot keep.\n // New children while the store already holds this depth is the document\n // rendered again in place - revalidate(\"all\") - and the page on screen\n // takes them under the key it has; see replaceActive.\n useEffect(() => {\n if (getSegmentState(depth)) replaceActive(depth, children);\n // Filed under the url's key, path and query, which is what every\n // navigation and refresh looks it up by; mounted under the server's, the\n // pathname the shell was frozen with. Seeded under the server's alone,\n // the first refresh of a page loaded at ?c=25 found nothing, mounted a\n // second copy, and showed every fallback in it.\n else if (pageKey) seedSegment(depth, seedKey(pageKey), children, pageKey);\n }, [depth, pageKey, children]);\n\n // Wrapped here rather than around the whole app because this is the closest\n // client component above a page: a redirect thrown inside the page's own\n // Suspense boundary surfaces at the nearest error boundary, and catching it\n // here leaves the layouts above mounted while the navigation runs. One\n // boundary per page, inside its Activity, not one around them all: a\n // boundary that catches renders its fallback in place of everything it\n // wraps, and one around them all unmounted every page being kept alive\n // behind the one redirecting - the destination among them, when it was\n // held - and then kept showing the fallback over the destination once it\n // arrived. The port's report was a sidebar and a breadcrumb over an empty\n // main.\n // The same shape before and after the seed. The server's render and the\n // first client render already place the children inside the retention\n // wrapper, keyed by the page, so when the store takes over after hydration\n // the tree changes state but not shape - and React keeps the DOM instead of\n // remounting the page, which was blank, then content, on every load.\n //\n // The Activity is there whether or not there is a page key to hang it on.\n // A parameterised route's PPR shell is rendered for every url it matches\n // and so carries no key - and the boundary used to leave the Activity out\n // then, so the shell had no <!--&--> markers where the client, hydrating\n // from the payload for the real url, rendered one. React 19.2 does not\n // recover from a hydration mismatch at an Activity: the boundary retries\n // hydrating, mismatches again, and the main thread never returns. A port\n // found /agent/tools/3 freezing the tab on every document load. The\n // markup of an Activity does not depend on its key, so the shell and the\n // client agree whenever both render one.\n if (!state) {\n return (\n <Activity key={pageKey} mode=\"visible\">\n <RedirectBoundary>{children}</RedirectBoundary>\n </Activity>\n );\n }\n\n return (\n <>\n {state.entries.map((entry) => (\n <Activity\n key={entry.identity ?? entry.key}\n mode={entry.key === state.activeKey ? \"visible\" : \"hidden\"}\n >\n <RedirectBoundary active={entry.key === state.activeKey}>\n {entry.tree as ReactNode}\n </RedirectBoundary>\n </Activity>\n ))}\n </>\n );\n}\n"]}
@@ -327,12 +327,12 @@ export async function createViteRscApp(container = document, interceptEntries =
327
327
  // Depth 0 is a whole document and replaces the root. Anything deeper is one
328
328
  // segment: handing it to the boundary at that depth leaves the layouts above
329
329
  // it mounted, which is the point of asking for a partial render at all.
330
- setNavigateHandler((tree, key, segmentDepth) => {
330
+ setNavigateHandler((tree, key, segmentDepth, inPlaceOf) => {
331
331
  const newTree = tree;
332
332
  // From here on the boundary animates; the seed commit before this did not.
333
333
  noteNavigation();
334
334
  if (segmentDepth > 0) {
335
- setSegment(segmentDepth, key, newTree);
335
+ setSegment(segmentDepth, key, newTree, inPlaceOf);
336
336
  return;
337
337
  }
338
338
  clearSegments();
@@ -1 +1 @@
1
- {"version":3,"file":"createViteRscApp.js","sourceRoot":"","sources":["../../src/js/createViteRscApp.ts"],"names":[],"mappings":"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","sourcesContent":["// Vite-engine client bootstrap. Uses @vitejs/plugin-rsc's browser runtime as\n// the Flight deserializer + action encoder, and drives the package's engine-agnostic\n// navigate.ts SPA engine (Link, prefetch, popstate) through it. This replaces\n// the bun engine's createRscApp + the hand-rolled webpack shim — the plugin\n// resolves client references itself.\nimport { SEARCH_PARAMS_FALLBACK } from \"./useSearchParams\";\nimport { recoverFromStaleAssets } from \"./staleAssets\";\nimport { afterHydration, replayEarlyClicks } from \"./earlyClicks\";\nimport { parseRedirectDigest } from \"../redirectDigest.js\";\nimport { showDevNotice } from \"./devNotice\";\nimport { caughtByLoading } from \"./fallbackReport\";\nimport { noteNavigation } from \"./segmentStore\";\nimport type { Route } from \"../routes.js\";\nimport { isSafeRedirect } from \"../safeUrl.js\";\nimport {\n createFromReadableStream,\n encodeReply,\n setServerCallback,\n} from \"@vitejs/plugin-rsc/browser\";\nimport { createElement, startTransition } from \"react\";\nimport { createRoot, hydrateRoot } from \"react-dom/client\";\nimport { activityMarkersIn } from \"./activityMarkers\";\nimport { ActivityRoot } from \"./ActivityRouter\";\nimport { ServerRedirectError, noteRedirected, throwForFailedAction } from \"./errors\";\nimport { fetchPagePayload } from \"./pagePayload\";\nimport { claimRead, setQueryCodec } from \"./queryClient\";\nimport { clearSegments, dropHidden, isHeld, prerenderSegment, restoreSegments, setSegment } from \"./segmentStore\";\nimport type { ReactNode } from \"react\";\nimport {\n cancelPrefetch,\n isPrefetched,\n navigate,\n setApiRoutes,\n refresh,\n applyRevalidations,\n prefetch,\n retentionKey,\n setCallServer,\n setHeldLayouts,\n setStaticPayloads,\n setStaticRoutes,\n seedStaticChain,\n payloadUrl,\n setDeserializer,\n setInterceptManifest,\n getHeldLayouts,\n setNavigateHandler,\n setHeldHandlers,\n setPrerenderHandler,\n setReplaceRootHandler,\n setRestoreHandler,\n setVersion,\n} from \"./navigate\";\n\n\n/**\n * A redirect that travelled as an error: the digest of the error itself, or\n * of the cause React wraps it in when it reports client-rendering a boundary\n * the server had already failed.\n */\nfunction isRedirect(error: unknown): boolean {\n const digest = (error as { digest?: unknown } | null)?.digest;\n const cause = (error as { cause?: { digest?: unknown } } | null)?.cause;\n\n return parseRedirectDigest(digest) !== null || parseRedirectDigest(cause?.digest) !== null;\n}\n\nexport async function createViteRscApp(\n container: Document | Element = document,\n interceptEntries: { urlPattern: string; slot: string }[] = [],\n options: { staticPayloads?: string | null; routes?: unknown[] | null; apiRoutes?: string[] } = {},\n): Promise<void> {\n // The urls a route.ts answers: a link to one is an anchor, never a\n // prefetch, never a payload fetch.\n if (options.apiRoutes) setApiRoutes(options.apiRoutes);\n // An exported build has no server to negotiate with, so payloads live at\n // their own urls rather than behind a header on the page's url.\n setStaticPayloads(options.staticPayloads ?? null);\n // Only an exported build ships this: with no server to negotiate with, the\n // client works out for itself how much of a page it still holds.\n if (options.routes) setStaticRoutes(options.routes as never);\n // The router has to recognise an intercepted link before it asks the server,\n // so the patterns are baked into the generated browser entry. Without them\n // every intercepted route falls through to a full-page navigation.\n setInterceptManifest(interceptEntries);\n\n async function callServer(id: string, args: unknown[]): Promise<unknown> {\n // A read opened a slot before calling the reference, and this is the first\n // point at which the id exists on the client — React keeps it private and\n // hands it over only here. Claiming the slot enqueues the read for the\n // batched GET instead of posting it.\n const read = claimRead(id, args);\n\n if (read) return await read;\n\n const encoded = await encodeReply(args);\n\n // encodeReply returns FormData as soon as an argument contains a File.\n // Sending that as multipart would make PHP consume php://input while\n // parsing it, leaving the action with an empty body — so serialize it to\n // raw bytes under an opaque content-type and send the real one in\n // X-RSC-Content-Type for the worker to rebuild FormData from.\n let body: BodyInit;\n let realContentType: string;\n\n if (encoded instanceof FormData) {\n const serialized = new Response(encoded);\n body = await serialized.arrayBuffer();\n realContentType =\n serialized.headers.get(\"content-type\") ?? \"multipart/form-data\";\n } else {\n body = encoded as BodyInit;\n realContentType = \"text/plain;charset=UTF-8\";\n }\n\n // Where the action was invoked from. The host resolves it to the\n // components that render the page, so anything the action says it\n // invalidated can come back with the answer instead of being fetched\n // afterwards - and what comes back is for this page, not whichever is\n // showing when it lands.\n const from = window.location.pathname + window.location.search;\n\n const res = await fetch(\"/_rsc/action\", {\n method: \"POST\",\n headers: {\n \"X-RSC-Action\": id,\n \"X-RSC-Referer\": from,\n \"X-RSC-Content-Type\": realContentType,\n \"Content-Type\": \"application/octet-stream\",\n \"X-XSRF-TOKEN\": decodeURIComponent(\n document.cookie.match(/XSRF-TOKEN=([^;]+)/)?.[1] ?? \"\",\n ),\n },\n body,\n });\n\n // A failed action does not answer with a Flight stream, and the decoder\n // cannot tell — it reports its own parse failure instead of what the\n // server said.\n try {\n await throwForFailedAction(res);\n } catch (err) {\n // A redirect is an instruction, not something for a form to display:\n // an expired session answers this way, and the destination is the login\n // page rather than a message about one.\n if (err instanceof ServerRedirectError) {\n // The destination came off a response header, so it is checked here\n // too — the engine refuses these at the source, but a proxy or a host\n // in front of it can write whatever it likes. A navigation, not a\n // document load: the layouts stay mounted and the history entry the\n // form was on is replaced, the way a redirect after a POST should\n // be - Back does not return to the submitted form.\n if (isSafeRedirect(err.location)) {\n void navigate(err.location as Route, { replace: true });\n }\n\n // Performed, so resolved - not thrown. The call's answer is \"you are\n // being taken somewhere\": an object saying so, the shape an action's\n // result already has, so a caller reading result.validationErrors\n // reads undefined rather than throwing. A caller that awaited the\n // action in a plain startTransition had no catch for a throw, the\n // rejection reached React, and the root unmounted to a white page\n // on every logout.\n noteRedirected(err.location);\n\n return { redirected: err.location };\n }\n\n throw err;\n }\n\n const answer = await createFromReadableStream(res.body!, { callServer });\n\n return unwrapRevalidated(answer, from);\n }\n\n /**\n * Put anything the action re-rendered on screen, and hand back its result.\n *\n * The trees travel with the answer rather than being fetched afterwards, so\n * the caller sees only what its action returned and never knows the page\n * was updated around it.\n */\n function unwrapRevalidated(answer: unknown, from: string): unknown {\n if (\n answer === null ||\n typeof answer !== \"object\" ||\n !(\"__rscRevalidated\" in answer)\n ) {\n return answer;\n }\n\n const envelope = answer as {\n __rscRevalidated: Record<string, unknown>;\n result: unknown;\n };\n\n applyRevalidations(from, envelope.__rscRevalidated as Record<string, ReactNode>);\n\n return envelope.result;\n }\n\n setDeserializer(createFromReadableStream as never);\n // The query transport speaks Flight too, and reaches the runtime through here\n // rather than importing it: a second import of the browser runtime from the\n // client-component graph is a second client-reference registry, and the\n // symptom is components that render as undefined with nothing logged.\n setQueryCodec({\n deserialize: (stream) =>\n createFromReadableStream(stream, { callServer }) as Promise<unknown>,\n encode: (args) => encodeReply(args) as Promise<string | FormData>,\n // The way back when a read cannot ride in a url. Re-entering callServer is\n // safe: the slot was cleared the moment the reference returned, so this\n // takes the ordinary POST path rather than claiming a read again.\n asAction: (id, args) => callServer(id, args),\n });\n setCallServer(callServer);\n // The plugin's own \"use server\" client stubs route through its registered\n // server callback — register the same transport there too.\n setServerCallback(callServer as never);\n\n // Link / Form / router live in a separate build graph and reach the SPA\n // engine through these globals.\n (window as unknown as { __rsc_navigate: typeof navigate }).__rsc_navigate =\n navigate;\n (window as unknown as { __rsc_prefetch: typeof prefetch }).__rsc_prefetch =\n prefetch;\n (\n window as unknown as { __rsc_cancel_prefetch: typeof cancelPrefetch }\n ).__rsc_cancel_prefetch = cancelPrefetch;\n (\n window as unknown as { __rsc_is_prefetched: typeof isPrefetched }\n ).__rsc_is_prefetched = isPrefetched;\n (window as unknown as { __rsc_refresh: typeof refresh }).__rsc_refresh =\n refresh;\n\n // Hydrate from the RSC endpoint (same url + X-RSC, no version header).\n //\n // Everything from here to the decode is failure handling, because this is\n // the one request with nothing watching it. A page whose shell is already\n // rendered looks fine while this fails, and its fallbacks stay on screen\n // indefinitely with nothing reported anywhere.\n const res = await fetchPagePayload(payloadUrl(window.location.href));\n\n // Seed the router with the build this DOCUMENT is, so a redeploy is caught\n // on the next navigation: the host answers 409 to a client of another\n // build, and the document is loaded again. From the document's own meta\n // first - a document a service worker served from its cache is the last\n // build's, while the payload just fetched is this one's, and seeding from\n // the payload would have the old client claim to be new. The header is\n // the fallback for a document with no meta.\n const documentBuild = document.querySelector('meta[name=\"rsc-kit:build\"]')?.getAttribute(\"content\");\n const servedVersion = documentBuild || res.headers.get(\"X-RSC-Version\");\n\n if (servedVersion) {\n setVersion(servedVersion);\n }\n\n // The chain this page is built from, so the next navigation can say what is\n // already mounted and be sent only what changed.\n // A server says what this page is built from; a file server says nothing,\n // so an exported build works it out from the table it was given.\n const servedLayouts = res.headers.get(\"X-RSC-Layouts\");\n\n if (servedLayouts !== null) {\n setHeldLayouts(servedLayouts.split(\",\"));\n } else if (!seedStaticChain(window.location.href)) {\n setHeldLayouts([]);\n }\n const tree = await createFromReadableStream(res.body!, { callServer });\n\n // Retaining the previous page behind <Activity> needs a wrapper above the\n // page, and React will not hydrate a *document* container through one: the\n // root child of a document has to be <html>, and wrapping it hangs the\n // renderer outright (React 19.2.7). An app whose root layout owns <html>\n // therefore hydrates the tree directly and navigations replace it, as before.\n //\n // Apps that hydrate into an element get retention. Giving it to document-\n // rooted apps means SPA navigation returning only the changed segment rather\n // than a whole document, which is an engine change, not a client one.\n const retains = container !== document;\n\n const shell = retains\n ? createElement(ActivityRoot, {\n initialKey: retentionKey(window.location.href, null),\n initialTree: tree as ReactNode,\n })\n : (tree as ReactNode);\n\n // A document that cannot be hydrated by this tree is client-rendered\n // instead - a repaint, not a freeze. React 19.2 does not recover from a\n // hydration mismatch at an <Activity>: it retries hydrating the boundary,\n // mismatches again, and never returns to the main thread. Every segment\n // boundary is an Activity, one per layout, so a document with none where\n // the page has layouts is that mismatch, guaranteed, before React starts.\n // What produced one: a parameterised route's PPR shell, rendered without\n // a page key and, by a build before this one, without the Activities too.\n // None rather than fewer: a boundary inside a Suspense hole the shell left\n // unfinished has no marker and is client-rendered by React on its own,\n // which is not a mismatch. The stale-asset reload does not apply - the\n // document would come back the same.\n const missing = retains && getHeldLayouts().length > 0 && activityMarkersIn(container) === 0;\n\n if (missing) {\n console.warn(\n \"[rsc-kit] The document has no <Activity> boundaries where the page has layouts, so it cannot be hydrated; rendering the page instead. A PPR shell built by an earlier release lacks them - rebuild.\",\n );\n }\n\n // The payload answered with an error status - the not-found page for a\n // url the shell was served for anyway. It is not the document on screen,\n // so it is rendered, not hydrated: a mismatch at an Activity is the loop\n // above, and this one is certain.\n const disagrees = !res.ok;\n\n const onRecoverableError = (error: unknown, errorInfo: unknown) => {\n // A client component whose chunk the server no longer has fails while\n // hydrating, and React reports that as recoverable: the page is loaded\n // again, with the current names.\n if (recoverFromStaleAssets(error)) return;\n\n // A redirect decided inside a boundary: the server's row carried it as\n // the digest, React client-renders the boundary and reports that it\n // did, and the RedirectBoundary is already performing it. Nothing to\n // read in the console about a page doing what it was told.\n if (isRedirect(error)) return;\n\n // A PPR shell is served with its Suspense boundaries deliberately\n // unfinished — the build aborts the render once the static part is out.\n // React reports that as #419 and client-renders the boundary from the\n // Flight payload, which is the intended path, not a fault to report.\n const message = String((error as { message?: string })?.message ?? error);\n\n if (\n message.includes(\"419\") ||\n message.includes(\"did not finish this Suspense boundary\")\n ) {\n return;\n }\n\n // A view transition the browser cancelled because the tab was not\n // visible. React reports it here; the update still landed, and a tab\n // in the background is not a fault in the page.\n if (message.includes(\"Transition was aborted\")) return;\n\n // A navigation another one overtook: its request was aborted, and a\n // row of its payload that a component was still reading rejects with\n // the abort. React recovers by rendering the root again synchronously\n // and reports the recovery here as #520, with the abort as the cause.\n // The page it recovered to is the one the second navigation asked for;\n // the abort was the design, not a fault.\n const cause = (error as { cause?: { name?: string; message?: string } } | null)?.cause;\n\n if (\n cause?.name === \"AbortError\" ||\n /\\baborted\\b/i.test(cause?.message ?? \"\") ||\n /\\baborted\\b/i.test(message)\n ) {\n return;\n }\n // A page whose query string was read under a boundary carries the\n // fallback there; React reports the recovery on hydration. Under a\n // boundary the developer wrote, that is the designed path and nothing\n // is said. With nothing closer than a loading.tsx, the whole segment\n // showed the fallback until the query arrived - said here, in the\n // page and the console, for whoever is looking at either. Production\n // has no stack to tell the two apart; the build's note on the route is\n // the record there.\n if (\n (error as { digest?: string })?.digest === SEARCH_PARAMS_FALLBACK ||\n message.includes(\"useSearchParams()\")\n ) {\n const stack = (errorInfo as { componentStack?: string } | null)\n ?.componentStack;\n\n if (!caughtByLoading(stack)) return;\n\n const hint =\n \"useSearchParams() was read on the server with nothing closer than a loading.tsx, so the \" +\n \"whole segment showed that fallback until the query arrived. A <Suspense> around the \" +\n \"component that reads keeps the rest of the page painted.\";\n\n showDevNotice(hint, stack);\n console.error(new Error(hint), errorInfo);\n\n return;\n }\n\n console.error(error, errorInfo);\n };\n\n const rootOptions = {\n onRecoverableError,\n // A chunk the deploy no longer serves is not a fault in the page; the\n // document is loaded again, and the new names come with it. Anything\n // else is reported the way React would have.\n onUncaughtError(error: unknown, errorInfo: unknown) {\n if (recoverFromStaleAssets(error)) return;\n\n console.error(error, errorInfo);\n },\n onCaughtError(error: unknown, errorInfo: unknown) {\n if (recoverFromStaleAssets(error)) return;\n // Caught by the RedirectBoundary, which is performing it.\n if (isRedirect(error)) return;\n\n console.error(error, errorInfo);\n },\n };\n\n const root = missing || disagrees\n ? (() => {\n const created = createRoot(container as Element, rootOptions);\n\n created.render(shell);\n\n return created;\n })()\n : hydrateRoot(container, shell, rootOptions);\n\n // Depth 0 is a whole document and replaces the root. Anything deeper is one\n // segment: handing it to the boundary at that depth leaves the layouts above\n // it mounted, which is the point of asking for a partial render at all.\n setNavigateHandler((tree: unknown, key: string, segmentDepth: number) => {\n const newTree = tree as ReactNode;\n\n // From here on the boundary animates; the seed commit before this did not.\n noteNavigation();\n\n if (segmentDepth > 0) {\n setSegment(segmentDepth, key, newTree);\n\n return;\n }\n\n clearSegments();\n root.render(newTree);\n });\n\n // The whole document again, in place - revalidate(\"all\"). Not through the\n // handler above: that clears the boundaries and renders the tree as a new\n // page, and a boundary emptied re-keys its Activity to the current url and\n // remounts everything under it. A port's \"added to cart\" went with the\n // form's state that way, on every product reached by a link. Here the root\n // takes the tree in a transition and each boundary hands its page the new\n // children under the key it has - see replaceActive.\n setReplaceRootHandler((tree: unknown) => {\n startTransition(() => root.render(tree as ReactNode));\n });\n\n // Back and forward reveal a page the boundaries are still holding, with the\n // form you were filling in still filled in, and without asking the server.\n setRestoreHandler((key: string, maxAge?: number) =>\n restoreSegments(key, maxAge),\n );\n setHeldHandlers(isHeld, dropHidden);\n\n // A touch or a settled hover: the page is rendered hidden now, and the\n // click reveals it. See warm() in navigate.ts and prerenderSegment.\n setPrerenderHandler((tree: unknown, key: string, segmentDepth: number) => {\n prerenderSegment(segmentDepth, key, tree as ReactNode);\n });\n\n window.addEventListener(\"popstate\", () => {\n // restore: back and forward reveal the page you were on, with its state.\n // Wherever the browser just went; not a literal this app wrote.\n navigate(window.location.href as Route, { replace: true, restore: true });\n });\n\n history.replaceState(\n { rscUrl: window.location.href },\n \"\",\n window.location.href,\n );\n\n // A tap held by the bootstrap script, navigated to once hydration has\n // committed - not now: the runtime's script running is seconds before\n // React can dispatch a click on a phone still downloading chunks, and\n // a tap in that window would be the browser's. See earlyClicks.ts.\n afterHydration(() => replayEarlyClicks((url) => navigate(url as Route)));\n}\n\n"]}
1
+ {"version":3,"file":"createViteRscApp.js","sourceRoot":"","sources":["../../src/js/createViteRscApp.ts"],"names":[],"mappings":"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","sourcesContent":["// Vite-engine client bootstrap. Uses @vitejs/plugin-rsc's browser runtime as\n// the Flight deserializer + action encoder, and drives the package's engine-agnostic\n// navigate.ts SPA engine (Link, prefetch, popstate) through it. This replaces\n// the bun engine's createRscApp + the hand-rolled webpack shim — the plugin\n// resolves client references itself.\nimport { SEARCH_PARAMS_FALLBACK } from \"./useSearchParams\";\nimport { recoverFromStaleAssets } from \"./staleAssets\";\nimport { afterHydration, replayEarlyClicks } from \"./earlyClicks\";\nimport { parseRedirectDigest } from \"../redirectDigest.js\";\nimport { showDevNotice } from \"./devNotice\";\nimport { caughtByLoading } from \"./fallbackReport\";\nimport { noteNavigation } from \"./segmentStore\";\nimport type { Route } from \"../routes.js\";\nimport { isSafeRedirect } from \"../safeUrl.js\";\nimport {\n createFromReadableStream,\n encodeReply,\n setServerCallback,\n} from \"@vitejs/plugin-rsc/browser\";\nimport { createElement, startTransition } from \"react\";\nimport { createRoot, hydrateRoot } from \"react-dom/client\";\nimport { activityMarkersIn } from \"./activityMarkers\";\nimport { ActivityRoot } from \"./ActivityRouter\";\nimport { ServerRedirectError, noteRedirected, throwForFailedAction } from \"./errors\";\nimport { fetchPagePayload } from \"./pagePayload\";\nimport { claimRead, setQueryCodec } from \"./queryClient\";\nimport { clearSegments, dropHidden, isHeld, prerenderSegment, restoreSegments, setSegment } from \"./segmentStore\";\nimport type { ReactNode } from \"react\";\nimport {\n cancelPrefetch,\n isPrefetched,\n navigate,\n setApiRoutes,\n refresh,\n applyRevalidations,\n prefetch,\n retentionKey,\n setCallServer,\n setHeldLayouts,\n setStaticPayloads,\n setStaticRoutes,\n seedStaticChain,\n payloadUrl,\n setDeserializer,\n setInterceptManifest,\n getHeldLayouts,\n setNavigateHandler,\n setHeldHandlers,\n setPrerenderHandler,\n setReplaceRootHandler,\n setRestoreHandler,\n setVersion,\n} from \"./navigate\";\n\n\n/**\n * A redirect that travelled as an error: the digest of the error itself, or\n * of the cause React wraps it in when it reports client-rendering a boundary\n * the server had already failed.\n */\nfunction isRedirect(error: unknown): boolean {\n const digest = (error as { digest?: unknown } | null)?.digest;\n const cause = (error as { cause?: { digest?: unknown } } | null)?.cause;\n\n return parseRedirectDigest(digest) !== null || parseRedirectDigest(cause?.digest) !== null;\n}\n\nexport async function createViteRscApp(\n container: Document | Element = document,\n interceptEntries: { urlPattern: string; slot: string }[] = [],\n options: { staticPayloads?: string | null; routes?: unknown[] | null; apiRoutes?: string[] } = {},\n): Promise<void> {\n // The urls a route.ts answers: a link to one is an anchor, never a\n // prefetch, never a payload fetch.\n if (options.apiRoutes) setApiRoutes(options.apiRoutes);\n // An exported build has no server to negotiate with, so payloads live at\n // their own urls rather than behind a header on the page's url.\n setStaticPayloads(options.staticPayloads ?? null);\n // Only an exported build ships this: with no server to negotiate with, the\n // client works out for itself how much of a page it still holds.\n if (options.routes) setStaticRoutes(options.routes as never);\n // The router has to recognise an intercepted link before it asks the server,\n // so the patterns are baked into the generated browser entry. Without them\n // every intercepted route falls through to a full-page navigation.\n setInterceptManifest(interceptEntries);\n\n async function callServer(id: string, args: unknown[]): Promise<unknown> {\n // A read opened a slot before calling the reference, and this is the first\n // point at which the id exists on the client — React keeps it private and\n // hands it over only here. Claiming the slot enqueues the read for the\n // batched GET instead of posting it.\n const read = claimRead(id, args);\n\n if (read) return await read;\n\n const encoded = await encodeReply(args);\n\n // encodeReply returns FormData as soon as an argument contains a File.\n // Sending that as multipart would make PHP consume php://input while\n // parsing it, leaving the action with an empty body — so serialize it to\n // raw bytes under an opaque content-type and send the real one in\n // X-RSC-Content-Type for the worker to rebuild FormData from.\n let body: BodyInit;\n let realContentType: string;\n\n if (encoded instanceof FormData) {\n const serialized = new Response(encoded);\n body = await serialized.arrayBuffer();\n realContentType =\n serialized.headers.get(\"content-type\") ?? \"multipart/form-data\";\n } else {\n body = encoded as BodyInit;\n realContentType = \"text/plain;charset=UTF-8\";\n }\n\n // Where the action was invoked from. The host resolves it to the\n // components that render the page, so anything the action says it\n // invalidated can come back with the answer instead of being fetched\n // afterwards - and what comes back is for this page, not whichever is\n // showing when it lands.\n const from = window.location.pathname + window.location.search;\n\n const res = await fetch(\"/_rsc/action\", {\n method: \"POST\",\n headers: {\n \"X-RSC-Action\": id,\n \"X-RSC-Referer\": from,\n \"X-RSC-Content-Type\": realContentType,\n \"Content-Type\": \"application/octet-stream\",\n \"X-XSRF-TOKEN\": decodeURIComponent(\n document.cookie.match(/XSRF-TOKEN=([^;]+)/)?.[1] ?? \"\",\n ),\n },\n body,\n });\n\n // A failed action does not answer with a Flight stream, and the decoder\n // cannot tell — it reports its own parse failure instead of what the\n // server said.\n try {\n await throwForFailedAction(res);\n } catch (err) {\n // A redirect is an instruction, not something for a form to display:\n // an expired session answers this way, and the destination is the login\n // page rather than a message about one.\n if (err instanceof ServerRedirectError) {\n // The destination came off a response header, so it is checked here\n // too — the engine refuses these at the source, but a proxy or a host\n // in front of it can write whatever it likes. A navigation, not a\n // document load: the layouts stay mounted and the history entry the\n // form was on is replaced, the way a redirect after a POST should\n // be - Back does not return to the submitted form.\n if (isSafeRedirect(err.location)) {\n void navigate(err.location as Route, { replace: true });\n }\n\n // Performed, so resolved - not thrown. The call's answer is \"you are\n // being taken somewhere\": an object saying so, the shape an action's\n // result already has, so a caller reading result.validationErrors\n // reads undefined rather than throwing. A caller that awaited the\n // action in a plain startTransition had no catch for a throw, the\n // rejection reached React, and the root unmounted to a white page\n // on every logout.\n noteRedirected(err.location);\n\n return { redirected: err.location };\n }\n\n throw err;\n }\n\n const answer = await createFromReadableStream(res.body!, { callServer });\n\n return unwrapRevalidated(answer, from);\n }\n\n /**\n * Put anything the action re-rendered on screen, and hand back its result.\n *\n * The trees travel with the answer rather than being fetched afterwards, so\n * the caller sees only what its action returned and never knows the page\n * was updated around it.\n */\n function unwrapRevalidated(answer: unknown, from: string): unknown {\n if (\n answer === null ||\n typeof answer !== \"object\" ||\n !(\"__rscRevalidated\" in answer)\n ) {\n return answer;\n }\n\n const envelope = answer as {\n __rscRevalidated: Record<string, unknown>;\n result: unknown;\n };\n\n applyRevalidations(from, envelope.__rscRevalidated as Record<string, ReactNode>);\n\n return envelope.result;\n }\n\n setDeserializer(createFromReadableStream as never);\n // The query transport speaks Flight too, and reaches the runtime through here\n // rather than importing it: a second import of the browser runtime from the\n // client-component graph is a second client-reference registry, and the\n // symptom is components that render as undefined with nothing logged.\n setQueryCodec({\n deserialize: (stream) =>\n createFromReadableStream(stream, { callServer }) as Promise<unknown>,\n encode: (args) => encodeReply(args) as Promise<string | FormData>,\n // The way back when a read cannot ride in a url. Re-entering callServer is\n // safe: the slot was cleared the moment the reference returned, so this\n // takes the ordinary POST path rather than claiming a read again.\n asAction: (id, args) => callServer(id, args),\n });\n setCallServer(callServer);\n // The plugin's own \"use server\" client stubs route through its registered\n // server callback — register the same transport there too.\n setServerCallback(callServer as never);\n\n // Link / Form / router live in a separate build graph and reach the SPA\n // engine through these globals.\n (window as unknown as { __rsc_navigate: typeof navigate }).__rsc_navigate =\n navigate;\n (window as unknown as { __rsc_prefetch: typeof prefetch }).__rsc_prefetch =\n prefetch;\n (\n window as unknown as { __rsc_cancel_prefetch: typeof cancelPrefetch }\n ).__rsc_cancel_prefetch = cancelPrefetch;\n (\n window as unknown as { __rsc_is_prefetched: typeof isPrefetched }\n ).__rsc_is_prefetched = isPrefetched;\n (window as unknown as { __rsc_refresh: typeof refresh }).__rsc_refresh =\n refresh;\n\n // Hydrate from the RSC endpoint (same url + X-RSC, no version header).\n //\n // Everything from here to the decode is failure handling, because this is\n // the one request with nothing watching it. A page whose shell is already\n // rendered looks fine while this fails, and its fallbacks stay on screen\n // indefinitely with nothing reported anywhere.\n const res = await fetchPagePayload(payloadUrl(window.location.href));\n\n // Seed the router with the build this DOCUMENT is, so a redeploy is caught\n // on the next navigation: the host answers 409 to a client of another\n // build, and the document is loaded again. From the document's own meta\n // first - a document a service worker served from its cache is the last\n // build's, while the payload just fetched is this one's, and seeding from\n // the payload would have the old client claim to be new. The header is\n // the fallback for a document with no meta.\n const documentBuild = document.querySelector('meta[name=\"rsc-kit:build\"]')?.getAttribute(\"content\");\n const servedVersion = documentBuild || res.headers.get(\"X-RSC-Version\");\n\n if (servedVersion) {\n setVersion(servedVersion);\n }\n\n // The chain this page is built from, so the next navigation can say what is\n // already mounted and be sent only what changed.\n // A server says what this page is built from; a file server says nothing,\n // so an exported build works it out from the table it was given.\n const servedLayouts = res.headers.get(\"X-RSC-Layouts\");\n\n if (servedLayouts !== null) {\n setHeldLayouts(servedLayouts.split(\",\"));\n } else if (!seedStaticChain(window.location.href)) {\n setHeldLayouts([]);\n }\n const tree = await createFromReadableStream(res.body!, { callServer });\n\n // Retaining the previous page behind <Activity> needs a wrapper above the\n // page, and React will not hydrate a *document* container through one: the\n // root child of a document has to be <html>, and wrapping it hangs the\n // renderer outright (React 19.2.7). An app whose root layout owns <html>\n // therefore hydrates the tree directly and navigations replace it, as before.\n //\n // Apps that hydrate into an element get retention. Giving it to document-\n // rooted apps means SPA navigation returning only the changed segment rather\n // than a whole document, which is an engine change, not a client one.\n const retains = container !== document;\n\n const shell = retains\n ? createElement(ActivityRoot, {\n initialKey: retentionKey(window.location.href, null),\n initialTree: tree as ReactNode,\n })\n : (tree as ReactNode);\n\n // A document that cannot be hydrated by this tree is client-rendered\n // instead - a repaint, not a freeze. React 19.2 does not recover from a\n // hydration mismatch at an <Activity>: it retries hydrating the boundary,\n // mismatches again, and never returns to the main thread. Every segment\n // boundary is an Activity, one per layout, so a document with none where\n // the page has layouts is that mismatch, guaranteed, before React starts.\n // What produced one: a parameterised route's PPR shell, rendered without\n // a page key and, by a build before this one, without the Activities too.\n // None rather than fewer: a boundary inside a Suspense hole the shell left\n // unfinished has no marker and is client-rendered by React on its own,\n // which is not a mismatch. The stale-asset reload does not apply - the\n // document would come back the same.\n const missing = retains && getHeldLayouts().length > 0 && activityMarkersIn(container) === 0;\n\n if (missing) {\n console.warn(\n \"[rsc-kit] The document has no <Activity> boundaries where the page has layouts, so it cannot be hydrated; rendering the page instead. A PPR shell built by an earlier release lacks them - rebuild.\",\n );\n }\n\n // The payload answered with an error status - the not-found page for a\n // url the shell was served for anyway. It is not the document on screen,\n // so it is rendered, not hydrated: a mismatch at an Activity is the loop\n // above, and this one is certain.\n const disagrees = !res.ok;\n\n const onRecoverableError = (error: unknown, errorInfo: unknown) => {\n // A client component whose chunk the server no longer has fails while\n // hydrating, and React reports that as recoverable: the page is loaded\n // again, with the current names.\n if (recoverFromStaleAssets(error)) return;\n\n // A redirect decided inside a boundary: the server's row carried it as\n // the digest, React client-renders the boundary and reports that it\n // did, and the RedirectBoundary is already performing it. Nothing to\n // read in the console about a page doing what it was told.\n if (isRedirect(error)) return;\n\n // A PPR shell is served with its Suspense boundaries deliberately\n // unfinished — the build aborts the render once the static part is out.\n // React reports that as #419 and client-renders the boundary from the\n // Flight payload, which is the intended path, not a fault to report.\n const message = String((error as { message?: string })?.message ?? error);\n\n if (\n message.includes(\"419\") ||\n message.includes(\"did not finish this Suspense boundary\")\n ) {\n return;\n }\n\n // A view transition the browser cancelled because the tab was not\n // visible. React reports it here; the update still landed, and a tab\n // in the background is not a fault in the page.\n if (message.includes(\"Transition was aborted\")) return;\n\n // A navigation another one overtook: its request was aborted, and a\n // row of its payload that a component was still reading rejects with\n // the abort. React recovers by rendering the root again synchronously\n // and reports the recovery here as #520, with the abort as the cause.\n // The page it recovered to is the one the second navigation asked for;\n // the abort was the design, not a fault.\n const cause = (error as { cause?: { name?: string; message?: string } } | null)?.cause;\n\n if (\n cause?.name === \"AbortError\" ||\n /\\baborted\\b/i.test(cause?.message ?? \"\") ||\n /\\baborted\\b/i.test(message)\n ) {\n return;\n }\n // A page whose query string was read under a boundary carries the\n // fallback there; React reports the recovery on hydration. Under a\n // boundary the developer wrote, that is the designed path and nothing\n // is said. With nothing closer than a loading.tsx, the whole segment\n // showed the fallback until the query arrived - said here, in the\n // page and the console, for whoever is looking at either. Production\n // has no stack to tell the two apart; the build's note on the route is\n // the record there.\n if (\n (error as { digest?: string })?.digest === SEARCH_PARAMS_FALLBACK ||\n message.includes(\"useSearchParams()\")\n ) {\n const stack = (errorInfo as { componentStack?: string } | null)\n ?.componentStack;\n\n if (!caughtByLoading(stack)) return;\n\n const hint =\n \"useSearchParams() was read on the server with nothing closer than a loading.tsx, so the \" +\n \"whole segment showed that fallback until the query arrived. A <Suspense> around the \" +\n \"component that reads keeps the rest of the page painted.\";\n\n showDevNotice(hint, stack);\n console.error(new Error(hint), errorInfo);\n\n return;\n }\n\n console.error(error, errorInfo);\n };\n\n const rootOptions = {\n onRecoverableError,\n // A chunk the deploy no longer serves is not a fault in the page; the\n // document is loaded again, and the new names come with it. Anything\n // else is reported the way React would have.\n onUncaughtError(error: unknown, errorInfo: unknown) {\n if (recoverFromStaleAssets(error)) return;\n\n console.error(error, errorInfo);\n },\n onCaughtError(error: unknown, errorInfo: unknown) {\n if (recoverFromStaleAssets(error)) return;\n // Caught by the RedirectBoundary, which is performing it.\n if (isRedirect(error)) return;\n\n console.error(error, errorInfo);\n },\n };\n\n const root = missing || disagrees\n ? (() => {\n const created = createRoot(container as Element, rootOptions);\n\n created.render(shell);\n\n return created;\n })()\n : hydrateRoot(container, shell, rootOptions);\n\n // Depth 0 is a whole document and replaces the root. Anything deeper is one\n // segment: handing it to the boundary at that depth leaves the layouts above\n // it mounted, which is the point of asking for a partial render at all.\n setNavigateHandler((tree: unknown, key: string, segmentDepth: number, inPlaceOf?: string | null) => {\n const newTree = tree as ReactNode;\n\n // From here on the boundary animates; the seed commit before this did not.\n noteNavigation();\n\n if (segmentDepth > 0) {\n setSegment(segmentDepth, key, newTree, inPlaceOf);\n\n return;\n }\n\n clearSegments();\n root.render(newTree);\n });\n\n // The whole document again, in place - revalidate(\"all\"). Not through the\n // handler above: that clears the boundaries and renders the tree as a new\n // page, and a boundary emptied re-keys its Activity to the current url and\n // remounts everything under it. A port's \"added to cart\" went with the\n // form's state that way, on every product reached by a link. Here the root\n // takes the tree in a transition and each boundary hands its page the new\n // children under the key it has - see replaceActive.\n setReplaceRootHandler((tree: unknown) => {\n startTransition(() => root.render(tree as ReactNode));\n });\n\n // Back and forward reveal a page the boundaries are still holding, with the\n // form you were filling in still filled in, and without asking the server.\n setRestoreHandler((key: string, maxAge?: number) =>\n restoreSegments(key, maxAge),\n );\n setHeldHandlers(isHeld, dropHidden);\n\n // A touch or a settled hover: the page is rendered hidden now, and the\n // click reveals it. See warm() in navigate.ts and prerenderSegment.\n setPrerenderHandler((tree: unknown, key: string, segmentDepth: number) => {\n prerenderSegment(segmentDepth, key, tree as ReactNode);\n });\n\n window.addEventListener(\"popstate\", () => {\n // restore: back and forward reveal the page you were on, with its state.\n // Wherever the browser just went; not a literal this app wrote.\n navigate(window.location.href as Route, { replace: true, restore: true });\n });\n\n history.replaceState(\n { rscUrl: window.location.href },\n \"\",\n window.location.href,\n );\n\n // A tap held by the bootstrap script, navigated to once hydration has\n // committed - not now: the runtime's script running is seconds before\n // React can dispatch a click on a phone still downloading chunks, and\n // a tap in that window would be the browser's. See earlyClicks.ts.\n afterHydration(() => replayEarlyClicks((url) => navigate(url as Route)));\n}\n\n"]}
@@ -36,7 +36,7 @@ export declare function setVersion(v: string): void;
36
36
  */
37
37
  export declare function setHeldLayouts(chain: string[]): void;
38
38
  export declare function getHeldLayouts(): string[];
39
- export declare function setNavigateHandler(fn: (tree: ReactNode, key: string, segmentDepth: number) => void): void;
39
+ export declare function setNavigateHandler(fn: (tree: ReactNode, key: string, segmentDepth: number, inPlaceOf?: string | null) => void): void;
40
40
  export declare function setReplaceRootHandler(fn: ((tree: ReactNode) => void) | null): void;
41
41
  export declare function setHeldHandlers(held: ((key: string, maxAge?: number) => boolean) | null, drop: (() => void) | null): void;
42
42
  /**
@@ -839,7 +839,15 @@ export async function navigate(url, opts) {
839
839
  interceptedAtDepth = interceptSlot ? segmentDepth : null;
840
840
  interceptedFrom = interceptSlot ? (interceptedFrom ?? previousUrl) : null;
841
841
  navigationReached("applied");
842
- onNavigate?.(tree, activityKey, segmentDepth);
842
+ // A replace to the same path with a new query is the page it replaces,
843
+ // moved: the entry left behind can never be gone back to, and mounting a
844
+ // new one showed every fallback in the page - a new chat's first message
845
+ // redirects /chat to /chat?c=25 this way. A push keeps its own page, so
846
+ // Back still restores the one it came from.
847
+ const inPlaceOf = opts?.replace && !interceptSlot && new URL(url, window.location.origin).pathname === new URL(previousUrl, window.location.origin).pathname
848
+ ? retentionKey(previousUrl, null)
849
+ : null;
850
+ onNavigate?.(tree, activityKey, segmentDepth, inPlaceOf);
843
851
  if (!opts?.preserveScroll && !interceptSlot) {
844
852
  // Wait for React to commit the DOM update before scrolling.
845
853
  // Intercepted navigations preserve scroll (e.g. modal over current page).
@@ -1 +1 @@
1
- {"version":3,"file":"navigate.js","sourceRoot":"","sources":["../../src/js/navigate.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Core SPA navigation engine for RSC.\n *\n * Uses module-level state (singleton in the browser bundle).\n * The Flight deserializer is injected by createViteRscApp to avoid\n * duplicate bundling of react-server-dom-webpack.\n */\n\nimport {\n announceDocumentLoad,\n isStaleAssetError,\n loadDocumentOnce,\n} from \"./staleAssets\";\nimport { isUpdated, markStale } from \"./updateStore\";\nimport { navigationAbandoned, navigationCommitted, navigationReached, navigationStarted } from \"./perf\";\nimport { preloadImages } from \"./imagePreload\";\nimport { preloadChunks } from \"./chunkPreload\";\nimport { isSafeRedirect } from \"../safeUrl.js\";\nimport type { Route } from \"../routes.js\";\nimport { reportReachable } from \"./onlineStore\";\nimport { clearSlots, setSlot } from \"./slotStore\";\n// Shared with the host: it stores a page under this key and the client looks\n// under it, so the format cannot live in two places.\nimport {\n matchRoute,\n retentionKey as retentionKeyFor,\n sharedDepth,\n} from \"../routing\";\nimport type { ManifestRoute } from \"../manifest\";\n\ntype ReactNode = unknown;\ntype Deserializer = (\n stream: ReadableStream,\n options: Record<string, unknown>,\n) => Promise<ReactNode>;\ntype CallServerFn = (id: string, args: unknown[]) => Promise<unknown>;\n\ninterface CacheEntry {\n /**\n * The payload as it arrived, undecoded. Decoding a payload is what loads\n * the client chunks it names, and a prefetch decoded on arrival loaded\n * the sign-in page's thirty chunks onto a landing page for every phone\n * visitor, whether they tapped or not. The text is kept; \\`tree\\` decodes\n * it the first time a navigation asks, which is the moment those chunks\n * are wanted.\n */\n body: Promise<string | null>;\n /** The decoded page, on first read. */\n readonly tree: Promise<ReactNode>;\n expiresAt: number;\n /**\n * What the server said about the payload. A prefetch is a real request, so\n * it comes back partial like any other — losing that and treating it as a\n * whole document replaces the root with a page that has no layouts.\n */\n segmentDepth: number;\n layouts: string[] | null;\n /**\n * The slot this payload fills, when it is one region rather than a segment.\n *\n * A prefetch is a real request and comes back as whatever the host answers.\n * An interception answers with the interceptor alone, and an entry that\n * forgets that is applied as a whole document — so a hovered modal link\n * renders the modal *as* the page, with nothing around it. Only after a\n * hover, which is why a scripted click never finds it.\n */\n slot: string | null;\n /**\n * The chain held when this was prefetched. A partial payload is only valid\n * against the chain it was rendered for; navigate somewhere else first and\n * it no longer composes.\n */\n heldWhenFetched: string;\n /**\n * Where the prefetch was sent instead, when the host answered a redirect.\n * The entry leaves the cache - a hover must not navigate - but a click\n * that took the entry while the request was in flight awaits its tree, and\n * a tree of null committed as the page was the whole document gone: url\n * changed, root unmounted, nothing in the console. On a phone the tap's\n * touchstart prefetches with no delay and the click lands 100-300 ms\n * later, the length of a round trip, so a tapped link to a guarded page\n * blanked the page about half the time. The navigation reads this and\n * follows it, the way it follows a redirect on its own request.\n */\n redirectTo: string | null;\n /** The request failed or was aborted; a navigation that took the entry asks again. */\n failed: boolean;\n}\n\ninterface InterceptEntry {\n urlPattern: string;\n slot: string;\n}\n\nlet version = \"\";\n/** Pages a navigation is fetching right now, so a prefetch does not ask again. */\nconst navigating = new Set<string>();\nlet onNavigate:\n ((tree: ReactNode, key: string, segmentDepth: number) => void) | null = null;\nlet onRestore: ((key: string, maxAge?: number) => boolean) | null = null;\n/**\n * Re-render the whole document in place, for revalidate(\"all\"): the page the\n * visitor is on, not a page they went to. Without one registered, the\n * navigation handler at depth 0 is used, which shows the tree as a page.\n */\nlet onReplaceRoot: ((tree: ReactNode) => void) | null = null;\n\n/** Whether a navigation to the key would reveal a held page, asked without revealing it. */\nlet isHeldPage: ((key: string, maxAge?: number) => boolean) | null = null;\n/** Drop the pages held behind the one on screen - after a mutation. */\nlet dropHeld: (() => void) | null = null;\n/**\n * Render a decoded page in the background, hidden, before the click - see\n * warm(). Given the same tree the navigation will hand to onNavigate, so\n * that the navigation is a reveal of work already done rather than a render.\n */\nlet onPrerender: ((tree: ReactNode, key: string, segmentDepth: number) => void) | null = null;\n\n/**\n * How stale a held page may be and still be revealed by a link.\n *\n * The back button ignores this: it names a moment, and the page from that\n * moment is the right answer however old. A link says \"go here\", so there is a\n * point past which answering with what you saw before is stale data presented\n * as fresh. Thirty seconds covers leaving a form to check something and coming\n * straight back, which is the case this exists for.\n */\nlet revealWithin = 30_000;\n\nexport function setRevealWindow(ms: number): void {\n revealWithin = ms;\n}\nlet flightDeserializer: Deserializer | null = null;\nlet callServerFn: CallServerFn | null = null;\nlet activeController: AbortController | null = null;\nconst cache = new Map<string, CacheEntry>();\n/** In-flight prefetches, so one the pointer moved away from can be dropped. */\nconst prefetchControllers = new Map<string, AbortController>();\nlet interceptManifest: InterceptEntry[] = [];\n\n// The layout chain currently mounted, outermost first. Sent so the server can\n// skip re-rendering the layouts still on screen.\nlet heldLayouts: string[] = [];\n\n/**\n * The chain each page was shown under, by retention key.\n *\n * A held page revealed - the back button, or a link to the page just left -\n * puts its layouts back on screen, and the chain has to say so. It used to\n * keep the chain of the page being left: home, a category, back to home,\n * then another category claimed the first category's layout as mounted. The\n * server sent the page alone, and the client put it in the boundary that\n * layout owns - inside the hidden category. The url changed and the page did\n * not, and every tap after it did the same, until a reload. The demo froze\n * on a phone within a dozen taps.\n *\n * Bounded like the payload cache: a key that is no longer held is never\n * asked for, so the oldest can go.\n */\nconst chainOf = new Map<string, string[]>();\nconst MAX_CHAINS = 64;\n\nfunction rememberChain(key: string): void {\n chainOf.delete(key);\n chainOf.set(key, heldLayouts);\n\n while (chainOf.size > MAX_CHAINS) {\n const oldest = chainOf.keys().next().value as string | undefined;\n\n if (oldest === undefined) break;\n\n chainOf.delete(oldest);\n }\n}\n\n/**\n * The boundary depth an interception was rendered at, while one is showing.\n *\n * An interceptor replaces a slot on the layout that declares it, so leaving the\n * intercepted view has to re-render that layout for the slot to go back to its\n * default. Left to itself the next navigation shares the whole chain, replaces\n * only the page below it, and the modal stays open over the new one.\n */\nlet interceptedAtDepth: number | null = null;\n\n/**\n * The url showing underneath an open interception.\n *\n * An interception puts something in a slot on a page that stays where it is,\n * so closing it is not a navigation at all — the page beneath was never\n * replaced. Remembering which url that is means going back to it costs\n * nothing, rather than fetching and rebuilding a page that is already on\n * screen with everything the user typed into it.\n */\nlet interceptedOver: string | null = null;\n\n/**\n * The url an interception was opened from, whichever way it was rendered -\n * the page still on screen under the modal. Only stillShowing asks.\n */\nlet interceptedFrom: string | null = null;\n\nconst DEFAULT_PREFETCH_TTL = 30_000;\n/**\n * How long a payload the host marked `public` is kept.\n *\n * The same build-time bytes for everyone, so the only way it changes is a\n * deploy, and the version handshake catches that on the tap. Thirty seconds\n * was Next's figure for a dynamic page; its static pages are held five\n * minutes, and a landing page read for a minute before the tap on Sign in\n * was, at thirty, an expired entry and a round trip on a phone.\n */\nconst STATIC_PREFETCH_TTL = 300_000;\n\n/**\n * How many prefetched payloads are kept. Entries carry a TTL but were only\n * dropped when read again, so a long session hovering its way through a big\n * nav held every payload it had ever fetched. On insert, anything expired\n * goes, and past the cap the oldest goes - insertion order is age.\n */\nconst MAX_CACHED = 50;\n\nfunction makeRoom(): void {\n const now = Date.now();\n\n for (const [key, entry] of cache) {\n if (entry.expiresAt <= now && !prefetchControllers.has(key))\n cache.delete(key);\n }\n\n while (cache.size >= MAX_CACHED) {\n const oldest = cache.keys().next().value as string | undefined;\n\n if (oldest === undefined) break;\n\n prefetchControllers.get(oldest)?.abort();\n prefetchControllers.delete(oldest);\n cache.delete(oldest);\n }\n}\n\n/**\n * Where a payload lives when there is no server to negotiate with.\n *\n * Normally the payload and the page share a url and are told apart by the\n * X-RSC header. A static host cannot vary by header — it serves one file per\n * url — so an exported build gives payloads their own addresses and the client\n * asks for those instead.\n */\nlet staticPayloadSuffix: string | null = null;\n\n/**\n * The route table, on a static host only.\n *\n * A server works out how much of the page to send by comparing the chain the\n * client sent with the route's own, and says so in a header. A file server\n * does neither — so on an exported site the client has to know the target's\n * layout chain before it asks, or every navigation takes the whole document\n * and replaces the root, which unmounts everything retained behind it.\n *\n * Inlined into the browser entry by the build, so it costs no request.\n */\nlet staticRoutes: ManifestRoute[] | null = null;\n\nexport function setStaticRoutes(routes: ManifestRoute[]): void {\n staticRoutes = routes;\n}\n\n/**\n * The layout chain of the page loaded from a file, since no header said.\n *\n * Without this the client believes it holds nothing, every navigation asks\n * for a whole document, and the depth variants sitting beside it are never\n * requested — the export looks correct and retention silently never happens.\n */\nexport function seedStaticChain(url: string): boolean {\n const segments = staticSegments(url);\n\n if (!segments) return false;\n\n heldLayouts = segments.chain;\n rememberChain(retentionKey(url, null));\n\n return true;\n}\n\n/**\n * The depth an exported payload should be asked for, and the chain it leaves\n * mounted — the two things a header would otherwise have carried.\n */\nfunction staticSegments(\n url: string,\n held: string[] = heldLayouts,\n): { depth: number; chain: string[] } | null {\n if (staticRoutes === null) return null;\n\n const path = new URL(url, window.location.origin).pathname;\n const match = matchRoute({ routes: staticRoutes } as never, path);\n\n if (!match) return null;\n\n return {\n // Against the chain the request is made with, never against whatever is\n // mounted by the time the answer arrives. A prefetch is fetched against\n // one chain and applied later, and reading live state here labels its\n // payload with a depth it was not rendered for.\n depth: sharedDepth(held.join(\",\"), match.route.layouts),\n // Copied: this is the build's table, and the caller assigns it to the\n // chain it holds — handing out the array itself makes the two the same\n // object.\n chain: [...match.route.layouts],\n };\n}\n\nexport function setStaticPayloads(suffix: string | null): void {\n staticPayloadSuffix = suffix;\n}\n\n/** The url to request a payload from, which is the page's own unless exported. */\nexport function payloadUrl(url: string, held: string[] = heldLayouts): string {\n if (staticPayloadSuffix === null) return url;\n\n const parsed = new URL(url, window.location.origin);\n const path = parsed.pathname.replace(/\\/+$/, \"\");\n const segments = staticSegments(url, held);\n\n // The variant for exactly the depth this client shares. Asking for the whole\n // document when a segment would do is not merely wasteful: it replaces the\n // root, and replacing the root throws away every page retained behind it.\n const name =\n segments && segments.depth > 0\n ? staticPayloadSuffix.replace(/^index\\./, `index.seg${segments.depth}.`)\n : staticPayloadSuffix;\n\n return `${path}/${name}${parsed.search}`;\n}\n\n/**\n * What a static payload was fetched as, recorded against its own response.\n *\n * The depth asked for and the depth applied have to be the same number. Worked\n * out separately at the two call sites they can disagree — and a payload\n * rendered whole but applied as a segment nests a boundary inside itself,\n * which does not error, it recurses until the renderer stops responding.\n */\nconst staticFetches = new WeakMap<\n Response,\n { depth: number; chain: string[] }\n>();\n\nexport function setVersion(v: string): void {\n version = v;\n}\n\n/**\n * Tell the worker which build the server is on, and wait to be heard - a\n * document load follows, and the message has to land before the request\n * the load makes. Bounded: a worker that does not answer is not worth a\n * visitor's wait, and a page with no worker has nothing to tell.\n */\nasync function tellWorkerServerBuild(build: string | null): Promise<void> {\n if (!build || typeof navigator === \"undefined\" || !(\"serviceWorker\" in navigator)) return;\n\n const worker = navigator.serviceWorker.controller;\n\n if (!worker) return;\n\n await new Promise<void>((resolve) => {\n const channel = new MessageChannel();\n const done = () => {\n clearTimeout(timer);\n resolve();\n };\n const timer = setTimeout(done, 300);\n\n channel.port1.onmessage = done;\n worker.postMessage({ type: \"rsc-kit:server-build\", version: build }, [channel.port2]);\n });\n\n // And look for the successor now rather than on the next navigation.\n void navigator.serviceWorker.getRegistration().then((registration) => registration?.update()).catch(() => {});\n}\n\n/**\n * The layout chain the client is holding.\n *\n * Seeded from the initial page's response and updated on every navigation, so\n * the next request can say what is already mounted.\n */\nexport function setHeldLayouts(chain: string[]): void {\n heldLayouts = chain;\n rememberChain(retentionKey(window.location.href, null));\n}\n\nexport function getHeldLayouts(): string[] {\n return heldLayouts;\n}\n\nexport function setNavigateHandler(\n fn: (tree: ReactNode, key: string, segmentDepth: number) => void,\n): void {\n onNavigate = fn;\n}\n\nexport function setReplaceRootHandler(fn: ((tree: ReactNode) => void) | null): void {\n onReplaceRoot = fn;\n}\n\nexport function setHeldHandlers(\n held: ((key: string, maxAge?: number) => boolean) | null,\n drop: (() => void) | null,\n): void {\n isHeldPage = held;\n dropHeld = drop;\n}\n\n/**\n * Everything the router holds about pages other than the one on screen,\n * dropped: prefetched payloads, and pages kept behind this one.\n *\n * After an action that revalidated. The list a link prefetched before the\n * mutation still shows the table without the new row - visit() landed on\n * it with no request made, and a reload showed the row. What was fetched\n * before a write is not a cache of what is true after it; the pages held\n * for the back button are from before it too.\n */\nexport function forgetOtherPages(): void {\n for (const [key, controller] of prefetchControllers) {\n controller.abort();\n prefetchControllers.delete(key);\n }\n\n cache.clear();\n dropHeld?.();\n}\n\nexport function setPrerenderHandler(\n fn: ((tree: ReactNode, key: string, segmentDepth: number) => void) | null,\n): void {\n onPrerender = fn;\n}\n\n/**\n * How the router reveals a page that is still mounted behind the current one.\n *\n * Returning true means the page was restored with its client state intact and\n * no request was made.\n */\nexport function setRestoreHandler(\n fn: (key: string, maxAge?: number) => boolean,\n): void {\n onRestore = fn;\n}\n\nexport function setDeserializer(fn: Deserializer): void {\n flightDeserializer = fn;\n}\n\nexport function setCallServer(fn: CallServerFn): void {\n callServerFn = fn;\n}\n\n/**\n * The urls a route.ts answers, so a link to one is treated as the anchor it\n * is: no prefetch - a hover must not run a route - and a full navigation\n * rather than a payload fetch, since the answer is a Response, not a page.\n * Baked into the generated browser entry from the route tree.\n */\nlet apiRoutePatterns: RegExp[] = [];\n\nexport function setApiRoutes(patterns: string[]): void {\n apiRoutePatterns = patterns.map(\n (pattern) =>\n new RegExp(\n \"^\" +\n pattern\n .split(\"/\")\n .map((part) =>\n part.startsWith(\"[...\") ? \".+\" : part.startsWith(\"[\") ? \"[^/]+\" : part.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"),\n )\n .join(\"/\") +\n \"/?$\",\n ),\n );\n}\n\n/** Whether a url is one a route.ts answers. */\nexport function isApiRoute(url: string): boolean {\n if (apiRoutePatterns.length === 0) return false;\n\n try {\n const { pathname } = new URL(url, window.location.origin);\n\n return apiRoutePatterns.some((pattern) => pattern.test(pathname));\n } catch {\n return false;\n }\n}\n\nexport function setInterceptManifest(entries: InterceptEntry[]): void {\n interceptManifest = entries;\n}\n\n/**\n * Check if a URL matches any intercept pattern.\n * Returns the matching slot name, or null if no match.\n */\nfunction matchIntercept(url: string): string | null {\n if (interceptManifest.length === 0) return null;\n\n let pathname: string;\n try {\n pathname = new URL(url, window.location.origin).pathname;\n } catch {\n pathname = url.split(\"?\")[0];\n }\n\n for (const entry of interceptManifest) {\n // urlPattern already has a leading slash (e.g. \"/docs/item/[id]\")\n const regex = new RegExp(\n \"^\" +\n entry.urlPattern\n .replace(/\\[\\.\\.\\.(\\w+)\\]/g, \"(.+)\")\n .replace(/\\[(\\w+)\\]/g, \"([^/]+)\") +\n \"$\",\n );\n\n if (regex.test(pathname)) {\n return entry.slot;\n }\n }\n\n return null;\n}\n\nexport function renderTree(tree: ReactNode): void {\n onNavigate?.(tree, retentionKey(window.location.href, null), 0);\n}\n\n/**\n * Identity of a page for retention purposes.\n *\n * Path and query only: a hash is a position within the same page, and an\n * intercepted route is a different rendering of the same URL, so it retains\n * separately from the full page.\n */\nexport function retentionKey(\n url: string,\n interceptSlot: string | null,\n): string {\n let path: string;\n\n try {\n const parsed = new URL(url, window.location.origin);\n path = parsed.pathname + parsed.search;\n } catch {\n path = url.split(\"#\")[0];\n }\n\n return retentionKeyFor(path, interceptSlot);\n}\n\nexport function getCallServer(): CallServerFn {\n if (!callServerFn) {\n throw new Error(\n \"callServer not initialized. Ensure createViteRscApp() has been called.\",\n );\n }\n return callServerFn;\n}\n\nfunction fetchRscPayload(\n url: string,\n signal?: AbortSignal,\n interceptSlot?: string,\n refererUrl?: string,\n chain: string[] = heldLayouts,\n // A prefetch is speculative and a navigation is not, but on the wire they\n // were identical — so a click could queue behind several prefetches the user\n // had already moved past. Over HTTP/1.1 a browser opens ~6 connections per\n // origin, which a sweep across a nav bar fills on its own.\n priority: \"high\" | \"low\" = \"high\",\n /**\n * A prefetch is speculative: a 409 on one must not load a document the\n * visitor never asked for. A viewport prefetch of the sign-in link, sent\n * from an old page after a deploy, took the visitor reading the home page\n * to /login half a second after it appeared - and a hover over a sidebar\n * link did the same to a half-filled form. The session is marked stale\n * instead, so the next navigation the visitor makes is a document load.\n */\n speculative = false,\n): Promise<Response> {\n const headers: Record<string, string> = {\n \"X-RSC\": \"true\",\n \"X-RSC-Version\": version,\n };\n\n if (chain.length) {\n headers[\"X-RSC-Segments\"] = chain.join(\",\");\n }\n\n if (interceptSlot) {\n headers[\"X-RSC-Intercept\"] = interceptSlot;\n }\n\n if (refererUrl) {\n headers[\"X-RSC-Referer\"] = refererUrl;\n }\n\n // `priority` is not in every lib.dom yet; browsers without it ignore it.\n const asked = staticSegments(url, chain);\n const request = fetch(payloadUrl(url, chain), {\n headers,\n signal,\n priority,\n } as RequestInit).catch((err: unknown) => {\n // Nothing answered at all. An abort is our own doing, not the network's —\n // leaving a link cancels its prefetch, and that must not read as offline.\n if (!(err instanceof DOMException && err.name === \"AbortError\")) {\n reportReachable(false);\n }\n\n throw err;\n });\n\n return request.then(async (response) => {\n // What this payload was asked for, so the apply side cannot work out a\n // different answer from state that has moved on since.\n if (asked) staticFetches.set(response, asked);\n\n // Something answered, whatever it said. A 500 is a reachable server.\n reportReachable(true);\n // Adopt the server's build version from the first response that carries\n // one. Until we know it we send an empty version, which the middleware\n // treats as \"no opinion\"; afterwards a redeploy mid-session answers 409.\n const served = response.headers.get(\"X-RSC-Version\");\n\n if (served && version === \"\") {\n version = served;\n }\n\n if (response.status === 409) {\n const location = response.headers.get(\"X-RSC-Location\");\n // Server-chosen, so checked again here: the engine refuses these at the\n // source, but a host in front of it can put anything on the header.\n // Once per url: a worker still serving the last build's document would\n // answer the load with it, and the next click would be here again.\n const to = isSafeRedirect(location ?? url) ? (location ?? url) : url;\n\n // The worker first. It serves a stored document from its cache, and\n // its cache is the build this page came from - the document it would\n // answer the load with is the one being left. Told which build the\n // server is on, it serves the network for a copy from any other, and\n // is asked to look for its successor. Then the load.\n await tellWorkerServerBuild(served);\n\n if (speculative) {\n markStale();\n\n throw new Error(\"This page is from an earlier build; the next navigation loads the document\");\n }\n\n throw new Error(\n loadDocumentOnce(to)\n ? \"This page is from an earlier build; loading the document from the current one\"\n : \"This page is from an earlier build, and loading the document did not bring the current one\",\n );\n }\n\n return response;\n });\n}\n\n/**\n * Deserialize a Flight response into a React tree.\n *\n * Client modules, CSS <link>s and <title>/<meta> all travel inside the Flight\n * payload — @vitejs/plugin-rsc emits stylesheet links as tree elements and\n * resolves client references through its own browser runtime, and React 19\n * hoists document metadata into <head>. Nothing needs injecting from headers.\n */\nfunction deserializeResponse(response: Response): Promise<ReactNode> {\n return flightDeserializer!(response.body!, {\n callServer:\n callServerFn ??\n (async () => {\n throw new Error(\"Server actions not initialized\");\n }),\n });\n}\n\nfunction isExternalUrl(url: string): boolean {\n try {\n return (\n new URL(url, window.location.origin).origin !== window.location.origin\n );\n } catch {\n return false;\n }\n}\n\n/**\n * Whether a cached payload can be used for a navigation claiming this chain.\n *\n * A partial payload only composes against the chain it was rendered for, so\n * the chain it was fetched against has to be the one the navigation is about\n * to claim — not whatever happens to be mounted.\n */\nfunction isUsable(cached: CacheEntry | undefined, chain: string[]): boolean {\n return (\n cached !== undefined &&\n cached.expiresAt > Date.now() &&\n cached.heldWhenFetched === chain.join(\",\")\n );\n}\n\n/**\n * Whether a navigation to this url would be served from the prefetch cache.\n *\n * Lets a caller decide whether showing an already-fetched page is free. A form\n * uses it to put its target route's shell on screen while the real query runs:\n * worth doing when the shell is in hand, never worth an extra request.\n */\nexport function isPrefetched(url: string): boolean {\n if (isExternalUrl(url)) return false;\n\n const interceptSlot = matchIntercept(url);\n const cacheKey = retentionKeyFor(url, interceptSlot);\n\n return isUsable(cache.get(cacheKey), claimedChain(interceptSlot));\n}\n\n/**\n * The layout chain a navigation to a url will claim.\n *\n * Leaving an interception claims fewer layouts than are held, which is what\n * forces the layout owning the slot to render again so the slot can empty.\n * Both sides have to agree on it: a prefetch recorded against a different\n * chain can never be used, so the close of every modal refetched a payload it\n * had already fetched.\n */\nfunction claimedChain(interceptSlot: string | null): string[] {\n return !interceptSlot && interceptedAtDepth !== null\n ? heldLayouts.slice(0, interceptedAtDepth)\n : heldLayouts;\n}\n\n/**\n * How many redirects a single navigation will follow before giving up.\n *\n * A page that redirects to itself is a mistake someone will make, and without\n * a ceiling it is an unbounded loop of requests rather than an error. The\n * browser's own limit for HTTP redirects is 20; this is smaller because these\n * are full renders, not header exchanges.\n */\nconst MAX_REDIRECTS = 8;\n\n/**\n * Go to a url, the way a Link does.\n *\n * `url` is typed to the routes the build found; cast with `as Route` when the\n * destination is computed rather than written.\n */\nexport async function navigate(\n url: Route,\n opts?: {\n replace?: boolean;\n preserveScroll?: boolean;\n restore?: boolean;\n /** Internal: how many redirects led here. */\n redirectsFollowed?: number;\n },\n): Promise<void> {\n const redirectsFollowed = opts?.redirectsFollowed ?? 0;\n\n // The worker has said a newer build is live. This page's client cannot\n // load what that build's payloads name, so the next navigation is the\n // document, from the new build - the router knows; the banner was only\n // advice. Not for a restore: going back to a page still held asks the\n // server for nothing.\n if (!opts?.restore && isUpdated()) {\n announceDocumentLoad(url, \"newer-build\");\n window.location.href = url;\n\n return;\n }\n\n if (redirectsFollowed > MAX_REDIRECTS) {\n throw new Error(\n `Too many redirects following a navigation (${MAX_REDIRECTS}); last was ${url}`,\n );\n }\n\n // External URLs can't be fetched (CORS) — go directly to full page navigation\n if (isExternalUrl(url)) {\n announceDocumentLoad(url, \"external\");\n window.location.href = url;\n return;\n }\n\n // A route.ts answers with a Response, not a page: a download, a redirect\n // that decides where someone belongs, a sign-out. The browser goes there.\n if (isApiRoute(url)) {\n announceDocumentLoad(url, \"api-route\");\n window.location.href = url;\n return;\n }\n\n // Hash-only URLs — let the browser handle scrolling natively\n if (url.startsWith(\"#\")) {\n window.location.hash = url;\n return;\n }\n\n // Abort any in-flight navigation\n activeController?.abort();\n\n navigationStarted(url);\n\n // Not window.stop(). It used to be called here while the document was\n // still loading, to free a single-threaded server for the new request -\n // and it cancels every load the page has in flight: the client chunks a\n // just-decoded tree still needs, the stylesheet, the boundaries still\n // streaming. A navigation that left the page before the runtime had\n // finished arriving rendered a document with nothing in it. The server\n // has workers; the page keeps loading.\n\n const controller = new AbortController();\n activeController = controller;\n\n // Check if this URL matches an intercept pattern.\n // If so, send the intercept slot + current URL as referer so the server\n // renders the full tree with the interceptor in the right slot.\n const interceptSlot = matchIntercept(url);\n const currentUrl = interceptSlot\n ? window.location.pathname + window.location.search\n : undefined;\n\n const activityKey = retentionKey(url, interceptSlot);\n\n // A page still being held is revealed rather than refetched, whichever\n // gesture asked for it — the back button or a link. Both mean \"the page I\n // was just on\", and having the form you were filling in survive one and not\n // the other is a distinction nobody makes while using the app.\n //\n // The cost is honest: what comes back is the tree from when you left, so its\n // data is from then. Retention is four pages deep, so this reaches only\n // somewhere you were moments ago, and `revalidate()` is how a page says its\n // data has moved on.\n // Closing an interception. The page underneath was never replaced, so this\n // is a matter of emptying the slot — no request, and nothing rebuilt. The\n // form behind the modal is still the one the user was filling in.\n if (\n !interceptSlot &&\n interceptedOver !== null &&\n retentionKey(url, null) === retentionKey(interceptedOver, null)\n ) {\n clearSlots();\n interceptedOver = null;\n interceptedFrom = null;\n interceptedAtDepth = null;\n\n if (opts?.replace) {\n history.replaceState({ rscUrl: url }, \"\", url);\n } else {\n history.pushState({ rscUrl: url }, \"\", url);\n }\n\n window.dispatchEvent(new CustomEvent(\"rsc-navigate\", { detail: url }));\n navigationCommitted();\n\n return;\n }\n\n // Not when the target is the page already showing: asking for this page\n // again means asking the server again, and revealing what is already there\n // would make refresh a no-op. Not while an interception is opening or\n // closing either — those rebuild the chain deliberately.\n const askingForThisPage =\n retentionKey(window.location.href, null) === retentionKey(url, null);\n //\n // And not while an interception is on screen. Leaving a modal has to\n // re-render the layout that owns the slot, because that is what empties it;\n // revealing the page underneath instead leaves the modal sitting over a page\n // whose url has already changed.\n const mayReveal =\n opts?.restore === true ||\n (!askingForThisPage &&\n !interceptSlot &&\n interceptedOver === null &&\n interceptedAtDepth === null);\n\n // Unbounded for the back button, bounded for a link.\n if (\n mayReveal &&\n onRestore?.(activityKey, opts?.restore ? undefined : revealWithin)\n ) {\n // A restored tree carries its own slot contents, so the flag only has to\n // reflect whether what is now showing is an intercepted view.\n if (!interceptSlot) {\n interceptedAtDepth = null;\n interceptedFrom = null;\n }\n\n // Its layouts are the ones on screen now - see chainOf.\n const chain = chainOf.get(activityKey);\n\n if (chain) heldLayouts = chain;\n\n // opts?.replace, not opts.replace: this branch used to be reachable only\n // with opts.restore set, so opts was always there. A link reaches it now\n // with nothing passed at all.\n if (opts?.replace) {\n history.replaceState({ rscUrl: url }, \"\", url);\n } else {\n history.pushState({ rscUrl: url }, \"\", url);\n }\n\n window.dispatchEvent(new CustomEvent(\"rsc-navigate\", { detail: url }));\n navigationCommitted();\n\n return;\n }\n\n // A prefetched payload was rendered against the chain held at prefetch time.\n let segmentDepth = 0;\n let nextLayouts: string[] | null = null;\n /** The slot this answer fills, when it is one region rather than a segment. */\n let slotPayload: string | null = null;\n /** The cache entry this navigation is using, whose metadata settles with it. */\n let reused: CacheEntry | null = null;\n const previousUrl = window.location.pathname + window.location.search;\n\n try {\n const cacheKey = retentionKeyFor(url, interceptSlot);\n const cached = cache.get(cacheKey);\n let treePromise: Promise<ReactNode>;\n\n const chain = claimedChain(interceptSlot);\n\n // A partial payload only composes against the chain it was rendered for —\n // the one this navigation is about to claim, not whatever is mounted.\n // Hovering a link inside a modal prefetches it against the full chain, so\n // reusing that here would skip the layout holding the modal and leave it\n // open over the page behind it.\n const usable = isUsable(cached, chain);\n\n if (usable) {\n treePromise = cached!.tree;\n // Read after the tree resolves, not now. A prefetch fills these in when\n // its response lands, and a click can land first — hover a modal link\n // and click it quickly and the entry still says depth 0, so the\n // interceptor is applied as a whole document and the modal renders *as*\n // the page. The fields are set before the tree promise resolves, so\n // waiting for it is what makes them true.\n reused = cached!;\n cache.delete(cacheKey);\n } else {\n cache.delete(cacheKey);\n\n // Marked while in flight, so a prefetch of the same page - a held\n // tap's replay landing beside the idle viewport prefetch of the link\n // it came from - does not ask for it a second time.\n navigating.add(cacheKey);\n\n let response: Response;\n\n try {\n response = await fetchRscPayload(\n url,\n controller.signal,\n interceptSlot ?? undefined,\n currentUrl,\n chain,\n );\n } finally {\n navigating.delete(cacheKey);\n }\n\n // The check is for a host that answered the page instead of the\n // payload, which is what a server does when it does not recognise the\n // header. An exported build asks a url that only ever holds a payload,\n // and a file server labels it by extension — commonly\n // application/octet-stream — so the check would reject every navigation\n // and send the browser on a full page load instead.\n // The render asked to go somewhere else, and said so before writing\n // anything — so this is still a navigation, not a page load. A redirect\n // decided later than that cannot travel here; it arrives in the payload\n // as an error digest and RedirectBoundary performs it.\n const redirectTo = response.headers.get(\"X-RSC-Redirect\");\n\n if (redirectTo) {\n // The url that redirected was never pushed - the history entry is\n // written after the tree arrives, below - so the destination takes\n // this navigation's own mode. `replace: true` here replaced the page\n // the visitor was ON, and Back from the login page skipped home.\n // Chosen by the server, not written here.\n await navigate(redirectTo as Route, {\n replace: opts?.replace,\n redirectsFollowed: redirectsFollowed + 1,\n });\n\n return;\n }\n\n const contentType = response.headers.get(\"Content-Type\") ?? \"\";\n\n if (\n staticPayloadSuffix === null &&\n !contentType.includes(\"text/x-component\")\n ) {\n announceDocumentLoad(url, `not-a-payload:${response.status}:${contentType.split(\";\")[0]}`);\n window.location.href = url;\n return;\n }\n\n // Headers on a server; worked out locally on a static host, where there\n // is nothing to send them.\n const served = staticFetches.get(response) ?? null;\n\n segmentDepth =\n Number(\n response.headers.get(\"X-RSC-Segment-Depth\") ?? served?.depth ?? 0,\n ) || 0;\n\n // Named region rather than a segment — see the apply below.\n slotPayload = response.headers.get(\"X-RSC-Revalidate\");\n\n const servedLayouts = response.headers.get(\"X-RSC-Layouts\");\n\n if (servedLayouts !== null) {\n nextLayouts = servedLayouts === \"\" ? [] : servedLayouts.split(\",\");\n } else if (served) {\n nextLayouts = served.chain;\n }\n\n treePromise = deserializeResponse(response);\n }\n\n let tree: ReactNode;\n\n try {\n tree = await treePromise;\n navigationReached(\"decoded\");\n } catch (error) {\n // A navigation another one overtook: its request was aborted, and\n // the decoder reports that as a failure of the payload. It is not one\n // - nothing of it was going to be shown - so it ends here, quietly,\n // rather than as a rejection nobody is waiting on.\n if (controller.signal.aborted) return;\n\n throw error;\n }\n\n if (reused) {\n if (controller.signal.aborted) return;\n\n // The prefetch this navigation took did not come back as a page. A\n // redirect is followed as one on this request would be; a failure is\n // asked again, from a cache that no longer holds the entry.\n if (reused.redirectTo) {\n await navigate(reused.redirectTo as Route, {\n replace: opts?.replace,\n redirectsFollowed: redirectsFollowed + 1,\n });\n\n return;\n }\n\n if (reused.failed) {\n await navigate(url, opts);\n\n return;\n }\n\n segmentDepth = reused.segmentDepth;\n nextLayouts = reused.layouts;\n slotPayload = reused.slot;\n }\n\n if (controller.signal.aborted) return;\n\n if (opts?.replace) {\n history.replaceState({ rscUrl: url }, \"\", url);\n } else {\n history.pushState({ rscUrl: url }, \"\", url);\n }\n\n if (nextLayouts !== null) heldLayouts = nextLayouts;\n rememberChain(activityKey);\n\n // The answer is one region, not a piece of the page: the host rendered\n // only the interceptor because the page underneath is already mounted and\n // still correct. Putting it in the slot leaves that page — and everything\n // typed into it — exactly as it was.\n if (slotPayload !== null) {\n setSlot(slotPayload, tree as ReactNode);\n interceptedOver = interceptedOver ?? previousUrl;\n interceptedFrom = interceptedFrom ?? previousUrl;\n interceptedAtDepth = null;\n\n return;\n }\n\n // A slot rendered for the page being left has no claim on the one being\n // arrived at.\n clearSlots();\n\n interceptedOver = null;\n interceptedAtDepth = interceptSlot ? segmentDepth : null;\n interceptedFrom = interceptSlot ? (interceptedFrom ?? previousUrl) : null;\n\n navigationReached(\"applied\");\n onNavigate?.(tree, activityKey, segmentDepth);\n\n if (!opts?.preserveScroll && !interceptSlot) {\n // Wait for React to commit the DOM update before scrolling.\n // Intercepted navigations preserve scroll (e.g. modal over current page).\n requestAnimationFrame(() => {\n window.scrollTo(0, 0);\n });\n }\n\n window.dispatchEvent(new CustomEvent(\"rsc-navigate\", { detail: url }));\n } catch (err) {\n navigationAbandoned();\n\n if (err instanceof DOMException && err.name === \"AbortError\") return;\n\n // A chunk the deploy no longer serves: the browser would have loaded the\n // document, and the new names with it. Do what it would have done.\n if (isStaleAssetError(err)) {\n announceDocumentLoad(url, `stale-asset:${String((err as Error)?.message ?? err).slice(0, 120)}`);\n window.location.href = url;\n\n return;\n }\n\n // Without this a navigation that fails does nothing observable: the click\n // clears its own pending state and the page stays as it was, with no\n // error, no fallback and nothing for an app to react to. Dispatched before\n // rethrowing, so a programmatic caller still sees the failure.\n window.dispatchEvent(\n new CustomEvent(\"rsc-navigate-error\", { detail: { url, error: err } }),\n );\n\n throw err;\n } finally {\n if (activeController === controller) {\n activeController = null;\n }\n }\n}\n\n/**\n * Put something the server re-rendered on screen.\n *\n * The trees arrive with an action's answer rather than being fetched, so this\n * is the same apply path a navigation uses — without a request, a url change\n * or a history entry.\n */\n/**\n * Whether the page an action was invoked from is the one on screen.\n *\n * The one underneath, when an interception is showing: a modal opened after\n * the submit sits over the same page.\n */\nexport function stillShowing(url: string): boolean {\n const key = retentionKey(url, null);\n const now = retentionKey(window.location.pathname + window.location.search, null);\n\n return key === now || (interceptedFrom !== null && key === retentionKey(interceptedFrom, null));\n}\n\n/**\n * Put what an action re-rendered on screen.\n *\n * `from` is the url the action was invoked on - what the host rendered the\n * trees for. A tap that left the page while the action was in flight has\n * changed what is showing, and a document rendered for the page before\n * cannot go under the url after: \"Add to cart\", then the brand link at\n * once, showed the home page and then, when the answer landed, the product\n * again under `/`. The write still happened, and the page on screen was\n * fetched before it - so that page is asked for again, whole, instead.\n */\nexport function applyRevalidations(from: string, revalidated: Record<string, ReactNode>): void {\n // What was fetched or held before the write is from before it.\n forgetOtherPages();\n\n if (!stillShowing(from)) {\n void refresh(\"all\");\n\n return;\n }\n\n for (const [target, tree] of Object.entries(revalidated)) {\n applyRevalidated(target, tree);\n }\n}\n\nexport function applyRevalidated(target: string, tree: ReactNode): void {\n const url = window.location.pathname + window.location.search;\n const key = retentionKey(url, null);\n\n if (target === \"all\") {\n // The whole document again, in place. Not a navigation to this url:\n // the visible entry may be keyed by the url the document loaded with,\n // and showing the tree under the current one made a second entry and\n // remounted the app under it.\n if (onReplaceRoot) onReplaceRoot(tree);\n else onNavigate?.(tree, key, 0);\n\n return;\n }\n\n if (target === \"page\") {\n onNavigate?.(tree, key, heldLayouts.length);\n\n return;\n }\n\n setSlot(target, tree);\n}\n\n/**\n * Ask the server for part of this page again.\n *\n * refresh() the page, leaving the layouts mounted\n * refresh('all') the whole document, layouts included\n * refresh('orders') one parallel slot, by the name its directory gave it\n *\n * The same words an action uses, so a thing can be invalidated from either\n * side. This is the path for a refresh nobody mutated anything to earn — a\n * button, a poll, a message saying that table has moved; what an action\n * invalidated travels back inside the action's own answer instead.\n *\n * A slot is the only region smaller than a page the server can name, so two\n * tables refresh apart from each other only if they are two slots. The page\n * form leaves the layouts alone, which is what makes it cheap and also why a\n * count living in a layout will not move until you ask for 'all'.\n */\nexport async function refresh(target = \"page\"): Promise<void> {\n const url = window.location.pathname + window.location.search;\n\n // Asked because the data moved on; what was fetched or held before is\n // from before.\n forgetOtherPages();\n\n if (target !== \"page\" && target !== \"all\") {\n const response = await fetch(payloadUrl(url), {\n headers: {\n \"X-RSC\": \"true\",\n \"X-RSC-Version\": version,\n \"X-RSC-Revalidate\": target,\n },\n });\n\n if (!response.ok) {\n throw new Error(\n `Could not revalidate ${target}: the server answered ${response.status}`,\n );\n }\n\n setSlot(target, await deserializeResponse(response));\n\n return;\n }\n\n const interceptSlot = matchIntercept(url);\n const cacheKey = retentionKeyFor(url, interceptSlot);\n\n // Never from the cache: refreshing asks what the server says now, not what\n // it said a moment ago.\n cache.delete(cacheKey);\n\n if (target === \"all\") {\n heldLayouts = [];\n }\n\n // A refresh is not a navigation: the same page stays under the reader, so\n // where they were reading has to survive the tree being replaced.\n //\n // `preserveScroll` is not enough on its own. It stops navigate() scrolling\n // to the top deliberately, and says nothing about the scroll positions\n // *inside* the page. Refreshing everything replaces the root, so every\n // element that scrolls is a new node and starts at zero — a sidebar,\n // a code block, any pane with its own overflow. The window survives because\n // the document element is not the thing being replaced, which is why this\n // looks fine until a page has a second scroller in it.\n const positions = scrollPositions();\n\n await navigate(url as Route, { replace: true, preserveScroll: true });\n\n restoreScroll(positions);\n}\n\ninterface ScrollPosition {\n tag: string;\n top: number;\n left: number;\n}\n\n/** Every element that can scroll, whether or not it currently is. */\nfunction scrollables(): HTMLElement[] {\n return [...document.querySelectorAll<HTMLElement>(\"*\")].filter(\n (el) =>\n el.scrollHeight > el.clientHeight || el.scrollWidth > el.clientWidth,\n );\n}\n\n/**\n * Where everything on the page is scrolled to, in document order.\n *\n * Identified by position in the list rather than by a selector: a refresh\n * re-renders the same page, so the nth scrollable element is the same one, and\n * a selector would have to survive whatever classes the markup happens to use.\n * The tag is carried only to notice when that assumption has broken.\n *\n * Everything that *can* scroll, not everything that *is* scrolled — the two\n * lists have to be built the same way or they do not line up. Recording only\n * the scrolled ones and restoring over the scrollable ones puts a sidebar's\n * position onto whatever element happens to come first, which on any page long\n * enough to scroll is <html>.\n */\nfunction scrollPositions(): ScrollPosition[] {\n return [\n { tag: \"window\", top: window.scrollY, left: window.scrollX },\n ...scrollables().map((el) => ({\n tag: el.tagName,\n top: el.scrollTop,\n left: el.scrollLeft,\n })),\n ];\n}\n\n/**\n * Put the page back where it was, once React has finished replacing it.\n *\n * Applied over several ticks rather than once, because `root.render()`\n * schedules the update instead of performing it: a single pass writes the\n * position onto the nodes that are about to be thrown away, and the ones that\n * replace them start at zero. There is nothing to await — the navigation\n * resolves when the tree is handed to React, not when React has committed it.\n *\n * `setTimeout`, not `requestAnimationFrame`. A hidden tab never runs an\n * animation frame, so a refresh in a background tab — an HMR update, a poll —\n * would leave the scroll state wrong the moment it came back into view. It\n * also makes this untestable in an automated browser, where the tab under test\n * is usually not the visible one.\n */\nconst RESTORE_ATTEMPTS = 5;\n\nfunction restoreScroll(positions: ScrollPosition[]): void {\n const [win, ...inner] = positions;\n\n const apply = (attempt: number) => {\n if (window.scrollY !== win.top || window.scrollX !== win.left) {\n window.scrollTo(win.left, win.top);\n }\n\n const now = scrollables();\n\n for (let i = 0; i < inner.length && i < now.length; i++) {\n // A different element here means the page came back a different shape,\n // and guessing further would scroll something nobody touched.\n if (now[i].tagName !== inner[i].tag) break;\n\n if (inner[i].top !== 0 && now[i].scrollTop !== inner[i].top)\n now[i].scrollTop = inner[i].top;\n if (inner[i].left !== 0 && now[i].scrollLeft !== inner[i].left)\n now[i].scrollLeft = inner[i].left;\n }\n\n if (attempt < RESTORE_ATTEMPTS) setTimeout(() => apply(attempt + 1), 16);\n };\n\n apply(1);\n}\n\n/**\n * Fetch a page's payload ahead of the navigation that may ask for it.\n *\n * `intent` is the difference between a link that came into view and one the\n * visitor is about to follow: a hover that settled, a touch. Only then is the\n * payload decoded on arrival - decoding is what loads the client chunks the\n * page names, and a viewport prefetch that decoded put the sign-in page's\n * thirty chunks onto a landing page for every phone visitor. A touch leads\n * its click by 100-300 ms, about a round trip, and a tap that found the\n * bytes here but not the chunks spent that round trip after the click\n * instead of before it: the tap-to-paint that was \"not zero\" beside Next,\n * whose prefetch decodes as it lands.\n */\nexport function prefetch(url: string, cacheForMs?: number, intent = false): void {\n // Never a route.ts: fetching one runs it, and a hover is not a click.\n if (isApiRoute(url)) return;\n\n // Never the page the visitor is on. A logo link to / on the home page,\n // in view, was a 14 KB payload for the page already on screen.\n if (retentionKey(url, null) === retentionKey(window.location.href, null)) return;\n\n // Nor a page still held behind this one, which a navigation would reveal\n // rather than fetch: the page just left, whose link is on every page,\n // was one wasted payload per navigation.\n if (!matchIntercept(url) && isHeldPage?.(retentionKey(url, null), revealWithin)) return;\n\n // Nor anything, once this page is known to be the previous build: the\n // next navigation is a document load, and a payload it would not use is\n // a 409 for nothing - one per tap, measured.\n if (isUpdated()) return;\n\n if (isExternalUrl(url)) return;\n\n const ttl = cacheForMs ?? DEFAULT_PREFETCH_TTL;\n const interceptSlot = matchIntercept(url);\n\n const held = { intent, explicitTtl: cacheForMs !== undefined };\n\n if (interceptSlot) {\n // Intercepted route — only prefetch the intercepted variant\n const currentUrl = window.location.pathname + window.location.search;\n const cacheKey = retentionKeyFor(url, interceptSlot);\n prefetchUrl(cacheKey, url, ttl, interceptSlot, currentUrl, held);\n } else {\n prefetchUrl(retentionKeyFor(url, null), url, ttl, undefined, undefined, held);\n }\n}\n\n/**\n * Do the click's work now: decode the held payload, which loads the chunks\n * it names, and render the page hidden so the click is a reveal.\n *\n * The numbers this came from, on an iPhone with everything prefetched: a\n * first visit to the landing page was 107 ms from tap to paint, 4 of them\n * decoding and 87 rendering; a page still held from a visit before was\n * 15 ms, a reveal. The render is the page's size on the phone's CPU, and\n * nothing in the payload's path shrinks it - but it can be paid before the\n * finger lifts. A touch leads its click by 100-300 ms; a settled hover, by\n * 200 or more. React renders a hidden Activity at idle priority, so the\n * work yields to scrolling, and the navigation then hands the boundary the\n * same tree it prerendered: React bails out of the whole subtree and flips\n * it visible.\n *\n * Only a segment at depth 1 or more, rendered against the chain held now: a\n * whole document replaces the root, and a slot is a region of a page not on\n * screen yet. A prefetch that landed on a redirect - a guarded link, on a\n * landing page all of them - warms the destination it prefetched instead:\n * the tap on Sign in decoded the login page and loaded its chunks after the\n * click, 154 ms of a 225 ms tap.\n */\nfunction warm(entry: CacheEntry, cacheKey: string, followed: Set<string> = new Set()): void {\n // A redirect this touch has already followed. Two guards can point at each\n // other - a guard's answer kept from before a sign-in beside the live one\n // after it - and a destination can normalise to the key of the entry that\n // named it (/agent/ to /agent). Every entry in such a chain is settled, so\n // following it is a chain of resolved promises: no request, no yield, the\n // tab pegged at 100% until it is killed. A port found its landing page\n // freezing on the first tap after a hard reload, with nothing in the\n // console and the network idle. Navigation caps the same walk at\n // MAX_REDIRECTS; this is the warm's own cap.\n if (followed.has(cacheKey) || followed.size > MAX_REDIRECTS) return;\n\n followed.add(cacheKey);\n\n // The tree is read by the navigation that takes the entry, and a decode\n // that fails - a chunk the deploy no longer serves - fails there, where it\n // is handled. Here the rejection has nobody to reach.\n entry.body\n .then((text) => {\n if (entry.redirectTo) {\n const destinationKey = retentionKeyFor(entry.redirectTo, matchIntercept(entry.redirectTo));\n const destination = cache.get(destinationKey);\n\n if (destination) warm(destination, destinationKey, followed);\n\n return;\n }\n\n if (text === null) return;\n\n // The page about to show: its pictures ahead of every other page's.\n preloadImages(text, \"high\");\n\n return entry.tree.then((tree) => {\n if (\n entry.slot !== null ||\n entry.segmentDepth === 0 ||\n !isUsable(entry, claimedChain(null)) ||\n cache.get(cacheKey) !== entry\n )\n return;\n\n onPrerender?.(tree, cacheKey, entry.segmentDepth);\n });\n })\n .catch(() => {});\n}\n\nfunction prefetchUrl(\n cacheKey: string,\n url: string,\n ttl: number,\n interceptSlot?: string,\n refererUrl?: string,\n held: { intent: boolean; explicitTtl: boolean } = { intent: false, explicitTtl: false },\n): void {\n const chain = claimedChain(interceptSlot ?? null);\n const existing = cache.get(cacheKey);\n\n if (existing && existing.expiresAt > Date.now()) {\n // Fetched as it came into view, undecoded; the touch says decode it.\n if (held.intent) warm(existing, cacheKey);\n\n return;\n }\n\n // A navigation is already fetching it; the answer is on its way.\n if (navigating.has(cacheKey)) return;\n\n cache.delete(cacheKey);\n makeRoom();\n\n const controller = new AbortController();\n prefetchControllers.set(cacheKey, controller);\n\n let decoded: Promise<ReactNode> | null = null;\n const entry: CacheEntry = {\n body: Promise.resolve(null),\n get tree() {\n return (decoded ??= this.body.then((text) => (text === null ? null : deserializeResponse(new Response(text)))));\n },\n expiresAt: Date.now() + ttl,\n segmentDepth: 0,\n layouts: null,\n slot: null,\n heldWhenFetched: chain.join(\",\"),\n redirectTo: null,\n failed: false,\n };\n\n // Low priority: the browser then lets a real navigation overtake a queue of\n // speculative requests instead of serving them in the order they were made.\n entry.body = fetchRscPayload(\n url,\n controller.signal,\n interceptSlot,\n refererUrl,\n chain,\n \"low\",\n true,\n )\n .then((response) => {\n // On a static host there are no headers to read, and dropping the depth\n // is not a small loss: the entry then claims a segment is a whole\n // document, and rendering a layout-less page as the document root does\n // not warn — it hangs the renderer.\n // A prefetch that lands on a redirect is not cached. Following it would\n // navigate on hover, and storing it would hand the click a 204 with no\n // body to deserialize. The click re-requests and redirects properly.\n const redirectTo = response.headers.get(\"X-RSC-Redirect\");\n\n if (redirectTo) {\n // The guard's answer is kept, for the entry's TTL, and the\n // destination is prefetched now. A tap on the link then goes\n // straight to a payload already here: no request for the page the\n // visitor may not see, none for the one they will. Before this,\n // every tap on a guarded link paid the guard's round trip and the\n // destination's, in sequence - on a phone, the two slowest things a\n // navigation can do, and the port's \"Sign in is slow from home\".\n // Next's prefetch follows the redirect the same way.\n entry.redirectTo = redirectTo;\n\n if (!isExternalUrl(redirectTo) && isSafeRedirect(redirectTo)) prefetch(redirectTo, ttl);\n\n return null;\n }\n\n entry.slot = response.headers.get(\"X-RSC-Revalidate\");\n\n const local = staticFetches.get(response) ?? null;\n\n entry.segmentDepth =\n Number(\n response.headers.get(\"X-RSC-Segment-Depth\") ?? local?.depth ?? 0,\n ) || 0;\n\n const served = response.headers.get(\"X-RSC-Layouts\");\n\n if (served !== null) {\n entry.layouts = served === \"\" ? [] : served.split(\",\");\n } else if (local) {\n entry.layouts = local.chain;\n }\n\n // Marked public: the build's bytes, the same for everyone, and held\n // for as long as Next holds a static page - unless the link said how\n // long. A deploy is caught by the version handshake, not by the clock.\n if (\n !held.explicitTtl &&\n /\\bpublic\\b/.test(response.headers.get(\"Cache-Control\") ?? \"\")\n ) {\n entry.expiresAt = Math.max(entry.expiresAt, Date.now() + STATIC_PREFETCH_TTL);\n }\n\n // The bytes, not the page: decoding is the navigation's, see CacheEntry\n // - unless the visitor is already on the way, see prefetch(). The\n // pictures the page shows are asked for now, though: on a phone they\n // take longer than the touch-to-click a hidden render has.\n return response.text().then((text) => {\n preloadImages(text);\n // And the code for its client components, so the first visit to a\n // page does not wait on a chunk after it has arrived.\n preloadChunks(text);\n\n return text;\n });\n })\n .catch(() => {\n entry.failed = true;\n cache.delete(cacheKey);\n return null;\n })\n .finally(() => {\n // Settled, so there is nothing left to abort. A completed prefetch stays\n // in the cache — only an in-flight one is ever dropped.\n if (prefetchControllers.get(cacheKey) === controller) {\n prefetchControllers.delete(cacheKey);\n }\n });\n\n cache.set(cacheKey, entry);\n\n if (held.intent) warm(entry, cacheKey);\n}\n\n/**\n * Drop a prefetch that is still in flight — the pointer left the link.\n *\n * The cache entry goes synchronously rather than in the abort's catch: the\n * rejection lands a tick later, and a click in between would find an entry\n * whose tree resolves to null and navigate to a blank page. A prefetch that\n * has already completed is kept; there is no request left to cancel and the\n * payload is still good.\n */\nexport function cancelPrefetch(url: string): void {\n if (isExternalUrl(url)) return;\n\n const interceptSlot = matchIntercept(url);\n const cacheKey = retentionKeyFor(url, interceptSlot);\n const controller = prefetchControllers.get(cacheKey);\n\n if (!controller) return;\n\n prefetchControllers.delete(cacheKey);\n cache.delete(cacheKey);\n controller.abort();\n}\n"]}
1
+ {"version":3,"file":"navigate.js","sourceRoot":"","sources":["../../src/js/navigate.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Core SPA navigation engine for RSC.\n *\n * Uses module-level state (singleton in the browser bundle).\n * The Flight deserializer is injected by createViteRscApp to avoid\n * duplicate bundling of react-server-dom-webpack.\n */\n\nimport {\n announceDocumentLoad,\n isStaleAssetError,\n loadDocumentOnce,\n} from \"./staleAssets\";\nimport { isUpdated, markStale } from \"./updateStore\";\nimport { navigationAbandoned, navigationCommitted, navigationReached, navigationStarted } from \"./perf\";\nimport { preloadImages } from \"./imagePreload\";\nimport { preloadChunks } from \"./chunkPreload\";\nimport { isSafeRedirect } from \"../safeUrl.js\";\nimport type { Route } from \"../routes.js\";\nimport { reportReachable } from \"./onlineStore\";\nimport { clearSlots, setSlot } from \"./slotStore\";\n// Shared with the host: it stores a page under this key and the client looks\n// under it, so the format cannot live in two places.\nimport {\n matchRoute,\n retentionKey as retentionKeyFor,\n sharedDepth,\n} from \"../routing\";\nimport type { ManifestRoute } from \"../manifest\";\n\ntype ReactNode = unknown;\ntype Deserializer = (\n stream: ReadableStream,\n options: Record<string, unknown>,\n) => Promise<ReactNode>;\ntype CallServerFn = (id: string, args: unknown[]) => Promise<unknown>;\n\ninterface CacheEntry {\n /**\n * The payload as it arrived, undecoded. Decoding a payload is what loads\n * the client chunks it names, and a prefetch decoded on arrival loaded\n * the sign-in page's thirty chunks onto a landing page for every phone\n * visitor, whether they tapped or not. The text is kept; \\`tree\\` decodes\n * it the first time a navigation asks, which is the moment those chunks\n * are wanted.\n */\n body: Promise<string | null>;\n /** The decoded page, on first read. */\n readonly tree: Promise<ReactNode>;\n expiresAt: number;\n /**\n * What the server said about the payload. A prefetch is a real request, so\n * it comes back partial like any other — losing that and treating it as a\n * whole document replaces the root with a page that has no layouts.\n */\n segmentDepth: number;\n layouts: string[] | null;\n /**\n * The slot this payload fills, when it is one region rather than a segment.\n *\n * A prefetch is a real request and comes back as whatever the host answers.\n * An interception answers with the interceptor alone, and an entry that\n * forgets that is applied as a whole document — so a hovered modal link\n * renders the modal *as* the page, with nothing around it. Only after a\n * hover, which is why a scripted click never finds it.\n */\n slot: string | null;\n /**\n * The chain held when this was prefetched. A partial payload is only valid\n * against the chain it was rendered for; navigate somewhere else first and\n * it no longer composes.\n */\n heldWhenFetched: string;\n /**\n * Where the prefetch was sent instead, when the host answered a redirect.\n * The entry leaves the cache - a hover must not navigate - but a click\n * that took the entry while the request was in flight awaits its tree, and\n * a tree of null committed as the page was the whole document gone: url\n * changed, root unmounted, nothing in the console. On a phone the tap's\n * touchstart prefetches with no delay and the click lands 100-300 ms\n * later, the length of a round trip, so a tapped link to a guarded page\n * blanked the page about half the time. The navigation reads this and\n * follows it, the way it follows a redirect on its own request.\n */\n redirectTo: string | null;\n /** The request failed or was aborted; a navigation that took the entry asks again. */\n failed: boolean;\n}\n\ninterface InterceptEntry {\n urlPattern: string;\n slot: string;\n}\n\nlet version = \"\";\n/** Pages a navigation is fetching right now, so a prefetch does not ask again. */\nconst navigating = new Set<string>();\nlet onNavigate:\n ((tree: ReactNode, key: string, segmentDepth: number, inPlaceOf?: string | null) => void) | null = null;\nlet onRestore: ((key: string, maxAge?: number) => boolean) | null = null;\n/**\n * Re-render the whole document in place, for revalidate(\"all\"): the page the\n * visitor is on, not a page they went to. Without one registered, the\n * navigation handler at depth 0 is used, which shows the tree as a page.\n */\nlet onReplaceRoot: ((tree: ReactNode) => void) | null = null;\n\n/** Whether a navigation to the key would reveal a held page, asked without revealing it. */\nlet isHeldPage: ((key: string, maxAge?: number) => boolean) | null = null;\n/** Drop the pages held behind the one on screen - after a mutation. */\nlet dropHeld: (() => void) | null = null;\n/**\n * Render a decoded page in the background, hidden, before the click - see\n * warm(). Given the same tree the navigation will hand to onNavigate, so\n * that the navigation is a reveal of work already done rather than a render.\n */\nlet onPrerender: ((tree: ReactNode, key: string, segmentDepth: number) => void) | null = null;\n\n/**\n * How stale a held page may be and still be revealed by a link.\n *\n * The back button ignores this: it names a moment, and the page from that\n * moment is the right answer however old. A link says \"go here\", so there is a\n * point past which answering with what you saw before is stale data presented\n * as fresh. Thirty seconds covers leaving a form to check something and coming\n * straight back, which is the case this exists for.\n */\nlet revealWithin = 30_000;\n\nexport function setRevealWindow(ms: number): void {\n revealWithin = ms;\n}\nlet flightDeserializer: Deserializer | null = null;\nlet callServerFn: CallServerFn | null = null;\nlet activeController: AbortController | null = null;\nconst cache = new Map<string, CacheEntry>();\n/** In-flight prefetches, so one the pointer moved away from can be dropped. */\nconst prefetchControllers = new Map<string, AbortController>();\nlet interceptManifest: InterceptEntry[] = [];\n\n// The layout chain currently mounted, outermost first. Sent so the server can\n// skip re-rendering the layouts still on screen.\nlet heldLayouts: string[] = [];\n\n/**\n * The chain each page was shown under, by retention key.\n *\n * A held page revealed - the back button, or a link to the page just left -\n * puts its layouts back on screen, and the chain has to say so. It used to\n * keep the chain of the page being left: home, a category, back to home,\n * then another category claimed the first category's layout as mounted. The\n * server sent the page alone, and the client put it in the boundary that\n * layout owns - inside the hidden category. The url changed and the page did\n * not, and every tap after it did the same, until a reload. The demo froze\n * on a phone within a dozen taps.\n *\n * Bounded like the payload cache: a key that is no longer held is never\n * asked for, so the oldest can go.\n */\nconst chainOf = new Map<string, string[]>();\nconst MAX_CHAINS = 64;\n\nfunction rememberChain(key: string): void {\n chainOf.delete(key);\n chainOf.set(key, heldLayouts);\n\n while (chainOf.size > MAX_CHAINS) {\n const oldest = chainOf.keys().next().value as string | undefined;\n\n if (oldest === undefined) break;\n\n chainOf.delete(oldest);\n }\n}\n\n/**\n * The boundary depth an interception was rendered at, while one is showing.\n *\n * An interceptor replaces a slot on the layout that declares it, so leaving the\n * intercepted view has to re-render that layout for the slot to go back to its\n * default. Left to itself the next navigation shares the whole chain, replaces\n * only the page below it, and the modal stays open over the new one.\n */\nlet interceptedAtDepth: number | null = null;\n\n/**\n * The url showing underneath an open interception.\n *\n * An interception puts something in a slot on a page that stays where it is,\n * so closing it is not a navigation at all — the page beneath was never\n * replaced. Remembering which url that is means going back to it costs\n * nothing, rather than fetching and rebuilding a page that is already on\n * screen with everything the user typed into it.\n */\nlet interceptedOver: string | null = null;\n\n/**\n * The url an interception was opened from, whichever way it was rendered -\n * the page still on screen under the modal. Only stillShowing asks.\n */\nlet interceptedFrom: string | null = null;\n\nconst DEFAULT_PREFETCH_TTL = 30_000;\n/**\n * How long a payload the host marked `public` is kept.\n *\n * The same build-time bytes for everyone, so the only way it changes is a\n * deploy, and the version handshake catches that on the tap. Thirty seconds\n * was Next's figure for a dynamic page; its static pages are held five\n * minutes, and a landing page read for a minute before the tap on Sign in\n * was, at thirty, an expired entry and a round trip on a phone.\n */\nconst STATIC_PREFETCH_TTL = 300_000;\n\n/**\n * How many prefetched payloads are kept. Entries carry a TTL but were only\n * dropped when read again, so a long session hovering its way through a big\n * nav held every payload it had ever fetched. On insert, anything expired\n * goes, and past the cap the oldest goes - insertion order is age.\n */\nconst MAX_CACHED = 50;\n\nfunction makeRoom(): void {\n const now = Date.now();\n\n for (const [key, entry] of cache) {\n if (entry.expiresAt <= now && !prefetchControllers.has(key))\n cache.delete(key);\n }\n\n while (cache.size >= MAX_CACHED) {\n const oldest = cache.keys().next().value as string | undefined;\n\n if (oldest === undefined) break;\n\n prefetchControllers.get(oldest)?.abort();\n prefetchControllers.delete(oldest);\n cache.delete(oldest);\n }\n}\n\n/**\n * Where a payload lives when there is no server to negotiate with.\n *\n * Normally the payload and the page share a url and are told apart by the\n * X-RSC header. A static host cannot vary by header — it serves one file per\n * url — so an exported build gives payloads their own addresses and the client\n * asks for those instead.\n */\nlet staticPayloadSuffix: string | null = null;\n\n/**\n * The route table, on a static host only.\n *\n * A server works out how much of the page to send by comparing the chain the\n * client sent with the route's own, and says so in a header. A file server\n * does neither — so on an exported site the client has to know the target's\n * layout chain before it asks, or every navigation takes the whole document\n * and replaces the root, which unmounts everything retained behind it.\n *\n * Inlined into the browser entry by the build, so it costs no request.\n */\nlet staticRoutes: ManifestRoute[] | null = null;\n\nexport function setStaticRoutes(routes: ManifestRoute[]): void {\n staticRoutes = routes;\n}\n\n/**\n * The layout chain of the page loaded from a file, since no header said.\n *\n * Without this the client believes it holds nothing, every navigation asks\n * for a whole document, and the depth variants sitting beside it are never\n * requested — the export looks correct and retention silently never happens.\n */\nexport function seedStaticChain(url: string): boolean {\n const segments = staticSegments(url);\n\n if (!segments) return false;\n\n heldLayouts = segments.chain;\n rememberChain(retentionKey(url, null));\n\n return true;\n}\n\n/**\n * The depth an exported payload should be asked for, and the chain it leaves\n * mounted — the two things a header would otherwise have carried.\n */\nfunction staticSegments(\n url: string,\n held: string[] = heldLayouts,\n): { depth: number; chain: string[] } | null {\n if (staticRoutes === null) return null;\n\n const path = new URL(url, window.location.origin).pathname;\n const match = matchRoute({ routes: staticRoutes } as never, path);\n\n if (!match) return null;\n\n return {\n // Against the chain the request is made with, never against whatever is\n // mounted by the time the answer arrives. A prefetch is fetched against\n // one chain and applied later, and reading live state here labels its\n // payload with a depth it was not rendered for.\n depth: sharedDepth(held.join(\",\"), match.route.layouts),\n // Copied: this is the build's table, and the caller assigns it to the\n // chain it holds — handing out the array itself makes the two the same\n // object.\n chain: [...match.route.layouts],\n };\n}\n\nexport function setStaticPayloads(suffix: string | null): void {\n staticPayloadSuffix = suffix;\n}\n\n/** The url to request a payload from, which is the page's own unless exported. */\nexport function payloadUrl(url: string, held: string[] = heldLayouts): string {\n if (staticPayloadSuffix === null) return url;\n\n const parsed = new URL(url, window.location.origin);\n const path = parsed.pathname.replace(/\\/+$/, \"\");\n const segments = staticSegments(url, held);\n\n // The variant for exactly the depth this client shares. Asking for the whole\n // document when a segment would do is not merely wasteful: it replaces the\n // root, and replacing the root throws away every page retained behind it.\n const name =\n segments && segments.depth > 0\n ? staticPayloadSuffix.replace(/^index\\./, `index.seg${segments.depth}.`)\n : staticPayloadSuffix;\n\n return `${path}/${name}${parsed.search}`;\n}\n\n/**\n * What a static payload was fetched as, recorded against its own response.\n *\n * The depth asked for and the depth applied have to be the same number. Worked\n * out separately at the two call sites they can disagree — and a payload\n * rendered whole but applied as a segment nests a boundary inside itself,\n * which does not error, it recurses until the renderer stops responding.\n */\nconst staticFetches = new WeakMap<\n Response,\n { depth: number; chain: string[] }\n>();\n\nexport function setVersion(v: string): void {\n version = v;\n}\n\n/**\n * Tell the worker which build the server is on, and wait to be heard - a\n * document load follows, and the message has to land before the request\n * the load makes. Bounded: a worker that does not answer is not worth a\n * visitor's wait, and a page with no worker has nothing to tell.\n */\nasync function tellWorkerServerBuild(build: string | null): Promise<void> {\n if (!build || typeof navigator === \"undefined\" || !(\"serviceWorker\" in navigator)) return;\n\n const worker = navigator.serviceWorker.controller;\n\n if (!worker) return;\n\n await new Promise<void>((resolve) => {\n const channel = new MessageChannel();\n const done = () => {\n clearTimeout(timer);\n resolve();\n };\n const timer = setTimeout(done, 300);\n\n channel.port1.onmessage = done;\n worker.postMessage({ type: \"rsc-kit:server-build\", version: build }, [channel.port2]);\n });\n\n // And look for the successor now rather than on the next navigation.\n void navigator.serviceWorker.getRegistration().then((registration) => registration?.update()).catch(() => {});\n}\n\n/**\n * The layout chain the client is holding.\n *\n * Seeded from the initial page's response and updated on every navigation, so\n * the next request can say what is already mounted.\n */\nexport function setHeldLayouts(chain: string[]): void {\n heldLayouts = chain;\n rememberChain(retentionKey(window.location.href, null));\n}\n\nexport function getHeldLayouts(): string[] {\n return heldLayouts;\n}\n\nexport function setNavigateHandler(\n fn: (tree: ReactNode, key: string, segmentDepth: number, inPlaceOf?: string | null) => void,\n): void {\n onNavigate = fn;\n}\n\nexport function setReplaceRootHandler(fn: ((tree: ReactNode) => void) | null): void {\n onReplaceRoot = fn;\n}\n\nexport function setHeldHandlers(\n held: ((key: string, maxAge?: number) => boolean) | null,\n drop: (() => void) | null,\n): void {\n isHeldPage = held;\n dropHeld = drop;\n}\n\n/**\n * Everything the router holds about pages other than the one on screen,\n * dropped: prefetched payloads, and pages kept behind this one.\n *\n * After an action that revalidated. The list a link prefetched before the\n * mutation still shows the table without the new row - visit() landed on\n * it with no request made, and a reload showed the row. What was fetched\n * before a write is not a cache of what is true after it; the pages held\n * for the back button are from before it too.\n */\nexport function forgetOtherPages(): void {\n for (const [key, controller] of prefetchControllers) {\n controller.abort();\n prefetchControllers.delete(key);\n }\n\n cache.clear();\n dropHeld?.();\n}\n\nexport function setPrerenderHandler(\n fn: ((tree: ReactNode, key: string, segmentDepth: number) => void) | null,\n): void {\n onPrerender = fn;\n}\n\n/**\n * How the router reveals a page that is still mounted behind the current one.\n *\n * Returning true means the page was restored with its client state intact and\n * no request was made.\n */\nexport function setRestoreHandler(\n fn: (key: string, maxAge?: number) => boolean,\n): void {\n onRestore = fn;\n}\n\nexport function setDeserializer(fn: Deserializer): void {\n flightDeserializer = fn;\n}\n\nexport function setCallServer(fn: CallServerFn): void {\n callServerFn = fn;\n}\n\n/**\n * The urls a route.ts answers, so a link to one is treated as the anchor it\n * is: no prefetch - a hover must not run a route - and a full navigation\n * rather than a payload fetch, since the answer is a Response, not a page.\n * Baked into the generated browser entry from the route tree.\n */\nlet apiRoutePatterns: RegExp[] = [];\n\nexport function setApiRoutes(patterns: string[]): void {\n apiRoutePatterns = patterns.map(\n (pattern) =>\n new RegExp(\n \"^\" +\n pattern\n .split(\"/\")\n .map((part) =>\n part.startsWith(\"[...\") ? \".+\" : part.startsWith(\"[\") ? \"[^/]+\" : part.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"),\n )\n .join(\"/\") +\n \"/?$\",\n ),\n );\n}\n\n/** Whether a url is one a route.ts answers. */\nexport function isApiRoute(url: string): boolean {\n if (apiRoutePatterns.length === 0) return false;\n\n try {\n const { pathname } = new URL(url, window.location.origin);\n\n return apiRoutePatterns.some((pattern) => pattern.test(pathname));\n } catch {\n return false;\n }\n}\n\nexport function setInterceptManifest(entries: InterceptEntry[]): void {\n interceptManifest = entries;\n}\n\n/**\n * Check if a URL matches any intercept pattern.\n * Returns the matching slot name, or null if no match.\n */\nfunction matchIntercept(url: string): string | null {\n if (interceptManifest.length === 0) return null;\n\n let pathname: string;\n try {\n pathname = new URL(url, window.location.origin).pathname;\n } catch {\n pathname = url.split(\"?\")[0];\n }\n\n for (const entry of interceptManifest) {\n // urlPattern already has a leading slash (e.g. \"/docs/item/[id]\")\n const regex = new RegExp(\n \"^\" +\n entry.urlPattern\n .replace(/\\[\\.\\.\\.(\\w+)\\]/g, \"(.+)\")\n .replace(/\\[(\\w+)\\]/g, \"([^/]+)\") +\n \"$\",\n );\n\n if (regex.test(pathname)) {\n return entry.slot;\n }\n }\n\n return null;\n}\n\nexport function renderTree(tree: ReactNode): void {\n onNavigate?.(tree, retentionKey(window.location.href, null), 0);\n}\n\n/**\n * Identity of a page for retention purposes.\n *\n * Path and query only: a hash is a position within the same page, and an\n * intercepted route is a different rendering of the same URL, so it retains\n * separately from the full page.\n */\nexport function retentionKey(\n url: string,\n interceptSlot: string | null,\n): string {\n let path: string;\n\n try {\n const parsed = new URL(url, window.location.origin);\n path = parsed.pathname + parsed.search;\n } catch {\n path = url.split(\"#\")[0];\n }\n\n return retentionKeyFor(path, interceptSlot);\n}\n\nexport function getCallServer(): CallServerFn {\n if (!callServerFn) {\n throw new Error(\n \"callServer not initialized. Ensure createViteRscApp() has been called.\",\n );\n }\n return callServerFn;\n}\n\nfunction fetchRscPayload(\n url: string,\n signal?: AbortSignal,\n interceptSlot?: string,\n refererUrl?: string,\n chain: string[] = heldLayouts,\n // A prefetch is speculative and a navigation is not, but on the wire they\n // were identical — so a click could queue behind several prefetches the user\n // had already moved past. Over HTTP/1.1 a browser opens ~6 connections per\n // origin, which a sweep across a nav bar fills on its own.\n priority: \"high\" | \"low\" = \"high\",\n /**\n * A prefetch is speculative: a 409 on one must not load a document the\n * visitor never asked for. A viewport prefetch of the sign-in link, sent\n * from an old page after a deploy, took the visitor reading the home page\n * to /login half a second after it appeared - and a hover over a sidebar\n * link did the same to a half-filled form. The session is marked stale\n * instead, so the next navigation the visitor makes is a document load.\n */\n speculative = false,\n): Promise<Response> {\n const headers: Record<string, string> = {\n \"X-RSC\": \"true\",\n \"X-RSC-Version\": version,\n };\n\n if (chain.length) {\n headers[\"X-RSC-Segments\"] = chain.join(\",\");\n }\n\n if (interceptSlot) {\n headers[\"X-RSC-Intercept\"] = interceptSlot;\n }\n\n if (refererUrl) {\n headers[\"X-RSC-Referer\"] = refererUrl;\n }\n\n // `priority` is not in every lib.dom yet; browsers without it ignore it.\n const asked = staticSegments(url, chain);\n const request = fetch(payloadUrl(url, chain), {\n headers,\n signal,\n priority,\n } as RequestInit).catch((err: unknown) => {\n // Nothing answered at all. An abort is our own doing, not the network's —\n // leaving a link cancels its prefetch, and that must not read as offline.\n if (!(err instanceof DOMException && err.name === \"AbortError\")) {\n reportReachable(false);\n }\n\n throw err;\n });\n\n return request.then(async (response) => {\n // What this payload was asked for, so the apply side cannot work out a\n // different answer from state that has moved on since.\n if (asked) staticFetches.set(response, asked);\n\n // Something answered, whatever it said. A 500 is a reachable server.\n reportReachable(true);\n // Adopt the server's build version from the first response that carries\n // one. Until we know it we send an empty version, which the middleware\n // treats as \"no opinion\"; afterwards a redeploy mid-session answers 409.\n const served = response.headers.get(\"X-RSC-Version\");\n\n if (served && version === \"\") {\n version = served;\n }\n\n if (response.status === 409) {\n const location = response.headers.get(\"X-RSC-Location\");\n // Server-chosen, so checked again here: the engine refuses these at the\n // source, but a host in front of it can put anything on the header.\n // Once per url: a worker still serving the last build's document would\n // answer the load with it, and the next click would be here again.\n const to = isSafeRedirect(location ?? url) ? (location ?? url) : url;\n\n // The worker first. It serves a stored document from its cache, and\n // its cache is the build this page came from - the document it would\n // answer the load with is the one being left. Told which build the\n // server is on, it serves the network for a copy from any other, and\n // is asked to look for its successor. Then the load.\n await tellWorkerServerBuild(served);\n\n if (speculative) {\n markStale();\n\n throw new Error(\"This page is from an earlier build; the next navigation loads the document\");\n }\n\n throw new Error(\n loadDocumentOnce(to)\n ? \"This page is from an earlier build; loading the document from the current one\"\n : \"This page is from an earlier build, and loading the document did not bring the current one\",\n );\n }\n\n return response;\n });\n}\n\n/**\n * Deserialize a Flight response into a React tree.\n *\n * Client modules, CSS <link>s and <title>/<meta> all travel inside the Flight\n * payload — @vitejs/plugin-rsc emits stylesheet links as tree elements and\n * resolves client references through its own browser runtime, and React 19\n * hoists document metadata into <head>. Nothing needs injecting from headers.\n */\nfunction deserializeResponse(response: Response): Promise<ReactNode> {\n return flightDeserializer!(response.body!, {\n callServer:\n callServerFn ??\n (async () => {\n throw new Error(\"Server actions not initialized\");\n }),\n });\n}\n\nfunction isExternalUrl(url: string): boolean {\n try {\n return (\n new URL(url, window.location.origin).origin !== window.location.origin\n );\n } catch {\n return false;\n }\n}\n\n/**\n * Whether a cached payload can be used for a navigation claiming this chain.\n *\n * A partial payload only composes against the chain it was rendered for, so\n * the chain it was fetched against has to be the one the navigation is about\n * to claim — not whatever happens to be mounted.\n */\nfunction isUsable(cached: CacheEntry | undefined, chain: string[]): boolean {\n return (\n cached !== undefined &&\n cached.expiresAt > Date.now() &&\n cached.heldWhenFetched === chain.join(\",\")\n );\n}\n\n/**\n * Whether a navigation to this url would be served from the prefetch cache.\n *\n * Lets a caller decide whether showing an already-fetched page is free. A form\n * uses it to put its target route's shell on screen while the real query runs:\n * worth doing when the shell is in hand, never worth an extra request.\n */\nexport function isPrefetched(url: string): boolean {\n if (isExternalUrl(url)) return false;\n\n const interceptSlot = matchIntercept(url);\n const cacheKey = retentionKeyFor(url, interceptSlot);\n\n return isUsable(cache.get(cacheKey), claimedChain(interceptSlot));\n}\n\n/**\n * The layout chain a navigation to a url will claim.\n *\n * Leaving an interception claims fewer layouts than are held, which is what\n * forces the layout owning the slot to render again so the slot can empty.\n * Both sides have to agree on it: a prefetch recorded against a different\n * chain can never be used, so the close of every modal refetched a payload it\n * had already fetched.\n */\nfunction claimedChain(interceptSlot: string | null): string[] {\n return !interceptSlot && interceptedAtDepth !== null\n ? heldLayouts.slice(0, interceptedAtDepth)\n : heldLayouts;\n}\n\n/**\n * How many redirects a single navigation will follow before giving up.\n *\n * A page that redirects to itself is a mistake someone will make, and without\n * a ceiling it is an unbounded loop of requests rather than an error. The\n * browser's own limit for HTTP redirects is 20; this is smaller because these\n * are full renders, not header exchanges.\n */\nconst MAX_REDIRECTS = 8;\n\n/**\n * Go to a url, the way a Link does.\n *\n * `url` is typed to the routes the build found; cast with `as Route` when the\n * destination is computed rather than written.\n */\nexport async function navigate(\n url: Route,\n opts?: {\n replace?: boolean;\n preserveScroll?: boolean;\n restore?: boolean;\n /** Internal: how many redirects led here. */\n redirectsFollowed?: number;\n },\n): Promise<void> {\n const redirectsFollowed = opts?.redirectsFollowed ?? 0;\n\n // The worker has said a newer build is live. This page's client cannot\n // load what that build's payloads name, so the next navigation is the\n // document, from the new build - the router knows; the banner was only\n // advice. Not for a restore: going back to a page still held asks the\n // server for nothing.\n if (!opts?.restore && isUpdated()) {\n announceDocumentLoad(url, \"newer-build\");\n window.location.href = url;\n\n return;\n }\n\n if (redirectsFollowed > MAX_REDIRECTS) {\n throw new Error(\n `Too many redirects following a navigation (${MAX_REDIRECTS}); last was ${url}`,\n );\n }\n\n // External URLs can't be fetched (CORS) — go directly to full page navigation\n if (isExternalUrl(url)) {\n announceDocumentLoad(url, \"external\");\n window.location.href = url;\n return;\n }\n\n // A route.ts answers with a Response, not a page: a download, a redirect\n // that decides where someone belongs, a sign-out. The browser goes there.\n if (isApiRoute(url)) {\n announceDocumentLoad(url, \"api-route\");\n window.location.href = url;\n return;\n }\n\n // Hash-only URLs — let the browser handle scrolling natively\n if (url.startsWith(\"#\")) {\n window.location.hash = url;\n return;\n }\n\n // Abort any in-flight navigation\n activeController?.abort();\n\n navigationStarted(url);\n\n // Not window.stop(). It used to be called here while the document was\n // still loading, to free a single-threaded server for the new request -\n // and it cancels every load the page has in flight: the client chunks a\n // just-decoded tree still needs, the stylesheet, the boundaries still\n // streaming. A navigation that left the page before the runtime had\n // finished arriving rendered a document with nothing in it. The server\n // has workers; the page keeps loading.\n\n const controller = new AbortController();\n activeController = controller;\n\n // Check if this URL matches an intercept pattern.\n // If so, send the intercept slot + current URL as referer so the server\n // renders the full tree with the interceptor in the right slot.\n const interceptSlot = matchIntercept(url);\n const currentUrl = interceptSlot\n ? window.location.pathname + window.location.search\n : undefined;\n\n const activityKey = retentionKey(url, interceptSlot);\n\n // A page still being held is revealed rather than refetched, whichever\n // gesture asked for it — the back button or a link. Both mean \"the page I\n // was just on\", and having the form you were filling in survive one and not\n // the other is a distinction nobody makes while using the app.\n //\n // The cost is honest: what comes back is the tree from when you left, so its\n // data is from then. Retention is four pages deep, so this reaches only\n // somewhere you were moments ago, and `revalidate()` is how a page says its\n // data has moved on.\n // Closing an interception. The page underneath was never replaced, so this\n // is a matter of emptying the slot — no request, and nothing rebuilt. The\n // form behind the modal is still the one the user was filling in.\n if (\n !interceptSlot &&\n interceptedOver !== null &&\n retentionKey(url, null) === retentionKey(interceptedOver, null)\n ) {\n clearSlots();\n interceptedOver = null;\n interceptedFrom = null;\n interceptedAtDepth = null;\n\n if (opts?.replace) {\n history.replaceState({ rscUrl: url }, \"\", url);\n } else {\n history.pushState({ rscUrl: url }, \"\", url);\n }\n\n window.dispatchEvent(new CustomEvent(\"rsc-navigate\", { detail: url }));\n navigationCommitted();\n\n return;\n }\n\n // Not when the target is the page already showing: asking for this page\n // again means asking the server again, and revealing what is already there\n // would make refresh a no-op. Not while an interception is opening or\n // closing either — those rebuild the chain deliberately.\n const askingForThisPage =\n retentionKey(window.location.href, null) === retentionKey(url, null);\n //\n // And not while an interception is on screen. Leaving a modal has to\n // re-render the layout that owns the slot, because that is what empties it;\n // revealing the page underneath instead leaves the modal sitting over a page\n // whose url has already changed.\n const mayReveal =\n opts?.restore === true ||\n (!askingForThisPage &&\n !interceptSlot &&\n interceptedOver === null &&\n interceptedAtDepth === null);\n\n // Unbounded for the back button, bounded for a link.\n if (\n mayReveal &&\n onRestore?.(activityKey, opts?.restore ? undefined : revealWithin)\n ) {\n // A restored tree carries its own slot contents, so the flag only has to\n // reflect whether what is now showing is an intercepted view.\n if (!interceptSlot) {\n interceptedAtDepth = null;\n interceptedFrom = null;\n }\n\n // Its layouts are the ones on screen now - see chainOf.\n const chain = chainOf.get(activityKey);\n\n if (chain) heldLayouts = chain;\n\n // opts?.replace, not opts.replace: this branch used to be reachable only\n // with opts.restore set, so opts was always there. A link reaches it now\n // with nothing passed at all.\n if (opts?.replace) {\n history.replaceState({ rscUrl: url }, \"\", url);\n } else {\n history.pushState({ rscUrl: url }, \"\", url);\n }\n\n window.dispatchEvent(new CustomEvent(\"rsc-navigate\", { detail: url }));\n navigationCommitted();\n\n return;\n }\n\n // A prefetched payload was rendered against the chain held at prefetch time.\n let segmentDepth = 0;\n let nextLayouts: string[] | null = null;\n /** The slot this answer fills, when it is one region rather than a segment. */\n let slotPayload: string | null = null;\n /** The cache entry this navigation is using, whose metadata settles with it. */\n let reused: CacheEntry | null = null;\n const previousUrl = window.location.pathname + window.location.search;\n\n try {\n const cacheKey = retentionKeyFor(url, interceptSlot);\n const cached = cache.get(cacheKey);\n let treePromise: Promise<ReactNode>;\n\n const chain = claimedChain(interceptSlot);\n\n // A partial payload only composes against the chain it was rendered for —\n // the one this navigation is about to claim, not whatever is mounted.\n // Hovering a link inside a modal prefetches it against the full chain, so\n // reusing that here would skip the layout holding the modal and leave it\n // open over the page behind it.\n const usable = isUsable(cached, chain);\n\n if (usable) {\n treePromise = cached!.tree;\n // Read after the tree resolves, not now. A prefetch fills these in when\n // its response lands, and a click can land first — hover a modal link\n // and click it quickly and the entry still says depth 0, so the\n // interceptor is applied as a whole document and the modal renders *as*\n // the page. The fields are set before the tree promise resolves, so\n // waiting for it is what makes them true.\n reused = cached!;\n cache.delete(cacheKey);\n } else {\n cache.delete(cacheKey);\n\n // Marked while in flight, so a prefetch of the same page - a held\n // tap's replay landing beside the idle viewport prefetch of the link\n // it came from - does not ask for it a second time.\n navigating.add(cacheKey);\n\n let response: Response;\n\n try {\n response = await fetchRscPayload(\n url,\n controller.signal,\n interceptSlot ?? undefined,\n currentUrl,\n chain,\n );\n } finally {\n navigating.delete(cacheKey);\n }\n\n // The check is for a host that answered the page instead of the\n // payload, which is what a server does when it does not recognise the\n // header. An exported build asks a url that only ever holds a payload,\n // and a file server labels it by extension — commonly\n // application/octet-stream — so the check would reject every navigation\n // and send the browser on a full page load instead.\n // The render asked to go somewhere else, and said so before writing\n // anything — so this is still a navigation, not a page load. A redirect\n // decided later than that cannot travel here; it arrives in the payload\n // as an error digest and RedirectBoundary performs it.\n const redirectTo = response.headers.get(\"X-RSC-Redirect\");\n\n if (redirectTo) {\n // The url that redirected was never pushed - the history entry is\n // written after the tree arrives, below - so the destination takes\n // this navigation's own mode. `replace: true` here replaced the page\n // the visitor was ON, and Back from the login page skipped home.\n // Chosen by the server, not written here.\n await navigate(redirectTo as Route, {\n replace: opts?.replace,\n redirectsFollowed: redirectsFollowed + 1,\n });\n\n return;\n }\n\n const contentType = response.headers.get(\"Content-Type\") ?? \"\";\n\n if (\n staticPayloadSuffix === null &&\n !contentType.includes(\"text/x-component\")\n ) {\n announceDocumentLoad(url, `not-a-payload:${response.status}:${contentType.split(\";\")[0]}`);\n window.location.href = url;\n return;\n }\n\n // Headers on a server; worked out locally on a static host, where there\n // is nothing to send them.\n const served = staticFetches.get(response) ?? null;\n\n segmentDepth =\n Number(\n response.headers.get(\"X-RSC-Segment-Depth\") ?? served?.depth ?? 0,\n ) || 0;\n\n // Named region rather than a segment — see the apply below.\n slotPayload = response.headers.get(\"X-RSC-Revalidate\");\n\n const servedLayouts = response.headers.get(\"X-RSC-Layouts\");\n\n if (servedLayouts !== null) {\n nextLayouts = servedLayouts === \"\" ? [] : servedLayouts.split(\",\");\n } else if (served) {\n nextLayouts = served.chain;\n }\n\n treePromise = deserializeResponse(response);\n }\n\n let tree: ReactNode;\n\n try {\n tree = await treePromise;\n navigationReached(\"decoded\");\n } catch (error) {\n // A navigation another one overtook: its request was aborted, and\n // the decoder reports that as a failure of the payload. It is not one\n // - nothing of it was going to be shown - so it ends here, quietly,\n // rather than as a rejection nobody is waiting on.\n if (controller.signal.aborted) return;\n\n throw error;\n }\n\n if (reused) {\n if (controller.signal.aborted) return;\n\n // The prefetch this navigation took did not come back as a page. A\n // redirect is followed as one on this request would be; a failure is\n // asked again, from a cache that no longer holds the entry.\n if (reused.redirectTo) {\n await navigate(reused.redirectTo as Route, {\n replace: opts?.replace,\n redirectsFollowed: redirectsFollowed + 1,\n });\n\n return;\n }\n\n if (reused.failed) {\n await navigate(url, opts);\n\n return;\n }\n\n segmentDepth = reused.segmentDepth;\n nextLayouts = reused.layouts;\n slotPayload = reused.slot;\n }\n\n if (controller.signal.aborted) return;\n\n if (opts?.replace) {\n history.replaceState({ rscUrl: url }, \"\", url);\n } else {\n history.pushState({ rscUrl: url }, \"\", url);\n }\n\n if (nextLayouts !== null) heldLayouts = nextLayouts;\n rememberChain(activityKey);\n\n // The answer is one region, not a piece of the page: the host rendered\n // only the interceptor because the page underneath is already mounted and\n // still correct. Putting it in the slot leaves that page — and everything\n // typed into it — exactly as it was.\n if (slotPayload !== null) {\n setSlot(slotPayload, tree as ReactNode);\n interceptedOver = interceptedOver ?? previousUrl;\n interceptedFrom = interceptedFrom ?? previousUrl;\n interceptedAtDepth = null;\n\n return;\n }\n\n // A slot rendered for the page being left has no claim on the one being\n // arrived at.\n clearSlots();\n\n interceptedOver = null;\n interceptedAtDepth = interceptSlot ? segmentDepth : null;\n interceptedFrom = interceptSlot ? (interceptedFrom ?? previousUrl) : null;\n\n navigationReached(\"applied\");\n // A replace to the same path with a new query is the page it replaces,\n // moved: the entry left behind can never be gone back to, and mounting a\n // new one showed every fallback in the page - a new chat's first message\n // redirects /chat to /chat?c=25 this way. A push keeps its own page, so\n // Back still restores the one it came from.\n const inPlaceOf =\n opts?.replace && !interceptSlot && new URL(url, window.location.origin).pathname === new URL(previousUrl, window.location.origin).pathname\n ? retentionKey(previousUrl, null)\n : null;\n onNavigate?.(tree, activityKey, segmentDepth, inPlaceOf);\n\n if (!opts?.preserveScroll && !interceptSlot) {\n // Wait for React to commit the DOM update before scrolling.\n // Intercepted navigations preserve scroll (e.g. modal over current page).\n requestAnimationFrame(() => {\n window.scrollTo(0, 0);\n });\n }\n\n window.dispatchEvent(new CustomEvent(\"rsc-navigate\", { detail: url }));\n } catch (err) {\n navigationAbandoned();\n\n if (err instanceof DOMException && err.name === \"AbortError\") return;\n\n // A chunk the deploy no longer serves: the browser would have loaded the\n // document, and the new names with it. Do what it would have done.\n if (isStaleAssetError(err)) {\n announceDocumentLoad(url, `stale-asset:${String((err as Error)?.message ?? err).slice(0, 120)}`);\n window.location.href = url;\n\n return;\n }\n\n // Without this a navigation that fails does nothing observable: the click\n // clears its own pending state and the page stays as it was, with no\n // error, no fallback and nothing for an app to react to. Dispatched before\n // rethrowing, so a programmatic caller still sees the failure.\n window.dispatchEvent(\n new CustomEvent(\"rsc-navigate-error\", { detail: { url, error: err } }),\n );\n\n throw err;\n } finally {\n if (activeController === controller) {\n activeController = null;\n }\n }\n}\n\n/**\n * Put something the server re-rendered on screen.\n *\n * The trees arrive with an action's answer rather than being fetched, so this\n * is the same apply path a navigation uses — without a request, a url change\n * or a history entry.\n */\n/**\n * Whether the page an action was invoked from is the one on screen.\n *\n * The one underneath, when an interception is showing: a modal opened after\n * the submit sits over the same page.\n */\nexport function stillShowing(url: string): boolean {\n const key = retentionKey(url, null);\n const now = retentionKey(window.location.pathname + window.location.search, null);\n\n return key === now || (interceptedFrom !== null && key === retentionKey(interceptedFrom, null));\n}\n\n/**\n * Put what an action re-rendered on screen.\n *\n * `from` is the url the action was invoked on - what the host rendered the\n * trees for. A tap that left the page while the action was in flight has\n * changed what is showing, and a document rendered for the page before\n * cannot go under the url after: \"Add to cart\", then the brand link at\n * once, showed the home page and then, when the answer landed, the product\n * again under `/`. The write still happened, and the page on screen was\n * fetched before it - so that page is asked for again, whole, instead.\n */\nexport function applyRevalidations(from: string, revalidated: Record<string, ReactNode>): void {\n // What was fetched or held before the write is from before it.\n forgetOtherPages();\n\n if (!stillShowing(from)) {\n void refresh(\"all\");\n\n return;\n }\n\n for (const [target, tree] of Object.entries(revalidated)) {\n applyRevalidated(target, tree);\n }\n}\n\nexport function applyRevalidated(target: string, tree: ReactNode): void {\n const url = window.location.pathname + window.location.search;\n const key = retentionKey(url, null);\n\n if (target === \"all\") {\n // The whole document again, in place. Not a navigation to this url:\n // the visible entry may be keyed by the url the document loaded with,\n // and showing the tree under the current one made a second entry and\n // remounted the app under it.\n if (onReplaceRoot) onReplaceRoot(tree);\n else onNavigate?.(tree, key, 0);\n\n return;\n }\n\n if (target === \"page\") {\n onNavigate?.(tree, key, heldLayouts.length);\n\n return;\n }\n\n setSlot(target, tree);\n}\n\n/**\n * Ask the server for part of this page again.\n *\n * refresh() the page, leaving the layouts mounted\n * refresh('all') the whole document, layouts included\n * refresh('orders') one parallel slot, by the name its directory gave it\n *\n * The same words an action uses, so a thing can be invalidated from either\n * side. This is the path for a refresh nobody mutated anything to earn — a\n * button, a poll, a message saying that table has moved; what an action\n * invalidated travels back inside the action's own answer instead.\n *\n * A slot is the only region smaller than a page the server can name, so two\n * tables refresh apart from each other only if they are two slots. The page\n * form leaves the layouts alone, which is what makes it cheap and also why a\n * count living in a layout will not move until you ask for 'all'.\n */\nexport async function refresh(target = \"page\"): Promise<void> {\n const url = window.location.pathname + window.location.search;\n\n // Asked because the data moved on; what was fetched or held before is\n // from before.\n forgetOtherPages();\n\n if (target !== \"page\" && target !== \"all\") {\n const response = await fetch(payloadUrl(url), {\n headers: {\n \"X-RSC\": \"true\",\n \"X-RSC-Version\": version,\n \"X-RSC-Revalidate\": target,\n },\n });\n\n if (!response.ok) {\n throw new Error(\n `Could not revalidate ${target}: the server answered ${response.status}`,\n );\n }\n\n setSlot(target, await deserializeResponse(response));\n\n return;\n }\n\n const interceptSlot = matchIntercept(url);\n const cacheKey = retentionKeyFor(url, interceptSlot);\n\n // Never from the cache: refreshing asks what the server says now, not what\n // it said a moment ago.\n cache.delete(cacheKey);\n\n if (target === \"all\") {\n heldLayouts = [];\n }\n\n // A refresh is not a navigation: the same page stays under the reader, so\n // where they were reading has to survive the tree being replaced.\n //\n // `preserveScroll` is not enough on its own. It stops navigate() scrolling\n // to the top deliberately, and says nothing about the scroll positions\n // *inside* the page. Refreshing everything replaces the root, so every\n // element that scrolls is a new node and starts at zero — a sidebar,\n // a code block, any pane with its own overflow. The window survives because\n // the document element is not the thing being replaced, which is why this\n // looks fine until a page has a second scroller in it.\n const positions = scrollPositions();\n\n await navigate(url as Route, { replace: true, preserveScroll: true });\n\n restoreScroll(positions);\n}\n\ninterface ScrollPosition {\n tag: string;\n top: number;\n left: number;\n}\n\n/** Every element that can scroll, whether or not it currently is. */\nfunction scrollables(): HTMLElement[] {\n return [...document.querySelectorAll<HTMLElement>(\"*\")].filter(\n (el) =>\n el.scrollHeight > el.clientHeight || el.scrollWidth > el.clientWidth,\n );\n}\n\n/**\n * Where everything on the page is scrolled to, in document order.\n *\n * Identified by position in the list rather than by a selector: a refresh\n * re-renders the same page, so the nth scrollable element is the same one, and\n * a selector would have to survive whatever classes the markup happens to use.\n * The tag is carried only to notice when that assumption has broken.\n *\n * Everything that *can* scroll, not everything that *is* scrolled — the two\n * lists have to be built the same way or they do not line up. Recording only\n * the scrolled ones and restoring over the scrollable ones puts a sidebar's\n * position onto whatever element happens to come first, which on any page long\n * enough to scroll is <html>.\n */\nfunction scrollPositions(): ScrollPosition[] {\n return [\n { tag: \"window\", top: window.scrollY, left: window.scrollX },\n ...scrollables().map((el) => ({\n tag: el.tagName,\n top: el.scrollTop,\n left: el.scrollLeft,\n })),\n ];\n}\n\n/**\n * Put the page back where it was, once React has finished replacing it.\n *\n * Applied over several ticks rather than once, because `root.render()`\n * schedules the update instead of performing it: a single pass writes the\n * position onto the nodes that are about to be thrown away, and the ones that\n * replace them start at zero. There is nothing to await — the navigation\n * resolves when the tree is handed to React, not when React has committed it.\n *\n * `setTimeout`, not `requestAnimationFrame`. A hidden tab never runs an\n * animation frame, so a refresh in a background tab — an HMR update, a poll —\n * would leave the scroll state wrong the moment it came back into view. It\n * also makes this untestable in an automated browser, where the tab under test\n * is usually not the visible one.\n */\nconst RESTORE_ATTEMPTS = 5;\n\nfunction restoreScroll(positions: ScrollPosition[]): void {\n const [win, ...inner] = positions;\n\n const apply = (attempt: number) => {\n if (window.scrollY !== win.top || window.scrollX !== win.left) {\n window.scrollTo(win.left, win.top);\n }\n\n const now = scrollables();\n\n for (let i = 0; i < inner.length && i < now.length; i++) {\n // A different element here means the page came back a different shape,\n // and guessing further would scroll something nobody touched.\n if (now[i].tagName !== inner[i].tag) break;\n\n if (inner[i].top !== 0 && now[i].scrollTop !== inner[i].top)\n now[i].scrollTop = inner[i].top;\n if (inner[i].left !== 0 && now[i].scrollLeft !== inner[i].left)\n now[i].scrollLeft = inner[i].left;\n }\n\n if (attempt < RESTORE_ATTEMPTS) setTimeout(() => apply(attempt + 1), 16);\n };\n\n apply(1);\n}\n\n/**\n * Fetch a page's payload ahead of the navigation that may ask for it.\n *\n * `intent` is the difference between a link that came into view and one the\n * visitor is about to follow: a hover that settled, a touch. Only then is the\n * payload decoded on arrival - decoding is what loads the client chunks the\n * page names, and a viewport prefetch that decoded put the sign-in page's\n * thirty chunks onto a landing page for every phone visitor. A touch leads\n * its click by 100-300 ms, about a round trip, and a tap that found the\n * bytes here but not the chunks spent that round trip after the click\n * instead of before it: the tap-to-paint that was \"not zero\" beside Next,\n * whose prefetch decodes as it lands.\n */\nexport function prefetch(url: string, cacheForMs?: number, intent = false): void {\n // Never a route.ts: fetching one runs it, and a hover is not a click.\n if (isApiRoute(url)) return;\n\n // Never the page the visitor is on. A logo link to / on the home page,\n // in view, was a 14 KB payload for the page already on screen.\n if (retentionKey(url, null) === retentionKey(window.location.href, null)) return;\n\n // Nor a page still held behind this one, which a navigation would reveal\n // rather than fetch: the page just left, whose link is on every page,\n // was one wasted payload per navigation.\n if (!matchIntercept(url) && isHeldPage?.(retentionKey(url, null), revealWithin)) return;\n\n // Nor anything, once this page is known to be the previous build: the\n // next navigation is a document load, and a payload it would not use is\n // a 409 for nothing - one per tap, measured.\n if (isUpdated()) return;\n\n if (isExternalUrl(url)) return;\n\n const ttl = cacheForMs ?? DEFAULT_PREFETCH_TTL;\n const interceptSlot = matchIntercept(url);\n\n const held = { intent, explicitTtl: cacheForMs !== undefined };\n\n if (interceptSlot) {\n // Intercepted route — only prefetch the intercepted variant\n const currentUrl = window.location.pathname + window.location.search;\n const cacheKey = retentionKeyFor(url, interceptSlot);\n prefetchUrl(cacheKey, url, ttl, interceptSlot, currentUrl, held);\n } else {\n prefetchUrl(retentionKeyFor(url, null), url, ttl, undefined, undefined, held);\n }\n}\n\n/**\n * Do the click's work now: decode the held payload, which loads the chunks\n * it names, and render the page hidden so the click is a reveal.\n *\n * The numbers this came from, on an iPhone with everything prefetched: a\n * first visit to the landing page was 107 ms from tap to paint, 4 of them\n * decoding and 87 rendering; a page still held from a visit before was\n * 15 ms, a reveal. The render is the page's size on the phone's CPU, and\n * nothing in the payload's path shrinks it - but it can be paid before the\n * finger lifts. A touch leads its click by 100-300 ms; a settled hover, by\n * 200 or more. React renders a hidden Activity at idle priority, so the\n * work yields to scrolling, and the navigation then hands the boundary the\n * same tree it prerendered: React bails out of the whole subtree and flips\n * it visible.\n *\n * Only a segment at depth 1 or more, rendered against the chain held now: a\n * whole document replaces the root, and a slot is a region of a page not on\n * screen yet. A prefetch that landed on a redirect - a guarded link, on a\n * landing page all of them - warms the destination it prefetched instead:\n * the tap on Sign in decoded the login page and loaded its chunks after the\n * click, 154 ms of a 225 ms tap.\n */\nfunction warm(entry: CacheEntry, cacheKey: string, followed: Set<string> = new Set()): void {\n // A redirect this touch has already followed. Two guards can point at each\n // other - a guard's answer kept from before a sign-in beside the live one\n // after it - and a destination can normalise to the key of the entry that\n // named it (/agent/ to /agent). Every entry in such a chain is settled, so\n // following it is a chain of resolved promises: no request, no yield, the\n // tab pegged at 100% until it is killed. A port found its landing page\n // freezing on the first tap after a hard reload, with nothing in the\n // console and the network idle. Navigation caps the same walk at\n // MAX_REDIRECTS; this is the warm's own cap.\n if (followed.has(cacheKey) || followed.size > MAX_REDIRECTS) return;\n\n followed.add(cacheKey);\n\n // The tree is read by the navigation that takes the entry, and a decode\n // that fails - a chunk the deploy no longer serves - fails there, where it\n // is handled. Here the rejection has nobody to reach.\n entry.body\n .then((text) => {\n if (entry.redirectTo) {\n const destinationKey = retentionKeyFor(entry.redirectTo, matchIntercept(entry.redirectTo));\n const destination = cache.get(destinationKey);\n\n if (destination) warm(destination, destinationKey, followed);\n\n return;\n }\n\n if (text === null) return;\n\n // The page about to show: its pictures ahead of every other page's.\n preloadImages(text, \"high\");\n\n return entry.tree.then((tree) => {\n if (\n entry.slot !== null ||\n entry.segmentDepth === 0 ||\n !isUsable(entry, claimedChain(null)) ||\n cache.get(cacheKey) !== entry\n )\n return;\n\n onPrerender?.(tree, cacheKey, entry.segmentDepth);\n });\n })\n .catch(() => {});\n}\n\nfunction prefetchUrl(\n cacheKey: string,\n url: string,\n ttl: number,\n interceptSlot?: string,\n refererUrl?: string,\n held: { intent: boolean; explicitTtl: boolean } = { intent: false, explicitTtl: false },\n): void {\n const chain = claimedChain(interceptSlot ?? null);\n const existing = cache.get(cacheKey);\n\n if (existing && existing.expiresAt > Date.now()) {\n // Fetched as it came into view, undecoded; the touch says decode it.\n if (held.intent) warm(existing, cacheKey);\n\n return;\n }\n\n // A navigation is already fetching it; the answer is on its way.\n if (navigating.has(cacheKey)) return;\n\n cache.delete(cacheKey);\n makeRoom();\n\n const controller = new AbortController();\n prefetchControllers.set(cacheKey, controller);\n\n let decoded: Promise<ReactNode> | null = null;\n const entry: CacheEntry = {\n body: Promise.resolve(null),\n get tree() {\n return (decoded ??= this.body.then((text) => (text === null ? null : deserializeResponse(new Response(text)))));\n },\n expiresAt: Date.now() + ttl,\n segmentDepth: 0,\n layouts: null,\n slot: null,\n heldWhenFetched: chain.join(\",\"),\n redirectTo: null,\n failed: false,\n };\n\n // Low priority: the browser then lets a real navigation overtake a queue of\n // speculative requests instead of serving them in the order they were made.\n entry.body = fetchRscPayload(\n url,\n controller.signal,\n interceptSlot,\n refererUrl,\n chain,\n \"low\",\n true,\n )\n .then((response) => {\n // On a static host there are no headers to read, and dropping the depth\n // is not a small loss: the entry then claims a segment is a whole\n // document, and rendering a layout-less page as the document root does\n // not warn — it hangs the renderer.\n // A prefetch that lands on a redirect is not cached. Following it would\n // navigate on hover, and storing it would hand the click a 204 with no\n // body to deserialize. The click re-requests and redirects properly.\n const redirectTo = response.headers.get(\"X-RSC-Redirect\");\n\n if (redirectTo) {\n // The guard's answer is kept, for the entry's TTL, and the\n // destination is prefetched now. A tap on the link then goes\n // straight to a payload already here: no request for the page the\n // visitor may not see, none for the one they will. Before this,\n // every tap on a guarded link paid the guard's round trip and the\n // destination's, in sequence - on a phone, the two slowest things a\n // navigation can do, and the port's \"Sign in is slow from home\".\n // Next's prefetch follows the redirect the same way.\n entry.redirectTo = redirectTo;\n\n if (!isExternalUrl(redirectTo) && isSafeRedirect(redirectTo)) prefetch(redirectTo, ttl);\n\n return null;\n }\n\n entry.slot = response.headers.get(\"X-RSC-Revalidate\");\n\n const local = staticFetches.get(response) ?? null;\n\n entry.segmentDepth =\n Number(\n response.headers.get(\"X-RSC-Segment-Depth\") ?? local?.depth ?? 0,\n ) || 0;\n\n const served = response.headers.get(\"X-RSC-Layouts\");\n\n if (served !== null) {\n entry.layouts = served === \"\" ? [] : served.split(\",\");\n } else if (local) {\n entry.layouts = local.chain;\n }\n\n // Marked public: the build's bytes, the same for everyone, and held\n // for as long as Next holds a static page - unless the link said how\n // long. A deploy is caught by the version handshake, not by the clock.\n if (\n !held.explicitTtl &&\n /\\bpublic\\b/.test(response.headers.get(\"Cache-Control\") ?? \"\")\n ) {\n entry.expiresAt = Math.max(entry.expiresAt, Date.now() + STATIC_PREFETCH_TTL);\n }\n\n // The bytes, not the page: decoding is the navigation's, see CacheEntry\n // - unless the visitor is already on the way, see prefetch(). The\n // pictures the page shows are asked for now, though: on a phone they\n // take longer than the touch-to-click a hidden render has.\n return response.text().then((text) => {\n preloadImages(text);\n // And the code for its client components, so the first visit to a\n // page does not wait on a chunk after it has arrived.\n preloadChunks(text);\n\n return text;\n });\n })\n .catch(() => {\n entry.failed = true;\n cache.delete(cacheKey);\n return null;\n })\n .finally(() => {\n // Settled, so there is nothing left to abort. A completed prefetch stays\n // in the cache — only an in-flight one is ever dropped.\n if (prefetchControllers.get(cacheKey) === controller) {\n prefetchControllers.delete(cacheKey);\n }\n });\n\n cache.set(cacheKey, entry);\n\n if (held.intent) warm(entry, cacheKey);\n}\n\n/**\n * Drop a prefetch that is still in flight — the pointer left the link.\n *\n * The cache entry goes synchronously rather than in the abort's catch: the\n * rejection lands a tick later, and a click in between would find an entry\n * whose tree resolves to null and navigate to a blank page. A prefetch that\n * has already completed is kept; there is no request left to cancel and the\n * payload is still good.\n */\nexport function cancelPrefetch(url: string): void {\n if (isExternalUrl(url)) return;\n\n const interceptSlot = matchIntercept(url);\n const cacheKey = retentionKeyFor(url, interceptSlot);\n const controller = prefetchControllers.get(cacheKey);\n\n if (!controller) return;\n\n prefetchControllers.delete(cacheKey);\n cache.delete(cacheKey);\n controller.abort();\n}\n"]}
@@ -38,6 +38,19 @@ type Tree = unknown;
38
38
  type Listener = () => void;
39
39
  interface Entry {
40
40
  key: string;
41
+ /**
42
+ * The key React mounts this page under, when it is not `key`.
43
+ *
44
+ * `key` is what a navigation files the page under - its path and query, so
45
+ * Back to ?q=a restores that page and not ?q=b. The identity is what keeps
46
+ * it mounted, and it has to survive two things that are not a new page: a
47
+ * page loaded with a query, which the server rendered under its pathname
48
+ * alone (the shell was frozen that way), and a replace to the same path with
49
+ * a new query - the first message of a chat - which leaves nothing to go
50
+ * back to. A new identity is a remount, and a remount shows every Suspense
51
+ * fallback in the page: a skeleton over the chat, on every reply.
52
+ */
53
+ identity?: string;
41
54
  tree: Tree;
42
55
  /**
43
56
  * When this tree arrived, so a link can decide whether it is still worth
@@ -82,7 +95,7 @@ export declare function getSegmentState(depth: number): DepthState | null;
82
95
  * Deeper segments belonged to the page being replaced; leaving them would
83
96
  * render the previous page inside the new one.
84
97
  */
85
- export declare function setSegment(depth: number, key: string, tree: Tree): void;
98
+ export declare function setSegment(depth: number, key: string, tree: Tree, inPlaceOf?: string | null): void;
86
99
  /**
87
100
  * Render a page hidden at `depth`, before any navigation to it.
88
101
  *
@@ -113,7 +126,7 @@ export declare function replaceActive(depth: number, tree: Tree): void;
113
126
  * Record the children the server rendered, so the page you arrived on can be
114
127
  * returned to later. Never changes what is showing.
115
128
  */
116
- export declare function seedSegment(depth: number, key: string, tree: Tree): void;
129
+ export declare function seedSegment(depth: number, key: string, tree: Tree, identity?: string): void;
117
130
  /**
118
131
  * Reveal a page the boundaries are still holding, without asking the server.
119
132
  *
@@ -72,11 +72,13 @@ function retain(entries, order, activeKey) {
72
72
  activeKey,
73
73
  };
74
74
  }
75
- function put(depth, key, tree) {
75
+ function put(depth, key, tree, identity) {
76
76
  const state = depths.get(depth);
77
+ // The same page again keeps the identity it is mounted under.
78
+ const kept = identity ?? state?.entries.find((entry) => entry.key === key)?.identity;
77
79
  const entries = [
78
80
  ...(state?.entries ?? []).filter((entry) => entry.key !== key),
79
- { key, tree, at: Date.now(), seq: ++tick },
81
+ { key, tree, at: Date.now(), seq: ++tick, ...(kept !== undefined && kept !== key ? { identity: kept } : {}) },
80
82
  ];
81
83
  const order = [...(state?.order ?? []).filter((k) => k !== key), key];
82
84
  depths.set(depth, retain(entries, order, key));
@@ -87,13 +89,27 @@ function put(depth, key, tree) {
87
89
  * Deeper segments belonged to the page being replaced; leaving them would
88
90
  * render the previous page inside the new one.
89
91
  */
90
- export function setSegment(depth, key, tree) {
92
+ export function setSegment(depth, key, tree, inPlaceOf) {
91
93
  // A guess about another page was wrong; the one about this page, if there
92
94
  // was one, is replaced by put() below - with the same tree, when the
93
95
  // prerender and the navigation read the same decoded payload, which is
94
96
  // what makes the update a reveal rather than a render.
95
97
  dropSpeculative(depth, key);
96
- put(depth, key, tree);
98
+ // A replace to the same path with a new query: the page it replaces is gone
99
+ // from history, so this is that page, moved - not a new one to mount beside
100
+ // it. It takes the old entry's identity, and the old entry goes.
101
+ const state = depths.get(depth);
102
+ const replaced = inPlaceOf && inPlaceOf !== key && !state?.entries.some((entry) => entry.key === key)
103
+ ? state?.entries.find((entry) => entry.key === inPlaceOf)
104
+ : undefined;
105
+ if (replaced && state) {
106
+ depths.set(depth, {
107
+ ...state,
108
+ entries: state.entries.filter((entry) => entry !== replaced),
109
+ order: state.order.filter((k) => k !== replaced.key),
110
+ });
111
+ }
112
+ put(depth, key, tree, replaced ? (replaced.identity ?? replaced.key) : undefined);
97
113
  const stale = [...depths.keys()].filter((d) => d > depth);
98
114
  for (const d of stale)
99
115
  depths.delete(d);
@@ -180,18 +196,18 @@ export function replaceActive(depth, tree) {
180
196
  * Record the children the server rendered, so the page you arrived on can be
181
197
  * returned to later. Never changes what is showing.
182
198
  */
183
- export function seedSegment(depth, key, tree) {
199
+ export function seedSegment(depth, key, tree, identity) {
184
200
  const state = depths.get(depth);
185
201
  if (state?.entries.some((entry) => entry.key === key))
186
202
  return;
187
203
  if (!state) {
188
- put(depth, key, tree);
204
+ put(depth, key, tree, identity);
189
205
  notify(depth);
190
206
  return;
191
207
  }
192
208
  // Older than whatever is showing, so it goes to the front of the eviction
193
209
  // order — and crucially does not become the active page.
194
- depths.set(depth, retain([...state.entries, { key, tree, at: Date.now(), seq: ++tick }], [key, ...state.order.filter((k) => k !== key)], state.activeKey));
210
+ depths.set(depth, retain([...state.entries, { key, tree, at: Date.now(), seq: ++tick, ...(identity !== undefined && identity !== key ? { identity } : {}) }], [key, ...state.order.filter((k) => k !== key)], state.activeKey));
195
211
  notify(depth);
196
212
  }
197
213
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"segmentStore.js","sourceRoot":"","sources":["../../src/js/segmentStore.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What each segment boundary is showing, and what it is keeping alive behind it.\n *\n * A navigation replaces one segment. Keeping the previous one mounted — hidden,\n * not unmounted — is what lets going back restore it with its client state:\n * the half-typed form, the open disclosure, the scrolled list. Unmounting\n * throws all of that away, which is what replacing the root used to do.\n *\n * Entries are keyed by page (the URL, or its intercept variant), so a boundary\n * can hold several and reveal one. Empty is meaningful: a boundary with nothing\n * stored renders the children the server gave it.\n *\n * A store rather than state, and not a preference — three things rule state out.\n * A boundary is inserted between every layout level, so there are several and a\n * navigation targets one by depth; they are separated by server components, so\n * no setter can be threaded down to them, because a function does not cross\n * that boundary; and navigate.ts is a plain module with no component instance\n * to call one on. Addressing a component you hold no reference to is what an\n * external store is for.\n *\n * Underneath it is the wire protocol. A partial navigation sends only the\n * segment that changed — see the X-RSC-Segments headers — so there is nothing\n * for a root to re-render with even if it held the state. Next.js keeps its\n * router in useState and derives every segment from it; that is the same trade\n * in the other direction.\n *\n * What it costs: React pins an external store's updates to synchronous\n * priority, because a store cannot be safely time-sliced. Synchronous is never\n * a transition, and anything that only runs for one — React's <ViewTransition>\n * among them — never ran for a navigation.\n *\n * Which is why SegmentBoundary does not read this with useSyncExternalStore\n * any more. The store still does the addressing, which is the part only it can\n * do; the boundary copies into state, so the render is a transition. See the\n * view transitions guide.\n */\n\ntype Tree = unknown;\ntype Listener = () => void;\n\ninterface Entry {\n key: string;\n tree: Tree;\n /**\n * When this tree arrived, so a link can decide whether it is still worth\n * revealing. The back button never asks — it means \"the page I was on\",\n * however long ago that was.\n */\n at: number;\n /**\n * Its place in the order things happened, for the question \"was this\n * here before the mutation?\" - which a clock answers wrongly for a seed\n * and a write in the same millisecond, and a test hit exactly that.\n */\n seq: number;\n /**\n * Rendered before the click, hidden, on the strength of a touch or a\n * settled hover - see prerenderSegment. Outside the retention window: it\n * is a guess, and a guess must not evict a page the visitor was on. One\n * per depth; the next guess replaces it, and a navigation to anything\n * else drops it.\n */\n speculative?: boolean;\n}\n\n/**\n * Immutable: useSyncExternalStore compares snapshots by identity, so a new\n * object per read reads as \"changed every render\" and loops forever. Every\n * mutation replaces this wholesale; nothing edits one in place.\n */\ninterface DepthState {\n readonly entries: readonly Entry[];\n readonly activeKey: string;\n /** Most recently shown last; eviction takes from the front. */\n readonly order: readonly string[];\n}\n\n/** Pages kept alive per boundary. Four covers ordinary back-and-forth. */\nexport const RETENTION = 4;\n\nconst depths = new Map<number, DepthState>();\n/** A counter every entry takes a number from, in order. */\nlet tick = 0;\n/** The number the last mutation took: everything held before it is wrong. */\nlet invalidatedAt = 0;\nconst listeners = new Map<number, Set<Listener>>();\n\nfunction notify(depth: number): void {\n for (const listener of listeners.get(depth) ?? []) listener();\n}\n\nexport function subscribeToSegment(\n depth: number,\n listener: Listener,\n): () => void {\n let set = listeners.get(depth);\n\n if (!set) {\n set = new Set();\n listeners.set(depth, set);\n }\n\n set.add(listener);\n\n return () => {\n set!.delete(listener);\n if (set!.size === 0) listeners.delete(depth);\n };\n}\n\n/** Everything a boundary at this depth needs to render, or null for \"use children\". */\nexport function getSegmentState(depth: number): DepthState | null {\n return depths.get(depth) ?? null;\n}\n\n/** Apply the retention window to a candidate state. */\nfunction retain(\n entries: readonly Entry[],\n order: readonly string[],\n activeKey: string,\n): DepthState {\n const kept = order.slice(-RETENTION);\n\n return {\n entries: entries.filter((entry) => kept.includes(entry.key) || entry.speculative),\n order: kept,\n activeKey,\n };\n}\n\nfunction put(depth: number, key: string, tree: Tree): void {\n const state = depths.get(depth);\n const entries = [\n ...(state?.entries ?? []).filter((entry) => entry.key !== key),\n { key, tree, at: Date.now(), seq: ++tick },\n ];\n const order = [...(state?.order ?? []).filter((k) => k !== key), key];\n\n depths.set(depth, retain(entries, order, key));\n}\n\n/**\n * Show `tree` at `depth` for `key`, retaining what was there.\n *\n * Deeper segments belonged to the page being replaced; leaving them would\n * render the previous page inside the new one.\n */\nexport function setSegment(depth: number, key: string, tree: Tree): void {\n // A guess about another page was wrong; the one about this page, if there\n // was one, is replaced by put() below - with the same tree, when the\n // prerender and the navigation read the same decoded payload, which is\n // what makes the update a reveal rather than a render.\n dropSpeculative(depth, key);\n put(depth, key, tree);\n\n const stale = [...depths.keys()].filter((d) => d > depth);\n for (const d of stale) depths.delete(d);\n\n notify(depth);\n for (const d of stale) notify(d);\n}\n\nfunction dropSpeculative(depth: number, except?: string): void {\n const state = depths.get(depth);\n\n if (!state?.entries.some((entry) => entry.speculative && entry.key !== except)) return;\n\n depths.set(depth, {\n ...state,\n entries: state.entries.filter((entry) => !entry.speculative || entry.key === except),\n });\n}\n\n/**\n * Render a page hidden at `depth`, before any navigation to it.\n *\n * The click then finds the work done: setSegment with the same tree is a\n * bail-out for React - same element, same props - and the Activity flips\n * from hidden to visible. What was 87 ms of rendering on a phone, after\n * the tap, is paid before the finger lifts, at idle priority, yielding to\n * the scroll. Never changes what is showing, never counts against\n * retention, and a page already held needs nothing.\n */\nexport function prerenderSegment(depth: number, key: string, tree: Tree): void {\n const state = depths.get(depth);\n\n // Nothing at this depth yet: the boundary is still showing the server's\n // children, and it has no page key to keep them under. A guess would take\n // the store over with no active entry to show. seedSegment runs on mount,\n // so this is the gap between hydration and that effect; the click will\n // render.\n if (!state) return;\n\n if (state.entries.some((entry) => entry.key === key)) return;\n\n depths.set(depth, {\n ...state,\n entries: [\n ...state.entries.filter((entry) => !entry.speculative),\n { key, tree, at: Date.now(), seq: ++tick, speculative: true },\n ],\n });\n\n notify(depth);\n}\n\n/** Whether a page is rendered hidden at `depth`, ahead of a navigation to it. */\nexport function isPrerendered(depth: number, key: string): boolean {\n return depths.get(depth)?.entries.some((entry) => entry.key === key && entry.speculative) ?? false;\n}\n\n/**\n * Give the page on screen at `depth` a new tree, under the key it has.\n *\n * For revalidate(\"all\"): the whole document rendered again, in place. The\n * root hands its layout the new tree, the layout hands its boundary new\n * children, and a boundary that holds state would otherwise keep showing\n * the store's tree and drop the new one on the floor - or, cleared first,\n * re-key its Activity to the current url and remount everything under it.\n * Neither. The entry that is showing takes the new tree and keeps its key,\n * so React reconciles the page in place, and the boundary below gets its\n * new children the same way.\n */\nexport function replaceActive(depth: number, tree: Tree): void {\n const state = depths.get(depth);\n\n if (!state) return;\n\n const active = state.entries.find((entry) => entry.key === state.activeKey);\n\n if (!active || active.tree === tree) return;\n\n // The tree changes; when the entry arrived does not. A layout's entry is\n // keyed by the page it was seeded with - \"/\" for a document loaded at\n // home - and stays active through every navigation below it. Stamped\n // with the re-render's time it read as held since the mutation, and a\n // tap on the brand link after \"Add to cart\" revealed it: the url went\n // to \"/\" and the product stayed, because the tree under that key was\n // now the product's document. See dropHidden and isHeld.\n depths.set(depth, {\n ...state,\n entries: state.entries.map((entry) => (entry === active ? { ...entry, tree } : entry)),\n });\n notify(depth);\n}\n\n/**\n * Record the children the server rendered, so the page you arrived on can be\n * returned to later. Never changes what is showing.\n */\nexport function seedSegment(depth: number, key: string, tree: Tree): void {\n const state = depths.get(depth);\n\n if (state?.entries.some((entry) => entry.key === key)) return;\n\n if (!state) {\n put(depth, key, tree);\n notify(depth);\n\n return;\n }\n\n // Older than whatever is showing, so it goes to the front of the eviction\n // order — and crucially does not become the active page.\n depths.set(\n depth,\n retain(\n [...state.entries, { key, tree, at: Date.now(), seq: ++tick }],\n [key, ...state.order.filter((k) => k !== key)],\n state.activeKey,\n ),\n );\n\n notify(depth);\n}\n\n/**\n * Reveal a page the boundaries are still holding, without asking the server.\n *\n * Restoring is anchored on the deepest boundary that can show the page. Deeper\n * ones than that belonged to the page being left — a section with its own\n * layout adds a boundary the page you are going back to never had — so they\n * are dropped, exactly as setSegment drops them. Requiring every boundary to\n * hold the key instead made any such page refuse to restore.\n *\n * Shallower boundaries need no key of their own: their trees contain the\n * deeper boundary, so they delegate to whatever it is showing. One that does\n * hold the key is switched to it, since that is a real change at its level.\n */\n/**\n * Whether a link to `key` would be answered by revealing a held page.\n *\n * The question restoreSegments answers, asked without acting on it: a\n * prefetch of a page the boundaries still hold is a request for nothing -\n * a navigation would reveal it. The page just left is the usual case, one\n * wasted payload per navigation.\n */\nexport function isHeld(key: string, maxAge?: number): boolean {\n const ages = [...depths.values()].flatMap((state) =>\n state.entries.filter((entry) => entry.key === key && !entry.speculative && entry.seq > invalidatedAt).map((entry) => entry.at),\n );\n\n if (ages.length === 0) return false;\n if (maxAge === undefined) return true;\n\n return Date.now() - Math.min(...ages) < maxAge;\n}\n\n/**\n * Drop every page held behind the one on screen.\n *\n * After a mutation: a page kept for the back button holds the data from\n * before it, and revealing it would show a row that is gone, a name that\n * changed. The page on screen stays - it was re-rendered by the action, or\n * is about to be.\n */\nexport function dropHidden(): void {\n // And the ones that stay - the active entry at each depth - are from\n // before it too. A layout's entry is keyed by the page it was seeded\n // with, and revealing that key later shows the page inside it as it was\n // then. Nothing seeded before this moment is revealed again.\n invalidatedAt = ++tick;\n\n for (const [depth, state] of depths) {\n if (state.entries.length <= 1 && !state.entries.some((entry) => entry.speculative)) continue;\n\n depths.set(depth, {\n entries: state.entries.filter((entry) => entry.key === state.activeKey),\n order: state.order.filter((key) => key === state.activeKey),\n activeKey: state.activeKey,\n });\n notify(depth);\n }\n}\n\n/**\n * Reveal a page still being held, if it is worth revealing.\n *\n * `maxAge` is what a link passes and the back button does not. Going back is\n * unambiguous — it names a moment, and the page from that moment is the right\n * answer however old. A link says \"go here\", and answering it with a tree from\n * twenty minutes ago is stale data presented as fresh, which is the objection\n * this design started with. Recent enough, and it is the same page you were\n * just on, with the form you were filling in still filled in.\n */\nexport function restoreSegments(key: string, maxAge?: number): boolean {\n // A guess is not a held page: revealing it would be showing prefetched\n // data as the page the visitor was on. The navigation takes the\n // prerendered tree through setSegment instead, where it is a reveal too.\n // Nor is a page from before a mutation - see dropHidden.\n const holding = [...depths.keys()].filter((d) =>\n depths.get(d)!.entries.some((entry) => entry.key === key && !entry.speculative && entry.seq > invalidatedAt),\n );\n\n if (holding.length === 0) return false;\n\n if (maxAge !== undefined) {\n const ages = holding.flatMap((d) =>\n depths\n .get(d)!\n .entries.filter((entry) => entry.key === key)\n .map((entry) => entry.at),\n );\n\n // The oldest layer decides: revealing a fresh page under a stale layout\n // would be a chain nobody rendered together.\n // >= rather than >, so a window of 0 means never rather than \"only within\n // the same millisecond\".\n if (Date.now() - Math.min(...ages) >= maxAge) return false;\n }\n\n const anchor = Math.max(...holding);\n\n for (const d of [...depths.keys()].filter((d) => d > anchor)) {\n depths.delete(d);\n notify(d);\n }\n\n for (const d of holding) {\n dropSpeculative(d);\n\n const state = depths.get(d)!;\n\n depths.set(\n d,\n retain(\n state.entries,\n [...state.order.filter((k) => k !== key), key],\n key,\n ),\n );\n notify(d);\n }\n\n return true;\n}\n\n/**\n * Drop everything, so boundaries fall back to their server-given children.\n *\n * A deployment invalidates them all: a segment from the previous build has no\n * claim on being correct for this one.\n */\nexport function clearSegments(): void {\n const all = [...depths.keys()];\n depths.clear();\n for (const depth of all) notify(depth);\n}\n\n/**\n * Whether a navigation has happened in this document.\n *\n * The first commit after hydration is the boundary taking over its\n * server-rendered children - the same page, re-keyed for retention. A view\n * transition for that commit fades the page into itself: the blank-then-\n * content a first load or a reload showed. Inertia transitions on visits and\n * never on load; so does this. The router notes the first navigation before\n * it updates a segment, and the boundary animates from then on.\n */\nlet navigated = false;\n\nexport function noteNavigation(): void {\n navigated = true;\n}\n\nexport function navigatedOnce(): boolean {\n return navigated;\n}\n"]}
1
+ {"version":3,"file":"segmentStore.js","sourceRoot":"","sources":["../../src/js/segmentStore.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What each segment boundary is showing, and what it is keeping alive behind it.\n *\n * A navigation replaces one segment. Keeping the previous one mounted — hidden,\n * not unmounted — is what lets going back restore it with its client state:\n * the half-typed form, the open disclosure, the scrolled list. Unmounting\n * throws all of that away, which is what replacing the root used to do.\n *\n * Entries are keyed by page (the URL, or its intercept variant), so a boundary\n * can hold several and reveal one. Empty is meaningful: a boundary with nothing\n * stored renders the children the server gave it.\n *\n * A store rather than state, and not a preference — three things rule state out.\n * A boundary is inserted between every layout level, so there are several and a\n * navigation targets one by depth; they are separated by server components, so\n * no setter can be threaded down to them, because a function does not cross\n * that boundary; and navigate.ts is a plain module with no component instance\n * to call one on. Addressing a component you hold no reference to is what an\n * external store is for.\n *\n * Underneath it is the wire protocol. A partial navigation sends only the\n * segment that changed — see the X-RSC-Segments headers — so there is nothing\n * for a root to re-render with even if it held the state. Next.js keeps its\n * router in useState and derives every segment from it; that is the same trade\n * in the other direction.\n *\n * What it costs: React pins an external store's updates to synchronous\n * priority, because a store cannot be safely time-sliced. Synchronous is never\n * a transition, and anything that only runs for one — React's <ViewTransition>\n * among them — never ran for a navigation.\n *\n * Which is why SegmentBoundary does not read this with useSyncExternalStore\n * any more. The store still does the addressing, which is the part only it can\n * do; the boundary copies into state, so the render is a transition. See the\n * view transitions guide.\n */\n\ntype Tree = unknown;\ntype Listener = () => void;\n\ninterface Entry {\n key: string;\n /**\n * The key React mounts this page under, when it is not `key`.\n *\n * `key` is what a navigation files the page under - its path and query, so\n * Back to ?q=a restores that page and not ?q=b. The identity is what keeps\n * it mounted, and it has to survive two things that are not a new page: a\n * page loaded with a query, which the server rendered under its pathname\n * alone (the shell was frozen that way), and a replace to the same path with\n * a new query - the first message of a chat - which leaves nothing to go\n * back to. A new identity is a remount, and a remount shows every Suspense\n * fallback in the page: a skeleton over the chat, on every reply.\n */\n identity?: string;\n tree: Tree;\n /**\n * When this tree arrived, so a link can decide whether it is still worth\n * revealing. The back button never asks — it means \"the page I was on\",\n * however long ago that was.\n */\n at: number;\n /**\n * Its place in the order things happened, for the question \"was this\n * here before the mutation?\" - which a clock answers wrongly for a seed\n * and a write in the same millisecond, and a test hit exactly that.\n */\n seq: number;\n /**\n * Rendered before the click, hidden, on the strength of a touch or a\n * settled hover - see prerenderSegment. Outside the retention window: it\n * is a guess, and a guess must not evict a page the visitor was on. One\n * per depth; the next guess replaces it, and a navigation to anything\n * else drops it.\n */\n speculative?: boolean;\n}\n\n/**\n * Immutable: useSyncExternalStore compares snapshots by identity, so a new\n * object per read reads as \"changed every render\" and loops forever. Every\n * mutation replaces this wholesale; nothing edits one in place.\n */\ninterface DepthState {\n readonly entries: readonly Entry[];\n readonly activeKey: string;\n /** Most recently shown last; eviction takes from the front. */\n readonly order: readonly string[];\n}\n\n/** Pages kept alive per boundary. Four covers ordinary back-and-forth. */\nexport const RETENTION = 4;\n\nconst depths = new Map<number, DepthState>();\n/** A counter every entry takes a number from, in order. */\nlet tick = 0;\n/** The number the last mutation took: everything held before it is wrong. */\nlet invalidatedAt = 0;\nconst listeners = new Map<number, Set<Listener>>();\n\nfunction notify(depth: number): void {\n for (const listener of listeners.get(depth) ?? []) listener();\n}\n\nexport function subscribeToSegment(\n depth: number,\n listener: Listener,\n): () => void {\n let set = listeners.get(depth);\n\n if (!set) {\n set = new Set();\n listeners.set(depth, set);\n }\n\n set.add(listener);\n\n return () => {\n set!.delete(listener);\n if (set!.size === 0) listeners.delete(depth);\n };\n}\n\n/** Everything a boundary at this depth needs to render, or null for \"use children\". */\nexport function getSegmentState(depth: number): DepthState | null {\n return depths.get(depth) ?? null;\n}\n\n/** Apply the retention window to a candidate state. */\nfunction retain(\n entries: readonly Entry[],\n order: readonly string[],\n activeKey: string,\n): DepthState {\n const kept = order.slice(-RETENTION);\n\n return {\n entries: entries.filter((entry) => kept.includes(entry.key) || entry.speculative),\n order: kept,\n activeKey,\n };\n}\n\nfunction put(depth: number, key: string, tree: Tree, identity?: string): void {\n const state = depths.get(depth);\n // The same page again keeps the identity it is mounted under.\n const kept = identity ?? state?.entries.find((entry) => entry.key === key)?.identity;\n const entries = [\n ...(state?.entries ?? []).filter((entry) => entry.key !== key),\n { key, tree, at: Date.now(), seq: ++tick, ...(kept !== undefined && kept !== key ? { identity: kept } : {}) },\n ];\n const order = [...(state?.order ?? []).filter((k) => k !== key), key];\n\n depths.set(depth, retain(entries, order, key));\n}\n\n/**\n * Show `tree` at `depth` for `key`, retaining what was there.\n *\n * Deeper segments belonged to the page being replaced; leaving them would\n * render the previous page inside the new one.\n */\nexport function setSegment(depth: number, key: string, tree: Tree, inPlaceOf?: string | null): void {\n // A guess about another page was wrong; the one about this page, if there\n // was one, is replaced by put() below - with the same tree, when the\n // prerender and the navigation read the same decoded payload, which is\n // what makes the update a reveal rather than a render.\n dropSpeculative(depth, key);\n\n // A replace to the same path with a new query: the page it replaces is gone\n // from history, so this is that page, moved - not a new one to mount beside\n // it. It takes the old entry's identity, and the old entry goes.\n const state = depths.get(depth);\n const replaced =\n inPlaceOf && inPlaceOf !== key && !state?.entries.some((entry) => entry.key === key)\n ? state?.entries.find((entry) => entry.key === inPlaceOf)\n : undefined;\n\n if (replaced && state) {\n depths.set(depth, {\n ...state,\n entries: state.entries.filter((entry) => entry !== replaced),\n order: state.order.filter((k) => k !== replaced.key),\n });\n }\n\n put(depth, key, tree, replaced ? (replaced.identity ?? replaced.key) : undefined);\n\n const stale = [...depths.keys()].filter((d) => d > depth);\n for (const d of stale) depths.delete(d);\n\n notify(depth);\n for (const d of stale) notify(d);\n}\n\nfunction dropSpeculative(depth: number, except?: string): void {\n const state = depths.get(depth);\n\n if (!state?.entries.some((entry) => entry.speculative && entry.key !== except)) return;\n\n depths.set(depth, {\n ...state,\n entries: state.entries.filter((entry) => !entry.speculative || entry.key === except),\n });\n}\n\n/**\n * Render a page hidden at `depth`, before any navigation to it.\n *\n * The click then finds the work done: setSegment with the same tree is a\n * bail-out for React - same element, same props - and the Activity flips\n * from hidden to visible. What was 87 ms of rendering on a phone, after\n * the tap, is paid before the finger lifts, at idle priority, yielding to\n * the scroll. Never changes what is showing, never counts against\n * retention, and a page already held needs nothing.\n */\nexport function prerenderSegment(depth: number, key: string, tree: Tree): void {\n const state = depths.get(depth);\n\n // Nothing at this depth yet: the boundary is still showing the server's\n // children, and it has no page key to keep them under. A guess would take\n // the store over with no active entry to show. seedSegment runs on mount,\n // so this is the gap between hydration and that effect; the click will\n // render.\n if (!state) return;\n\n if (state.entries.some((entry) => entry.key === key)) return;\n\n depths.set(depth, {\n ...state,\n entries: [\n ...state.entries.filter((entry) => !entry.speculative),\n { key, tree, at: Date.now(), seq: ++tick, speculative: true },\n ],\n });\n\n notify(depth);\n}\n\n/** Whether a page is rendered hidden at `depth`, ahead of a navigation to it. */\nexport function isPrerendered(depth: number, key: string): boolean {\n return depths.get(depth)?.entries.some((entry) => entry.key === key && entry.speculative) ?? false;\n}\n\n/**\n * Give the page on screen at `depth` a new tree, under the key it has.\n *\n * For revalidate(\"all\"): the whole document rendered again, in place. The\n * root hands its layout the new tree, the layout hands its boundary new\n * children, and a boundary that holds state would otherwise keep showing\n * the store's tree and drop the new one on the floor - or, cleared first,\n * re-key its Activity to the current url and remount everything under it.\n * Neither. The entry that is showing takes the new tree and keeps its key,\n * so React reconciles the page in place, and the boundary below gets its\n * new children the same way.\n */\nexport function replaceActive(depth: number, tree: Tree): void {\n const state = depths.get(depth);\n\n if (!state) return;\n\n const active = state.entries.find((entry) => entry.key === state.activeKey);\n\n if (!active || active.tree === tree) return;\n\n // The tree changes; when the entry arrived does not. A layout's entry is\n // keyed by the page it was seeded with - \"/\" for a document loaded at\n // home - and stays active through every navigation below it. Stamped\n // with the re-render's time it read as held since the mutation, and a\n // tap on the brand link after \"Add to cart\" revealed it: the url went\n // to \"/\" and the product stayed, because the tree under that key was\n // now the product's document. See dropHidden and isHeld.\n depths.set(depth, {\n ...state,\n entries: state.entries.map((entry) => (entry === active ? { ...entry, tree } : entry)),\n });\n notify(depth);\n}\n\n/**\n * Record the children the server rendered, so the page you arrived on can be\n * returned to later. Never changes what is showing.\n */\nexport function seedSegment(depth: number, key: string, tree: Tree, identity?: string): void {\n const state = depths.get(depth);\n\n if (state?.entries.some((entry) => entry.key === key)) return;\n\n if (!state) {\n put(depth, key, tree, identity);\n notify(depth);\n\n return;\n }\n\n // Older than whatever is showing, so it goes to the front of the eviction\n // order — and crucially does not become the active page.\n depths.set(\n depth,\n retain(\n [...state.entries, { key, tree, at: Date.now(), seq: ++tick, ...(identity !== undefined && identity !== key ? { identity } : {}) }],\n [key, ...state.order.filter((k) => k !== key)],\n state.activeKey,\n ),\n );\n\n notify(depth);\n}\n\n/**\n * Reveal a page the boundaries are still holding, without asking the server.\n *\n * Restoring is anchored on the deepest boundary that can show the page. Deeper\n * ones than that belonged to the page being left — a section with its own\n * layout adds a boundary the page you are going back to never had — so they\n * are dropped, exactly as setSegment drops them. Requiring every boundary to\n * hold the key instead made any such page refuse to restore.\n *\n * Shallower boundaries need no key of their own: their trees contain the\n * deeper boundary, so they delegate to whatever it is showing. One that does\n * hold the key is switched to it, since that is a real change at its level.\n */\n/**\n * Whether a link to `key` would be answered by revealing a held page.\n *\n * The question restoreSegments answers, asked without acting on it: a\n * prefetch of a page the boundaries still hold is a request for nothing -\n * a navigation would reveal it. The page just left is the usual case, one\n * wasted payload per navigation.\n */\nexport function isHeld(key: string, maxAge?: number): boolean {\n const ages = [...depths.values()].flatMap((state) =>\n state.entries.filter((entry) => entry.key === key && !entry.speculative && entry.seq > invalidatedAt).map((entry) => entry.at),\n );\n\n if (ages.length === 0) return false;\n if (maxAge === undefined) return true;\n\n return Date.now() - Math.min(...ages) < maxAge;\n}\n\n/**\n * Drop every page held behind the one on screen.\n *\n * After a mutation: a page kept for the back button holds the data from\n * before it, and revealing it would show a row that is gone, a name that\n * changed. The page on screen stays - it was re-rendered by the action, or\n * is about to be.\n */\nexport function dropHidden(): void {\n // And the ones that stay - the active entry at each depth - are from\n // before it too. A layout's entry is keyed by the page it was seeded\n // with, and revealing that key later shows the page inside it as it was\n // then. Nothing seeded before this moment is revealed again.\n invalidatedAt = ++tick;\n\n for (const [depth, state] of depths) {\n if (state.entries.length <= 1 && !state.entries.some((entry) => entry.speculative)) continue;\n\n depths.set(depth, {\n entries: state.entries.filter((entry) => entry.key === state.activeKey),\n order: state.order.filter((key) => key === state.activeKey),\n activeKey: state.activeKey,\n });\n notify(depth);\n }\n}\n\n/**\n * Reveal a page still being held, if it is worth revealing.\n *\n * `maxAge` is what a link passes and the back button does not. Going back is\n * unambiguous — it names a moment, and the page from that moment is the right\n * answer however old. A link says \"go here\", and answering it with a tree from\n * twenty minutes ago is stale data presented as fresh, which is the objection\n * this design started with. Recent enough, and it is the same page you were\n * just on, with the form you were filling in still filled in.\n */\nexport function restoreSegments(key: string, maxAge?: number): boolean {\n // A guess is not a held page: revealing it would be showing prefetched\n // data as the page the visitor was on. The navigation takes the\n // prerendered tree through setSegment instead, where it is a reveal too.\n // Nor is a page from before a mutation - see dropHidden.\n const holding = [...depths.keys()].filter((d) =>\n depths.get(d)!.entries.some((entry) => entry.key === key && !entry.speculative && entry.seq > invalidatedAt),\n );\n\n if (holding.length === 0) return false;\n\n if (maxAge !== undefined) {\n const ages = holding.flatMap((d) =>\n depths\n .get(d)!\n .entries.filter((entry) => entry.key === key)\n .map((entry) => entry.at),\n );\n\n // The oldest layer decides: revealing a fresh page under a stale layout\n // would be a chain nobody rendered together.\n // >= rather than >, so a window of 0 means never rather than \"only within\n // the same millisecond\".\n if (Date.now() - Math.min(...ages) >= maxAge) return false;\n }\n\n const anchor = Math.max(...holding);\n\n for (const d of [...depths.keys()].filter((d) => d > anchor)) {\n depths.delete(d);\n notify(d);\n }\n\n for (const d of holding) {\n dropSpeculative(d);\n\n const state = depths.get(d)!;\n\n depths.set(\n d,\n retain(\n state.entries,\n [...state.order.filter((k) => k !== key), key],\n key,\n ),\n );\n notify(d);\n }\n\n return true;\n}\n\n/**\n * Drop everything, so boundaries fall back to their server-given children.\n *\n * A deployment invalidates them all: a segment from the previous build has no\n * claim on being correct for this one.\n */\nexport function clearSegments(): void {\n const all = [...depths.keys()];\n depths.clear();\n for (const depth of all) notify(depth);\n}\n\n/**\n * Whether a navigation has happened in this document.\n *\n * The first commit after hydration is the boundary taking over its\n * server-rendered children - the same page, re-keyed for retention. A view\n * transition for that commit fades the page into itself: the blank-then-\n * content a first load or a reload showed. Inertia transitions on visits and\n * never on load; so does this. The router notes the first navigation before\n * it updates a segment, and the boundary animates from then on.\n */\nlet navigated = false;\n\nexport function noteNavigation(): void {\n navigated = true;\n}\n\nexport function navigatedOnce(): boolean {\n return navigated;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rsc-kit/core",
3
- "version": "0.22.5",
3
+ "version": "0.22.6",
4
4
  "description": "React Server Components as a Vite plugin. Routing, streaming, server actions, typed urls and build-time prerendering — deploy to Bun, Node, Workers, Vercel or Deno.",
5
5
  "license": "MIT",
6
6
  "type": "module",