@rsc-kit/core 0.16.3 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/dist/barrelImports.d.ts +6 -0
  2. package/dist/barrelImports.js +93 -0
  3. package/dist/barrelImports.js.map +1 -0
  4. package/dist/buildReport.d.ts +6 -1
  5. package/dist/buildReport.js +16 -18
  6. package/dist/buildReport.js.map +1 -1
  7. package/dist/cache.js +8 -4
  8. package/dist/cache.js.map +1 -1
  9. package/dist/clientEntries.d.ts +32 -0
  10. package/dist/clientEntries.js +107 -0
  11. package/dist/clientEntries.js.map +1 -0
  12. package/dist/clientImports.d.ts +36 -0
  13. package/dist/clientImports.js +36 -0
  14. package/dist/clientImports.js.map +1 -0
  15. package/dist/devReload.d.ts +19 -0
  16. package/dist/devReload.js +32 -0
  17. package/dist/devReload.js.map +1 -0
  18. package/dist/events.d.ts +57 -0
  19. package/dist/events.js +113 -0
  20. package/dist/events.js.map +1 -0
  21. package/dist/host.d.ts +16 -6
  22. package/dist/host.js +219 -124
  23. package/dist/host.js.map +1 -1
  24. package/dist/hostCalls.d.ts +27 -0
  25. package/dist/hostCalls.js +127 -12
  26. package/dist/hostCalls.js.map +1 -1
  27. package/dist/hostRouting.d.ts +53 -0
  28. package/dist/hostRouting.js +100 -0
  29. package/dist/hostRouting.js.map +1 -0
  30. package/dist/js/DefaultRouteError.d.ts +3 -0
  31. package/dist/js/DefaultRouteError.js +61 -0
  32. package/dist/js/DefaultRouteError.js.map +1 -0
  33. package/dist/js/Form.js +54 -6
  34. package/dist/js/Form.js.map +1 -1
  35. package/dist/js/Link.d.ts +0 -3
  36. package/dist/js/Link.js +3 -6
  37. package/dist/js/Link.js.map +1 -1
  38. package/dist/js/SegmentBoundary.d.ts +38 -2
  39. package/dist/js/SegmentBoundary.js +51 -13
  40. package/dist/js/SegmentBoundary.js.map +1 -1
  41. package/dist/js/createViteRscApp.js +32 -17
  42. package/dist/js/createViteRscApp.js.map +1 -1
  43. package/dist/js/devNotice.d.ts +2 -2
  44. package/dist/js/devNotice.js +17 -7
  45. package/dist/js/devNotice.js.map +1 -1
  46. package/dist/js/fallbackReport.d.ts +2 -0
  47. package/dist/js/fallbackReport.js +51 -0
  48. package/dist/js/fallbackReport.js.map +1 -0
  49. package/dist/js/navigate.d.ts +1 -1
  50. package/dist/js/navigate.js +55 -23
  51. package/dist/js/navigate.js.map +1 -1
  52. package/dist/js/queryClient.d.ts +2 -1
  53. package/dist/js/queryClient.js +0 -12
  54. package/dist/js/queryClient.js.map +1 -1
  55. package/dist/js/router.d.ts +2 -2
  56. package/dist/js/router.js.map +1 -1
  57. package/dist/js/segmentStore.d.ts +2 -0
  58. package/dist/js/segmentStore.js +21 -1
  59. package/dist/js/segmentStore.js.map +1 -1
  60. package/dist/js/staleAssets.js +10 -1
  61. package/dist/js/staleAssets.js.map +1 -1
  62. package/dist/js/standardSchema.d.ts +6 -0
  63. package/dist/js/standardSchema.js +19 -1
  64. package/dist/js/standardSchema.js.map +1 -1
  65. package/dist/js/useEvents.d.ts +25 -0
  66. package/dist/js/useEvents.js +78 -0
  67. package/dist/js/useEvents.js.map +1 -0
  68. package/dist/js/useLinkStatus.d.ts +14 -1
  69. package/dist/js/useLinkStatus.js +15 -1
  70. package/dist/js/useLinkStatus.js.map +1 -1
  71. package/dist/js/usePolling.d.ts +29 -0
  72. package/dist/js/usePolling.js +141 -0
  73. package/dist/js/usePolling.js.map +1 -0
  74. package/dist/manifest.d.ts +18 -1
  75. package/dist/manifest.js.map +1 -1
  76. package/dist/metadata.d.ts +94 -15
  77. package/dist/metadata.js.map +1 -1
  78. package/dist/metadataRoutes.d.ts +61 -0
  79. package/dist/metadataRoutes.js +173 -0
  80. package/dist/metadataRoutes.js.map +1 -0
  81. package/dist/prerender.js +44 -10
  82. package/dist/prerender.js.map +1 -1
  83. package/dist/reactCache.d.ts +1 -0
  84. package/dist/reactCache.js +52 -0
  85. package/dist/reactCache.js.map +1 -0
  86. package/dist/redirect.d.ts +16 -2
  87. package/dist/redirect.js +10 -19
  88. package/dist/redirect.js.map +1 -1
  89. package/dist/request.d.ts +18 -1
  90. package/dist/request.js +91 -5
  91. package/dist/request.js.map +1 -1
  92. package/dist/revalidate.d.ts +6 -4
  93. package/dist/revalidate.js +6 -5
  94. package/dist/revalidate.js.map +1 -1
  95. package/dist/routes.d.ts +16 -3
  96. package/dist/routes.js +5 -5
  97. package/dist/routes.js.map +1 -1
  98. package/dist/routing.d.ts +2 -2
  99. package/dist/routing.js +47 -25
  100. package/dist/routing.js.map +1 -1
  101. package/dist/useSsr.d.ts +19 -0
  102. package/dist/useSsr.js +104 -0
  103. package/dist/useSsr.js.map +1 -0
  104. package/dist/vite.d.ts +86 -9
  105. package/dist/vite.js +827 -24
  106. package/dist/vite.js.map +1 -1
  107. package/package.json +13 -1
