@rshono/core 1.0.0-rc.16 → 1.0.0-rc.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -5
- package/dist/builder/env-shadow-loader.cjs +58 -2
- package/dist/builder/rspack-config.d.ts.map +1 -1
- package/dist/builder/rspack-config.js +46 -6
- package/dist/builder/rspack-config.js.map +1 -1
- package/dist/cli/build.d.ts.map +1 -1
- package/dist/cli/build.js +24 -1
- package/dist/cli/build.js.map +1 -1
- package/dist/cli/dev.d.ts.map +1 -1
- package/dist/cli/dev.js +4 -0
- package/dist/cli/dev.js.map +1 -1
- package/dist/cli/index.js +14 -8
- package/dist/cli/index.js.map +1 -1
- package/dist/config.d.ts +10 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/deploy/cloudflare/runtime.d.ts.map +1 -1
- package/dist/deploy/cloudflare/runtime.js +31 -5
- package/dist/deploy/cloudflare/runtime.js.map +1 -1
- package/dist/deploy/contract.d.ts +6 -2
- package/dist/deploy/contract.d.ts.map +1 -1
- package/dist/deploy/contract.js.map +1 -1
- package/dist/deploy/filesystem.d.ts.map +1 -1
- package/dist/deploy/filesystem.js +2 -1
- package/dist/deploy/filesystem.js.map +1 -1
- package/dist/deploy/node/runtime.d.ts.map +1 -1
- package/dist/deploy/node/runtime.js +3 -4
- package/dist/deploy/node/runtime.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/router.d.ts +60 -7
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js.map +1 -1
- package/dist/runtime/context.d.ts +51 -7
- package/dist/runtime/context.d.ts.map +1 -1
- package/dist/runtime/context.js +49 -5
- package/dist/runtime/context.js.map +1 -1
- package/dist/runtime/entry.client.js +230 -277
- package/dist/runtime/entry.client.js.map +1 -1
- package/dist/runtime/entry.rsc.d.ts.map +1 -1
- package/dist/runtime/entry.rsc.js +187 -39
- package/dist/runtime/entry.rsc.js.map +1 -1
- package/dist/runtime/flight-inject.d.ts +1 -1
- package/dist/runtime/flight-inject.d.ts.map +1 -1
- package/dist/runtime/flight-inject.js +207 -40
- package/dist/runtime/flight-inject.js.map +1 -1
- package/dist/runtime/navigation.d.ts +4 -0
- package/dist/runtime/navigation.d.ts.map +1 -1
- package/dist/runtime/navigation.js.map +1 -1
- package/dist/runtime/request.d.ts.map +1 -1
- package/dist/runtime/request.js +10 -0
- package/dist/runtime/request.js.map +1 -1
- package/dist/runtime/validate-entries.d.ts +33 -0
- package/dist/runtime/validate-entries.d.ts.map +1 -0
- package/dist/runtime/validate-entries.js +185 -0
- package/dist/runtime/validate-entries.js.map +1 -0
- package/dist/server/prerendered.d.ts +30 -6
- package/dist/server/prerendered.d.ts.map +1 -1
- package/dist/server/prerendered.js +71 -13
- package/dist/server/prerendered.js.map +1 -1
- package/dist/server/server-config.d.ts +12 -0
- package/dist/server/server-config.d.ts.map +1 -1
- package/dist/server/server-config.js +25 -0
- package/dist/server/server-config.js.map +1 -1
- package/dist/server/ssg.d.ts.map +1 -1
- package/dist/server/ssg.js +151 -25
- package/dist/server/ssg.js.map +1 -1
- package/dist/server/static.d.ts.map +1 -1
- package/dist/server/static.js +3 -1
- package/dist/server/static.js.map +1 -1
- package/package.json +7 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry.rsc.js","sourceRoot":"","sources":["../../src/runtime/entry.rsc.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { Context, Handler } from 'hono';\nimport { Hono } from 'hono';\nimport { HTTPException } from 'hono/http-exception';\n// Type-only side effect: augments Hono's `ContextVariableMap` with `secureHeadersNonce`, read in `cspNonce`.\nimport type {} from 'hono/secure-headers';\nimport type { ContentfulStatusCode, RedirectStatusCode } from 'hono/utils/http-status';\nimport type React from 'react';\nimport type { ReactFormState } from 'react-dom/client';\n// Called directly rather than as `<Page {...props} />`: a spread would drop the non-enumerable `ctx`\n// prop. See `pageProps`.\nimport { jsx } from 'react/jsx-runtime';\n// The bare specifier, not `/server.node`: the RSC layer's `conditionNames` picks the build for the\n// deploy target being compiled for.\nimport {\n createTemporaryReferenceSet,\n decodeAction,\n decodeFormState,\n decodeReply,\n loadServerAction,\n renderToReadableStream,\n type ServerEntry,\n type TemporaryReferenceSet,\n} from 'react-server-dom-rspack/server';\n// Aliased at build time to the selected preset's runtime — the one place this file knows where it runs.\nimport { runtime } from '@rshono/deploy';\n// @ts-expect-error — resolved by the '@rshono/routes' alias to the app's routes.ts\nimport { routes as userRoutes } from '@rshono/routes';\n// @ts-expect-error — resolved by the '@rshono/server-app' alias (src/server.ts or the empty fallback)\nimport * as serverAppModule from '@rshono/server-app';\nimport { isPageRoute, type ErrorPageInfo, type FallbackPage, type PageComponent, type PageProps, type Route, type RouteConfig } from '../router.js';\nimport { appendVary, etagMatches } from '../server/headers.js';\nimport { beginPageRender, getRequestContext, publicUrl, readParams, reportServerError, runWithContext } from './context.js';\nimport { isControlSignal, RedirectSignal, type ControlSignal } from './control.js';\nimport { renderHTML } from './entry.ssr.js';\n// Type-only, so it is erased — the RSC layer does not take its own instance of the SSR layer's module.\nimport type { CancellableTransformer } from './flight-inject.js';\nimport { RouterProvider } from './navigation.js';\nimport { asksForRsc, isActionRequest, parseRenderRequest, requestWantsRsc, RSC_VARY_HEADER, wantsRsc } from './request.js';\n\nconst serverApp = ((serverAppModule as { default?: unknown }).default ?? null) as Hono | null;\n\n// Compiled into the bundle from rshono.config.ts by DefinePlugin; there is no runtime env-var interface.\nconst { isDev } = __RSHONO_CONFIG__;\n\n/** How long a prerendered page may be reused before revalidating. Also what `public/` files get. */\nconst SSG_CACHE_CONTROL = 'public, max-age=300';\n\n/** The two content types a page can be served as, from the same URL — which is what makes `Vary` non-optional. */\nconst PAGE_CONTENT_TYPE = /^(?:text\\/html|text\\/x-component)\\b/;\n\nruntime.loadEnv();\n\nconst routeConfig = userRoutes as RouteConfig;\nexport const routes: readonly Route[] = routeConfig.routes;\n\n/** The result of a server action, as a `Result<T, E>` rather than an `ok` flag over one field. */\nexport type ActionResult = { ok: true; value: unknown } | { ok: false; error: unknown };\n\nexport type RscPayload = {\n root: React.ReactNode;\n returnValue?: ActionResult;\n formState?: ReactFormState;\n redirect?: string;\n notFound?: boolean;\n};\n\n/**\n * The per-request CSP nonce, if the app asked for one.\n *\n * The framework never mints it: `secureHeaders()` does, when its policy contains the `NONCE`\n * placeholder, and stores it here — so all the framework does is stamp the value into the render. It is\n * readable from a route handler because `secureHeaders` resolves its directives before `next()`.\n */\nfunction cspNonce(c: Context): string | undefined {\n return c.get('secureHeadersNonce');\n}\n\n/**\n * Whether a `<form action={serverAction}>` post came from another site, and so must not be allowed to run one.\n *\n * This is not CSRF policy — that is `csrf()` from Hono, registered in `src/server.ts`, which runs ahead of\n * every page route and covers far more than this. It is the framework declining to run *its own* action\n * mechanism for a request that mechanism cannot legitimately produce, in the one place the two action shapes\n * are not equally exposed:\n *\n * - A client-initiated action carries `x-rsc-action`, which is not a CORS-simple header. A cross-origin caller\n * needs a preflight it will not be given, so that shape cannot be forged from a browser at all.\n * - A form post is `multipart/form-data` or `application/x-www-form-urlencoded` with no header of its own —\n * the content types that need no preflight. It is forgeable, and an app with no `src/server.ts` has nothing\n * standing in front of it.\n *\n * Both halves are required, because either alone refuses something real:\n *\n * - `Sec-Fetch-Site: cross-site` is the browser's own statement of provenance, and every browser that can post\n * a form to a server action sends it. An absent header means a non-browser client, which cannot be a CSRF\n * victim; `same-site` is left alone too, since a subdomain policy is `csrf()`'s to express.\n * - An `Origin` that is the app's own contradicts that label — a browser calls a post from the app's own pages\n * `same-origin` — so the pair is a shape no browser produces, and refusing it would only catch a proxy or a\n * test client setting the label by hand while posting from the app itself.\n *\n * `publicUrl(c)` rather than `c.req.url`, so it honours `trustProxy` and compares against the origin the\n * browser actually used — which behind a proxy, `rshono dev`'s included, is not the one the server was reached\n * on. The cost is that an app deliberately accepting cross-site *form* posts to an action cannot; that is what\n * an `{ type: 'endpoint' }` route is for.\n */\nfunction refusesCrossSiteForm(c: Context): boolean {\n if (c.req.header('sec-fetch-site') !== 'cross-site') return false;\n const origin = c.req.header('origin');\n return origin !== undefined && origin !== publicUrl(c).origin;\n}\n\nasync function loadPageModule(load: () => Promise<{ default: PageComponent }>, label: string): Promise<ServerEntry<PageComponent>> {\n const mod = await load();\n const Page = mod.default as ServerEntry<PageComponent> | undefined;\n if (typeof Page !== 'function') {\n throw new Error(`[rshono] The page module for ${label} must default-export a server component.`);\n }\n if (!Page.entryJsFiles) {\n throw new Error(\n `[rshono] The page component for ${label} is missing its client-asset info ('use server-entry'). ` +\n \"The directive is added automatically for inline `component: () => import('…')` thunks in routes.ts. \" +\n \"If this page is wired up another way, put 'use server-entry' on the first line of the page module yourself — \" +\n \"and make sure the page is a server component (a 'use client' page must be wrapped by a server component instead).\",\n );\n }\n return Page;\n}\n\n/** A browser navigation or a crawler, as opposed to a fetch that would rather have plain text. */\nfunction acceptsHtml(c: Context): boolean {\n return c.req.header('accept')?.includes('text/html') ?? false;\n}\n\n/**\n * The 404 for an app with no `notFound` page, and for a client that wanted neither HTML nor a flight\n * payload. It carries the `Vary` too: this is one of the answers a page URL gives depending on the `RSC` request header.\n */\nfunction plainNotFound(c: Context): Response {\n return c.text('Not Found', 404, { vary: RSC_VARY_HEADER });\n}\n\n/** A lazy once-cell: runs `load` at most once, but clears a rejection so a later call can retry. */\nfunction once<T>(load: () => Promise<T>): () => Promise<T> {\n let promise: Promise<T> | undefined;\n return () => {\n if (!promise) {\n const pending = (promise = load());\n pending.catch(() => {\n if (promise === pending) promise = undefined;\n });\n }\n return promise;\n };\n}\n\n/**\n * Passes `stream` through untouched, calling `done` however it ends — for the flight-only response\n * path, which has no transform of its own to hang a completion hook off. `done` must be idempotent.\n */\nfunction releaseWhenDone(stream: ReadableStream<Uint8Array>, done: () => void): ReadableStream<Uint8Array> {\n return stream.pipeThrough(\n new TransformStream<Uint8Array, Uint8Array>({\n transform(chunk, controller) {\n controller.enqueue(chunk);\n },\n flush: done,\n cancel: done,\n } as CancellableTransformer<Uint8Array, Uint8Array>),\n );\n}\n\ninterface ComponentRenderOptions {\n status?: number;\n isRsc: boolean;\n formState?: ReactFormState;\n returnValue?: RscPayload['returnValue'];\n temporaryReferences?: TemporaryReferenceSet;\n /** Passed when the page being rendered is the `error` page, which takes it as an extra prop. */\n errorInfo?: ErrorPageInfo;\n /** Marks the payload as the not-found page, so a soft navigation can tell it apart from the page it asked for. */\n notFound?: boolean;\n}\n\n/**\n * Builds the props a page component is called with.\n *\n * `ctx` is *defined* rather than assigned, and both halves are load-bearing:\n *\n * - **A getter**, so nothing is built for the pages that never read it, and a `render: 'static'` page\n * that does gets {@link getRequestContext}'s prerendering error rather than a bare `undefined`.\n * - **Non-enumerable**, so React's dev-only serialization of a server component's props skips it. That\n * walks own enumerable properties, and `ctx.hono.env` holds the runtime's bindings — an enumerable\n * `ctx` would ship every secret to the browser in dev.\n *\n * The cost: the element is created by handing this object to `jsx()` by reference, since a\n * `<Page {...props} />` spread would silently drop `ctx`.\n */\nfunction pageProps(c: Context, errorInfo: ErrorPageInfo | undefined): PageProps & { error?: ErrorPageInfo } {\n const props = { url: publicUrl(c), params: readParams(c), ...(errorInfo ? { error: errorInfo } : null) };\n Object.defineProperty(props, 'ctx', { get: getRequestContext, enumerable: false, configurable: true });\n return props as PageProps & { error?: ErrorPageInfo };\n}\n\nasync function renderComponent(c: Context, Page: ServerEntry<PageComponent>, opts: ComponentRenderOptions): Promise<Response> {\n // React's renderers must never be handed `c.req.raw.signal`: they add an `abort` listener and only\n // remove it if the abort fires, so on the happy path it stays on a request-lifetime signal and pins the\n // whole rendered tree. The render gets its own controller and the request signal forwards into it —\n // `release` detaches on the normal path. Not `AbortSignal.any()`, whose composite signals Node holds in\n // a process-lifetime set until they abort.\n const requestSignal = c.req.raw.signal;\n const renderAbort = new AbortController();\n const signal = renderAbort.signal;\n const forwardAbort = () => renderAbort.abort(requestSignal.reason);\n if (requestSignal.aborted) renderAbort.abort(requestSignal.reason);\n else requestSignal.addEventListener('abort', forwardAbort, { once: true });\n const release = () => requestSignal.removeEventListener('abort', forwardAbort);\n\n // Documents only: the nonce goes on the bootstrap scripts and the `<meta>` React hydrates from, and a\n // flight payload has neither — which is what keeps a prerendered one servable under a nonce-based CSP.\n const nonce = opts.isRsc ? undefined : cspNonce(c);\n const props = pageProps(c, opts.errorInfo);\n const root = (\n <>\n {nonce && <meta property=\"csp-nonce\" nonce={nonce} />}\n {Page.entryCssFiles?.map((href) => (\n <link key={href} rel=\"stylesheet\" href={href} precedence=\"default\" />\n ))}\n {/* `href`, not the `URL`: these props cross into a client component, so they have to be serializable. */}\n <RouterProvider href={props.url.href} params={props.params}>\n {jsx(Page, props)}\n </RouterProvider>\n </>\n );\n\n // `notFound` only when true, so an ordinary page's payload doesn't carry the key.\n const rscPayload: RscPayload = { root, formState: opts.formState, returnValue: opts.returnValue, ...(opts.notFound ? { notFound: true } : null) };\n\n // The last thing before the render: past here the response head is the framework's, so `ctx.setHeader()`\n // starts throwing — while the action `renderPage` just ran, and the middleware around it, legitimately wrote.\n beginPageRender(c);\n\n let controlSignal: ControlSignal | undefined;\n const rscStream = renderToReadableStream(rscPayload, {\n temporaryReferences: opts.temporaryReferences,\n signal,\n onError(error) {\n if (isControlSignal(error)) {\n controlSignal = error;\n return error.digest;\n }\n if (!signal.aborted) reportServerError(error, { source: 'render', request: c.req.raw, message: '[rshono] render error:' });\n },\n });\n\n if (opts.isRsc) {\n return c.body(releaseWhenDone(rscStream, release), (opts.status ?? 200) as ContentfulStatusCode, {\n 'content-type': 'text/x-component;charset=utf-8',\n });\n }\n\n let ssrResult: Awaited<ReturnType<typeof renderHTML>>;\n try {\n ssrResult = await renderHTML(rscStream, {\n bootstrapScripts: Page.entryJsFiles,\n formState: opts.formState,\n signal,\n nonce,\n onDone: release,\n onShellError: (error) => reportServerError(error, { source: 'ssr', request: c.req.raw, message: '[rshono] SSR shell error:' }),\n onError: (error) => reportServerError(error, { source: 'ssr', request: c.req.raw, message: '[rshono] SSR error:' }),\n });\n } catch (error) {\n release();\n if (controlSignal) throw controlSignal;\n throw error;\n }\n if (controlSignal) {\n // The shell resolved, so this response is live: React is being pumped into the payload-injecting\n // transform, and a `redirect()` that surfaced from a boundary settling just before the shell was ready\n // lands here. Nothing will read that stream now — the signal becomes a redirect instead — so it is stopped\n // rather than left to render to completion for a response that was replaced.\n //\n // Both calls, because they stop different halves. `abort` reaches the two renders through the signal they\n // were handed; cancelling the response readable propagates back through the transform to release the teed\n // flight branch it holds a reader on, which `abort` alone does not.\n renderAbort.abort();\n void ssrResult.stream.cancel().catch(() => {\n // Already errored or locked — there is nothing left to release either way.\n });\n release();\n throw controlSignal;\n }\n return c.body(ssrResult.stream, (ssrResult.status ?? opts.status ?? 200) as ContentfulStatusCode, {\n 'content-type': 'text/html;charset=utf-8',\n });\n}\n\nasync function renderPage(c: Context, loadPage: () => Promise<ServerEntry<PageComponent>>): Promise<Response> {\n const request = c.req.raw;\n const renderRequest = parseRenderRequest(request);\n\n let returnValue: ActionResult | undefined;\n let formState: ReactFormState | undefined;\n let temporaryReferences: TemporaryReferenceSet | undefined;\n let actionStatus: number | undefined;\n if (isActionRequest(renderRequest)) {\n if (renderRequest.kind === 'rsc-action') {\n // Before the body is decoded, so an unknown id costs nothing to reject. `hasOwn` so `__proto__`\n // does not resolve to a manifest entry.\n if (!Object.hasOwn(__rspack_rsc_manifest__.serverManifest, renderRequest.actionId)) {\n return c.text('Bad Request: unknown server action', 400);\n }\n const contentType = request.headers.get('content-type');\n const body = contentType?.startsWith('multipart/form-data') ? await request.formData() : await request.text();\n temporaryReferences = createTemporaryReferenceSet();\n const args = await decodeReply<unknown[]>(body, { temporaryReferences });\n const action = loadServerAction(renderRequest.actionId);\n try {\n returnValue = { ok: true, value: await action(...args) };\n } catch (error) {\n if (isControlSignal(error)) throw error;\n // In production React sends a thrown action error to the client as an opaque marker, so this is\n // the only place the real one is visible.\n reportServerError(error, { source: 'action', request, message: '[rshono] server action error:' });\n returnValue = { ok: false, error };\n actionStatus = 500;\n }\n } else {\n // A `<form action={serverAction}>` post, which is the path that runs before hydration and with\n // JavaScript off. Unlike the client-initiated one it carries no custom header, so it is also the only\n // action shape a browser can be made to send from another site: see `refusesCrossSiteForm`.\n if (refusesCrossSiteForm(c)) {\n return c.text('Forbidden: cross-site form post to a server action', 403, { vary: RSC_VARY_HEADER });\n }\n const formData = await request.formData();\n const decodedAction = await decodeAction(formData, __rspack_rsc_manifest__.serverManifest);\n if (decodedAction) {\n let result: unknown;\n try {\n result = await decodedAction();\n } catch (error) {\n if (isControlSignal(error)) throw error;\n // Reported here so a no-JS form post is attributed to the action that threw, exactly as the\n // client-initiated path is — the top-level handler would call it a `request`. Then re-thrown,\n // because this path has no client boundary and no `useActionState` to hand the error to, so the\n // app's `error` page is the honest answer. `reportServerError` de-duplicates, so the re-throw\n // reaching `onError` does not report it a second time.\n reportServerError(error, { source: 'action', request, message: '[rshono] server action error:' });\n throw error;\n }\n formState = (await decodeFormState(result, formData, __rspack_rsc_manifest__.serverManifest)) ?? undefined;\n }\n }\n }\n\n const Page = await loadPage();\n return renderComponent(c, Page, {\n status: actionStatus,\n isRsc: wantsRsc(renderRequest),\n formState,\n returnValue,\n temporaryReferences,\n });\n}\n\nfunction buildApp(): Hono {\n const app = new Hono();\n\n // A floor, not a policy: an app wanting the full set registers `secureHeaders()` in src/server.ts, and\n // because this is registered first it unwinds last, so the \"only if unset\" checks stand aside for it.\n // Owned by the framework because it also has to cover `mountStaticAssets` — a terminal handler the\n // app's own middleware never sees.\n app.use(async (c, next) => {\n await next();\n const headers = c.res.headers;\n if (!headers.has('x-content-type-options')) headers.set('x-content-type-options', 'nosniff');\n if (!headers.has('referrer-policy')) headers.set('referrer-policy', 'strict-origin-when-cross-origin');\n if (!headers.has('x-frame-options')) headers.set('x-frame-options', 'SAMEORIGIN');\n\n // React Refresh compiles updates with `eval`, so a dev build cannot run under a production CSP.\n // Widened here so one policy in src/server.ts serves both.\n if (isDev) {\n const csp = headers.get('content-security-policy');\n if (csp?.includes('script-src ')) {\n headers.set('content-security-policy', csp.replace('script-src ', \"script-src 'unsafe-eval' \"));\n }\n }\n\n // Page responses only from here down.\n if (!PAGE_CONTENT_TYPE.test(headers.get('content-type') ?? '')) return;\n appendVary(headers, RSC_VARY_HEADER);\n // Without a default a shared cache is free to store a logged-in user's page and hand it to someone\n // else. `private, no-cache` forbids that without blocking bfcache, which `no-store` would.\n if (!headers.has('cache-control')) headers.set('cache-control', 'private, no-cache');\n });\n\n runtime.mountStaticAssets(app);\n\n // Ahead of the page routes, so the app's own middleware (`csrf()`, `bodyLimit()`, auth, logging) wraps\n // page requests too. The flip side: a *terminal* handler in src/server.ts shadows a page at the same path.\n if (serverApp) {\n app.route('/', serverApp);\n }\n\n const memoizePage = (page: FallbackPage, label: string) => once(() => loadPageModule(page.component, label));\n const loadNotFoundPage = routeConfig.notFound ? memoizePage(routeConfig.notFound, 'the notFound page') : null;\n\n /** Turns a thrown `redirect()` / `notFound()` into the response it stands for. */\n const respondToControlSignal = async (c: Context, signal: ControlSignal): Promise<Response> => {\n const isRsc = requestWantsRsc(c.req.raw);\n if (signal instanceof RedirectSignal) {\n if (isRsc) {\n // No `signal`: two fields and no component tree, so there is nothing worth aborting.\n return c.body(renderToReadableStream({ root: null, redirect: signal.location } satisfies RscPayload), 200, {\n 'content-type': 'text/x-component;charset=utf-8',\n });\n }\n return c.redirect(signal.location, signal.status as RedirectStatusCode);\n }\n if (loadNotFoundPage) {\n return renderComponent(c, await loadNotFoundPage(), { status: 404, isRsc, notFound: true });\n }\n return plainNotFound(c);\n };\n\n for (const route of routes) {\n if (isPageRoute(route)) {\n // Both fixed for the life of the process, so resolved once rather than per request.\n const servesPrerendered = !isDev && route.render === 'static';\n const loadPage = once(() => loadPageModule(route.component, `\"${route.path}\"`));\n\n const handler: Handler = async (c) => {\n try {\n if (servesPrerendered && c.req.method === 'GET') {\n const isRsc = asksForRsc(c.req.raw);\n // One fixed set of bytes cannot carry a per-request nonce, so a document has to be rendered\n // where the app's CSP has one. Decided per request, so an app whose policy carries no `NONCE`\n // keeps its prerendered documents. A flight payload never carries a nonce either way.\n const mustRenderForNonce = !isRsc && cspNonce(c) !== undefined;\n if (!mustRenderForNonce) {\n const page = await runtime.readPrerendered(c, isRsc ? 'flight' : 'html');\n // Request-independent by construction, so it is safe to cache publicly; the ETag turns the\n // revalidation that follows into a 304. Answered outside `runWithContext` — no app code runs\n // on this path, so there is no `getRequestContext()` to serve.\n if (page !== null) {\n const headers = {\n 'cache-control': SSG_CACHE_CONTROL,\n etag: page.etag,\n vary: RSC_VARY_HEADER,\n 'content-type': isRsc ? 'text/x-component;charset=utf-8' : 'text/html;charset=utf-8',\n };\n if (etagMatches(c.req.header('if-none-match'), page.etag)) return c.body(null, 304, headers);\n return c.body(page.body, 200, { ...headers, 'content-length': page.contentLength });\n }\n }\n }\n return await runWithContext(c, () => renderPage(c, loadPage));\n } catch (error) {\n if (isControlSignal(error)) return runWithContext(c, () => respondToControlSignal(c, error));\n throw error;\n }\n };\n app.on(['GET', 'POST'], route.path, handler);\n } else {\n const loadEndpoint = once(() => route.server());\n const handler: Handler = async (c, next) => {\n const { handler: endpointHandler } = await loadEndpoint();\n // Hono's `Handler` leaves its return parameter defaulted to `any`, so this hands back exactly what\n // the app's own handler is declared to return — there is nothing narrower to assert here.\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return endpointHandler(c, next);\n };\n const method = route.method ?? 'all';\n if (method === 'all') app.all(route.path, handler);\n else app.on(method.toUpperCase(), route.path, handler);\n }\n }\n\n runtime.mountPublicFallback(app);\n\n app.notFound(async (c) => {\n const isRsc = requestWantsRsc(c.req.raw);\n if (loadNotFoundPage && (isRsc || acceptsHtml(c))) {\n return runWithContext(c, async () => renderComponent(c, await loadNotFoundPage(), { status: 404, isRsc }));\n }\n return plainNotFound(c);\n });\n\n const loadErrorPage = routeConfig.error ? memoizePage(routeConfig.error, 'the error page') : null;\n app.onError(async (error, c) => {\n if (isControlSignal(error)) return runWithContext(c, () => respondToControlSignal(c, error));\n // Registering an `onError` replaces Hono's default handler, which is what turns an `HTTPException`\n // into the response it carries — without this, `csrf()`'s 403 and `bodyLimit()`'s 413 would both\n // surface as a 500 error page. Rebuilt through `c`, as Hono's default does, so headers middleware\n // already prepared survive.\n if (error instanceof HTTPException) {\n const res = error.getResponse();\n return c.newResponse(res.body, res);\n }\n reportServerError(error, { source: 'request', request: c.req.raw, message: '[rshono] request error:' });\n const isRsc = requestWantsRsc(c.req.raw);\n if (loadErrorPage && (isRsc || acceptsHtml(c))) {\n const errorInfo: ErrorPageInfo = isDev\n ? {\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n }\n : { message: 'Internal Server Error' };\n try {\n return await runWithContext(c, async () => renderComponent(c, await loadErrorPage(), { status: 500, isRsc, errorInfo }));\n } catch (renderError) {\n reportServerError(renderError, { source: 'request', request: c.req.raw, message: '[rshono] the error page failed to render:' });\n }\n }\n const detail = isDev ? `\\n\\n${error instanceof Error ? (error.stack ?? error.message) : String(error)}` : '';\n return c.text(`Internal Server Error${detail}`, 500, { vary: RSC_VARY_HEADER });\n });\n\n return app;\n}\n\nexport const app = buildApp();\n\n/**\n * The app, handed to whatever is hosting it: this binds a port and exports nothing where rshono owns the\n * process, and *is* the export the platform looks for where the host owns it — so one entry serves both.\n *\n * `app` and `routes` stay named exports either way, because `rshono build` imports them to prerender\n * `render: 'static'` routes.\n */\nexport default runtime.serveApp(app);\n"]}
|
|
1
|
+
{"version":3,"file":"entry.rsc.js","sourceRoot":"","sources":["../../src/runtime/entry.rsc.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { Context, Handler } from 'hono';\nimport { Hono } from 'hono';\nimport { HTTPException } from 'hono/http-exception';\n// Type-only side effect: augments Hono's `ContextVariableMap` with `secureHeadersNonce`, read in `cspNonce`.\nimport type {} from 'hono/secure-headers';\nimport type { ContentfulStatusCode, RedirectStatusCode } from 'hono/utils/http-status';\nimport type React from 'react';\nimport type { ReactFormState } from 'react-dom/client';\n// Called directly rather than as `<Page {...props} />`: a spread would drop the non-enumerable `ctx`\n// prop. See `pageProps`.\nimport { jsx } from 'react/jsx-runtime';\n// The bare specifier, not `/server.node`: the RSC layer's `conditionNames` picks the build for the\n// deploy target being compiled for.\nimport {\n createTemporaryReferenceSet,\n decodeAction,\n decodeFormState,\n decodeReply,\n loadServerAction,\n renderToReadableStream,\n type ServerEntry,\n type TemporaryReferenceSet,\n} from 'react-server-dom-rspack/server';\n// Aliased at build time to the selected preset's runtime — the one place this file knows where it runs.\nimport { runtime } from '@rshono/deploy';\n// @ts-expect-error — resolved by the '@rshono/routes' alias to the app's routes.ts\nimport { routes as userRoutes } from '@rshono/routes';\n// @ts-expect-error — resolved by the '@rshono/server-app' alias (src/server.ts or the empty fallback)\nimport * as serverAppModule from '@rshono/server-app';\nimport { isPageRoute, type ErrorPageInfo, type FallbackPage, type PageComponent, type PageProps, type Route } from '../router.js';\nimport { appendVary, etagMatches } from '../server/headers.js';\nimport { beginPageRender, getRequestContext, publicUrl, readParams, reportServerError, runWithContext } from './context.js';\nimport { isControlSignal, RedirectSignal, type ControlSignal } from './control.js';\nimport { renderHTML } from './entry.ssr.js';\n// Type-only, so it is erased — the RSC layer does not take its own instance of the SSR layer's module.\nimport type { CancellableTransformer } from './flight-inject.js';\nimport { RouterProvider } from './navigation.js';\nimport { asksForRsc, isActionRequest, parseRenderRequest, requestWantsRsc, RSC_VARY_HEADER, wantsRsc } from './request.js';\nimport { validateRoutesModule, validateServerApp } from './validate-entries.js';\n\nconst serverApp = validateServerApp(serverAppModule);\n\n// Compiled into the bundle from rshono.config.ts by DefinePlugin; there is no runtime env-var interface.\nconst { isDev } = __RSHONO_CONFIG__;\n\n/**\n * How long a prerendered page may be reused before revalidating. Also what `public/` files get.\n *\n * Not a config field, deliberately: it is a per-response header, and `rshono.config.ts` is compiled into the\n * bundle — a cache policy you cannot change without a rebuild is the wrong shape. An app that wants a longer\n * `max-age`, or a `stale-while-revalidate`, sets it from middleware **after `await next()`**:\n *\n * ```ts\n * server.use('/docs/*', async (c, next) => {\n * await next();\n * c.res.headers.set('cache-control', 'public, max-age=86400, stale-while-revalidate=604800');\n * });\n * ```\n *\n * After, because the response below is built with `cache-control` in the bag it hands `c.body(...)`, and\n * that replaces a header prepared with `c.header(...)` before the handler ran. The `ETag` is untouched\n * either way, so revalidation still costs a 304 rather than the page.\n */\nconst SSG_CACHE_CONTROL = 'public, max-age=300';\n\n/**\n * What a page response gets when nothing else set one: without it a shared cache is free to store a logged-in\n * user's page and hand it to someone else. `private, no-cache` forbids that without blocking bfcache, which\n * `no-store` would.\n */\nconst PAGE_CACHE_CONTROL = 'private, no-cache';\n\n/** The two content types a page can be served as, from the same URL — which is what makes `Vary` non-optional. */\nconst PAGE_CONTENT_TYPE = /^(?:text\\/html|text\\/x-component)\\b/;\n\nruntime.loadEnv();\n\n// Checked rather than cast: these two modules are the app's, and a mistake in either used to surface as a\n// `TypeError` from somewhere else entirely — or, for a duplicated path, as nothing at all.\nconst routeConfig = validateRoutesModule(userRoutes);\nexport const routes: readonly Route[] = routeConfig.routes;\n\n/** The result of a server action, as a `Result<T, E>` rather than an `ok` flag over one field. */\nexport type ActionResult = { ok: true; value: unknown } | { ok: false; error: unknown };\n\nexport type RscPayload = {\n root: React.ReactNode;\n returnValue?: ActionResult;\n formState?: ReactFormState;\n redirect?: string;\n notFound?: boolean;\n};\n\n/**\n * The result of an action that has already run, for the request whose *render* then failed.\n *\n * The action and the page it answers with are one response: an action returns its value through the payload\n * of the page rendered after it. So when that render throws — a page module that will not load, most\n * plausibly a chunk that went away mid-deploy — `onError` renders the `error` page in its place, and without\n * this the reply carries no `returnValue` at all. The caller of an action that ran, and may well have\n * written something, would be told only that a field was missing.\n *\n * Keyed on the Hono context the way `beginPageRender` keys its own marker, and weakly, so nothing outlives\n * the request it belongs to.\n */\nconst actionResults = new WeakMap<Context, ActionResult>();\n\n/**\n * The per-request CSP nonce, if the app asked for one.\n *\n * The framework never mints it: `secureHeaders()` does, when its policy contains the `NONCE`\n * placeholder, and stores it here — so all the framework does is stamp the value into the render. It is\n * readable from a route handler because `secureHeaders` resolves its directives before `next()`.\n */\nfunction cspNonce(c: Context): string | undefined {\n return c.get('secureHeadersNonce');\n}\n\n/**\n * Whether a `<form action={serverAction}>` post came from another site, and so must not be allowed to run one.\n *\n * This is not CSRF policy — that is `csrf()` from Hono, registered in `src/server.ts`, which runs ahead of\n * every page route and covers far more than this. It is the framework declining to run *its own* action\n * mechanism for a request that mechanism cannot legitimately produce, in the one place the two action shapes\n * are not equally exposed:\n *\n * - A client-initiated action carries `x-rsc-action`, which is not a CORS-simple header. A cross-origin caller\n * needs a preflight it will not be given, so that shape cannot be forged from a browser at all.\n * - A form post is `multipart/form-data` or `application/x-www-form-urlencoded` with no header of its own —\n * the content types that need no preflight. It is forgeable, and an app with no `src/server.ts` has nothing\n * standing in front of it.\n *\n * Both halves are required, because either alone refuses something real:\n *\n * - `Sec-Fetch-Site` is the browser's own statement of provenance, unforgeable by page script, and every\n * browser that can post a form to a server action sends it. `cross-site` and `same-site` are the two labels\n * that mean \"not from this origin\" — `same-site` is what a *sibling subdomain* gets, which is a user-content\n * host, a stale CNAME or a subdomain takeover, so leaving it to `csrf()` meant an app without one could have\n * any `'use server'` export driven from next door. An absent header means a non-browser client, which cannot\n * be a CSRF victim. `same-origin` and `none` settle it on their own, and are what a genuine post carries\n * however many proxies rewrote `Host` on the way in.\n * - An `Origin` that is the app's own contradicts either label — a browser calls a post from the app's own pages\n * `same-origin` — so the pair is a shape no browser produces, and refusing it would only catch a proxy or a\n * test client setting the label by hand while posting from the app itself. Nothing else clears the label:\n * an `Origin` of `null` (a sandboxed iframe, a `data:` URL, `Referrer-Policy: no-referrer`) and no `Origin`\n * at all are both refused. A browser attaches one to every non-GET request, so neither is a shape it\n * produces — but a security predicate that says \"not proven foreign\" rather than \"proven local\" fails open\n * the day something does produce it.\n *\n * `publicUrl(c)` rather than `c.req.url`, so it honours `trustProxy` and compares against the origin the\n * browser actually used — which behind a proxy, `rshono dev`'s included, is not the one the server was reached\n * on. The cost is that an app deliberately accepting *form* posts to an action from another origin of its own\n * cannot, `csrf()`'s allowlist included; that is what an `{ type: 'endpoint' }` route is for.\n */\nfunction refusesCrossSiteForm(c: Context): boolean {\n const site = c.req.header('sec-fetch-site');\n if (site !== 'cross-site' && site !== 'same-site') return false;\n return c.req.header('origin') !== publicUrl(c).origin;\n}\n\nasync function loadPageModule(load: () => Promise<{ default: PageComponent }>, label: string): Promise<ServerEntry<PageComponent>> {\n const mod = await load();\n const Page = mod.default as ServerEntry<PageComponent> | undefined;\n if (typeof Page !== 'function') {\n throw new Error(`[rshono] The page module for ${label} must default-export a server component.`);\n }\n if (!Page.entryJsFiles) {\n throw new Error(\n `[rshono] The page component for ${label} is missing its client-asset info ('use server-entry'). ` +\n \"The directive is added automatically for inline `component: () => import('…')` thunks in routes.ts. \" +\n \"If this page is wired up another way, put 'use server-entry' on the first line of the page module yourself — \" +\n \"and make sure the page is a server component (a 'use client' page must be wrapped by a server component instead).\",\n );\n }\n return Page;\n}\n\n/** A browser navigation or a crawler, as opposed to a fetch that would rather have plain text. */\nfunction acceptsHtml(c: Context): boolean {\n return c.req.header('accept')?.includes('text/html') ?? false;\n}\n\n/**\n * The 404 for an app with no `notFound` page, and for a client that wanted neither HTML nor a flight\n * payload. It carries the `Vary` too: this is one of the answers a page URL gives depending on the `RSC` request header.\n */\nfunction plainNotFound(c: Context): Response {\n // `cache-control` explicitly, because the default above is applied to page *content types* and this is\n // `text/plain`. A 404 is heuristically cacheable under RFC 9111, so without it a shared cache may store\n // this one — while the rendered HTML 404 next to it, the same answer to the same request from a client\n // that asked for HTML, is correctly private.\n return c.text('Not Found', 404, { vary: RSC_VARY_HEADER, 'cache-control': PAGE_CACHE_CONTROL });\n}\n\n/** A lazy once-cell: runs `load` at most once, but clears a rejection so a later call can retry. */\nfunction once<T>(load: () => Promise<T>): () => Promise<T> {\n let promise: Promise<T> | undefined;\n return () => {\n if (!promise) {\n const pending = (promise = load());\n pending.catch(() => {\n if (promise === pending) promise = undefined;\n });\n }\n return promise;\n };\n}\n\n/**\n * Passes `stream` through untouched, calling `done` however it ends — for the flight-only response\n * path, which has no transform of its own to hang a completion hook off. `done` must be idempotent.\n */\nfunction releaseWhenDone(stream: ReadableStream<Uint8Array>, done: () => void): ReadableStream<Uint8Array> {\n return stream.pipeThrough(\n new TransformStream<Uint8Array, Uint8Array>({\n transform(chunk, controller) {\n controller.enqueue(chunk);\n },\n flush: done,\n cancel: done,\n } as CancellableTransformer<Uint8Array, Uint8Array>),\n );\n}\n\n/**\n * A macrotask boundary: `setImmediate` where there is one — the current turn's check phase rather than a\n * timer — and `setTimeout` as the portable fallback, for a runtime without it. `flight-inject.ts` has the\n * same two lines and the same reason; they are not shared because that module belongs to the SSR layer, and\n * importing it here would give the RSC layer its own instance of it.\n */\nconst deferTask: (run: () => void) => void =\n typeof setImmediate === 'function'\n ? setImmediate\n : (run) => {\n setTimeout(run, 0);\n };\n\n/**\n * Dev-only: says that a control signal arrived too late to be one.\n *\n * The root fix is in app code, so authoring time is where this has to be said, and a docs paragraph is not\n * where anyone reads it. `isDev` is the baked build flag, so a production server pays one boolean check on a\n * path that has already gone wrong — and says nothing.\n */\nfunction warnLateControlSignal(c: Context, signal: ControlSignal): void {\n const isRedirect = signal instanceof RedirectSignal;\n console.warn(\n `[rshono] ${isRedirect ? `redirect(${JSON.stringify(signal.location)})` : 'notFound()'} was called from a boundary that ` +\n `resolved after the page shell had already been sent (${c.req.method} ${c.req.path}), so it cannot become a real ` +\n `${isRedirect ? '3xx' : '404'}: the response is committed as 200 text/html. A browser with JavaScript follows the ` +\n `digest that rides the payload; one without stays on the Suspense fallback, and a crawler indexes the 200.${\n isRedirect ? '' : ' A JavaScript client recovers by reloading, which renders this same page again.'\n }` +\n ' Decide before the render starts streaming — in Hono middleware, or in the page component body above the boundary.',\n );\n}\n\ninterface ComponentRenderOptions {\n status?: number;\n isRsc: boolean;\n formState?: ReactFormState;\n returnValue?: RscPayload['returnValue'];\n temporaryReferences?: TemporaryReferenceSet;\n /** Passed when the page being rendered is the `error` page, which takes it as an extra prop. */\n errorInfo?: ErrorPageInfo;\n /** Marks the payload as the not-found page, so a soft navigation can tell it apart from the page it asked for. */\n notFound?: boolean;\n}\n\n/**\n * Builds the props a page component is called with.\n *\n * `ctx` is *defined* rather than assigned, and both halves are load-bearing:\n *\n * - **A getter**, so nothing is built for the pages that never read it, and a `render: 'static'` page\n * that does gets {@link getRequestContext}'s prerendering error rather than a bare `undefined`.\n * - **Non-enumerable**, so React's dev-only serialization of a server component's props skips it. That\n * walks own enumerable properties, and `ctx.hono.env` holds the runtime's bindings — an enumerable\n * `ctx` would ship every secret to the browser in dev.\n *\n * The cost: the element is created by handing this object to `jsx()` by reference, since a\n * `<Page {...props} />` spread would silently drop `ctx`.\n */\nfunction pageProps(c: Context, errorInfo: ErrorPageInfo | undefined): PageProps & { error?: ErrorPageInfo } {\n const props = { url: publicUrl(c), params: readParams(c), ...(errorInfo ? { error: errorInfo } : null) };\n Object.defineProperty(props, 'ctx', { get: getRequestContext, enumerable: false, configurable: true });\n return props as PageProps & { error?: ErrorPageInfo };\n}\n\nasync function renderComponent(c: Context, Page: ServerEntry<PageComponent>, opts: ComponentRenderOptions): Promise<Response> {\n // React's renderers must never be handed `c.req.raw.signal`: they add an `abort` listener and only\n // remove it if the abort fires, so on the happy path it stays on a request-lifetime signal and pins the\n // whole rendered tree. The render gets its own controller and the request signal forwards into it —\n // `release` detaches on the normal path. Not `AbortSignal.any()`, whose composite signals Node holds in\n // a process-lifetime set until they abort.\n const requestSignal = c.req.raw.signal;\n const renderAbort = new AbortController();\n const signal = renderAbort.signal;\n const forwardAbort = () => renderAbort.abort(requestSignal.reason);\n if (requestSignal.aborted) renderAbort.abort(requestSignal.reason);\n else requestSignal.addEventListener('abort', forwardAbort, { once: true });\n const release = () => requestSignal.removeEventListener('abort', forwardAbort);\n\n // Documents only: the nonce goes on the bootstrap scripts and the `<meta>` React hydrates from, and a\n // flight payload has neither — which is what keeps a prerendered one servable under a nonce-based CSP.\n const nonce = opts.isRsc ? undefined : cspNonce(c);\n const props = pageProps(c, opts.errorInfo);\n const root = (\n <>\n {nonce && <meta property=\"csp-nonce\" nonce={nonce} />}\n {Page.entryCssFiles?.map((href) => (\n <link key={href} rel=\"stylesheet\" href={href} precedence=\"default\" />\n ))}\n {/* `href`, not the `URL`: these props cross into a client component, so they have to be serializable. */}\n <RouterProvider href={props.url.href} params={props.params}>\n {jsx(Page, props)}\n </RouterProvider>\n </>\n );\n\n // `notFound` only when true, so an ordinary page's payload doesn't carry the key.\n const rscPayload: RscPayload = { root, formState: opts.formState, returnValue: opts.returnValue, ...(opts.notFound ? { notFound: true } : null) };\n\n // The last thing before the render: past here the response head is the framework's, so `ctx.setHeader()`\n // starts throwing — while the action `renderPage` just ran, and the middleware around it, legitimately wrote.\n beginPageRender(c);\n\n let controlSignal: ControlSignal | undefined;\n /** Set once `renderHTML` has returned, which is where the response head stops being changeable. */\n let shellFlushed = false;\n const rscStream = renderToReadableStream(rscPayload, {\n temporaryReferences: opts.temporaryReferences,\n signal,\n onError(error) {\n if (isControlSignal(error)) {\n controlSignal = error;\n if (shellFlushed) {\n if (isDev) warnLateControlSignal(c, error);\n // Past the shell the status line, the headers and the first bytes are on the wire, so the digest\n // React writes into the payload is the only path left — and everything still rendering is for a\n // page the browser is about to navigate away from. Winding it down stops those boundaries, runs\n // `flight-inject`'s cancel/flush, and fires the `release()` above now rather than whenever the\n // doomed render happens to finish.\n //\n // One macrotask later rather than from inside `onError`, where React is still handling the error\n // that produced the digest — the row carrying it is the only recovery the client has, and an abort\n // that re-entered React there could cut the render off before it is written. Measured to survive\n // either way on react-server-dom-rspack 0.1.0; deferred anyway, because that ordering is an\n // internal the `^19.1.0` peer range does not promise, and the cost is one macrotask on a render\n // that is already doomed. The reason is the signal itself, so every boundary the abort errors\n // carries the digest rather than a bare AbortError the client would paint as a fault.\n if (!signal.aborted) deferTask(() => renderAbort.abort(error));\n }\n return error.digest;\n }\n if (!signal.aborted) reportServerError(error, { source: 'render', hono: c, message: '[rshono] render error:' });\n },\n });\n\n if (opts.isRsc) {\n return c.body(releaseWhenDone(rscStream, release), (opts.status ?? 200) as ContentfulStatusCode, {\n 'content-type': 'text/x-component;charset=utf-8',\n });\n }\n\n let ssrResult: Awaited<ReturnType<typeof renderHTML>>;\n try {\n ssrResult = await renderHTML(rscStream, {\n bootstrapScripts: Page.entryJsFiles,\n formState: opts.formState,\n signal,\n nonce,\n onDone: release,\n onShellError: (error) => reportServerError(error, { source: 'ssr', hono: c, message: '[rshono] SSR shell error:' }),\n onError: (error) => reportServerError(error, { source: 'ssr', hono: c, message: '[rshono] SSR error:' }),\n });\n } catch (error) {\n release();\n if (controlSignal) throw controlSignal;\n throw error;\n }\n // `renderHTML` returns at *shell ready*, so from here the response is the one that ships. Set before the\n // check below rather than after it, so nothing lands in the window between the two: a signal that arrives\n // in it is handled there *and* schedules an abort, and aborting an aborted controller is a no-op.\n shellFlushed = true;\n if (controlSignal) {\n // The shell resolved, so this response is live: React is being pumped into the payload-injecting\n // transform, and a `redirect()` that surfaced from a boundary settling just before the shell was ready\n // lands here. Nothing will read that stream now — the signal becomes a redirect instead — so it is stopped\n // rather than left to render to completion for a response that was replaced.\n //\n // Both calls, because they stop different halves. `abort` reaches the two renders through the signal they\n // were handed; cancelling the response readable propagates back through the transform to release the teed\n // flight branch it holds a reader on, which `abort` alone does not.\n renderAbort.abort();\n void ssrResult.stream.cancel().catch(() => {\n // Already errored or locked — there is nothing left to release either way.\n });\n release();\n throw controlSignal;\n }\n return c.body(ssrResult.stream, (ssrResult.status ?? opts.status ?? 200) as ContentfulStatusCode, {\n 'content-type': 'text/html;charset=utf-8',\n });\n}\n\nasync function renderPage(c: Context, loadPage: () => Promise<ServerEntry<PageComponent>>): Promise<Response> {\n const request = c.req.raw;\n const renderRequest = parseRenderRequest(request);\n\n let returnValue: ActionResult | undefined;\n let formState: ReactFormState | undefined;\n let temporaryReferences: TemporaryReferenceSet | undefined;\n let actionStatus: number | undefined;\n if (isActionRequest(renderRequest)) {\n if (renderRequest.kind === 'rsc-action') {\n // Before the body is decoded, so an unknown id costs nothing to reject. `hasOwn` so `__proto__`\n // does not resolve to a manifest entry.\n if (!Object.hasOwn(__rspack_rsc_manifest__.serverManifest, renderRequest.actionId)) {\n return c.text('Bad Request: unknown server action', 400);\n }\n const contentType = request.headers.get('content-type');\n const body = contentType?.startsWith('multipart/form-data') ? await request.formData() : await request.text();\n temporaryReferences = createTemporaryReferenceSet();\n const args = await decodeReply<unknown[]>(body, { temporaryReferences });\n const action = loadServerAction(renderRequest.actionId);\n try {\n returnValue = { ok: true, value: await action(...args) };\n } catch (error) {\n if (isControlSignal(error)) throw error;\n // In production React sends a thrown action error to the client as an opaque marker, so this is\n // the only place the real one is visible.\n reportServerError(error, { source: 'action', hono: c, message: '[rshono] server action error:' });\n returnValue = { ok: false, error };\n actionStatus = 500;\n }\n // The action is done and its result is the caller's, whatever becomes of the render below. See\n // {@link actionResults}.\n actionResults.set(c, returnValue);\n } else {\n // A `<form action={serverAction}>` post, which is the path that runs before hydration and with\n // JavaScript off. Unlike the client-initiated one it carries no custom header, so it is also the only\n // action shape a browser can be made to send from another site: see `refusesCrossSiteForm`.\n if (refusesCrossSiteForm(c)) {\n return c.text('Forbidden: cross-site form post to a server action', 403, { vary: RSC_VARY_HEADER });\n }\n const formData = await request.formData();\n const decodedAction = await decodeAction(formData, __rspack_rsc_manifest__.serverManifest);\n if (decodedAction) {\n let result: unknown;\n try {\n result = await decodedAction();\n } catch (error) {\n if (isControlSignal(error)) throw error;\n // Reported here so a no-JS form post is attributed to the action that threw, exactly as the\n // client-initiated path is — the top-level handler would call it a `request`. Then re-thrown,\n // because this path has no client boundary and no `useActionState` to hand the error to, so the\n // app's `error` page is the honest answer. `reportServerError` de-duplicates, so the re-throw\n // reaching `onError` does not report it a second time.\n reportServerError(error, { source: 'action', hono: c, message: '[rshono] server action error:' });\n throw error;\n }\n formState = (await decodeFormState(result, formData, __rspack_rsc_manifest__.serverManifest)) ?? undefined;\n }\n }\n }\n\n const Page = await loadPage();\n return renderComponent(c, Page, {\n status: actionStatus,\n isRsc: wantsRsc(renderRequest),\n formState,\n returnValue,\n temporaryReferences,\n });\n}\n\nfunction buildApp(): Hono {\n const app = new Hono();\n\n // A floor, not a policy: an app wanting the full set registers `secureHeaders()` in src/server.ts, and\n // because this is registered first it unwinds last, so the \"only if unset\" checks stand aside for it.\n // Owned by the framework so that an app with no src/server.ts at all still gets it.\n app.use(async (c, next) => {\n await next();\n const headers = c.res.headers;\n if (!headers.has('x-content-type-options')) headers.set('x-content-type-options', 'nosniff');\n if (!headers.has('referrer-policy')) headers.set('referrer-policy', 'strict-origin-when-cross-origin');\n if (!headers.has('x-frame-options')) headers.set('x-frame-options', 'SAMEORIGIN');\n\n // React Refresh compiles updates with `eval`, so a dev build cannot run under a production CSP.\n // Widened here so one policy in src/server.ts serves both.\n if (isDev) {\n const csp = headers.get('content-security-policy');\n if (csp?.includes('script-src ')) {\n headers.set('content-security-policy', csp.replace('script-src ', \"script-src 'unsafe-eval' \"));\n }\n }\n\n // Page responses only from here down.\n if (!PAGE_CONTENT_TYPE.test(headers.get('content-type') ?? '')) return;\n appendVary(headers, RSC_VARY_HEADER);\n if (!headers.has('cache-control')) headers.set('cache-control', PAGE_CACHE_CONTROL);\n });\n\n // First, so the app's own middleware (`csrf()`, `bodyLimit()`, auth, logging) wraps everything registered\n // below: the page routes, and the asset handlers too. Assets used to be mounted ahead of this, which left\n // `/_static/*` answered by a terminal handler nothing of the app's ever saw — no `secureHeaders()`, and so\n // no HSTS on exactly the requests a downgrade attack lands on. The flip side is the same one it always had,\n // one path wider: a *terminal* handler in src/server.ts shadows a page at the same path, and unscoped\n // middleware now also runs for `/_static`, which is a reserved prefix an app should not be matching on\n // purpose anyway.\n if (serverApp) {\n app.route('/', serverApp);\n }\n\n runtime.mountStaticAssets(app);\n\n const memoizePage = (page: FallbackPage, label: string) => once(() => loadPageModule(page.component, label));\n const loadNotFoundPage = routeConfig.notFound ? memoizePage(routeConfig.notFound, 'the notFound page') : null;\n\n /** Turns a thrown `redirect()` / `notFound()` into the response it stands for. */\n const respondToControlSignal = async (c: Context, signal: ControlSignal): Promise<Response> => {\n const isRsc = requestWantsRsc(c.req.raw);\n if (signal instanceof RedirectSignal) {\n if (isRsc) {\n // No `signal`: two fields and no component tree, so there is nothing worth aborting.\n return c.body(renderToReadableStream({ root: null, redirect: signal.location } satisfies RscPayload), 200, {\n 'content-type': 'text/x-component;charset=utf-8',\n });\n }\n return c.redirect(signal.location, signal.status as RedirectStatusCode);\n }\n if (loadNotFoundPage) {\n try {\n return await renderComponent(c, await loadNotFoundPage(), { status: 404, isRsc, notFound: true });\n } catch (error) {\n // The `notFound` page is already the answer to a request that went wrong, so a failure here has\n // nowhere to escalate to: this runs from `onError` as well as from the page handler, and Hono calls\n // `onError` inside its own catch — a throw from there rejects `app.fetch`, which\n // `@hono/node-server` turns into a bodiless 500 with nothing in the log. So it is answered here, the\n // way a failing `error` page is answered below.\n //\n // A `redirect()` from the page is the exception: nothing is committed yet, the branch above cannot\n // fail, and this is what the same page does when `app.notFound` renders it — so it is honoured, and\n // recurses exactly once.\n if (error instanceof RedirectSignal) return respondToControlSignal(c, error);\n reportServerError(error, { source: 'render', hono: c, message: '[rshono] the notFound page failed to render:' });\n }\n }\n return plainNotFound(c);\n };\n\n for (const route of routes) {\n if (isPageRoute(route)) {\n // Both fixed for the life of the process, so resolved once rather than per request.\n const servesPrerendered = !isDev && route.render === 'static';\n const loadPage = once(() => loadPageModule(route.component, `\"${route.path}\"`));\n\n /** Everything the route answers, before a HEAD has its body taken off it. */\n const respond = async (c: Context): Promise<Response> => {\n try {\n // A HEAD takes the GET path, prerendered bytes included: the headers it promises are the ones a\n // GET would send, `etag` and `content-length` among them.\n if (servesPrerendered && (c.req.method === 'GET' || c.req.method === 'HEAD')) {\n const isRsc = asksForRsc(c.req.raw);\n // One fixed set of bytes cannot carry a per-request nonce, so a document has to be rendered\n // where the app's CSP has one. Decided per request, so an app whose policy carries no `NONCE`\n // keeps its prerendered documents. A flight payload never carries a nonce either way.\n const mustRenderForNonce = !isRsc && cspNonce(c) !== undefined;\n if (!mustRenderForNonce) {\n const page = await runtime.readPrerendered(c, isRsc ? 'flight' : 'html');\n // Request-independent by construction, so it is safe to cache publicly; the ETag turns the\n // revalidation that follows into a 304. Answered outside `runWithContext` — no app code runs\n // on this path, so there is no `getRequestContext()` to serve.\n if (page !== null) {\n const headers = {\n 'cache-control': SSG_CACHE_CONTROL,\n etag: page.etag,\n vary: RSC_VARY_HEADER,\n 'content-type': isRsc ? 'text/x-component;charset=utf-8' : 'text/html;charset=utf-8',\n };\n if (etagMatches(c.req.header('if-none-match'), page.etag)) return c.body(null, 304, headers);\n return c.body(page.body, 200, { ...headers, 'content-length': page.contentLength });\n }\n }\n }\n return await runWithContext(c, () => renderPage(c, loadPage));\n } catch (error) {\n if (isControlSignal(error)) return runWithContext(c, () => respondToControlSignal(c, error));\n throw error;\n }\n };\n\n const handler: Handler = async (c) => {\n const response = await respond(c);\n // Hono dispatches a HEAD to the GET route and then rebuilds the response as `new Response(null, res)`,\n // which drops the body without reading it — so for a rendered page nothing ever consumes the stream:\n // `flight-inject`'s `cancel` never runs, and neither does the `release()` that detaches the abort\n // forwarder from the request signal. Cancelling here is what ends the render nobody asked to read.\n if (c.req.method === 'HEAD' && response.body !== null) {\n void response.body.cancel().catch(() => {\n // Already errored or locked, and there is nothing left to release either way.\n });\n return new Response(null, response);\n }\n return response;\n };\n app.on(['GET', 'POST'], route.path, handler);\n } else {\n const loadEndpoint = once(() => route.server());\n const handler: Handler = async (c, next) => {\n const { handler: endpointHandler } = await loadEndpoint();\n // Hono's `Handler` leaves its return parameter defaulted to `any`, so this hands back exactly what\n // the app's own handler is declared to return — there is nothing narrower to assert here.\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return endpointHandler(c, next);\n };\n // De-duplicated, because `app.on(['GET', 'GET'], …)` registers the path twice. Validation refuses\n // `'all'` inside a list, so a list that reaches here is concrete methods only.\n const methods = [...new Set([route.method ?? 'all'].flat())];\n if (methods.includes('all')) app.all(route.path, handler);\n else {\n app.on(\n methods.map((method) => method.toUpperCase()),\n route.path,\n handler,\n );\n }\n }\n }\n\n runtime.mountPublicFallback(app);\n\n app.notFound(async (c) => {\n const isRsc = requestWantsRsc(c.req.raw);\n if (loadNotFoundPage && (isRsc || acceptsHtml(c))) {\n // `notFound: true` here as well as on the signal path: the two produce the same page for the same\n // status, and a payload that says so from one route and not the other is a wire contract with a hole\n // in it. The client reads it to tell \"this is the 404 page\" from \"this is the page you asked for\".\n return runWithContext(c, async () => renderComponent(c, await loadNotFoundPage(), { status: 404, isRsc, notFound: true }));\n }\n return plainNotFound(c);\n });\n\n const loadErrorPage = routeConfig.error ? memoizePage(routeConfig.error, 'the error page') : null;\n app.onError(async (error, c) => {\n if (isControlSignal(error)) return runWithContext(c, () => respondToControlSignal(c, error));\n // Registering an `onError` replaces Hono's default handler, which is what turns an `HTTPException`\n // into the response it carries — without this, `csrf()`'s 403 and `bodyLimit()`'s 413 would both\n // surface as a 500 error page. Rebuilt through `c`, as Hono's default does, so headers middleware\n // already prepared survive.\n if (error instanceof HTTPException) {\n const res = error.getResponse();\n return c.newResponse(res.body, res);\n }\n reportServerError(error, { source: 'request', hono: c, message: '[rshono] request error:' });\n const isRsc = requestWantsRsc(c.req.raw);\n if (loadErrorPage && (isRsc || acceptsHtml(c))) {\n const errorInfo: ErrorPageInfo = isDev\n ? {\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n }\n : { message: 'Internal Server Error' };\n try {\n return await runWithContext(c, async () =>\n renderComponent(c, await loadErrorPage(), { status: 500, isRsc, errorInfo, returnValue: actionResults.get(c) }),\n );\n } catch (renderError) {\n reportServerError(renderError, { source: 'request', hono: c, message: '[rshono] the error page failed to render:' });\n }\n }\n const detail = isDev ? `\\n\\n${error instanceof Error ? (error.stack ?? error.message) : String(error)}` : '';\n // Same reason as `plainNotFound`, minus the urgency: a 500 is not heuristically cacheable, so this half\n // is consistency — the framework's own answers should not differ in what they promise about caching.\n return c.text(`Internal Server Error${detail}`, 500, { vary: RSC_VARY_HEADER, 'cache-control': PAGE_CACHE_CONTROL });\n });\n\n return app;\n}\n\nexport const app = buildApp();\n\n/**\n * The app, handed to whatever is hosting it: this binds a port and exports nothing where rshono owns the\n * process, and *is* the export the platform looks for where the host owns it — so one entry serves both.\n *\n * `app` and `routes` stay named exports either way, because `rshono build` imports them to prerender\n * `render: 'static'` routes.\n */\nexport default runtime.serveApp(app);\n"]}
|
|
@@ -20,5 +20,5 @@ export type CancellableTransformer<I, O> = Transformer<I, O> & {
|
|
|
20
20
|
export declare function injectFlightPayload(rscStream: ReadableStream<Uint8Array>, options?: {
|
|
21
21
|
nonce?: string;
|
|
22
22
|
onDone?: () => void;
|
|
23
|
-
}):
|
|
23
|
+
}): ReadableWritablePair<Uint8Array, Uint8Array>;
|
|
24
24
|
//# sourceMappingURL=flight-inject.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flight-inject.d.ts","sourceRoot":"","sources":["../../src/runtime/flight-inject.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,sBAAsB,CAAC,CAAC,EAAE,CAAC,IAAI,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG;IAAE,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;CAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"flight-inject.d.ts","sourceRoot":"","sources":["../../src/runtime/flight-inject.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,sBAAsB,CAAC,CAAC,EAAE,CAAC,IAAI,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG;IAAE,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;CAAE,CAAC;AAiFvG,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,cAAc,CAAC,UAAU,CAAC,EACrC,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;CAAO,GACpD,oBAAoB,CAAC,UAAU,EAAE,UAAU,CAAC,CA6S9C"}
|
|
@@ -48,14 +48,51 @@ function endsWithTrailer(buffer, length) {
|
|
|
48
48
|
}
|
|
49
49
|
return true;
|
|
50
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* How many of `buffer`'s last bytes could still turn into the document trailer — the length of the longest
|
|
53
|
+
* suffix of `buffer[0..length)` that is a prefix of it, `TRAILER_BYTES.length` for the whole thing.
|
|
54
|
+
*
|
|
55
|
+
* At most 14 bytes are ever held back, and in practice 0: a React flush ends with a closed tag, not with the
|
|
56
|
+
* start of one. Cheaper than it looks, too — the first comparison rejects every suffix whose first byte is
|
|
57
|
+
* not `<`.
|
|
58
|
+
*/
|
|
59
|
+
function trailerPrefixLength(buffer, length) {
|
|
60
|
+
candidate: for (let take = Math.min(length, TRAILER_BYTES.length); take > 0; take--) {
|
|
61
|
+
const from = length - take;
|
|
62
|
+
for (let i = 0; i < take; i++)
|
|
63
|
+
if (buffer[from + i] !== TRAILER_BYTES[i])
|
|
64
|
+
continue candidate;
|
|
65
|
+
return take;
|
|
66
|
+
}
|
|
67
|
+
return 0;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The characters a CSP nonce may be made of: base64 and base64url, which is what every generator of one emits
|
|
71
|
+
* — Hono's `secureHeaders()`, the only source the framework reads, produces base64 of 16 random bytes.
|
|
72
|
+
*
|
|
73
|
+
* The tag below is built by hand rather than by React, so this is the one attribute value in a rendered
|
|
74
|
+
* document that nothing else escapes. The value is not attacker-controlled today, but the framework does not
|
|
75
|
+
* own where it comes from: `c.get('secureHeadersNonce')` is an ordinary context variable that any middleware
|
|
76
|
+
* can set, and a nonce carrying a `"` would close the attribute and open a script-injection point in the
|
|
77
|
+
* document. Anything outside this set is dropped rather than escaped, because a value made of other characters
|
|
78
|
+
* is not a nonce at all: a page whose payload scripts the policy then refuses is the visible failure to have,
|
|
79
|
+
* where an escaped garbage nonce would be a silent one.
|
|
80
|
+
*/
|
|
81
|
+
const NONCE_CHARS = /^[A-Za-z0-9+/=_-]+$/;
|
|
51
82
|
export function injectFlightPayload(rscStream, options = {}) {
|
|
52
83
|
const { nonce, onDone } = options;
|
|
53
|
-
const
|
|
84
|
+
const safeNonce = nonce !== undefined && NONCE_CHARS.test(nonce) ? nonce : undefined;
|
|
85
|
+
const scriptOpen = `<script${safeNonce ? ` nonce="${safeNonce}"` : ''}>(self.__FLIGHT_DATA||=[]).push(`;
|
|
54
86
|
const scriptClose = ')</script>';
|
|
55
87
|
const { promise: flightWritten, resolve: flightDone } = Promise.withResolvers();
|
|
56
88
|
let startedFlight = false;
|
|
57
89
|
const batch = [];
|
|
58
90
|
let boundary = null;
|
|
91
|
+
/**
|
|
92
|
+
* The tail of the last batch that could still be the start of the document trailer, carried into the next
|
|
93
|
+
* one. See {@link emitBatch}.
|
|
94
|
+
*/
|
|
95
|
+
let carry = null;
|
|
59
96
|
/**
|
|
60
97
|
* Set once the consumer has gone away, so nothing tries to enqueue into a readable that cannot take it.
|
|
61
98
|
*
|
|
@@ -67,16 +104,106 @@ export function injectFlightPayload(rscStream, options = {}) {
|
|
|
67
104
|
/** Held so {@link cancelled} can release the teed RSC branch rather than leaving it to be pumped. */
|
|
68
105
|
let flightReader = null;
|
|
69
106
|
/**
|
|
70
|
-
*
|
|
71
|
-
*
|
|
107
|
+
* One permit per chunk the consumer has asked for: the backpressure a `TransformStream` alone does not give
|
|
108
|
+
* this module.
|
|
109
|
+
*
|
|
110
|
+
* A transform's writable side parks a write while its readable's queue is over the mark, which covers the
|
|
111
|
+
* HTML — but only once something has been enqueued, and `transform` defers that to a macrotask. So a
|
|
112
|
+
* producer that writes a whole document without ever yielding the microtask queue is admitted in full, and
|
|
113
|
+
* {@link writeFlight}, which pumps the payload into the same controller from a detached promise, is never
|
|
114
|
+
* gated at all: measured, a consumer that read one chunk and stalled still pulled all 500 chunks of a test
|
|
115
|
+
* payload into the queue, where this brings it down to 3. `controller.desiredSize` is no help — a transform
|
|
116
|
+
* readable's high-water mark is 0, so it is never positive.
|
|
117
|
+
*
|
|
118
|
+
* The wrapper readable this function returns is the missing signal: its `pull` runs exactly when the
|
|
119
|
+
* consumer wants another chunk, and releases one permit. Both producers — the HTML batcher and the payload
|
|
120
|
+
* pump — take one before they enqueue, so a stalled client parks React instead of filling the process. The
|
|
121
|
+
* Streams standard calls `pull` again only once the previous call has settled, and a call only settles once
|
|
122
|
+
* a chunk has arrived, so permits are handed out one at a time and the queue is bounded at a chunk.
|
|
123
|
+
*
|
|
124
|
+
* What is left buffered is one React flush, because a flush has to leave here as a single chunk (see
|
|
125
|
+
* {@link emitBatch}) — the same bound React itself holds while it builds one. The two enqueues in `flush`
|
|
126
|
+
* are ungated for a related reason: the response is over by then, and parking its last two chunks on a
|
|
127
|
+
* permit would only add a way for it not to end. They are also why the count can reach two at the very
|
|
128
|
+
* end — an ungated enqueue settles a pull without spending its permit — which is harmless, there being
|
|
129
|
+
* nothing left to produce.
|
|
130
|
+
*
|
|
131
|
+
* The cost is one extra stream hop and a microtask per chunk: 3.6ms → 4.0ms to push a 187 kB page through
|
|
132
|
+
* this module with nothing else in the way, which is not the shape of a real response, where the socket
|
|
133
|
+
* dominates by orders of magnitude.
|
|
134
|
+
*/
|
|
135
|
+
let permits = 0;
|
|
136
|
+
const waiting = [];
|
|
137
|
+
/** Returns nothing when a permit was already free, so the common case costs no microtask. */
|
|
138
|
+
function takePermit() {
|
|
139
|
+
// Nothing will release another permit once the consumer is gone, and there is nothing left to protect:
|
|
140
|
+
// the caller goes on to a failing enqueue, which is what tears the pipeline down.
|
|
141
|
+
if (cancelled)
|
|
142
|
+
return;
|
|
143
|
+
if (permits > 0) {
|
|
144
|
+
permits--;
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
return new Promise((resolve) => waiting.push(resolve));
|
|
148
|
+
}
|
|
149
|
+
function releasePermit() {
|
|
150
|
+
const next = waiting.shift();
|
|
151
|
+
if (next)
|
|
152
|
+
next();
|
|
153
|
+
else
|
|
154
|
+
permits++;
|
|
155
|
+
}
|
|
156
|
+
/** Fires `onDone` at most once, however the response ended — both cancel paths can reach it. */
|
|
157
|
+
let ended = false;
|
|
158
|
+
function reportDone() {
|
|
159
|
+
if (ended)
|
|
160
|
+
return;
|
|
161
|
+
ended = true;
|
|
162
|
+
onDone?.();
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* The consumer has gone away: stop producing, release everything the request was holding, and unpark both
|
|
166
|
+
* producers so they see {@link cancelled} rather than a permit that will never come.
|
|
72
167
|
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
* a shape it produces.
|
|
168
|
+
* Called from the wrapper readable's `cancel`, which is reliable, and from the transformer's, which the
|
|
169
|
+
* standard skips once the close algorithm has started — so it has to be idempotent.
|
|
76
170
|
*/
|
|
77
|
-
function
|
|
171
|
+
function teardown(reason) {
|
|
172
|
+
cancelled = true;
|
|
173
|
+
if (boundary) {
|
|
174
|
+
unschedule(boundary);
|
|
175
|
+
boundary = null;
|
|
176
|
+
}
|
|
177
|
+
batch.length = 0;
|
|
178
|
+
carry = null;
|
|
179
|
+
for (const resolve of waiting.splice(0))
|
|
180
|
+
resolve();
|
|
181
|
+
// Otherwise the teed RSC branch keeps being pumped for a response nobody will read, and the tee's
|
|
182
|
+
// other half buffers every chunk waiting for this one to catch up.
|
|
183
|
+
flightReader?.cancel(reason).catch(() => { });
|
|
184
|
+
// Unparks `flush` if it is waiting on a payload that will now never arrive.
|
|
185
|
+
flightDone();
|
|
186
|
+
reportDone();
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Emits the HTML buffered since the last boundary, holding back the document trailer for `flush` to re-emit
|
|
190
|
+
* after the payload scripts.
|
|
191
|
+
*
|
|
192
|
+
* The batch is joined before the trailer is looked for, so one React split across two views is still found.
|
|
193
|
+
* A trailer split across two *batches* is not a shape React produces — it writes its final flush in one
|
|
194
|
+
* synchronous run — but this injector exists because `rsc-html-stream` made a narrower version of that same
|
|
195
|
+
* assumption and was wrong (see the module header), so anything that could still become a trailer is held
|
|
196
|
+
* back in {@link carry} rather than assumed not to be. Only `final`, the call from `flush`, may emit such a
|
|
197
|
+
* tail: by then there is no next batch for it to complete.
|
|
198
|
+
*
|
|
199
|
+
* A tail that never does complete therefore leaves after the payload scripts rather than before them, which
|
|
200
|
+
* is the deliberate half of the trade: releasing it the moment a script wants to go out is the very bug this
|
|
201
|
+
* guards, because the next batch may be the rest of the trailer. It costs at most 13 bytes of a truncated
|
|
202
|
+
* document arriving late, still inside `<body>`.
|
|
203
|
+
*/
|
|
204
|
+
function emitBatch(controller, final = false) {
|
|
78
205
|
boundary = null;
|
|
79
|
-
let total = 0;
|
|
206
|
+
let total = carry?.byteLength ?? 0;
|
|
80
207
|
for (const chunk of batch)
|
|
81
208
|
total += chunk.byteLength;
|
|
82
209
|
if (total === 0) {
|
|
@@ -85,12 +212,21 @@ export function injectFlightPayload(rscStream, options = {}) {
|
|
|
85
212
|
}
|
|
86
213
|
const joined = new Uint8Array(total);
|
|
87
214
|
let at = 0;
|
|
215
|
+
if (carry) {
|
|
216
|
+
joined.set(carry, at);
|
|
217
|
+
at += carry.byteLength;
|
|
218
|
+
carry = null;
|
|
219
|
+
}
|
|
88
220
|
for (const chunk of batch) {
|
|
89
221
|
joined.set(chunk, at);
|
|
90
222
|
at += chunk.byteLength;
|
|
91
223
|
}
|
|
92
224
|
batch.length = 0;
|
|
93
|
-
const
|
|
225
|
+
const held = final ? (endsWithTrailer(joined, total) ? TRAILER_BYTES.length : 0) : trailerPrefixLength(joined, total);
|
|
226
|
+
const end = total - held;
|
|
227
|
+
// Copied rather than a `subarray`, which would keep the whole joined flush alive for 14 bytes.
|
|
228
|
+
if (held > 0 && !final)
|
|
229
|
+
carry = joined.slice(end);
|
|
94
230
|
if (end > 0)
|
|
95
231
|
controller.enqueue(joined.subarray(0, end));
|
|
96
232
|
}
|
|
@@ -99,7 +235,14 @@ export function injectFlightPayload(rscStream, options = {}) {
|
|
|
99
235
|
// `fatal`, so a chunk that split a multi-byte character throws instead of emitting U+FFFD; the catch
|
|
100
236
|
// below falls back to a byte-exact encoding for it.
|
|
101
237
|
const decoder = new TextDecoder('utf-8', { fatal: true });
|
|
102
|
-
const push = (literal) =>
|
|
238
|
+
const push = async (literal) => {
|
|
239
|
+
const permit = takePermit();
|
|
240
|
+
if (permit)
|
|
241
|
+
await permit;
|
|
242
|
+
if (cancelled)
|
|
243
|
+
return;
|
|
244
|
+
controller.enqueue(encoder.encode(scriptOpen + literal + scriptClose));
|
|
245
|
+
};
|
|
103
246
|
for (;;) {
|
|
104
247
|
if (cancelled)
|
|
105
248
|
return;
|
|
@@ -120,7 +263,7 @@ export function injectFlightPayload(rscStream, options = {}) {
|
|
|
120
263
|
// A failed enqueue means the consumer is gone: release the RSC branch so `flush` unparks now rather
|
|
121
264
|
// than whenever the payload would have ended on its own.
|
|
122
265
|
try {
|
|
123
|
-
push(literal);
|
|
266
|
+
await push(literal);
|
|
124
267
|
}
|
|
125
268
|
catch {
|
|
126
269
|
cancelled = true;
|
|
@@ -132,13 +275,23 @@ export function injectFlightPayload(rscStream, options = {}) {
|
|
|
132
275
|
return;
|
|
133
276
|
const remaining = decoder.decode();
|
|
134
277
|
if (remaining.length)
|
|
135
|
-
push(escapeScript(JSON.stringify(remaining)));
|
|
278
|
+
await push(escapeScript(JSON.stringify(remaining)));
|
|
136
279
|
}
|
|
137
280
|
const transformer = {
|
|
138
|
-
transform(chunk, controller) {
|
|
139
|
-
|
|
140
|
-
|
|
281
|
+
async transform(chunk, controller) {
|
|
282
|
+
if (boundary) {
|
|
283
|
+
batch.push(chunk);
|
|
141
284
|
return;
|
|
285
|
+
}
|
|
286
|
+
// The permit is taken once per *batch*, not once per chunk: React writes a whole flush in one microtask
|
|
287
|
+
// cascade and the flush has to leave here as one chunk (see `emitBatch`), so a per-chunk gate would
|
|
288
|
+
// hand the consumer one chunk per read instead. `transform` is never re-entered concurrently — the
|
|
289
|
+
// writable side serializes it on the promise this returns — so nothing else can claim the batch in
|
|
290
|
+
// between.
|
|
291
|
+
const permit = takePermit();
|
|
292
|
+
if (permit)
|
|
293
|
+
await permit;
|
|
294
|
+
batch.push(chunk);
|
|
142
295
|
// A macrotask, not a microtask: React writes a whole flush in one synchronous run but `pipeThrough`
|
|
143
296
|
// delivers it one microtask at a time, and a script injected between two chunks lands inside a tag.
|
|
144
297
|
boundary = schedule(() => {
|
|
@@ -146,8 +299,10 @@ export function injectFlightPayload(rscStream, options = {}) {
|
|
|
146
299
|
emitBatch(controller);
|
|
147
300
|
}
|
|
148
301
|
catch (error) {
|
|
302
|
+
// A dead consumer, all but always. `teardown` rather than `flightDone` alone: a payload pump parked
|
|
303
|
+
// on a permit has to be unparked too, and the RSC branch it holds released.
|
|
149
304
|
controller.error(error);
|
|
150
|
-
|
|
305
|
+
teardown(error);
|
|
151
306
|
return;
|
|
152
307
|
}
|
|
153
308
|
if (!startedFlight) {
|
|
@@ -163,12 +318,11 @@ export function injectFlightPayload(rscStream, options = {}) {
|
|
|
163
318
|
async flush(controller) {
|
|
164
319
|
// Both of these have to happen *before* the await, and in this order.
|
|
165
320
|
try {
|
|
166
|
-
// Anything still batched belongs ahead of the payload scripts, which sit at the end of
|
|
167
|
-
|
|
321
|
+
// Anything still batched — or carried — belongs ahead of the payload scripts, which sit at the end of
|
|
322
|
+
// `<body>`. Called unconditionally: a `carry` outlives its boundary, and an empty batch returns early.
|
|
323
|
+
if (boundary)
|
|
168
324
|
unschedule(boundary);
|
|
169
|
-
|
|
170
|
-
emitBatch(controller);
|
|
171
|
-
}
|
|
325
|
+
emitBatch(controller, true);
|
|
172
326
|
// A writable side that closed without ever reaching `transform` — an HTML stream with no chunks at
|
|
173
327
|
// all — leaves nothing to have started the payload, and `flightDone` is only ever called from that
|
|
174
328
|
// chain or from `cancel`. Without this the await below parks on a promise nothing will settle and the
|
|
@@ -183,13 +337,10 @@ export function injectFlightPayload(rscStream, options = {}) {
|
|
|
183
337
|
.then(flightDone);
|
|
184
338
|
}
|
|
185
339
|
}
|
|
186
|
-
catch {
|
|
340
|
+
catch (error) {
|
|
187
341
|
// The consumer went away while the batch was being emitted, so there is nothing left to write to and
|
|
188
342
|
// nothing to wait for. Settled explicitly rather than left dangling, so the payload chain is released.
|
|
189
|
-
|
|
190
|
-
flightReader?.cancel().catch(() => { });
|
|
191
|
-
flightDone();
|
|
192
|
-
onDone?.();
|
|
343
|
+
teardown(error);
|
|
193
344
|
return;
|
|
194
345
|
}
|
|
195
346
|
await flightWritten;
|
|
@@ -207,24 +358,40 @@ export function injectFlightPayload(rscStream, options = {}) {
|
|
|
207
358
|
}
|
|
208
359
|
finally {
|
|
209
360
|
// A `finally` because `onDone` releases the abort forwarder in `renderComponent`, however this ended.
|
|
210
|
-
|
|
361
|
+
reportDone();
|
|
211
362
|
}
|
|
212
363
|
},
|
|
213
364
|
cancel(reason) {
|
|
214
|
-
|
|
215
|
-
if (boundary) {
|
|
216
|
-
unschedule(boundary);
|
|
217
|
-
boundary = null;
|
|
218
|
-
}
|
|
219
|
-
batch.length = 0;
|
|
220
|
-
// Otherwise the teed RSC branch keeps being pumped for a response nobody will read, and the tee's
|
|
221
|
-
// other half buffers every chunk waiting for this one to catch up.
|
|
222
|
-
flightReader?.cancel(reason).catch(() => { });
|
|
223
|
-
// Unparks `flush` if it is waiting on a payload that will now never arrive.
|
|
224
|
-
flightDone();
|
|
225
|
-
onDone?.();
|
|
365
|
+
teardown(reason);
|
|
226
366
|
},
|
|
227
367
|
};
|
|
228
|
-
|
|
368
|
+
const inner = new TransformStream(transformer);
|
|
369
|
+
const innerReader = inner.readable.getReader();
|
|
370
|
+
/**
|
|
371
|
+
* A pull-driven wrapper around the transform's readable, and the only reason this function does not simply
|
|
372
|
+
* return the transform: `pull` runs once per chunk the consumer takes, which is the demand signal the two
|
|
373
|
+
* producers park on (see {@link takePermit}). It is also the one cancel notification the standard never
|
|
374
|
+
* skips, which is what makes {@link teardown} reliable.
|
|
375
|
+
*/
|
|
376
|
+
const readable = new ReadableStream({
|
|
377
|
+
async pull(controller) {
|
|
378
|
+
releasePermit();
|
|
379
|
+
const { done, value } = await innerReader.read();
|
|
380
|
+
try {
|
|
381
|
+
if (done)
|
|
382
|
+
controller.close();
|
|
383
|
+
else
|
|
384
|
+
controller.enqueue(value);
|
|
385
|
+
}
|
|
386
|
+
catch {
|
|
387
|
+
// Cancelled while this pull was in flight. `teardown` has already run; there is nobody to hand it to.
|
|
388
|
+
}
|
|
389
|
+
},
|
|
390
|
+
cancel(reason) {
|
|
391
|
+
teardown(reason);
|
|
392
|
+
return innerReader.cancel(reason);
|
|
393
|
+
},
|
|
394
|
+
});
|
|
395
|
+
return { readable, writable: inner.writable };
|
|
229
396
|
}
|
|
230
397
|
//# sourceMappingURL=flight-inject.js.map
|