@tanstack/router-core
Version:
Modern and scalable routing for React applications
1 lines • 40.1 kB
Source Map (JSON)
{"version":3,"file":"transformStreamWithRouter.cjs","names":[],"sources":["../../../src/ssr/transformStreamWithRouter.ts"],"sourcesContent":["import { Readable } from 'node:stream'\nimport {\n DOCUMENT_CLOSE_ANCHOR_INDEX,\n DOCUMENT_CLOSE_BYTES,\n SCRIPT_CLOSE_ANCHOR_INDEX,\n SCRIPT_CLOSE_BYTES,\n advanceByteMatcher,\n encodeIntoBoundedChunk,\n findExactBytes,\n getExactBytesPrefixAtEnd,\n} from './htmlBoundaryScanner'\nimport {\n HYDRATION_SCRIPT_BOUNDARY_ANCHOR_INDEX,\n HYDRATION_SCRIPT_BOUNDARY_BYTES,\n HydrationScriptOutputState,\n} from './hydrationScripts'\nimport type { ReadableStream as NodeReadableStream } from 'node:stream/web'\nimport type { AnyRouter } from '../router'\nimport type { ByteMatcherState } from './htmlBoundaryScanner'\nimport type { HydrationScriptOutput } from './hydrationScripts'\n\nexport type TransformStreamWithRouterOptions = {\n /** Timeout for serialization to complete after app render finishes (default: 60000ms) */\n timeoutMs?: number\n /** Maximum lifetime of the stream transform. Defaults to twice timeoutMs. */\n lifetimeMs?: number\n /** Cancels the transform and releases SSR state when the request ends. */\n signal?: AbortSignal\n /**\n * Additional point after which the renderer guarantees that a router script\n * can be inserted. This is an adapter contract, not a user streaming policy.\n * The router boundary, canonical document close, and EOF are always safe.\n */\n rendererSafePoint?: 'script-close' | 'record-end'\n /**\n * Called exactly once when the stream is torn down due to abort/error/\n * cancel/timeout — NOT on natural successful completion. Use this to\n * abort a hidden producer upstream of any stream passed to this transform.\n * Errors thrown from this callback are swallowed.\n */\n onAbort?: (reason?: unknown) => void\n}\n\ntype AppStreamValue = Uint8Array | string\n/** Renderer output: UTF-8 bytes, or string records from a Node pipeable. */\ntype AppStream =\n | ReadableStream<Uint8Array>\n | ReadableStream<string>\n | ReadableStream<AppStreamValue>\n | NodeReadableStream<AppStreamValue>\n\nexport function transformPipeableStreamWithRouter(\n router: AnyRouter,\n routerStream: Readable,\n opts?: TransformStreamWithRouterOptions,\n) {\n return Readable.fromWeb(\n transformReadableStreamWithRouter(\n router,\n Readable.toWeb(routerStream) as AppStream,\n opts,\n ) as NodeReadableStream<Uint8Array>,\n )\n}\n\nexport async function transformHtmlStringWithRouter(\n router: AnyRouter,\n html: string,\n opts?: TransformStreamWithRouterOptions,\n) {\n const serverSsr = router.serverSsr\n if (!serverSsr) {\n throw new Error('Invariant failed: router.serverSsr is required')\n }\n const hydrationScripts = serverSsr.hydrationScripts\n if (hydrationScripts.reserveFastPath()) {\n try {\n opts?.signal?.throwIfAborted()\n serverSsr.setRenderFinished()\n return '<!DOCTYPE html>' + html\n } catch (error) {\n try {\n opts?.onAbort?.(error)\n } catch {\n // User cleanup must not block SSR cleanup.\n }\n throw error\n } finally {\n serverSsr.cleanup()\n }\n }\n\n // The merge path chunks string records itself.\n const appStream = new ReadableStream<string>({\n start(controller) {\n controller.enqueue('<!DOCTYPE html>')\n controller.enqueue(html)\n controller.close()\n },\n })\n const output = transformReadableStreamWithRouter(router, appStream, opts)\n return readUtf8Stream(output)\n}\n\nasync function readUtf8Stream(stream: ReadableStream<Uint8Array>) {\n const reader = stream.getReader()\n const decoder = new TextDecoder()\n let text = ''\n try {\n for (;;) {\n const { done, value } = await reader.read()\n if (done) {\n break\n }\n text += decoder.decode(value, { stream: true })\n }\n return text + decoder.decode()\n } finally {\n reader.releaseLock()\n }\n}\n\nconst DEFAULT_SERIALIZATION_TIMEOUT_MS = 60_000\nconst MIN_APPLICATION_STRING_CHUNK_BYTES = 256\nconst MAX_APPLICATION_STRING_CHUNK_BYTES = 64 * 1024\n\nconst ApplicationPhase = {\n BeforeBoundary: 0,\n Merge: 1,\n HeldClose: 2,\n PassThrough: 3,\n} as const\n\ntype ApplicationPhase = (typeof ApplicationPhase)[keyof typeof ApplicationPhase]\ntype Termination = 'complete' | 'cancel' | 'failure'\ntype AppStreamReader = ReadableStreamDefaultReader<AppStreamValue>\n\nfunction releaseReader(reader: AppStreamReader) {\n try {\n reader.releaseLock()\n } catch {\n // A nonstandard reader may still reject lock release.\n }\n}\n\nfunction cancelReader(reader: AppStreamReader, reason?: unknown) {\n const cancelled = reader.cancel(reason).catch(() => {})\n // Native readers close synchronously when cancel() starts. Release the lock\n // before an arbitrary underlying cancel promise has a chance to park.\n releaseReader(reader)\n return cancelled\n}\n\nfunction finalizeSsrStream(\n kind: Termination,\n reason: unknown,\n controller: ReadableStreamDefaultController<Uint8Array>,\n reader: AppStreamReader,\n serverSsr: NonNullable<AnyRouter['serverSsr']>,\n onAbort?: (reason?: unknown) => void,\n) {\n try {\n if (kind === 'complete') {\n controller.close()\n } else if (kind === 'failure') {\n controller.error(reason)\n }\n } catch {\n // The stream already reached a terminal state.\n }\n\n const aborted = kind !== 'complete'\n if (aborted) {\n try {\n onAbort?.(reason)\n } catch {\n // User cleanup must not block SSR cleanup.\n }\n }\n\n const readerDone = aborted\n ? cancelReader(reader, reason)\n : releaseReader(reader)\n serverSsr.cleanup()\n return readerDone\n}\n\nfunction getLifetimeMs(opts?: TransformStreamWithRouterOptions) {\n return (\n opts?.lifetimeMs ??\n (opts?.timeoutMs ?? DEFAULT_SERIALIZATION_TIMEOUT_MS) * 2\n )\n}\n\n// External serverSsr.cleanup() severs router ownership. The transform must\n// release the renderer, timers, listeners, and buffers immediately instead of\n// retaining them until the lifetime backstop fires. AbortError identifies this\n// intentional cancellation to downstream consumers.\nfunction createCleanupAbortError() {\n const error = new Error('SSR stream transform aborted by router SSR cleanup')\n error.name = 'AbortError'\n return error\n}\n\nfunction listenForAbort(\n signal: AbortSignal | undefined,\n onAbort: (reason: unknown) => void,\n) {\n if (!signal) {\n return undefined\n }\n const listener = () => onAbort(signal.reason)\n signal.addEventListener('abort', listener, { once: true })\n return () => signal.removeEventListener('abort', listener)\n}\n\n/**\n * Create a timer that does not keep the Node.js process alive when this\n * last-resort stream backstop is the only remaining work.\n *\n * Node's global `setTimeout()` returns a `Timeout` object with `unref()`.\n * Web-standard runtimes return a numeric timer ID instead. Cloudflare Workers\n * retain that Web behavior for global timers even when `nodejs_compat` is\n * enabled. Accessing an optional property on a numeric ID is safe, so timer\n * creation can normalize the Node-only capability without allocating a\n * wrapper object. The native handle is returned unchanged for `clearTimeout`.\n */\nfunction setUnrefTimeout(callback: () => void, timeoutMs: number) {\n const handle = setTimeout(callback, timeoutMs)\n const portableHandle = handle as typeof handle & { unref?: () => void }\n portableHandle.unref?.()\n return handle\n}\n\n/**\n * Arm the shared teardown triggers of a transform stream: the lifetime\n * backstop timer, the request-abort listener, and the external-cleanup\n * listener. Returns a disarm function that `terminate()` calls exactly once;\n * teardown ordering must stay identical between the fast and merge paths.\n */\nfunction armStreamLifecycle(\n serverSsr: NonNullable<AnyRouter['serverSsr']>,\n opts: TransformStreamWithRouterOptions | undefined,\n isTerminal: () => boolean,\n terminate: (kind: Termination, reason?: unknown) => unknown,\n) {\n const signal = opts?.signal\n let lifetimeTimeoutHandle: ReturnType<typeof setTimeout> | undefined\n let stopAbortListener: (() => void) | undefined\n const disarm = () => {\n stopAbortListener?.()\n stopAbortListener = undefined\n if (signal && serverSsr.hydrationScripts.requestSignal === signal) {\n serverSsr.hydrationScripts.requestSignal = undefined\n }\n if (lifetimeTimeoutHandle !== undefined) {\n clearTimeout(lifetimeTimeoutHandle)\n lifetimeTimeoutHandle = undefined\n }\n }\n\n const lifetimeMs = getLifetimeMs(opts)\n lifetimeTimeoutHandle = setUnrefTimeout(() => {\n if (isTerminal()) {\n return\n }\n const error = new Error('Stream lifetime exceeded')\n console.warn(\n `SSR stream transform exceeded maximum lifetime (${lifetimeMs}ms), forcing cleanup`,\n )\n terminate('failure', error)\n }, lifetimeMs)\n stopAbortListener = listenForAbort(signal, (reason) => {\n terminate('failure', reason)\n })\n if (signal) {\n serverSsr.hydrationScripts.requestSignal = signal\n }\n // External serverSsr.cleanup() must release the reader, renderer, timer,\n // and buffers promptly — a parked pump only wakes through its own\n // subscriptions, and a discarded response never pulls at all.\n serverSsr.onCleanup(() => {\n if (!isTerminal()) {\n terminate('failure', createCleanupAbortError())\n }\n })\n return disarm\n}\n\nfunction cleanupFailedStreamCreation(\n serverSsr: NonNullable<AnyRouter['serverSsr']>,\n onAbort: TransformStreamWithRouterOptions['onAbort'],\n error: unknown,\n) {\n try {\n onAbort?.(error)\n } catch {\n // User cleanup must not block SSR cleanup.\n }\n serverSsr.cleanup()\n}\n\nfunction encodeStringSource(value: string, offset: number) {\n const remaining = value.length - offset\n const capacity = Math.min(\n MAX_APPLICATION_STRING_CHUNK_BYTES,\n Math.max(\n MIN_APPLICATION_STRING_CHUNK_BYTES,\n Math.min(value.length, remaining * 3),\n ),\n )\n const output = new Uint8Array(capacity)\n const { read, written } = encodeIntoBoundedChunk(value, offset, output)\n return {\n bytes: written === output.length ? output : output.subarray(0, written),\n read,\n }\n}\n\nexport function transformReadableStreamWithRouter(\n router: AnyRouter,\n appStream: AppStream,\n opts?: TransformStreamWithRouterOptions,\n) {\n const serverSsr = router.serverSsr\n if (!serverSsr) {\n throw new Error('Invariant failed: router.serverSsr is required')\n }\n const hydrationScripts = serverSsr.hydrationScripts\n\n let reader: AppStreamReader\n try {\n reader = appStream.getReader() as AppStreamReader\n } catch (error) {\n cleanupFailedStreamCreation(serverSsr, opts?.onAbort, error)\n throw error\n }\n\n try {\n opts?.signal?.throwIfAborted()\n if (hydrationScripts.reserveFastPath()) {\n // Hydration already drained: pass application output through from the\n // first byte. The merge stream handles this with the same pass-through\n // it uses after hydration finishes mid-stream.\n return makeMergeStream(serverSsr, reader, undefined, opts)\n }\n const hydrationOutput = hydrationScripts.claimOutput()\n if (hydrationOutput.state === HydrationScriptOutputState.Failed) {\n throw hydrationOutput.error\n }\n return makeMergeStream(serverSsr, reader, hydrationOutput, opts)\n } catch (error) {\n void cancelReader(reader, error)\n cleanupFailedStreamCreation(serverSsr, opts?.onAbort, error)\n throw error\n }\n}\n\n// The merge path searches only router- and renderer-owned ASCII delimiters.\n// Application bytes otherwise leave through zero-copy subarray views.\n// Without a hydration output the stream starts in pass-through.\nfunction makeMergeStream(\n serverSsr: NonNullable<AnyRouter['serverSsr']>,\n reader: AppStreamReader,\n hydrationOutput: HydrationScriptOutput | undefined,\n opts?: TransformStreamWithRouterOptions,\n) {\n const hydrationScripts = serverSsr.hydrationScripts\n let controller!: ReadableStreamDefaultController<Uint8Array>\n let terminal = false\n let appDone = false\n let applicationPhase: ApplicationPhase = hydrationOutput\n ? ApplicationPhase.BeforeBoundary\n : ApplicationPhase.PassThrough\n let insertionBoundary = false\n\n let stopHydrationOutputListener: (() => void) | undefined\n let appReadPending = false\n let settledAppRead: ReadableStreamReadValueResult<AppStreamValue> | undefined\n\n let appBytes: Uint8Array | undefined\n let appOffset = 0\n let documentCloseIndex: number | undefined\n let appString: string | undefined\n let appStringOffset = 0\n\n const useScriptCloseSafePoints = opts?.rendererSafePoint === 'script-close'\n const useRecordEndSafePoints = opts?.rendererSafePoint === 'record-end'\n\n // Both matchers are created on first use; pass-through never needs them.\n let barrierMatcher: ByteMatcherState | undefined\n let safePointMatcher: ByteMatcherState | undefined\n // Split document closes carry at most 13 bytes across chunks. This uses\n // findExactBytes + getExactBytesPrefixAtEnd instead of advanceByteMatcher\n // because `</body></html>` repeats its first byte (`<` at 0 and 7), which\n // violates the matcher's unique-first-byte resync precondition.\n let closeCarry: Uint8Array | undefined\n\n let wakeResolve: (() => void) | undefined\n // Assigned after the stream exists; `terminate` can run before that when an\n // already-cleaned owner fires its cleanup listener synchronously.\n let disarmLifecycle = (): void => {}\n\n function waitForWake() {\n return new Promise<void>((resolve) => {\n wakeResolve = resolve\n })\n }\n\n function wakePump() {\n const resolve = wakeResolve\n wakeResolve = undefined\n resolve?.()\n }\n\n // Returns true when a chunk was enqueued. Every process* function\n // propagates this boolean so pump() emits at most one chunk per downstream\n // pull — the backpressure contract of this transform.\n function enqueueAppBytes(value: Uint8Array) {\n if (value.length === 0) {\n return false\n }\n controller.enqueue(value)\n return true\n }\n\n function finishAppChunk() {\n appBytes = undefined\n documentCloseIndex = undefined\n if (\n appString === undefined &&\n useRecordEndSafePoints &&\n closeCarry === undefined\n ) {\n insertionBoundary = true\n }\n }\n\n function emitAppRange(\n end: number,\n safePoint: boolean,\n finishCurrentChunk = end === appBytes!.length,\n ) {\n const value = appBytes!\n const output =\n appOffset === 0 && end === value.length\n ? value\n : value.subarray(appOffset, end)\n appOffset = end\n if (safePoint) {\n insertionBoundary = true\n }\n if (finishCurrentChunk) {\n finishAppChunk()\n }\n return enqueueAppBytes(output)\n }\n\n function loadNextAppStringChunk() {\n const value = appString!\n const encoded = encodeStringSource(value, appStringOffset)\n appStringOffset += encoded.read\n appBytes = encoded.bytes\n appOffset = 0\n if (appStringOffset === value.length) {\n appString = undefined\n }\n }\n\n function processUntilBarrier() {\n const value = appBytes!\n if (!hydrationScripts.isInitialTaken()) {\n // The rendered boundary can only exist after the initial script take,\n // so earlier renderer bytes pass through without scanning. This skips\n // the barrier scan for the whole pre-<Scripts> document and prevents\n // barrier-lookalike bytes in application content from lifting the\n // barrier early.\n return emitAppRange(value.length, false)\n }\n const matchEnd = advanceByteMatcher(\n (barrierMatcher ??= {\n pattern: HYDRATION_SCRIPT_BOUNDARY_BYTES,\n anchorIndex: HYDRATION_SCRIPT_BOUNDARY_ANCHOR_INDEX,\n matched: 0,\n }),\n value,\n appOffset,\n )\n if (matchEnd === undefined) {\n return emitAppRange(value.length, false)\n }\n\n applicationPhase = ApplicationPhase.Merge\n hydrationScripts.liftBarrier()\n return emitAppRange(matchEnd, true)\n }\n\n // Advance past a canonical close that ends `consumed` bytes into the current\n // chunk and hold it until the transform completes.\n function enterHeldClose(consumed: number, prefix: Uint8Array | undefined) {\n appOffset = consumed\n applicationPhase = ApplicationPhase.HeldClose\n if (safePointMatcher) {\n // The removed close breaks byte continuity with later renderer bytes.\n safePointMatcher.matched = 0\n }\n insertionBoundary = true\n if (appOffset === appBytes!.length) {\n finishAppChunk()\n }\n return prefix ? enqueueAppBytes(prefix) : false\n }\n\n function holdDocumentClose(matchStart: number) {\n const value = appBytes!\n return enterHeldClose(\n matchStart + DOCUMENT_CLOSE_BYTES.length,\n matchStart === appOffset\n ? undefined\n : value.subarray(appOffset, matchStart),\n )\n }\n\n function processUntilSafePoint(endIndex: number) {\n const value = appBytes!\n const matchEnd = findSafePointEnd(value, appOffset, endIndex)\n if (matchEnd === undefined) {\n return false\n }\n\n return emitAppRange(matchEnd, true)\n }\n\n function findSafePointEnd(\n value: Uint8Array,\n startIndex: number,\n endIndex: number,\n ) {\n // Merge-only: pass-through never scans for safe points.\n const hydrationState = hydrationOutput!.state\n if (\n endIndex === startIndex ||\n hydrationState === HydrationScriptOutputState.Done\n ) {\n return undefined\n }\n\n const scanValue =\n endIndex === value.length ? value : value.subarray(0, endIndex)\n const matcher = (safePointMatcher ??= {\n pattern: SCRIPT_CLOSE_BYTES,\n anchorIndex: SCRIPT_CLOSE_ANCHOR_INDEX,\n matched: 0,\n })\n // Active drains before app bytes, Done is excluded above, and Failed\n // terminates through the subscriber; only Ready and Waiting reach here.\n const waiting = hydrationState === HydrationScriptOutputState.Waiting\n const matchEnd = advanceByteMatcher(matcher, scanValue, startIndex, waiting)\n if (matchEnd === undefined) {\n return undefined\n }\n if (waiting) {\n // Bytes after the last match are processed again on the next pull.\n matcher.matched = 0\n }\n return matchEnd\n }\n\n function processCloseCarry() {\n const value = appBytes!\n const carry = closeCarry!\n const headLength = Math.min(\n value.length - appOffset,\n DOCUMENT_CLOSE_BYTES.length,\n )\n const combined = new Uint8Array(carry.length + headLength)\n combined.set(carry)\n combined.set(\n value.subarray(appOffset, appOffset + headLength),\n carry.length,\n )\n\n const matchStart = findExactBytes(\n combined,\n DOCUMENT_CLOSE_BYTES,\n 0,\n DOCUMENT_CLOSE_ANCHOR_INDEX,\n )\n const partial =\n matchStart < 0\n ? getExactBytesPrefixAtEnd(combined, DOCUMENT_CLOSE_BYTES)\n : undefined\n const safeEnd = matchStart >= 0 ? matchStart : (partial ?? combined.length)\n\n if (useScriptCloseSafePoints) {\n const safePointEnd = findSafePointEnd(combined, 0, safeEnd)\n if (safePointEnd !== undefined) {\n appOffset += safePointEnd - carry.length\n closeCarry = undefined\n insertionBoundary = true\n if (appOffset === value.length) {\n finishAppChunk()\n }\n return enqueueAppBytes(combined.subarray(0, safePointEnd))\n }\n }\n\n if (matchStart >= 0) {\n closeCarry = undefined\n return enterHeldClose(\n appOffset + matchStart + DOCUMENT_CLOSE_BYTES.length - carry.length,\n matchStart === 0 ? undefined : combined.subarray(0, matchStart),\n )\n }\n\n closeCarry = partial === undefined ? undefined : combined.slice(partial)\n appOffset += headLength\n return enqueueAppBytes(\n safeEnd === combined.length ? combined : combined.subarray(0, safeEnd),\n )\n }\n\n function processUntilDocumentClose() {\n const value = appBytes!\n\n if (closeCarry) {\n if (processCloseCarry()) {\n return true\n }\n if (applicationPhase === ApplicationPhase.HeldClose) {\n return false\n }\n if (appOffset >= value.length) {\n finishAppChunk()\n return false\n }\n }\n\n // Safe points only advance within this chunk, so keep its close or miss.\n const matchStart = (documentCloseIndex ??= findExactBytes(\n value,\n DOCUMENT_CLOSE_BYTES,\n appOffset,\n DOCUMENT_CLOSE_ANCHOR_INDEX,\n ))\n if (matchStart >= 0) {\n if (useScriptCloseSafePoints && processUntilSafePoint(matchStart)) {\n return true\n }\n return holdDocumentClose(matchStart)\n }\n\n const partial = getExactBytesPrefixAtEnd(\n value,\n DOCUMENT_CLOSE_BYTES,\n appOffset,\n )\n const safeEnd = partial ?? value.length\n if (useScriptCloseSafePoints && processUntilSafePoint(safeEnd)) {\n return true\n }\n closeCarry = partial === undefined ? undefined : value.slice(partial)\n return emitAppRange(safeEnd, false, true)\n }\n\n function processAppChunk() {\n if (appOffset >= appBytes!.length) {\n finishAppChunk()\n return false\n }\n insertionBoundary = false\n if (applicationPhase === ApplicationPhase.BeforeBoundary) {\n return processUntilBarrier()\n }\n if (applicationPhase === ApplicationPhase.Merge) {\n return processUntilDocumentClose()\n }\n const value = appBytes!\n if (useScriptCloseSafePoints && processUntilSafePoint(value.length)) {\n return true\n }\n\n return emitAppRange(value.length, false)\n }\n\n function terminate(kind: Termination, reason?: unknown) {\n if (terminal) {\n return\n }\n terminal = true\n\n stopHydrationOutputListener?.()\n stopHydrationOutputListener = undefined\n disarmLifecycle()\n\n settledAppRead = undefined\n appBytes = undefined\n documentCloseIndex = undefined\n appString = undefined\n closeCarry = undefined\n wakePump()\n\n return finalizeSsrStream(\n kind,\n reason,\n controller,\n reader,\n serverSsr,\n opts?.onAbort,\n )\n }\n\n function startAppRead() {\n if (appReadPending || settledAppRead || terminal) {\n return\n }\n appReadPending = true\n void reader.read().then(\n (result) => {\n appReadPending = false\n if (!terminal) {\n if (result.done) {\n acceptAppRead(result)\n } else {\n settledAppRead = result\n }\n wakePump()\n }\n },\n (error) => {\n appReadPending = false\n if (!terminal) {\n handlePumpError(error)\n }\n },\n )\n }\n\n function acceptAppRead(result: ReadableStreamReadResult<AppStreamValue>) {\n if (result.done) {\n appDone = true\n insertionBoundary = closeCarry === undefined\n // The serialization deadline is a transport concern of this merge\n // path; the lifecycle signal below stays a plain notification.\n hydrationScripts.startSerializationTimeout(\n opts?.timeoutMs ?? DEFAULT_SERIALIZATION_TIMEOUT_MS,\n )\n serverSsr.setRenderFinished()\n return\n }\n const value = result.value\n if (typeof value === 'string') {\n if (value.length === 0) {\n return\n }\n appString = value\n appStringOffset = 0\n insertionBoundary = false\n loadNextAppStringChunk()\n return\n }\n if (value.byteLength === 0) {\n return\n }\n appBytes = value\n appOffset = 0\n insertionBoundary = false\n }\n\n async function loadNextAppChunk() {\n if (appString !== undefined) {\n loadNextAppStringChunk()\n return\n }\n if (settledAppRead) {\n const settled = settledAppRead\n settledAppRead = undefined\n acceptAppRead(settled)\n return\n }\n\n const scriptsCanInterruptRead =\n applicationPhase !== ApplicationPhase.BeforeBoundary &&\n insertionBoundary &&\n hydrationOutput!.state !== HydrationScriptOutputState.Done\n if (!scriptsCanInterruptRead && !appReadPending) {\n const result = await reader.read()\n if (terminal) {\n return\n }\n acceptAppRead(result)\n return\n }\n\n const wake = waitForWake()\n startAppRead()\n await wake\n }\n\n // Pass-through forwards application records unchanged and only encodes\n // string records; it skips the merge bookkeeping entirely.\n async function pumpPassThrough() {\n try {\n for (;;) {\n if (appBytes) {\n const remainder =\n appOffset === 0 ? appBytes : appBytes.subarray(appOffset)\n appBytes = undefined\n if (enqueueAppBytes(remainder)) {\n return\n }\n continue\n }\n if (appString !== undefined) {\n loadNextAppStringChunk()\n continue\n }\n if (appDone) {\n terminate('complete')\n return\n }\n if (appReadPending) {\n // A merge-phase prefetch is still in flight; it wakes the pump.\n await waitForWake()\n continue\n }\n let result: ReadableStreamReadResult<AppStreamValue> | undefined =\n settledAppRead\n if (result) {\n settledAppRead = undefined\n } else {\n result = await reader.read()\n if (terminal) {\n return\n }\n }\n if (result.done || typeof result.value === 'string') {\n acceptAppRead(result)\n continue\n }\n if (result.value.byteLength > 0) {\n controller.enqueue(result.value)\n return\n }\n }\n } catch (error) {\n handlePumpError(error)\n }\n }\n\n async function pump() {\n const output = hydrationOutput!\n while (!terminal) {\n const hydrationState = output.state\n if (hydrationState === HydrationScriptOutputState.Active) {\n controller.enqueue(output.pullChunk())\n return\n }\n if (\n applicationPhase !== ApplicationPhase.BeforeBoundary &&\n insertionBoundary &&\n hydrationState === HydrationScriptOutputState.Ready\n ) {\n if (!appDone && !appBytes && appString === undefined) {\n startAppRead()\n }\n controller.enqueue(output.pullChunk())\n return\n }\n if (\n applicationPhase === ApplicationPhase.Merge &&\n hydrationState === HydrationScriptOutputState.Done &&\n closeCarry === undefined &&\n hydrationScripts.reserveFastPath(output)\n ) {\n applicationPhase = ApplicationPhase.PassThrough\n stopHydrationOutputListener?.()\n stopHydrationOutputListener = undefined\n return pumpPassThrough()\n }\n if (appBytes) {\n if (processAppChunk()) {\n return\n }\n continue\n }\n\n if (appDone) {\n if (applicationPhase === ApplicationPhase.BeforeBoundary) {\n // No <Scripts> boundary was rendered. The document is already\n // delivered, so emit the hydration sources after it instead of\n // failing the response.\n hydrationScripts.skipInitialTake()\n applicationPhase = ApplicationPhase.Merge\n insertionBoundary = true\n continue\n }\n if (closeCarry) {\n // A close prefix that never completed is ordinary content, exactly\n // like a document without a canonical close.\n const carry = closeCarry\n closeCarry = undefined\n insertionBoundary = true\n if (enqueueAppBytes(carry)) {\n return\n }\n continue\n }\n if (hydrationState === HydrationScriptOutputState.Waiting) {\n await waitForWake()\n continue\n }\n if (applicationPhase === ApplicationPhase.HeldClose) {\n controller.enqueue(DOCUMENT_CLOSE_BYTES.slice())\n terminate('complete')\n return\n }\n terminate('complete')\n return\n }\n\n await loadNextAppChunk()\n }\n }\n\n function handlePumpError(error: unknown) {\n if (terminal) {\n return\n }\n console.error('Error processing appStream:', error)\n terminate('failure', error)\n }\n\n const stream = new ReadableStream<Uint8Array>({\n start(c) {\n controller = c\n },\n pull() {\n // One async frame per pull: pass-through must stay as cheap as a plain\n // read-and-forward loop.\n return applicationPhase === ApplicationPhase.PassThrough\n ? pumpPassThrough()\n : pump().catch(handlePumpError)\n },\n cancel(reason) {\n return terminate('cancel', reason)\n },\n })\n\n if (hydrationOutput) {\n stopHydrationOutputListener = hydrationOutput.subscribe(() => {\n if (hydrationOutput.state === HydrationScriptOutputState.Failed) {\n terminate('failure', hydrationOutput.error)\n return\n }\n wakePump()\n })\n }\n disarmLifecycle = armStreamLifecycle(\n serverSsr,\n opts,\n () => terminal,\n terminate,\n )\n\n return stream\n}\n"],"mappings":"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"}