@@ -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 { showDevNotice } from \"./devNotice\";\nimport type { Href } from \"../routes.js\";\nimport { isSafeRedirect } from \"../safeUrl.js\";\nimport {\n createFromReadableStream,\n encodeReply,\n setServerCallback,\n} from \"@vitejs/plugin-rsc/browser\";\nimport { createElement } from \"react\";\nimport { hydrateRoot } from \"react-dom/client\";\nimport { ActivityRoot } from \"./ActivityRouter\";\nimport { ServerRedirectError, throwForFailedAction } from \"./errors\";\nimport { fetchPagePayload } from \"./pagePayload\";\nimport { claimRead, setQueryCodec } from \"./queryClient\";\nimport { clearSegments, restoreSegments, setSegment } from \"./segmentStore\";\nimport type { ReactNode } from \"react\";\nimport {\n cancelPrefetch,\n isPrefetched,\n navigate,\n refresh,\n applyRevalidated,\n prefetch,\n retentionKey,\n setCallServer,\n setHeldLayouts,\n setStaticPayloads,\n setStaticRoutes,\n seedStaticChain,\n payloadUrl,\n setDeserializer,\n setInterceptManifest,\n setNavigateHandler,\n setRestoreHandler,\n setVersion,\n} from \"./navigate\";\n\nexport async function createViteRscApp(\n container: Document | Element = document,\n interceptEntries: { urlPattern: string; slot: string }[] = [],\n options: { staticPayloads?: string | null; routes?: unknown[] | null } = {},\n): Promise<void> {\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 const res = await fetch(\"/_rsc/action\", {\n method: \"POST\",\n headers: {\n \"X-RSC-Action\": id,\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.\n \"X-RSC-Referer\": window.location.pathname + window.location.search,\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.\n if (isSafeRedirect(err.location)) window.location.href = err.location;\n }\n\n throw err;\n }\n\n const answer = await createFromReadableStream(res.body!, { callServer });\n\n return unwrapRevalidated(answer);\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): 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 for (const [target, tree] of Object.entries(envelope.__rscRevalidated)) {\n applyRevalidated(target, tree);\n }\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 SPA engine with the build this page was served from, so a\n // redeploy mid-session is caught on the next navigation. This matters most\n // behind a CDN, where the shell may be cached from an older build.\n const servedVersion = 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 const root = hydrateRoot(container, shell, {\n onRecoverableError(error: unknown, errorInfo: unknown) {\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 // A stored page whose query string was read under a boundary carries\n // the fallback there, and React reports the recovery on hydration. It is\n // reported here too - the boundary is the developer's to move - but in\n // its own words: in production React sends only the digest, and the\n // generic message says nothing about which read, or where.\n if (\n (error as { digest?: string })?.digest === SEARCH_PARAMS_FALLBACK &&\n !message.includes(\"useSearchParams()\")\n ) {\n const hint =\n \"useSearchParams() was read while rendering on the server, where there is no query string to give. \" +\n \"The fallback was stored and the real value rendered here. Wrap the component in <Suspense> \" +\n \"- or add a loading.tsx beside the page - closer to the read, so less of the page waits for it.\";\n\n showDevNotice(\n hint,\n (errorInfo as { componentStack?: string } | null)?.componentStack,\n );\n console.error(new Error(hint), errorInfo);\n\n return;\n }\n\n // In development React's message carries the server's own text; the\n // page shows it too, for whoever is looking at the page and not the\n // console.\n if (message.includes(\"useSearchParams()\")) {\n showDevNotice(\n message.replace(/^.*?(?=useSearchParams\\(\\))/s, \"\"),\n (errorInfo as { componentStack?: string } | null)?.componentStack,\n );\n }\n\n console.error(error, errorInfo);\n },\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\n console.error(error, errorInfo);\n },\n });\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 if (segmentDepth > 0) {\n setSegment(segmentDepth, key, newTree);\n\n return;\n }\n\n clearSegments();\n root.render(newTree);\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\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 Href, { replace: true, restore: true });\n });\n\n history.replaceState(\n { rscUrl: window.location.href },\n \"\",\n window.location.href,\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 { showDevNotice } from \"./devNotice\";\nimport { caughtByLoading } from \"./fallbackReport\";\nimport { noteNavigation } from \"./segmentStore\";\nimport type { Href } from \"../routes.js\";\nimport { isSafeRedirect } from \"../safeUrl.js\";\nimport {\n createFromReadableStream,\n encodeReply,\n setServerCallback,\n} from \"@vitejs/plugin-rsc/browser\";\nimport { createElement } from \"react\";\nimport { hydrateRoot } from \"react-dom/client\";\nimport { ActivityRoot } from \"./ActivityRouter\";\nimport { ServerRedirectError, throwForFailedAction } from \"./errors\";\nimport { fetchPagePayload } from \"./pagePayload\";\nimport { claimRead, setQueryCodec } from \"./queryClient\";\nimport { clearSegments, restoreSegments, setSegment } from \"./segmentStore\";\nimport type { ReactNode } from \"react\";\nimport {\n cancelPrefetch,\n isPrefetched,\n navigate,\n refresh,\n applyRevalidated,\n prefetch,\n retentionKey,\n setCallServer,\n setHeldLayouts,\n setStaticPayloads,\n setStaticRoutes,\n seedStaticChain,\n payloadUrl,\n setDeserializer,\n setInterceptManifest,\n setNavigateHandler,\n setRestoreHandler,\n setVersion,\n} from \"./navigate\";\n\nexport async function createViteRscApp(\n container: Document | Element = document,\n interceptEntries: { urlPattern: string; slot: string }[] = [],\n options: { staticPayloads?: string | null; routes?: unknown[] | null } = {},\n): Promise<void> {\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 const res = await fetch(\"/_rsc/action\", {\n method: \"POST\",\n headers: {\n \"X-RSC-Action\": id,\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.\n \"X-RSC-Referer\": window.location.pathname + window.location.search,\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.\n if (isSafeRedirect(err.location)) window.location.href = err.location;\n }\n\n throw err;\n }\n\n const answer = await createFromReadableStream(res.body!, { callServer });\n\n return unwrapRevalidated(answer);\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): 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 for (const [target, tree] of Object.entries(envelope.__rscRevalidated)) {\n applyRevalidated(target, tree);\n }\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 SPA engine with the build this page was served from, so a\n // redeploy mid-session is caught on the next navigation. This matters most\n // behind a CDN, where the shell may be cached from an older build.\n const servedVersion = 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 const root = hydrateRoot(container, shell, {\n 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 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 // 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 // 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\n console.error(error, errorInfo);\n },\n });\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 // 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\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 Href, { replace: true, restore: true });\n });\n\n history.replaceState(\n { rscUrl: window.location.href },\n \"\",\n window.location.href,\n );\n}\n"]}
@@ -4,8 +4,8 @@
4
4
  * The dev server prints the boundary the build will want, and the browser
5
5
  * console reports it; the person looking at the page sees neither. Next.js
6
6
  * shows a small badge for the same reason. This is that: fixed to the bottom
7
- * of the viewport, the message and the component it came from, gone on a
8
- * click. Nothing here reaches a production bundle - the DEV check is a
7
+ * of the viewport, the message and the component it came from, with a
8
+ * button to dismiss it. Nothing here reaches a production bundle - the DEV check is a
9
9
  * constant at build time and the code behind it is dropped.
10
10
  */
11
11
  /** The first component in a React component stack: `at AuthTrigger (...)` → `AuthTrigger`. */
@@ -4,8 +4,8 @@
4
4
  * The dev server prints the boundary the build will want, and the browser
5
5
  * console reports it; the person looking at the page sees neither. Next.js
6
6
  * shows a small badge for the same reason. This is that: fixed to the bottom
7
- * of the viewport, the message and the component it came from, gone on a
8
- * click. Nothing here reaches a production bundle - the DEV check is a
7
+ * of the viewport, the message and the component it came from, with a
8
+ * button to dismiss it. Nothing here reaches a production bundle - the DEV check is a
9
9
  * constant at build time and the code behind it is dropped.
10
10
  */
11
11
  const ID = "rsc-kit-dev-notice";
@@ -27,15 +27,25 @@ export function showDevNotice(message, componentStack) {
27
27
  box.style.cssText =
28
28
  "position:fixed;left:12px;right:12px;bottom:12px;z-index:2147483647;" +
29
29
  "font:12px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace;color:#fff;background:#b91c1c;" +
30
- "border-radius:6px;padding:10px 36px 10px 14px;box-shadow:0 4px 16px rgba(0,0,0,.35);" +
31
- "max-height:40vh;overflow:auto;white-space:pre-wrap;cursor:pointer";
32
- box.title = "rsc-kit · click to dismiss";
33
- box.addEventListener("click", () => box?.remove());
30
+ "border-radius:6px;padding:10px 40px 10px 14px;box-shadow:0 4px 16px rgba(0,0,0,.35);" +
31
+ "max-height:40vh;overflow:auto;white-space:pre-wrap;user-select:text";
32
+ // A button, not a click anywhere: the text is there to be selected and
33
+ // copied, and a box that vanishes on the first click cannot be.
34
+ const close = document.createElement("button");
35
+ close.type = "button";
36
+ close.textContent = "\u00d7";
37
+ close.setAttribute("aria-label", "Dismiss");
38
+ close.title = "Dismiss";
39
+ close.style.cssText =
40
+ "position:absolute;top:6px;right:8px;border:0;background:transparent;color:#fff;" +
41
+ "font:16px/1 ui-monospace,SFMono-Regular,Menlo,monospace;cursor:pointer;padding:4px 6px";
42
+ close.addEventListener("click", () => box?.remove());
43
+ box.appendChild(close);
34
44
  document.body.appendChild(box);
35
45
  }
36
46
  // The same line twice is one problem, not two.
37
47
  for (const line of Array.from(box.children)) {
38
- if (line.textContent === text)
48
+ if (line.tagName !== "BUTTON" && line.textContent === text)
39
49
  return;
40
50
  }
41
51
  const line = document.createElement("div");
@@ -1 +1 @@
1
- {"version":3,"file":"devNotice.js","sourceRoot":"","sources":["../../src/js/devNotice.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,EAAE,GAAG,oBAAoB,CAAC;AAEhC,8FAA8F;AAC9F,MAAM,UAAU,WAAW,CACzB,cAAyC;IAEzC,MAAM,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC;IAE5D,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,OAAe,EACf,cAA8B;IAE9B,IAAI,CAAC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,OAAO,QAAQ,KAAK,WAAW;QAAE,OAAO;IAErE,MAAM,KAAK,GAAG,WAAW,CAAC,cAAc,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC;IAEnD,IAAI,GAAG,GAAG,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;IAEtC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACpC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC;QACZ,GAAG,CAAC,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACnC,GAAG,CAAC,KAAK,CAAC,OAAO;YACf,qEAAqE;gBACrE,0FAA0F;gBAC1F,sFAAsF;gBACtF,mEAAmE,CAAC;QACtE,GAAG,CAAC,KAAK,GAAG,4BAA4B,CAAC;QACzC,GAAG,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;QACnD,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;IAED,+CAA+C;IAC/C,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5C,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI;YAAE,OAAO;IACxC,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAE3C,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IACxB,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC","sourcesContent":["/**\n * A line at the bottom of the page, in development only.\n *\n * The dev server prints the boundary the build will want, and the browser\n * console reports it; the person looking at the page sees neither. Next.js\n * shows a small badge for the same reason. This is that: fixed to the bottom\n * of the viewport, the message and the component it came from, gone on a\n * click. Nothing here reaches a production bundle - the DEV check is a\n * constant at build time and the code behind it is dropped.\n */\n\nconst ID = \"rsc-kit-dev-notice\";\n\n/** The first component in a React component stack: `at AuthTrigger (...)` → `AuthTrigger`. */\nexport function componentIn(\n componentStack: string | undefined | null,\n): string | null {\n const match = /at ([A-Z][\\w$]*)/.exec(componentStack ?? \"\");\n\n return match ? match[1]! : null;\n}\n\nexport function showDevNotice(\n message: string,\n componentStack?: string | null,\n): void {\n if (!import.meta.env?.DEV || typeof document === \"undefined\") return;\n\n const where = componentIn(componentStack);\n const text = (where ? `${where}: ` : \"\") + message;\n\n let box = document.getElementById(ID);\n\n if (!box) {\n box = document.createElement(\"div\");\n box.id = ID;\n box.setAttribute(\"role\", \"status\");\n box.style.cssText =\n \"position:fixed;left:12px;right:12px;bottom:12px;z-index:2147483647;\" +\n \"font:12px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace;color:#fff;background:#b91c1c;\" +\n \"border-radius:6px;padding:10px 36px 10px 14px;box-shadow:0 4px 16px rgba(0,0,0,.35);\" +\n \"max-height:40vh;overflow:auto;white-space:pre-wrap;cursor:pointer\";\n box.title = \"rsc-kit · click to dismiss\";\n box.addEventListener(\"click\", () => box?.remove());\n document.body.appendChild(box);\n }\n\n // The same line twice is one problem, not two.\n for (const line of Array.from(box.children)) {\n if (line.textContent === text) return;\n }\n\n const line = document.createElement(\"div\");\n\n line.textContent = text;\n box.appendChild(line);\n}\n"]}
1
+ {"version":3,"file":"devNotice.js","sourceRoot":"","sources":["../../src/js/devNotice.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,EAAE,GAAG,oBAAoB,CAAC;AAEhC,8FAA8F;AAC9F,MAAM,UAAU,WAAW,CACzB,cAAyC;IAEzC,MAAM,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC;IAE5D,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,OAAe,EACf,cAA8B;IAE9B,IAAI,CAAC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,OAAO,QAAQ,KAAK,WAAW;QAAE,OAAO;IAErE,MAAM,KAAK,GAAG,WAAW,CAAC,cAAc,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC;IAEnD,IAAI,GAAG,GAAG,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;IAEtC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACpC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC;QACZ,GAAG,CAAC,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACnC,GAAG,CAAC,KAAK,CAAC,OAAO;YACf,qEAAqE;gBACrE,0FAA0F;gBAC1F,sFAAsF;gBACtF,qEAAqE,CAAC;QAExE,uEAAuE;QACvE,gEAAgE;QAChE,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAE/C,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC;QACtB,KAAK,CAAC,WAAW,GAAG,QAAQ,CAAC;QAC7B,KAAK,CAAC,YAAY,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;QAC5C,KAAK,CAAC,KAAK,GAAG,SAAS,CAAC;QACxB,KAAK,CAAC,KAAK,CAAC,OAAO;YACjB,iFAAiF;gBACjF,wFAAwF,CAAC;QAC3F,KAAK,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;QACrD,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACvB,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;IAED,+CAA+C;IAC/C,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5C,IAAI,IAAI,CAAC,OAAO,KAAK,QAAQ,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI;YAAE,OAAO;IACrE,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAE3C,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IACxB,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC","sourcesContent":["/**\n * A line at the bottom of the page, in development only.\n *\n * The dev server prints the boundary the build will want, and the browser\n * console reports it; the person looking at the page sees neither. Next.js\n * shows a small badge for the same reason. This is that: fixed to the bottom\n * of the viewport, the message and the component it came from, with a\n * button to dismiss it. Nothing here reaches a production bundle - the DEV check is a\n * constant at build time and the code behind it is dropped.\n */\n\nconst ID = \"rsc-kit-dev-notice\";\n\n/** The first component in a React component stack: `at AuthTrigger (...)` → `AuthTrigger`. */\nexport function componentIn(\n componentStack: string | undefined | null,\n): string | null {\n const match = /at ([A-Z][\\w$]*)/.exec(componentStack ?? \"\");\n\n return match ? match[1]! : null;\n}\n\nexport function showDevNotice(\n message: string,\n componentStack?: string | null,\n): void {\n if (!import.meta.env?.DEV || typeof document === \"undefined\") return;\n\n const where = componentIn(componentStack);\n const text = (where ? `${where}: ` : \"\") + message;\n\n let box = document.getElementById(ID);\n\n if (!box) {\n box = document.createElement(\"div\");\n box.id = ID;\n box.setAttribute(\"role\", \"status\");\n box.style.cssText =\n \"position:fixed;left:12px;right:12px;bottom:12px;z-index:2147483647;\" +\n \"font:12px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace;color:#fff;background:#b91c1c;\" +\n \"border-radius:6px;padding:10px 40px 10px 14px;box-shadow:0 4px 16px rgba(0,0,0,.35);\" +\n \"max-height:40vh;overflow:auto;white-space:pre-wrap;user-select:text\";\n\n // A button, not a click anywhere: the text is there to be selected and\n // copied, and a box that vanishes on the first click cannot be.\n const close = document.createElement(\"button\");\n\n close.type = \"button\";\n close.textContent = \"\\u00d7\";\n close.setAttribute(\"aria-label\", \"Dismiss\");\n close.title = \"Dismiss\";\n close.style.cssText =\n \"position:absolute;top:6px;right:8px;border:0;background:transparent;color:#fff;\" +\n \"font:16px/1 ui-monospace,SFMono-Regular,Menlo,monospace;cursor:pointer;padding:4px 6px\";\n close.addEventListener(\"click\", () => box?.remove());\n box.appendChild(close);\n document.body.appendChild(box);\n }\n\n // The same line twice is one problem, not two.\n for (const line of Array.from(box.children)) {\n if (line.tagName !== \"BUTTON\" && line.textContent === text) return;\n }\n\n const line = document.createElement(\"div\");\n\n line.textContent = text;\n box.appendChild(line);\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export declare function caughtByLoading(componentStack: string | null | undefined): boolean;
2
+ export declare function cancelledByConsumer(error: unknown): boolean;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Whether a read React caught at a boundary fell through to a loading.tsx.
3
+ *
4
+ * A component that reads the query string under a <Suspense> the developer
5
+ * wrote is the designed path: the fallback is stored, the browser fills it,
6
+ * and nothing needs saying. The same read with nothing closer than a
7
+ * loading.tsx - a boundary the engine put there for the whole segment - is
8
+ * worth a line, because the whole segment shows the fallback until the query
9
+ * arrives, and a boundary closer to the read would keep the rest painted.
10
+ *
11
+ * The component stack says which: frames run from the component outward,
12
+ * and the engine's segment boundaries render through SegmentBoundary or
13
+ * SlotBoundary, so the frame just outside the nearest Suspense tells whose
14
+ * it is. Only development has the stack; production reports nothing here,
15
+ * and the build's own note or warning on the route is the record.
16
+ */
17
+ const ENGINE_BOUNDARY = /^\s*at (SegmentBoundary|SlotBoundary)\b/;
18
+ export function caughtByLoading(componentStack) {
19
+ const frames = (componentStack ?? "")
20
+ .split("\n")
21
+ .filter((line) => /^\s*at /.test(line));
22
+ const at = frames.findIndex((line) => /^\s*at Suspense\b/.test(line));
23
+ if (at === -1)
24
+ return false;
25
+ return frames
26
+ .slice(at + 1, at + 3)
27
+ .some((line) => ENGINE_BOUNDARY.test(line));
28
+ }
29
+ /**
30
+ * Whether a render error is the consumer cancelling, not the app failing.
31
+ *
32
+ * React's server renderer reports an abort as an error, and the reason it
33
+ * gives when the stream was simply cancelled - a browser that left the page
34
+ * mid-stream, a prefetch abandoned, a proxy that closed - is its own fixed
35
+ * message. Logged, it reads as a fault in the page, and the page had none:
36
+ * "[rsc-kit:ssr] Error: The render was aborted by the server without a
37
+ * reason." on a dev console, every so often, for nothing. The same message
38
+ * from the payload renderer means the same thing.
39
+ */
40
+ const CANCELLED = /^The render was aborted by the server (?:without a reason|with a promise)\.$/;
41
+ export function cancelledByConsumer(error) {
42
+ if (error instanceof DOMException)
43
+ return error.name === "AbortError";
44
+ const message = typeof error === "object" && error !== null && "message" in error
45
+ ? String(error.message)
46
+ : typeof error === "string"
47
+ ? error
48
+ : "";
49
+ return CANCELLED.test(message);
50
+ }
51
+ //# sourceMappingURL=fallbackReport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallbackReport.js","sourceRoot":"","sources":["../../src/js/fallbackReport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,eAAe,GAAG,yCAAyC,CAAC;AAElE,MAAM,UAAU,eAAe,CAC7B,cAAyC;IAEzC,MAAM,MAAM,GAAG,CAAC,cAAc,IAAI,EAAE,CAAC;SAClC,KAAK,CAAC,IAAI,CAAC;SACX,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1C,MAAM,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAEtE,IAAI,EAAE,KAAK,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAE5B,OAAO,MAAM;SACV,KAAK,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;SACrB,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAChD,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,SAAS,GACb,8EAA8E,CAAC;AAEjF,MAAM,UAAU,mBAAmB,CAAC,KAAc;IAChD,IAAI,KAAK,YAAY,YAAY;QAAE,OAAO,KAAK,CAAC,IAAI,KAAK,YAAY,CAAC;IAEtE,MAAM,OAAO,GACX,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,SAAS,IAAI,KAAK;QAC/D,CAAC,CAAC,MAAM,CAAE,KAA8B,CAAC,OAAO,CAAC;QACjD,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ;YACzB,CAAC,CAAC,KAAK;YACP,CAAC,CAAC,EAAE,CAAC;IAEX,OAAO,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC","sourcesContent":["/**\n * Whether a read React caught at a boundary fell through to a loading.tsx.\n *\n * A component that reads the query string under a <Suspense> the developer\n * wrote is the designed path: the fallback is stored, the browser fills it,\n * and nothing needs saying. The same read with nothing closer than a\n * loading.tsx - a boundary the engine put there for the whole segment - is\n * worth a line, because the whole segment shows the fallback until the query\n * arrives, and a boundary closer to the read would keep the rest painted.\n *\n * The component stack says which: frames run from the component outward,\n * and the engine's segment boundaries render through SegmentBoundary or\n * SlotBoundary, so the frame just outside the nearest Suspense tells whose\n * it is. Only development has the stack; production reports nothing here,\n * and the build's own note or warning on the route is the record.\n */\nconst ENGINE_BOUNDARY = /^\\s*at (SegmentBoundary|SlotBoundary)\\b/;\n\nexport function caughtByLoading(\n componentStack: string | null | undefined,\n): boolean {\n const frames = (componentStack ?? \"\")\n .split(\"\\n\")\n .filter((line) => /^\\s*at /.test(line));\n const at = frames.findIndex((line) => /^\\s*at Suspense\\b/.test(line));\n\n if (at === -1) return false;\n\n return frames\n .slice(at + 1, at + 3)\n .some((line) => ENGINE_BOUNDARY.test(line));\n}\n\n/**\n * Whether a render error is the consumer cancelling, not the app failing.\n *\n * React's server renderer reports an abort as an error, and the reason it\n * gives when the stream was simply cancelled - a browser that left the page\n * mid-stream, a prefetch abandoned, a proxy that closed - is its own fixed\n * message. Logged, it reads as a fault in the page, and the page had none:\n * \"[rsc-kit:ssr] Error: The render was aborted by the server without a\n * reason.\" on a dev console, every so often, for nothing. The same message\n * from the payload renderer means the same thing.\n */\nconst CANCELLED =\n /^The render was aborted by the server (?:without a reason|with a promise)\\.$/;\n\nexport function cancelledByConsumer(error: unknown): boolean {\n if (error instanceof DOMException) return error.name === \"AbortError\";\n\n const message =\n typeof error === \"object\" && error !== null && \"message\" in error\n ? String((error as { message: unknown }).message)\n : typeof error === \"string\"\n ? error\n : \"\";\n\n return CANCELLED.test(message);\n}\n"]}
@@ -5,7 +5,7 @@
5
5
  * The Flight deserializer is injected by createViteRscApp to avoid
6
6
  * duplicate bundling of react-server-dom-webpack.
7
7
  */
8
- import type { Href } from '../routes.js';
8
+ import type { Href } from "../routes.js";
9
9
  import type { ManifestRoute } from "../manifest";
10
10
  type ReactNode = unknown;
11
11
  type Deserializer = (stream: ReadableStream, options: Record<string, unknown>) => Promise<ReactNode>;
@@ -5,12 +5,13 @@
5
5
  * The Flight deserializer is injected by createViteRscApp to avoid
6
6
  * duplicate bundling of react-server-dom-webpack.
7
7
  */
8
- import { isSafeRedirect } from '../safeUrl.js';
8
+ import { isStaleAssetError } from "./staleAssets";
9
+ import { isSafeRedirect } from "../safeUrl.js";
9
10
  import { reportReachable } from "./onlineStore";
10
11
  import { clearSlots, setSlot } from "./slotStore";
11
12
  // Shared with the host: it stores a page under this key and the client looks
12
13
  // under it, so the format cannot live in two places.
13
- import { matchRoute, retentionKey as retentionKeyFor, sharedDepth } from "../routing";
14
+ import { matchRoute, retentionKey as retentionKeyFor, sharedDepth, } from "../routing";
14
15
  let version = "";
15
16
  let onNavigate = null;
16
17
  let onRestore = null;
@@ -278,7 +279,11 @@ priority = "high") {
278
279
  }
279
280
  // `priority` is not in every lib.dom yet; browsers without it ignore it.
280
281
  const asked = staticSegments(url, chain);
281
- const request = fetch(payloadUrl(url, chain), { headers, signal, priority }).catch((err) => {
282
+ const request = fetch(payloadUrl(url, chain), {
283
+ headers,
284
+ signal,
285
+ priority,
286
+ }).catch((err) => {
282
287
  // Nothing answered at all. An abort is our own doing, not the network's —
283
288
  // leaving a link cancels its prefetch, and that must not read as offline.
284
289
  if (!(err instanceof DOMException && err.name === "AbortError")) {
@@ -304,7 +309,9 @@ priority = "high") {
304
309
  const location = response.headers.get("X-RSC-Location");
305
310
  // Server-chosen, so checked again here: the engine refuses these at the
306
311
  // source, but a host in front of it can put anything on the header.
307
- window.location.href = isSafeRedirect(location ?? url) ? (location ?? url) : url;
312
+ window.location.href = isSafeRedirect(location ?? url)
313
+ ? (location ?? url)
314
+ : url;
308
315
  throw new Error("Version mismatch — full reload triggered");
309
316
  }
310
317
  return response;
@@ -320,14 +327,15 @@ priority = "high") {
320
327
  */
321
328
  function deserializeResponse(response) {
322
329
  return flightDeserializer(response.body, {
323
- callServer: callServerFn ?? (async () => {
324
- throw new Error("Server actions not initialized");
325
- }),
330
+ callServer: callServerFn ??
331
+ (async () => {
332
+ throw new Error("Server actions not initialized");
333
+ }),
326
334
  });
327
335
  }
328
336
  function isExternalUrl(url) {
329
337
  try {
330
- return new URL(url, window.location.origin).origin !== window.location.origin;
338
+ return (new URL(url, window.location.origin).origin !== window.location.origin);
331
339
  }
332
340
  catch {
333
341
  return false;
@@ -458,9 +466,13 @@ export async function navigate(url, opts) {
458
466
  // revealing the page underneath instead leaves the modal sitting over a page
459
467
  // whose url has already changed.
460
468
  const mayReveal = opts?.restore === true ||
461
- (!askingForThisPage && !interceptSlot && interceptedOver === null && interceptedAtDepth === null);
469
+ (!askingForThisPage &&
470
+ !interceptSlot &&
471
+ interceptedOver === null &&
472
+ interceptedAtDepth === null);
462
473
  // Unbounded for the back button, bounded for a link.
463
- if (mayReveal && onRestore?.(activityKey, opts?.restore ? undefined : revealWithin)) {
474
+ if (mayReveal &&
475
+ onRestore?.(activityKey, opts?.restore ? undefined : revealWithin)) {
464
476
  // A restored tree carries its own slot contents, so the flag only has to
465
477
  // reflect whether what is now showing is an intercepted view.
466
478
  if (!interceptSlot)
@@ -525,18 +537,23 @@ export async function navigate(url, opts) {
525
537
  // replace: the url that redirected never became a page the user was
526
538
  // on, so Back must not return to it and redirect again.
527
539
  // Chosen by the server, not written here.
528
- await navigate(redirectTo, { replace: true, redirectsFollowed: redirectsFollowed + 1 });
540
+ await navigate(redirectTo, {
541
+ replace: true,
542
+ redirectsFollowed: redirectsFollowed + 1,
543
+ });
529
544
  return;
530
545
  }
531
546
  const contentType = response.headers.get("Content-Type") ?? "";
532
- if (staticPayloadSuffix === null && !contentType.includes("text/x-component")) {
547
+ if (staticPayloadSuffix === null &&
548
+ !contentType.includes("text/x-component")) {
533
549
  window.location.href = url;
534
550
  return;
535
551
  }
536
552
  // Headers on a server; worked out locally on a static host, where there
537
553
  // is nothing to send them.
538
554
  const served = staticFetches.get(response) ?? null;
539
- segmentDepth = Number(response.headers.get("X-RSC-Segment-Depth") ?? served?.depth ?? 0) || 0;
555
+ segmentDepth =
556
+ Number(response.headers.get("X-RSC-Segment-Depth") ?? served?.depth ?? 0) || 0;
540
557
  // Named region rather than a segment — see the apply below.
541
558
  slotPayload = response.headers.get("X-RSC-Revalidate");
542
559
  const servedLayouts = response.headers.get("X-RSC-Layouts");
@@ -592,6 +609,12 @@ export async function navigate(url, opts) {
592
609
  catch (err) {
593
610
  if (err instanceof DOMException && err.name === "AbortError")
594
611
  return;
612
+ // A chunk the deploy no longer serves: the browser would have loaded the
613
+ // document, and the new names with it. Do what it would have done.
614
+ if (isStaleAssetError(err)) {
615
+ window.location.href = url;
616
+ return;
617
+ }
595
618
  // Without this a navigation that fails does nothing observable: the click
596
619
  // clears its own pending state and the page stays as it was, with no
597
620
  // error, no fallback and nothing for an app to react to. Dispatched before
@@ -615,12 +638,12 @@ export async function navigate(url, opts) {
615
638
  export function applyRevalidated(target, tree) {
616
639
  const url = window.location.pathname + window.location.search;
617
640
  const key = retentionKey(url, null);
618
- if (target === 'all') {
641
+ if (target === "all") {
619
642
  // Depth 0 replaces the root, which is what re-rendering the layouts means.
620
643
  onNavigate?.(tree, key, 0);
621
644
  return;
622
645
  }
623
- if (target === 'page') {
646
+ if (target === "page") {
624
647
  onNavigate?.(tree, key, heldLayouts.length);
625
648
  return;
626
649
  }
@@ -643,11 +666,15 @@ export function applyRevalidated(target, tree) {
643
666
  * form leaves the layouts alone, which is what makes it cheap and also why a
644
667
  * count living in a layout will not move until you ask for 'all'.
645
668
  */
646
- export async function refresh(target = 'page') {
669
+ export async function refresh(target = "page") {
647
670
  const url = window.location.pathname + window.location.search;
648
- if (target !== 'page' && target !== 'all') {
671
+ if (target !== "page" && target !== "all") {
649
672
  const response = await fetch(payloadUrl(url), {
650
- headers: { "X-RSC": "true", "X-RSC-Version": version, "X-RSC-Revalidate": target },
673
+ headers: {
674
+ "X-RSC": "true",
675
+ "X-RSC-Version": version,
676
+ "X-RSC-Revalidate": target,
677
+ },
651
678
  });
652
679
  if (!response.ok) {
653
680
  throw new Error(`Could not revalidate ${target}: the server answered ${response.status}`);
@@ -660,7 +687,7 @@ export async function refresh(target = 'page') {
660
687
  // Never from the cache: refreshing asks what the server says now, not what
661
688
  // it said a moment ago.
662
689
  cache.delete(cacheKey);
663
- if (target === 'all') {
690
+ if (target === "all") {
664
691
  heldLayouts = [];
665
692
  }
666
693
  // A refresh is not a navigation: the same page stays under the reader, so
@@ -679,7 +706,7 @@ export async function refresh(target = 'page') {
679
706
  }
680
707
  /** Every element that can scroll, whether or not it currently is. */
681
708
  function scrollables() {
682
- return [...document.querySelectorAll('*')].filter((el) => el.scrollHeight > el.clientHeight || el.scrollWidth > el.clientWidth);
709
+ return [...document.querySelectorAll("*")].filter((el) => el.scrollHeight > el.clientHeight || el.scrollWidth > el.clientWidth);
683
710
  }
684
711
  /**
685
712
  * Where everything on the page is scrolled to, in document order.
@@ -697,8 +724,12 @@ function scrollables() {
697
724
  */
698
725
  function scrollPositions() {
699
726
  return [
700
- { tag: 'window', top: window.scrollY, left: window.scrollX },
701
- ...scrollables().map((el) => ({ tag: el.tagName, top: el.scrollTop, left: el.scrollLeft })),
727
+ { tag: "window", top: window.scrollY, left: window.scrollX },
728
+ ...scrollables().map((el) => ({
729
+ tag: el.tagName,
730
+ top: el.scrollTop,
731
+ left: el.scrollLeft,
732
+ })),
702
733
  ];
703
734
  }
704
735
  /**
@@ -789,7 +820,8 @@ function prefetchUrl(cacheKey, url, ttl, interceptSlot, refererUrl) {
789
820
  }
790
821
  entry.slot = response.headers.get("X-RSC-Revalidate");
791
822
  const local = staticFetches.get(response) ?? null;
792
- entry.segmentDepth = Number(response.headers.get("X-RSC-Segment-Depth") ?? local?.depth ?? 0) || 0;
823
+ entry.segmentDepth =
824
+ Number(response.headers.get("X-RSC-Segment-Depth") ?? local?.depth ?? 0) || 0;
793
825
  const served = response.headers.get("X-RSC-Layouts");
794
826
  if (served !== null) {
795
827
  entry.layouts = served === "" ? [] : served.split(",");