@reckona/mreact-server 0.0.138 → 0.0.140
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/boundary.d.ts.map +1 -1
- package/dist/boundary.js +5 -1
- package/dist/boundary.js.map +1 -1
- package/dist/buffer-sink.d.ts.map +1 -1
- package/dist/buffer-sink.js +1 -5
- package/dist/buffer-sink.js.map +1 -1
- package/dist/flight.js +56 -24
- package/dist/flight.js.map +1 -1
- package/dist/html-helpers.js +52 -6
- package/dist/html-helpers.js.map +1 -1
- package/dist/html-internals.d.ts.map +1 -1
- package/dist/html-internals.js +55 -9
- package/dist/html-internals.js.map +1 -1
- package/package.json +3 -3
- package/src/boundary.ts +6 -2
- package/src/buffer-sink.ts +1 -5
- package/src/flight.ts +80 -18
- package/src/html-helpers.ts +68 -5
- package/src/html-internals.ts +71 -9
package/dist/boundary.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boundary.d.ts","sourceRoot":"","sources":["../src/boundary.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0CAA0C,CAAC;AASzE,MAAM,WAAW,oBAAoB;IACnC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACrE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,yBAA0B,SAAQ,oBAAoB;IACrE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAC3D,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,8BAA8B;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,0BAA0B;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,4BAA6B,SAAQ,oBAAoB;IACxE,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gCAAgC;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,mBAAmB,CAAC,CAAC,IAAI,CACnC,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,KACd,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;AAI9B,wBAAsB,mBAAmB,CAAC,CAAC,EACzC,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,CAAC,EACR,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAC,EAC9B,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,IAAI,CAAC,CAgBf;
|
|
1
|
+
{"version":3,"file":"boundary.d.ts","sourceRoot":"","sources":["../src/boundary.ts"],"names":[],"mappings":"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"}
|
package/dist/boundary.js
CHANGED
|
@@ -23,6 +23,7 @@ export async function renderAsyncBoundary(sink, value, render, options = {}) {
|
|
|
23
23
|
// "you're sending a lot of data" hint pattern used by other frameworks.
|
|
24
24
|
const AWAIT_PAYLOAD_WARN_BYTES = 100 * 1024;
|
|
25
25
|
const AWAIT_PAYLOAD_ERROR_BYTES = 1024 * 1024;
|
|
26
|
+
const textEncoder = typeof TextEncoder !== "undefined" ? new TextEncoder() : undefined;
|
|
26
27
|
function isProductionMode() {
|
|
27
28
|
// `process` may not exist in cross-runtime environments (Cloudflare/Deno).
|
|
28
29
|
// The server tsconfig does not include `@types/node`, so we look it up
|
|
@@ -83,7 +84,10 @@ function containsNonSerializableSurface(value) {
|
|
|
83
84
|
return false;
|
|
84
85
|
}
|
|
85
86
|
function reportAwaitPayloadSize(json, awaitId) {
|
|
86
|
-
|
|
87
|
+
if (json.length * 3 < AWAIT_PAYLOAD_WARN_BYTES) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const byteLength = textEncoder?.encode(json).length ?? json.length;
|
|
87
91
|
if (byteLength > AWAIT_PAYLOAD_ERROR_BYTES) {
|
|
88
92
|
console.error(`[mreact] <Await> payload for "${awaitId}" is ${(byteLength / 1024 / 1024).toFixed(2)}MB, ` +
|
|
89
93
|
`exceeding the 1MB error threshold. Large payloads inflate HTML response size and ` +
|
package/dist/boundary.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boundary.js","sourceRoot":"","sources":["../src/boundary.ts"],"names":[],"mappings":"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","sourcesContent":["import type { HtmlSink } from \"@reckona/mreact-shared/compiler-contract\";\nimport {\n escapeAttribute,\n isPromiseLikeUnknown,\n renderNonceAttribute,\n serializeScriptJson,\n} from \"./html-internals.js\";\nimport { createStringSink, type StringHtmlSink } from \"./sink.js\";\n\nexport interface AsyncBoundaryOptions {\n catch?: (sink: HtmlSink, error: unknown) => void | PromiseLike<void>;\n hydrationAwaitId?: string;\n}\n\nexport interface OutOfOrderBoundaryOptions extends AsyncBoundaryOptions {\n hydration?: boolean;\n placeholder?: (sink: HtmlSink) => void | PromiseLike<void>;\n placeholderTag?: string;\n}\n\nexport interface OutOfOrderReorderScriptOptions {\n nonce?: string;\n src?: string;\n}\n\nexport interface HydrationScriptOptions {\n nonce?: string;\n}\n\nexport interface ReactSuspenseScriptOptions {\n nonce?: string;\n src?: string;\n}\n\nexport interface ReactSuspenseBoundaryOptions extends AsyncBoundaryOptions {\n fallback?: (sink: HtmlSink) => void | PromiseLike<void>;\n nonce?: string;\n}\n\nexport interface ReactSuspenseClientRenderOptions {\n message?: string;\n stack?: string;\n}\n\nexport type AsyncBoundaryRender<T> = (\n sink: HtmlSink,\n value: Awaited<T>,\n) => void | PromiseLike<void>;\n\nconst outOfOrderBoundaryInstances = new WeakMap<HtmlSink, Map<string, number>>();\n\nexport async function renderAsyncBoundary<T>(\n sink: HtmlSink,\n value: T,\n render: AsyncBoundaryRender<T>,\n options: AsyncBoundaryOptions = {},\n): Promise<void> {\n try {\n const resolved = await value;\n await sink.backpressure?.();\n await render(sink, resolved);\n if (options.hydrationAwaitId !== undefined) {\n appendAwaitHydrationData(sink, options.hydrationAwaitId, resolved);\n }\n } catch (error) {\n if (options.catch === undefined) {\n throw error;\n }\n\n await sink.backpressure?.();\n await options.catch(sink, error);\n }\n}\n\n// Threshold for `<Await>` payload size warnings (UTF-8 byte length of\n// JSON-serialized representation). 100KB warn / 1MB error follow the\n// \"you're sending a lot of data\" hint pattern used by other frameworks.\nconst AWAIT_PAYLOAD_WARN_BYTES = 100 * 1024;\nconst AWAIT_PAYLOAD_ERROR_BYTES = 1024 * 1024;\n\nfunction isProductionMode(): boolean {\n // `process` may not exist in cross-runtime environments (Cloudflare/Deno).\n // The server tsconfig does not include `@types/node`, so we look it up\n // through `globalThis` with a minimal local typing.\n const globalProcess = (globalThis as { process?: { env?: Record<string, string | undefined> } })\n .process;\n\n try {\n return globalProcess?.env?.[\"NODE_ENV\"] === \"production\";\n } catch {\n return false;\n }\n}\n\nfunction appendAwaitHydrationData(\n sink: HtmlSink,\n awaitId: string,\n resolved: unknown,\n): void {\n const serialized = serializeAwaitHydrationValue(resolved, awaitId);\n\n if (serialized === undefined) {\n return;\n }\n\n const idLiteral = JSON.stringify(awaitId).replaceAll(\"<\", \"\\\\u003c\");\n sink.append(\n `<script data-mreact-await=\"${escapeAttribute(awaitId)}\">(self.__mreactAwaitData||(self.__mreactAwaitData={}))[${idLiteral}]={value:${serialized}}</script>`,\n );\n}\n\n// Emits a single console.warn in dev when `resolved` contains shapes the\n// wire format will silently drop or coerce (Date / Map / Set / RegExp /\n// class instance / function / Symbol / nested non-POJO).\nfunction warnIfNonSerializableAwaitValue(value: unknown, awaitId: string): void {\n if (isProductionMode()) {\n return;\n }\n\n if (!containsNonSerializableSurface(value)) {\n return;\n }\n\n console.warn(\n `[mreact] <Await value={...}> for \"${awaitId}\" includes non-serializable ` +\n `data (Date / Map / Set / RegExp / class instance / function / Symbol). ` +\n `The wire format uses JSON.stringify, so the client-side renderer may ` +\n `receive a different shape after the JSON round-trip. Convert to plain ` +\n `JSON-serializable data before it reaches <Await>. See ` +\n `https://github.com/t-k/mreact#streaming-loading-and-await.`,\n );\n}\n\nfunction containsNonSerializableSurface(value: unknown): boolean {\n if (value === null || value === undefined || typeof value !== \"object\") {\n return false;\n }\n\n if (value instanceof Date || value instanceof Map || value instanceof Set || value instanceof RegExp) {\n return true;\n }\n\n if (Array.isArray(value)) {\n return value.some((entry) => containsNonSerializableSurface(entry));\n }\n\n const proto = Object.getPrototypeOf(value);\n\n if (proto !== Object.prototype && proto !== null) {\n return true;\n }\n\n for (const entry of Object.values(value as Record<string, unknown>)) {\n if (containsNonSerializableSurface(entry)) {\n return true;\n }\n }\n\n return false;\n}\n\nfunction reportAwaitPayloadSize(json: string, awaitId: string): void {\n const byteLength =\n typeof TextEncoder !== \"undefined\" ? new TextEncoder().encode(json).length : json.length;\n\n if (byteLength > AWAIT_PAYLOAD_ERROR_BYTES) {\n console.error(\n `[mreact] <Await> payload for \"${awaitId}\" is ${(byteLength / 1024 / 1024).toFixed(2)}MB, ` +\n `exceeding the 1MB error threshold. Large payloads inflate HTML response size and ` +\n `client memory pressure. Stream the data via loader or split into smaller boundaries.`,\n );\n return;\n }\n\n if (byteLength > AWAIT_PAYLOAD_WARN_BYTES) {\n console.warn(\n `[mreact] large await payload for \"${awaitId}\": ${(byteLength / 1024).toFixed(1)}KB ` +\n `(over the 100KB warning threshold). Consider streaming the data via loader or ` +\n `splitting into smaller boundaries.`,\n );\n }\n}\n\nfunction serializeAwaitHydrationValue(value: unknown, awaitId: string): string | undefined {\n try {\n const json = JSON.stringify(value);\n if (json === undefined) {\n return undefined;\n }\n\n warnIfNonSerializableAwaitValue(value, awaitId);\n reportAwaitPayloadSize(json, awaitId);\n\n // Defuse `</script>` and runaway control characters so the data can be\n // safely embedded inside a `<script>` element.\n return json\n .replaceAll(\"<\", \"\\\\u003c\")\n .replaceAll(\"\\u2028\", \"\\\\u2028\")\n .replaceAll(\"\\u2029\", \"\\\\u2029\");\n } catch {\n return undefined;\n }\n}\n\nfunction inheritBackpressure(childSink: StringHtmlSink, parentSink: HtmlSink): StringHtmlSink {\n if (parentSink.backpressure === undefined) {\n return childSink;\n }\n\n return {\n ...childSink,\n backpressure: parentSink.backpressure,\n };\n}\n\nexport function renderOutOfOrderBoundary<T>(\n sink: HtmlSink,\n id: string,\n value: T,\n render: AsyncBoundaryRender<T>,\n options: OutOfOrderBoundaryOptions = {},\n): void {\n const boundaryId = nextOutOfOrderBoundaryInstanceId(sink, id);\n const placeholderSink = createStringSink();\n void options.placeholder?.(placeholderSink);\n const placeholderTag = normalizeOutOfOrderPlaceholderTag(options.placeholderTag);\n const hydrationStart =\n options.hydration === true ? `<!--mreact-h:start:${encodeURIComponent(boundaryId)}-->` : \"\";\n const hydrationEnd =\n options.hydration === true ? `<!--mreact-h:end:${encodeURIComponent(boundaryId)}-->` : \"\";\n sink.append(\n `${hydrationStart}<${placeholderTag} data-mreact-oob-placeholder=\"${escapeAttribute(boundaryId)}\">${placeholderSink.toString()}</${placeholderTag}>${hydrationEnd}`,\n );\n\n const task = renderOutOfOrderFragment(sink, boundaryId, value, render, options);\n\n if (sink.defer === undefined) {\n void task;\n return;\n }\n\n sink.defer(task);\n}\n\nfunction normalizeOutOfOrderPlaceholderTag(tag: unknown): string {\n if (typeof tag !== \"string\") {\n return \"span\";\n }\n\n const normalized = tag.trim().toLowerCase();\n return /^[a-z][a-z0-9-]*$/.test(normalized) ? normalized : \"span\";\n}\n\nasync function renderOutOfOrderFragment<T>(\n sink: HtmlSink,\n id: string,\n value: T,\n render: AsyncBoundaryRender<T>,\n options: OutOfOrderBoundaryOptions,\n): Promise<void> {\n const fragmentSink = inheritBackpressure(createStringSink(), sink);\n let resolvedValue: unknown;\n let hasResolvedValue = false;\n\n await renderAsyncBoundary(\n fragmentSink,\n value,\n async (childSink, resolved) => {\n resolvedValue = resolved;\n hasResolvedValue = true;\n await render(childSink, resolved);\n },\n options.catch === undefined ? {} : { catch: options.catch },\n );\n await fragmentSink.drain();\n\n sink.append(\n `<template data-mreact-oob-fragment=\"${escapeAttribute(id)}\">${fragmentSink.toString()}</template>`,\n );\n\n if (hasResolvedValue && options.hydrationAwaitId !== undefined) {\n appendAwaitHydrationData(sink, options.hydrationAwaitId, resolvedValue);\n }\n}\n\nexport function renderOutOfOrderReorderScript(\n sink: HtmlSink,\n options: OutOfOrderReorderScriptOptions = {},\n): void {\n const nonceAttribute =\n options.nonce === undefined ? \"\" : ` nonce=\"${escapeAttribute(options.nonce)}\"`;\n\n if (options.src !== undefined) {\n sink.append(\n `<script data-mreact-oob-reorder${nonceAttribute} src=\"${escapeAttribute(options.src)}\"></script>`,\n );\n return;\n }\n\n sink.append(\n `<script data-mreact-oob-reorder${nonceAttribute}>${outOfOrderReorderScript}</script>`,\n );\n}\n\nexport function renderReactSuspenseBoundary(\n sink: HtmlSink,\n render: (sink: HtmlSink) => void | PromiseLike<void>,\n): void | PromiseLike<void> {\n sink.append(\"<!--$-->\");\n const result = render(sink);\n\n if (isPromiseLike(result)) {\n return result.then(() => {\n sink.append(\"<!--/$-->\");\n });\n }\n\n sink.append(\"<!--/$-->\");\n}\n\nexport function renderReactSuspenseOutOfOrderBoundary<T>(\n sink: HtmlSink,\n boundaryId: string,\n segmentId: string,\n value: T,\n render: AsyncBoundaryRender<T>,\n options: ReactSuspenseBoundaryOptions = {},\n): void {\n const actualBoundaryId = nextOutOfOrderBoundaryInstanceId(sink, boundaryId);\n const suffix = actualBoundaryId.slice(boundaryId.length);\n const actualSegmentId = `${segmentId}${suffix}`;\n const fallbackSink = createStringSink();\n void options.fallback?.(fallbackSink);\n sink.append(\n `<!--$?--><template id=\"${escapeAttribute(actualBoundaryId)}\"></template>${fallbackSink.toString()}<!--/$-->`,\n );\n\n const task = renderReactSuspenseSegment(\n sink,\n actualBoundaryId,\n actualSegmentId,\n value,\n render,\n options,\n );\n\n if (sink.defer === undefined) {\n void task;\n return;\n }\n\n sink.defer(task);\n}\n\nfunction nextOutOfOrderBoundaryInstanceId(sink: HtmlSink, id: string): string {\n let instances = outOfOrderBoundaryInstances.get(sink);\n\n if (instances === undefined) {\n instances = new Map();\n outOfOrderBoundaryInstances.set(sink, instances);\n }\n\n const count = instances.get(id) ?? 0;\n instances.set(id, count + 1);\n\n return count === 0 ? id : `${id}-${count.toString(36)}`;\n}\n\nexport function renderReactSuspenseClientRenderBoundary(\n sink: HtmlSink,\n fallback: (sink: HtmlSink) => void | PromiseLike<void>,\n options: ReactSuspenseClientRenderOptions = {},\n): void | PromiseLike<void> {\n sink.append(`<!--$!--><template${renderReactSuspenseErrorAttributes(options)}></template>`);\n const result = fallback(sink);\n\n if (isPromiseLike(result)) {\n return result.then(() => {\n sink.append(\"<!--/$-->\");\n });\n }\n\n sink.append(\"<!--/$-->\");\n}\n\nasync function renderReactSuspenseSegment<T>(\n sink: HtmlSink,\n boundaryId: string,\n segmentId: string,\n value: T,\n render: AsyncBoundaryRender<T>,\n options: ReactSuspenseBoundaryOptions,\n): Promise<void> {\n const segmentSink = inheritBackpressure(createStringSink(), sink);\n\n await renderAsyncBoundary(\n segmentSink,\n value,\n render,\n options.catch === undefined ? {} : { catch: options.catch },\n );\n\n sink.append(\n `<div hidden id=\"${escapeAttribute(segmentId)}\">${segmentSink.toString()}</div>${renderReactSuspenseRevealScript(boundaryId, segmentId, options)}`,\n );\n}\n\nfunction renderReactSuspenseErrorAttributes(options: ReactSuspenseClientRenderOptions): string {\n const message =\n options.message === undefined ? \"\" : ` data-msg=\"${escapeAttribute(options.message)}\"`;\n const stack = options.stack === undefined ? \"\" : ` data-stck=\"${escapeAttribute(options.stack)}\"`;\n\n return `${message}${stack}`;\n}\n\nfunction renderReactSuspenseRevealScript(\n boundaryId: string,\n segmentId: string,\n options: ReactSuspenseScriptOptions = {},\n): string {\n if (options.src !== undefined) {\n return `<script data-mreact-react-suspense-reveal${renderNonceAttribute(options.nonce)} src=\"${escapeAttribute(options.src)}\" data-boundary-id=\"${escapeAttribute(boundaryId)}\" data-segment-id=\"${escapeAttribute(segmentId)}\"></script>`;\n }\n\n return `<script${renderNonceAttribute(options.nonce)}>${reactSuspenseRevealScriptBody};$RC(${serializeScriptJson(boundaryId)},${serializeScriptJson(segmentId)})</script>`;\n}\n\nexport function renderHydrationBoundary(\n sink: HtmlSink,\n id: string,\n render: (sink: HtmlSink) => void | PromiseLike<void>,\n): void | PromiseLike<void> {\n const markerId = encodeURIComponent(id);\n sink.append(`<!--mreact-h:start:${markerId}-->`);\n const result = render(sink);\n\n if (isPromiseLike(result)) {\n return result.then(() => {\n sink.append(`<!--mreact-h:end:${markerId}-->`);\n });\n }\n\n sink.append(`<!--mreact-h:end:${markerId}-->`);\n}\n\nfunction isPromiseLike(value: unknown): value is PromiseLike<void> {\n return isPromiseLikeUnknown(value);\n}\n\nconst outOfOrderReorderScript = `(()=>{function apply(root){const fragments=Array.from(root.querySelectorAll(\"template[data-mreact-oob-fragment]\"));for(const fragment of fragments){const id=fragment.getAttribute(\"data-mreact-oob-fragment\");if(id===null)continue;const placeholders=Array.from(root.querySelectorAll(\"[data-mreact-oob-placeholder]\"));const placeholder=placeholders.find((candidate)=>candidate.getAttribute(\"data-mreact-oob-placeholder\")===id);if(placeholder===undefined)continue;placeholder.replaceWith(fragment.content.cloneNode(true));fragment.remove();}}apply(document);new MutationObserver(()=>apply(document)).observe(document.documentElement,{childList:true,subtree:true});})();`;\n\nconst reactSuspenseRevealScriptBody = `(self.$RC=self.$RC||function(bid,sid){var b=document.getElementById(bid);var s=document.getElementById(sid);if(!b||!s)return;var p=b.parentNode;var e=b.nextSibling;var d=0;var r=[];for(var n=e;n;n=n.nextSibling){if(n.nodeType===8){if(n.data===\"$\"||n.data===\"$?\"||n.data===\"$!\")d++;else if(n.data===\"/$\"){if(d===0){e=n;break;}d--;}}r.push(n);}for(var i=0;r[i];i++)p.removeChild(r[i]);while(s.firstChild)p.insertBefore(s.firstChild,e);s.remove();b.data=\"$\";})`;\n\nexport const reactSuspenseRevealExternalScript = `(()=>{${reactSuspenseRevealScriptBody};var s=document.currentScript;if(!s)return;var b=s.getAttribute(\"data-boundary-id\");var seg=s.getAttribute(\"data-segment-id\");if(b!==null&&seg!==null)self.$RC(b,seg);})();`;\n"]}
|
|
1
|
+
{"version":3,"file":"boundary.js","sourceRoot":"","sources":["../src/boundary.ts"],"names":[],"mappings":"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","sourcesContent":["import type { HtmlSink } from \"@reckona/mreact-shared/compiler-contract\";\nimport {\n escapeAttribute,\n isPromiseLikeUnknown,\n renderNonceAttribute,\n serializeScriptJson,\n} from \"./html-internals.js\";\nimport { createStringSink, type StringHtmlSink } from \"./sink.js\";\n\nexport interface AsyncBoundaryOptions {\n catch?: (sink: HtmlSink, error: unknown) => void | PromiseLike<void>;\n hydrationAwaitId?: string;\n}\n\nexport interface OutOfOrderBoundaryOptions extends AsyncBoundaryOptions {\n hydration?: boolean;\n placeholder?: (sink: HtmlSink) => void | PromiseLike<void>;\n placeholderTag?: string;\n}\n\nexport interface OutOfOrderReorderScriptOptions {\n nonce?: string;\n src?: string;\n}\n\nexport interface HydrationScriptOptions {\n nonce?: string;\n}\n\nexport interface ReactSuspenseScriptOptions {\n nonce?: string;\n src?: string;\n}\n\nexport interface ReactSuspenseBoundaryOptions extends AsyncBoundaryOptions {\n fallback?: (sink: HtmlSink) => void | PromiseLike<void>;\n nonce?: string;\n}\n\nexport interface ReactSuspenseClientRenderOptions {\n message?: string;\n stack?: string;\n}\n\nexport type AsyncBoundaryRender<T> = (\n sink: HtmlSink,\n value: Awaited<T>,\n) => void | PromiseLike<void>;\n\nconst outOfOrderBoundaryInstances = new WeakMap<HtmlSink, Map<string, number>>();\n\nexport async function renderAsyncBoundary<T>(\n sink: HtmlSink,\n value: T,\n render: AsyncBoundaryRender<T>,\n options: AsyncBoundaryOptions = {},\n): Promise<void> {\n try {\n const resolved = await value;\n await sink.backpressure?.();\n await render(sink, resolved);\n if (options.hydrationAwaitId !== undefined) {\n appendAwaitHydrationData(sink, options.hydrationAwaitId, resolved);\n }\n } catch (error) {\n if (options.catch === undefined) {\n throw error;\n }\n\n await sink.backpressure?.();\n await options.catch(sink, error);\n }\n}\n\n// Threshold for `<Await>` payload size warnings (UTF-8 byte length of\n// JSON-serialized representation). 100KB warn / 1MB error follow the\n// \"you're sending a lot of data\" hint pattern used by other frameworks.\nconst AWAIT_PAYLOAD_WARN_BYTES = 100 * 1024;\nconst AWAIT_PAYLOAD_ERROR_BYTES = 1024 * 1024;\nconst textEncoder = typeof TextEncoder !== \"undefined\" ? new TextEncoder() : undefined;\n\nfunction isProductionMode(): boolean {\n // `process` may not exist in cross-runtime environments (Cloudflare/Deno).\n // The server tsconfig does not include `@types/node`, so we look it up\n // through `globalThis` with a minimal local typing.\n const globalProcess = (globalThis as { process?: { env?: Record<string, string | undefined> } })\n .process;\n\n try {\n return globalProcess?.env?.[\"NODE_ENV\"] === \"production\";\n } catch {\n return false;\n }\n}\n\nfunction appendAwaitHydrationData(\n sink: HtmlSink,\n awaitId: string,\n resolved: unknown,\n): void {\n const serialized = serializeAwaitHydrationValue(resolved, awaitId);\n\n if (serialized === undefined) {\n return;\n }\n\n const idLiteral = JSON.stringify(awaitId).replaceAll(\"<\", \"\\\\u003c\");\n sink.append(\n `<script data-mreact-await=\"${escapeAttribute(awaitId)}\">(self.__mreactAwaitData||(self.__mreactAwaitData={}))[${idLiteral}]={value:${serialized}}</script>`,\n );\n}\n\n// Emits a single console.warn in dev when `resolved` contains shapes the\n// wire format will silently drop or coerce (Date / Map / Set / RegExp /\n// class instance / function / Symbol / nested non-POJO).\nfunction warnIfNonSerializableAwaitValue(value: unknown, awaitId: string): void {\n if (isProductionMode()) {\n return;\n }\n\n if (!containsNonSerializableSurface(value)) {\n return;\n }\n\n console.warn(\n `[mreact] <Await value={...}> for \"${awaitId}\" includes non-serializable ` +\n `data (Date / Map / Set / RegExp / class instance / function / Symbol). ` +\n `The wire format uses JSON.stringify, so the client-side renderer may ` +\n `receive a different shape after the JSON round-trip. Convert to plain ` +\n `JSON-serializable data before it reaches <Await>. See ` +\n `https://github.com/t-k/mreact#streaming-loading-and-await.`,\n );\n}\n\nfunction containsNonSerializableSurface(value: unknown): boolean {\n if (value === null || value === undefined || typeof value !== \"object\") {\n return false;\n }\n\n if (value instanceof Date || value instanceof Map || value instanceof Set || value instanceof RegExp) {\n return true;\n }\n\n if (Array.isArray(value)) {\n return value.some((entry) => containsNonSerializableSurface(entry));\n }\n\n const proto = Object.getPrototypeOf(value);\n\n if (proto !== Object.prototype && proto !== null) {\n return true;\n }\n\n for (const entry of Object.values(value as Record<string, unknown>)) {\n if (containsNonSerializableSurface(entry)) {\n return true;\n }\n }\n\n return false;\n}\n\nfunction reportAwaitPayloadSize(json: string, awaitId: string): void {\n if (json.length * 3 < AWAIT_PAYLOAD_WARN_BYTES) {\n return;\n }\n\n const byteLength = textEncoder?.encode(json).length ?? json.length;\n\n if (byteLength > AWAIT_PAYLOAD_ERROR_BYTES) {\n console.error(\n `[mreact] <Await> payload for \"${awaitId}\" is ${(byteLength / 1024 / 1024).toFixed(2)}MB, ` +\n `exceeding the 1MB error threshold. Large payloads inflate HTML response size and ` +\n `client memory pressure. Stream the data via loader or split into smaller boundaries.`,\n );\n return;\n }\n\n if (byteLength > AWAIT_PAYLOAD_WARN_BYTES) {\n console.warn(\n `[mreact] large await payload for \"${awaitId}\": ${(byteLength / 1024).toFixed(1)}KB ` +\n `(over the 100KB warning threshold). Consider streaming the data via loader or ` +\n `splitting into smaller boundaries.`,\n );\n }\n}\n\nfunction serializeAwaitHydrationValue(value: unknown, awaitId: string): string | undefined {\n try {\n const json = JSON.stringify(value);\n if (json === undefined) {\n return undefined;\n }\n\n warnIfNonSerializableAwaitValue(value, awaitId);\n reportAwaitPayloadSize(json, awaitId);\n\n // Defuse `</script>` and runaway control characters so the data can be\n // safely embedded inside a `<script>` element.\n return json\n .replaceAll(\"<\", \"\\\\u003c\")\n .replaceAll(\"\\u2028\", \"\\\\u2028\")\n .replaceAll(\"\\u2029\", \"\\\\u2029\");\n } catch {\n return undefined;\n }\n}\n\nfunction inheritBackpressure(childSink: StringHtmlSink, parentSink: HtmlSink): StringHtmlSink {\n if (parentSink.backpressure === undefined) {\n return childSink;\n }\n\n return {\n ...childSink,\n backpressure: parentSink.backpressure,\n };\n}\n\nexport function renderOutOfOrderBoundary<T>(\n sink: HtmlSink,\n id: string,\n value: T,\n render: AsyncBoundaryRender<T>,\n options: OutOfOrderBoundaryOptions = {},\n): void {\n const boundaryId = nextOutOfOrderBoundaryInstanceId(sink, id);\n const placeholderSink = createStringSink();\n void options.placeholder?.(placeholderSink);\n const placeholderTag = normalizeOutOfOrderPlaceholderTag(options.placeholderTag);\n const hydrationStart =\n options.hydration === true ? `<!--mreact-h:start:${encodeURIComponent(boundaryId)}-->` : \"\";\n const hydrationEnd =\n options.hydration === true ? `<!--mreact-h:end:${encodeURIComponent(boundaryId)}-->` : \"\";\n sink.append(\n `${hydrationStart}<${placeholderTag} data-mreact-oob-placeholder=\"${escapeAttribute(boundaryId)}\">${placeholderSink.toString()}</${placeholderTag}>${hydrationEnd}`,\n );\n\n const task = renderOutOfOrderFragment(sink, boundaryId, value, render, options);\n\n if (sink.defer === undefined) {\n void task;\n return;\n }\n\n sink.defer(task);\n}\n\nfunction normalizeOutOfOrderPlaceholderTag(tag: unknown): string {\n if (typeof tag !== \"string\") {\n return \"span\";\n }\n\n const normalized = tag.trim().toLowerCase();\n return /^[a-z][a-z0-9-]*$/.test(normalized) ? normalized : \"span\";\n}\n\nasync function renderOutOfOrderFragment<T>(\n sink: HtmlSink,\n id: string,\n value: T,\n render: AsyncBoundaryRender<T>,\n options: OutOfOrderBoundaryOptions,\n): Promise<void> {\n const fragmentSink = inheritBackpressure(createStringSink(), sink);\n let resolvedValue: unknown;\n let hasResolvedValue = false;\n\n await renderAsyncBoundary(\n fragmentSink,\n value,\n async (childSink, resolved) => {\n resolvedValue = resolved;\n hasResolvedValue = true;\n await render(childSink, resolved);\n },\n options.catch === undefined ? {} : { catch: options.catch },\n );\n await fragmentSink.drain();\n\n sink.append(\n `<template data-mreact-oob-fragment=\"${escapeAttribute(id)}\">${fragmentSink.toString()}</template>`,\n );\n\n if (hasResolvedValue && options.hydrationAwaitId !== undefined) {\n appendAwaitHydrationData(sink, options.hydrationAwaitId, resolvedValue);\n }\n}\n\nexport function renderOutOfOrderReorderScript(\n sink: HtmlSink,\n options: OutOfOrderReorderScriptOptions = {},\n): void {\n const nonceAttribute =\n options.nonce === undefined ? \"\" : ` nonce=\"${escapeAttribute(options.nonce)}\"`;\n\n if (options.src !== undefined) {\n sink.append(\n `<script data-mreact-oob-reorder${nonceAttribute} src=\"${escapeAttribute(options.src)}\"></script>`,\n );\n return;\n }\n\n sink.append(\n `<script data-mreact-oob-reorder${nonceAttribute}>${outOfOrderReorderScript}</script>`,\n );\n}\n\nexport function renderReactSuspenseBoundary(\n sink: HtmlSink,\n render: (sink: HtmlSink) => void | PromiseLike<void>,\n): void | PromiseLike<void> {\n sink.append(\"<!--$-->\");\n const result = render(sink);\n\n if (isPromiseLike(result)) {\n return result.then(() => {\n sink.append(\"<!--/$-->\");\n });\n }\n\n sink.append(\"<!--/$-->\");\n}\n\nexport function renderReactSuspenseOutOfOrderBoundary<T>(\n sink: HtmlSink,\n boundaryId: string,\n segmentId: string,\n value: T,\n render: AsyncBoundaryRender<T>,\n options: ReactSuspenseBoundaryOptions = {},\n): void {\n const actualBoundaryId = nextOutOfOrderBoundaryInstanceId(sink, boundaryId);\n const suffix = actualBoundaryId.slice(boundaryId.length);\n const actualSegmentId = `${segmentId}${suffix}`;\n const fallbackSink = createStringSink();\n void options.fallback?.(fallbackSink);\n sink.append(\n `<!--$?--><template id=\"${escapeAttribute(actualBoundaryId)}\"></template>${fallbackSink.toString()}<!--/$-->`,\n );\n\n const task = renderReactSuspenseSegment(\n sink,\n actualBoundaryId,\n actualSegmentId,\n value,\n render,\n options,\n );\n\n if (sink.defer === undefined) {\n void task;\n return;\n }\n\n sink.defer(task);\n}\n\nfunction nextOutOfOrderBoundaryInstanceId(sink: HtmlSink, id: string): string {\n let instances = outOfOrderBoundaryInstances.get(sink);\n\n if (instances === undefined) {\n instances = new Map();\n outOfOrderBoundaryInstances.set(sink, instances);\n }\n\n const count = instances.get(id) ?? 0;\n instances.set(id, count + 1);\n\n return count === 0 ? id : `${id}-${count.toString(36)}`;\n}\n\nexport function renderReactSuspenseClientRenderBoundary(\n sink: HtmlSink,\n fallback: (sink: HtmlSink) => void | PromiseLike<void>,\n options: ReactSuspenseClientRenderOptions = {},\n): void | PromiseLike<void> {\n sink.append(`<!--$!--><template${renderReactSuspenseErrorAttributes(options)}></template>`);\n const result = fallback(sink);\n\n if (isPromiseLike(result)) {\n return result.then(() => {\n sink.append(\"<!--/$-->\");\n });\n }\n\n sink.append(\"<!--/$-->\");\n}\n\nasync function renderReactSuspenseSegment<T>(\n sink: HtmlSink,\n boundaryId: string,\n segmentId: string,\n value: T,\n render: AsyncBoundaryRender<T>,\n options: ReactSuspenseBoundaryOptions,\n): Promise<void> {\n const segmentSink = inheritBackpressure(createStringSink(), sink);\n\n await renderAsyncBoundary(\n segmentSink,\n value,\n render,\n options.catch === undefined ? {} : { catch: options.catch },\n );\n\n sink.append(\n `<div hidden id=\"${escapeAttribute(segmentId)}\">${segmentSink.toString()}</div>${renderReactSuspenseRevealScript(boundaryId, segmentId, options)}`,\n );\n}\n\nfunction renderReactSuspenseErrorAttributes(options: ReactSuspenseClientRenderOptions): string {\n const message =\n options.message === undefined ? \"\" : ` data-msg=\"${escapeAttribute(options.message)}\"`;\n const stack = options.stack === undefined ? \"\" : ` data-stck=\"${escapeAttribute(options.stack)}\"`;\n\n return `${message}${stack}`;\n}\n\nfunction renderReactSuspenseRevealScript(\n boundaryId: string,\n segmentId: string,\n options: ReactSuspenseScriptOptions = {},\n): string {\n if (options.src !== undefined) {\n return `<script data-mreact-react-suspense-reveal${renderNonceAttribute(options.nonce)} src=\"${escapeAttribute(options.src)}\" data-boundary-id=\"${escapeAttribute(boundaryId)}\" data-segment-id=\"${escapeAttribute(segmentId)}\"></script>`;\n }\n\n return `<script${renderNonceAttribute(options.nonce)}>${reactSuspenseRevealScriptBody};$RC(${serializeScriptJson(boundaryId)},${serializeScriptJson(segmentId)})</script>`;\n}\n\nexport function renderHydrationBoundary(\n sink: HtmlSink,\n id: string,\n render: (sink: HtmlSink) => void | PromiseLike<void>,\n): void | PromiseLike<void> {\n const markerId = encodeURIComponent(id);\n sink.append(`<!--mreact-h:start:${markerId}-->`);\n const result = render(sink);\n\n if (isPromiseLike(result)) {\n return result.then(() => {\n sink.append(`<!--mreact-h:end:${markerId}-->`);\n });\n }\n\n sink.append(`<!--mreact-h:end:${markerId}-->`);\n}\n\nfunction isPromiseLike(value: unknown): value is PromiseLike<void> {\n return isPromiseLikeUnknown(value);\n}\n\nconst outOfOrderReorderScript = `(()=>{function apply(root){const fragments=Array.from(root.querySelectorAll(\"template[data-mreact-oob-fragment]\"));for(const fragment of fragments){const id=fragment.getAttribute(\"data-mreact-oob-fragment\");if(id===null)continue;const placeholders=Array.from(root.querySelectorAll(\"[data-mreact-oob-placeholder]\"));const placeholder=placeholders.find((candidate)=>candidate.getAttribute(\"data-mreact-oob-placeholder\")===id);if(placeholder===undefined)continue;placeholder.replaceWith(fragment.content.cloneNode(true));fragment.remove();}}apply(document);new MutationObserver(()=>apply(document)).observe(document.documentElement,{childList:true,subtree:true});})();`;\n\nconst reactSuspenseRevealScriptBody = `(self.$RC=self.$RC||function(bid,sid){var b=document.getElementById(bid);var s=document.getElementById(sid);if(!b||!s)return;var p=b.parentNode;var e=b.nextSibling;var d=0;var r=[];for(var n=e;n;n=n.nextSibling){if(n.nodeType===8){if(n.data===\"$\"||n.data===\"$?\"||n.data===\"$!\")d++;else if(n.data===\"/$\"){if(d===0){e=n;break;}d--;}}r.push(n);}for(var i=0;r[i];i++)p.removeChild(r[i]);while(s.firstChild)p.insertBefore(s.firstChild,e);s.remove();b.data=\"$\";})`;\n\nexport const reactSuspenseRevealExternalScript = `(()=>{${reactSuspenseRevealScriptBody};var s=document.currentScript;if(!s)return;var b=s.getAttribute(\"data-boundary-id\");var seg=s.getAttribute(\"data-segment-id\");if(b!==null&&seg!==null)self.$RC(b,seg);})();`;\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buffer-sink.d.ts","sourceRoot":"","sources":["../src/buffer-sink.ts"],"names":[],"mappings":"AAcA,UAAU,UAAW,SAAQ,UAAU;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAClE,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAChE,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACjG,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;CACpD;AAaD,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAAC;IACzC,QAAQ,IAAI,UAAU,CAAC;IACvB,QAAQ,IAAI,MAAM,CAAC;IACnB,IAAI,IAAI,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;GAQG;AACH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,KAAK,IAAI,IAAI,CAAC;IACd,IAAI,IAAI,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,0BAA0B;IACzC;oEACgE;IAChE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;6DACyD;IACzD,OAAO,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;CACnC;AAED,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,0BAA0B,GAClC,mBAAmB,CA6BrB;AAyDD,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,iBAAsB,GAAG,UAAU,
|
|
1
|
+
{"version":3,"file":"buffer-sink.d.ts","sourceRoot":"","sources":["../src/buffer-sink.ts"],"names":[],"mappings":"AAcA,UAAU,UAAW,SAAQ,UAAU;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAClE,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAChE,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACjG,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;CACpD;AAaD,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAAC;IACzC,QAAQ,IAAI,UAAU,CAAC;IACvB,QAAQ,IAAI,MAAM,CAAC;IACnB,IAAI,IAAI,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;GAQG;AACH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,KAAK,IAAI,IAAI,CAAC;IACd,IAAI,IAAI,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,0BAA0B;IACzC;oEACgE;IAChE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;6DACyD;IACzD,OAAO,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;CACnC;AAED,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,0BAA0B,GAClC,mBAAmB,CA6BrB;AAyDD,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,iBAAsB,GAAG,UAAU,CA8C5E"}
|
package/dist/buffer-sink.js
CHANGED
|
@@ -110,11 +110,7 @@ export function createBufferSink(options = {}) {
|
|
|
110
110
|
return {
|
|
111
111
|
append(chunk) {
|
|
112
112
|
if (typeof chunk === "string") {
|
|
113
|
-
|
|
114
|
-
// can encode in a single `write()` call without a measurement
|
|
115
|
-
// pass; the actual encoded length is returned by `write()`.
|
|
116
|
-
const upperBound = chunk.length * 4;
|
|
117
|
-
ensure(upperBound);
|
|
113
|
+
ensure(Buffer.byteLength(chunk, "utf8"));
|
|
118
114
|
offset += buffer.write(chunk, offset, "utf8");
|
|
119
115
|
return;
|
|
120
116
|
}
|
package/dist/buffer-sink.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buffer-sink.js","sourceRoot":"","sources":["../src/buffer-sink.ts"],"names":[],"mappings":"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","sourcesContent":["// Node 専用 buffer sink — issue 050 の対応。\n//\n// `createStringSink` (cross-runtime, string accumulator) と並べて、\n// Node の `Buffer` を直接 accumulate する sink を提供する。HTTP response\n// body へ `response.write(buffer)` で直接渡すと string → UTF-8 encode の\n// cost を 1 回にまとめられる利点がある。\n//\n// 注: Cloudflare Workers / Deno など `Buffer` を持たない runtime では\n// import 時に runtime error になる。cross-runtime ポータビリティが必要な\n// callsite は `@reckona/mreact-server` 本体の `createStringSink` を使う。\n//\n// tsconfig は `lib: ES2022 + DOM`, `types: []` なので `@types/node` に\n// 依存しないよう、`Buffer` の最小型を本 file 内で declare する。\n\ninterface NodeBuffer extends Uint8Array {\n toString(encoding?: string, start?: number, end?: number): string;\n write(input: string, offset: number, encoding?: string): number;\n copy(target: NodeBuffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number;\n subarray(start?: number, end?: number): NodeBuffer;\n}\n\ninterface BufferConstructor {\n from(input: string, encoding?: string): NodeBuffer;\n from(input: ArrayBufferLike | ArrayLike<number>): NodeBuffer;\n alloc(size: number): NodeBuffer;\n allocUnsafe(size: number): NodeBuffer;\n byteLength(input: string, encoding?: string): number;\n isBuffer(input: unknown): input is NodeBuffer;\n}\n\ndeclare const Buffer: BufferConstructor;\n\nexport interface BufferSink {\n append(chunk: string | NodeBuffer): void;\n toBuffer(): NodeBuffer;\n toString(): string;\n size(): number;\n}\n\nexport interface BufferSinkOptions {\n /**\n * Initial backing buffer size (UTF-8 bytes). The buffer grows\n * geometrically as needed. Default: 8192.\n */\n initialSize?: number;\n /**\n * Growth multiplier when the backing buffer needs to expand.\n * Default: 2.\n */\n growthFactor?: number;\n}\n\n/**\n * Creates a Node-only buffer sink with a single pre-allocated growing\n * backing `Buffer`. UTF-8 encoding happens in-place at the current write\n * offset, avoiding per-chunk Buffer allocation and a final concat.\n *\n * Compared to `Buffer.concat`-style implementations, this trades a small\n * amount of headroom memory for ~5-10x throughput on small chunks\n * (see docs/benchmarks/2026-05-12-server-sink-strategy.md).\n */\n/**\n * A streaming-flavored buffer sink used by\n * `renderToReadableStream`. Coalesces successive `append(chunk)` calls\n * into a single byte buffer, then hands the buffer to a consumer\n * callback either on demand (`flush()`) or automatically once the\n * accumulated UTF-8 byte length crosses a threshold.\n *\n * The contract:\n * - Each call to `flush()` (or an auto-flush triggered from within\n * `append`) delivers **exactly one** non-empty byte buffer to the\n * consumer. Empty buffers are never delivered — callers do not\n * need to filter them out.\n * - The delivered buffer is exclusively owned by the consumer; the\n * sink will not mutate it afterwards. Internally we allocate a\n * fresh backing buffer per epoch, so handing off a `subarray` view\n * is safe with no copy.\n *\n * Issue 084: motivated by the streaming SSR throughput gap to\n * marko-run (mreact was at 0.66x marko's ops/sec because the previous\n * implementation paid a `TextEncoder.encode` + Web Streams\n * `controller.enqueue` round-trip per `sink.append()` call).\n */\nexport interface StreamingBufferSink {\n append(chunk: string): void;\n flush(): void;\n size(): number;\n}\n\nexport interface StreamingBufferSinkOptions {\n /** UTF-8 byte threshold that triggers an automatic flush from inside\n * `append`. Default 8 KiB (one common TCP segment payload). */\n flushThreshold?: number;\n /** Initial backing buffer size; same semantics as `BufferSinkOptions`. */\n initialSize?: number;\n /** Consumer hook — invoked at most once per `flush()` (manual or\n * automatic), and only with a non-empty byte buffer. */\n onFlush(buffer: Uint8Array): void;\n}\n\nexport function createStreamingBufferSink(\n options: StreamingBufferSinkOptions,\n): StreamingBufferSink {\n if (!hasNodeBuffer()) {\n return createStreamingEncodedSink(options);\n }\n\n const flushThreshold = options.flushThreshold ?? 8192;\n const initialSize = options.initialSize ?? flushThreshold;\n let inner = createBufferSink({ initialSize });\n const emitAndReset = () => {\n const buf = inner.toBuffer();\n inner = createBufferSink({ initialSize });\n options.onFlush(buf);\n };\n return {\n append(chunk) {\n if (chunk === \"\") return;\n inner.append(chunk);\n if (inner.size() >= flushThreshold) {\n emitAndReset();\n }\n },\n flush() {\n if (inner.size() === 0) return;\n emitAndReset();\n },\n size() {\n return inner.size();\n },\n };\n}\n\nfunction createStreamingEncodedSink(options: StreamingBufferSinkOptions): StreamingBufferSink {\n const flushThreshold = options.flushThreshold ?? 8192;\n const encoder = new TextEncoder();\n let chunks: Uint8Array[] = [];\n let byteLength = 0;\n\n const emitAndReset = () => {\n const output = concatUint8Arrays(chunks, byteLength);\n chunks = [];\n byteLength = 0;\n options.onFlush(output);\n };\n\n return {\n append(chunk) {\n if (chunk === \"\") return;\n\n const bytes = encoder.encode(chunk);\n chunks.push(bytes);\n byteLength += bytes.byteLength;\n\n if (byteLength >= flushThreshold) {\n emitAndReset();\n }\n },\n flush() {\n if (byteLength === 0) return;\n emitAndReset();\n },\n size() {\n return byteLength;\n },\n };\n}\n\nfunction concatUint8Arrays(chunks: Uint8Array[], byteLength: number): Uint8Array {\n if (chunks.length === 1) {\n return chunks[0] ?? new Uint8Array();\n }\n\n const output = new Uint8Array(byteLength);\n let offset = 0;\n\n for (const chunk of chunks) {\n output.set(chunk, offset);\n offset += chunk.byteLength;\n }\n\n return output;\n}\n\nfunction hasNodeBuffer(): boolean {\n return typeof Buffer !== \"undefined\" && typeof Buffer.allocUnsafe === \"function\";\n}\n\nexport function createBufferSink(options: BufferSinkOptions = {}): BufferSink {\n const initialSize = options.initialSize ?? 8192;\n const growthFactor = options.growthFactor ?? 2;\n let buffer = Buffer.allocUnsafe(initialSize);\n let offset = 0;\n\n function ensure(requiredBytes: number): void {\n const required = offset + requiredBytes;\n\n if (required <= buffer.length) {\n return;\n }\n\n let newCapacity = buffer.length === 0 ? initialSize : buffer.length;\n\n while (newCapacity < required) {\n newCapacity = Math.ceil(newCapacity * growthFactor);\n }\n\n const grown = Buffer.allocUnsafe(newCapacity);\n buffer.copy(grown, 0, 0, offset);\n buffer = grown;\n }\n\n return {\n append(chunk) {\n if (typeof chunk === \"string\") {\n // Reserve worst-case byte length (4 bytes/char) up front so we\n // can encode in a single `write()` call without a measurement\n // pass; the actual encoded length is returned by `write()`.\n const upperBound = chunk.length * 4;\n ensure(upperBound);\n offset += buffer.write(chunk, offset, \"utf8\");\n return;\n }\n\n ensure(chunk.length);\n chunk.copy(buffer, offset);\n offset += chunk.length;\n },\n toBuffer() {\n return buffer.subarray(0, offset);\n },\n toString() {\n return buffer.toString(\"utf8\", 0, offset);\n },\n size() {\n return offset;\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"buffer-sink.js","sourceRoot":"","sources":["../src/buffer-sink.ts"],"names":[],"mappings":"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","sourcesContent":["// Node 専用 buffer sink — issue 050 の対応。\n//\n// `createStringSink` (cross-runtime, string accumulator) と並べて、\n// Node の `Buffer` を直接 accumulate する sink を提供する。HTTP response\n// body へ `response.write(buffer)` で直接渡すと string → UTF-8 encode の\n// cost を 1 回にまとめられる利点がある。\n//\n// 注: Cloudflare Workers / Deno など `Buffer` を持たない runtime では\n// import 時に runtime error になる。cross-runtime ポータビリティが必要な\n// callsite は `@reckona/mreact-server` 本体の `createStringSink` を使う。\n//\n// tsconfig は `lib: ES2022 + DOM`, `types: []` なので `@types/node` に\n// 依存しないよう、`Buffer` の最小型を本 file 内で declare する。\n\ninterface NodeBuffer extends Uint8Array {\n toString(encoding?: string, start?: number, end?: number): string;\n write(input: string, offset: number, encoding?: string): number;\n copy(target: NodeBuffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number;\n subarray(start?: number, end?: number): NodeBuffer;\n}\n\ninterface BufferConstructor {\n from(input: string, encoding?: string): NodeBuffer;\n from(input: ArrayBufferLike | ArrayLike<number>): NodeBuffer;\n alloc(size: number): NodeBuffer;\n allocUnsafe(size: number): NodeBuffer;\n byteLength(input: string, encoding?: string): number;\n isBuffer(input: unknown): input is NodeBuffer;\n}\n\ndeclare const Buffer: BufferConstructor;\n\nexport interface BufferSink {\n append(chunk: string | NodeBuffer): void;\n toBuffer(): NodeBuffer;\n toString(): string;\n size(): number;\n}\n\nexport interface BufferSinkOptions {\n /**\n * Initial backing buffer size (UTF-8 bytes). The buffer grows\n * geometrically as needed. Default: 8192.\n */\n initialSize?: number;\n /**\n * Growth multiplier when the backing buffer needs to expand.\n * Default: 2.\n */\n growthFactor?: number;\n}\n\n/**\n * Creates a Node-only buffer sink with a single pre-allocated growing\n * backing `Buffer`. UTF-8 encoding happens in-place at the current write\n * offset, avoiding per-chunk Buffer allocation and a final concat.\n *\n * Compared to `Buffer.concat`-style implementations, this trades a small\n * amount of headroom memory for ~5-10x throughput on small chunks\n * (see docs/benchmarks/2026-05-12-server-sink-strategy.md).\n */\n/**\n * A streaming-flavored buffer sink used by\n * `renderToReadableStream`. Coalesces successive `append(chunk)` calls\n * into a single byte buffer, then hands the buffer to a consumer\n * callback either on demand (`flush()`) or automatically once the\n * accumulated UTF-8 byte length crosses a threshold.\n *\n * The contract:\n * - Each call to `flush()` (or an auto-flush triggered from within\n * `append`) delivers **exactly one** non-empty byte buffer to the\n * consumer. Empty buffers are never delivered — callers do not\n * need to filter them out.\n * - The delivered buffer is exclusively owned by the consumer; the\n * sink will not mutate it afterwards. Internally we allocate a\n * fresh backing buffer per epoch, so handing off a `subarray` view\n * is safe with no copy.\n *\n * Issue 084: motivated by the streaming SSR throughput gap to\n * marko-run (mreact was at 0.66x marko's ops/sec because the previous\n * implementation paid a `TextEncoder.encode` + Web Streams\n * `controller.enqueue` round-trip per `sink.append()` call).\n */\nexport interface StreamingBufferSink {\n append(chunk: string): void;\n flush(): void;\n size(): number;\n}\n\nexport interface StreamingBufferSinkOptions {\n /** UTF-8 byte threshold that triggers an automatic flush from inside\n * `append`. Default 8 KiB (one common TCP segment payload). */\n flushThreshold?: number;\n /** Initial backing buffer size; same semantics as `BufferSinkOptions`. */\n initialSize?: number;\n /** Consumer hook — invoked at most once per `flush()` (manual or\n * automatic), and only with a non-empty byte buffer. */\n onFlush(buffer: Uint8Array): void;\n}\n\nexport function createStreamingBufferSink(\n options: StreamingBufferSinkOptions,\n): StreamingBufferSink {\n if (!hasNodeBuffer()) {\n return createStreamingEncodedSink(options);\n }\n\n const flushThreshold = options.flushThreshold ?? 8192;\n const initialSize = options.initialSize ?? flushThreshold;\n let inner = createBufferSink({ initialSize });\n const emitAndReset = () => {\n const buf = inner.toBuffer();\n inner = createBufferSink({ initialSize });\n options.onFlush(buf);\n };\n return {\n append(chunk) {\n if (chunk === \"\") return;\n inner.append(chunk);\n if (inner.size() >= flushThreshold) {\n emitAndReset();\n }\n },\n flush() {\n if (inner.size() === 0) return;\n emitAndReset();\n },\n size() {\n return inner.size();\n },\n };\n}\n\nfunction createStreamingEncodedSink(options: StreamingBufferSinkOptions): StreamingBufferSink {\n const flushThreshold = options.flushThreshold ?? 8192;\n const encoder = new TextEncoder();\n let chunks: Uint8Array[] = [];\n let byteLength = 0;\n\n const emitAndReset = () => {\n const output = concatUint8Arrays(chunks, byteLength);\n chunks = [];\n byteLength = 0;\n options.onFlush(output);\n };\n\n return {\n append(chunk) {\n if (chunk === \"\") return;\n\n const bytes = encoder.encode(chunk);\n chunks.push(bytes);\n byteLength += bytes.byteLength;\n\n if (byteLength >= flushThreshold) {\n emitAndReset();\n }\n },\n flush() {\n if (byteLength === 0) return;\n emitAndReset();\n },\n size() {\n return byteLength;\n },\n };\n}\n\nfunction concatUint8Arrays(chunks: Uint8Array[], byteLength: number): Uint8Array {\n if (chunks.length === 1) {\n return chunks[0] ?? new Uint8Array();\n }\n\n const output = new Uint8Array(byteLength);\n let offset = 0;\n\n for (const chunk of chunks) {\n output.set(chunk, offset);\n offset += chunk.byteLength;\n }\n\n return output;\n}\n\nfunction hasNodeBuffer(): boolean {\n return typeof Buffer !== \"undefined\" && typeof Buffer.allocUnsafe === \"function\";\n}\n\nexport function createBufferSink(options: BufferSinkOptions = {}): BufferSink {\n const initialSize = options.initialSize ?? 8192;\n const growthFactor = options.growthFactor ?? 2;\n let buffer = Buffer.allocUnsafe(initialSize);\n let offset = 0;\n\n function ensure(requiredBytes: number): void {\n const required = offset + requiredBytes;\n\n if (required <= buffer.length) {\n return;\n }\n\n let newCapacity = buffer.length === 0 ? initialSize : buffer.length;\n\n while (newCapacity < required) {\n newCapacity = Math.ceil(newCapacity * growthFactor);\n }\n\n const grown = Buffer.allocUnsafe(newCapacity);\n buffer.copy(grown, 0, 0, offset);\n buffer = grown;\n }\n\n return {\n append(chunk) {\n if (typeof chunk === \"string\") {\n ensure(Buffer.byteLength(chunk, \"utf8\"));\n offset += buffer.write(chunk, offset, \"utf8\");\n return;\n }\n\n ensure(chunk.length);\n chunk.copy(buffer, offset);\n offset += chunk.length;\n },\n toBuffer() {\n return buffer.subarray(0, offset);\n },\n toString() {\n return buffer.toString(\"utf8\", 0, offset);\n },\n size() {\n return offset;\n },\n };\n}\n"]}
|
package/dist/flight.js
CHANGED
|
@@ -352,7 +352,9 @@ export function renderFlightPreloadLinks(response, options = {}) {
|
|
|
352
352
|
.map((chunk) => `<link rel="modulepreload" href="${escapeAttribute(chunk)}"${nonceAttribute}>`)
|
|
353
353
|
.join("");
|
|
354
354
|
}
|
|
355
|
-
function resolveFlightPromiseChunks(model, modelChunks, errorChunks) {
|
|
355
|
+
function resolveFlightPromiseChunks(model, modelChunks, errorChunks, depth = 0, context = createFlightDecodeContext()) {
|
|
356
|
+
if (depth > MAX_FLIGHT_DECODE_DEPTH)
|
|
357
|
+
flightTooDeep();
|
|
356
358
|
if (model === null ||
|
|
357
359
|
typeof model === "string" ||
|
|
358
360
|
typeof model === "number" ||
|
|
@@ -360,7 +362,7 @@ function resolveFlightPromiseChunks(model, modelChunks, errorChunks) {
|
|
|
360
362
|
return model;
|
|
361
363
|
}
|
|
362
364
|
if (Array.isArray(model)) {
|
|
363
|
-
return model.map((item) => resolveFlightPromiseChunks(item, modelChunks, errorChunks));
|
|
365
|
+
return model.map((item) => resolveFlightPromiseChunks(item, modelChunks, errorChunks, depth + 1, context));
|
|
364
366
|
}
|
|
365
367
|
if (model.kind === "promise") {
|
|
366
368
|
const error = errorChunks.get(model.id);
|
|
@@ -368,7 +370,16 @@ function resolveFlightPromiseChunks(model, modelChunks, errorChunks) {
|
|
|
368
370
|
return error;
|
|
369
371
|
}
|
|
370
372
|
if (modelChunks.has(model.id)) {
|
|
371
|
-
|
|
373
|
+
if (context.inProgressChunkIds.has(model.id)) {
|
|
374
|
+
flightCycle(model.id);
|
|
375
|
+
}
|
|
376
|
+
context.inProgressChunkIds.add(model.id);
|
|
377
|
+
try {
|
|
378
|
+
return decodeReactFlightModel(modelChunks.get(model.id), modelChunks, errorChunks, depth + 1, context);
|
|
379
|
+
}
|
|
380
|
+
finally {
|
|
381
|
+
context.inProgressChunkIds.delete(model.id);
|
|
382
|
+
}
|
|
372
383
|
}
|
|
373
384
|
return model;
|
|
374
385
|
}
|
|
@@ -377,7 +388,7 @@ function resolveFlightPromiseChunks(model, modelChunks, errorChunks) {
|
|
|
377
388
|
...model,
|
|
378
389
|
props: Object.fromEntries(Object.entries(model.props).map(([key, value]) => [
|
|
379
390
|
key,
|
|
380
|
-
resolveFlightPromiseChunks(value, modelChunks, errorChunks),
|
|
391
|
+
resolveFlightPromiseChunks(value, modelChunks, errorChunks, depth + 1, context),
|
|
381
392
|
])),
|
|
382
393
|
};
|
|
383
394
|
}
|
|
@@ -385,15 +396,15 @@ function resolveFlightPromiseChunks(model, modelChunks, errorChunks) {
|
|
|
385
396
|
return {
|
|
386
397
|
...model,
|
|
387
398
|
entries: model.entries.map(([key, value]) => [
|
|
388
|
-
resolveFlightPromiseChunks(key, modelChunks, errorChunks),
|
|
389
|
-
resolveFlightPromiseChunks(value, modelChunks, errorChunks),
|
|
399
|
+
resolveFlightPromiseChunks(key, modelChunks, errorChunks, depth + 1, context),
|
|
400
|
+
resolveFlightPromiseChunks(value, modelChunks, errorChunks, depth + 1, context),
|
|
390
401
|
]),
|
|
391
402
|
};
|
|
392
403
|
}
|
|
393
404
|
if (model.kind === "set") {
|
|
394
405
|
return {
|
|
395
406
|
...model,
|
|
396
|
-
values: model.values.map((value) => resolveFlightPromiseChunks(value, modelChunks, errorChunks)),
|
|
407
|
+
values: model.values.map((value) => resolveFlightPromiseChunks(value, modelChunks, errorChunks, depth + 1, context)),
|
|
397
408
|
};
|
|
398
409
|
}
|
|
399
410
|
if ("kind" in model) {
|
|
@@ -401,7 +412,9 @@ function resolveFlightPromiseChunks(model, modelChunks, errorChunks) {
|
|
|
401
412
|
}
|
|
402
413
|
return Object.fromEntries(Object.entries(model).map(([key, value]) => [
|
|
403
414
|
key,
|
|
404
|
-
value === undefined
|
|
415
|
+
value === undefined
|
|
416
|
+
? undefined
|
|
417
|
+
: resolveFlightPromiseChunks(value, modelChunks, errorChunks, depth + 1, context),
|
|
405
418
|
]));
|
|
406
419
|
}
|
|
407
420
|
function encodeReactFlightModel(model, state) {
|
|
@@ -713,7 +726,15 @@ class FlightDecodeError extends Error {
|
|
|
713
726
|
function flightTooDeep() {
|
|
714
727
|
throw new FlightDecodeError(`MR_FLIGHT_TOO_DEEP: nested deeper than ${MAX_FLIGHT_DECODE_DEPTH} levels`);
|
|
715
728
|
}
|
|
716
|
-
function
|
|
729
|
+
function flightCycle(id) {
|
|
730
|
+
throw new FlightDecodeError(`MR_FLIGHT_CYCLE: cyclic chunk reference ${id}`);
|
|
731
|
+
}
|
|
732
|
+
function createFlightDecodeContext() {
|
|
733
|
+
return {
|
|
734
|
+
inProgressChunkIds: new Set(),
|
|
735
|
+
};
|
|
736
|
+
}
|
|
737
|
+
function decodeReactFlightModel(value, modelChunks = new Map(), errorChunks = new Map(), depth = 0, context = createFlightDecodeContext()) {
|
|
717
738
|
if (depth > MAX_FLIGHT_DECODE_DEPTH)
|
|
718
739
|
flightTooDeep();
|
|
719
740
|
if (value === null ||
|
|
@@ -722,7 +743,7 @@ function decodeReactFlightModel(value, modelChunks = new Map(), errorChunks = ne
|
|
|
722
743
|
return value;
|
|
723
744
|
}
|
|
724
745
|
if (typeof value === "string") {
|
|
725
|
-
return decodeReactFlightString(value, modelChunks, errorChunks);
|
|
746
|
+
return decodeReactFlightString(value, modelChunks, errorChunks, depth, context);
|
|
726
747
|
}
|
|
727
748
|
if (Array.isArray(value)) {
|
|
728
749
|
if (value[0] === "$") {
|
|
@@ -730,20 +751,20 @@ function decodeReactFlightModel(value, modelChunks = new Map(), errorChunks = ne
|
|
|
730
751
|
kind: "element",
|
|
731
752
|
type: decodeReactFlightElementType(value[1]),
|
|
732
753
|
key: typeof value[2] === "string" ? value[2] : null,
|
|
733
|
-
props: decodeReactFlightProps(valueIsObject(value[3]) ? value[3] : {}, modelChunks, errorChunks, depth + 1),
|
|
754
|
+
props: decodeReactFlightProps(valueIsObject(value[3]) ? value[3] : {}, modelChunks, errorChunks, depth + 1, context),
|
|
734
755
|
};
|
|
735
756
|
}
|
|
736
|
-
return value.map((item) => decodeReactFlightModel(item, modelChunks, errorChunks, depth + 1));
|
|
757
|
+
return value.map((item) => decodeReactFlightModel(item, modelChunks, errorChunks, depth + 1, context));
|
|
737
758
|
}
|
|
738
759
|
if (isReactFlightBinaryModel(value)) {
|
|
739
760
|
return value;
|
|
740
761
|
}
|
|
741
762
|
if (valueIsObject(value)) {
|
|
742
|
-
return decodeReactFlightProps(value, modelChunks, errorChunks, depth + 1);
|
|
763
|
+
return decodeReactFlightProps(value, modelChunks, errorChunks, depth + 1, context);
|
|
743
764
|
}
|
|
744
765
|
return { kind: "undefined" };
|
|
745
766
|
}
|
|
746
|
-
function decodeReactFlightString(value, modelChunks, errorChunks) {
|
|
767
|
+
function decodeReactFlightString(value, modelChunks, errorChunks, depth, context) {
|
|
747
768
|
if (value === "$undefined" || value === "$u") {
|
|
748
769
|
return { kind: "undefined" };
|
|
749
770
|
}
|
|
@@ -769,7 +790,7 @@ function decodeReactFlightString(value, modelChunks, errorChunks) {
|
|
|
769
790
|
return { kind: "bigint", value: value.slice(2) };
|
|
770
791
|
}
|
|
771
792
|
if (/^\$[AOoUSsLlGgMmV][0-9a-f]+$/.test(value)) {
|
|
772
|
-
return decodeReactFlightChunk(value.slice(2), modelChunks, errorChunks);
|
|
793
|
+
return decodeReactFlightChunk(value.slice(2), modelChunks, errorChunks, depth + 1, context);
|
|
773
794
|
}
|
|
774
795
|
if (value.startsWith("$S")) {
|
|
775
796
|
return { kind: "symbol", name: value.slice(2) };
|
|
@@ -793,7 +814,7 @@ function decodeReactFlightString(value, modelChunks, errorChunks) {
|
|
|
793
814
|
};
|
|
794
815
|
}
|
|
795
816
|
if (/^\$Q[0-9a-f]+$/i.test(value)) {
|
|
796
|
-
const decoded = decodeReactFlightChunk(value.slice(2), modelChunks, errorChunks);
|
|
817
|
+
const decoded = decodeReactFlightChunk(value.slice(2), modelChunks, errorChunks, depth + 1, context);
|
|
797
818
|
const entries = Array.isArray(decoded)
|
|
798
819
|
? decoded.map((entry) => Array.isArray(entry) ? [entry[0] ?? { kind: "undefined" }, entry[1] ?? { kind: "undefined" }] : [entry, { kind: "undefined" }])
|
|
799
820
|
: [];
|
|
@@ -803,14 +824,14 @@ function decodeReactFlightString(value, modelChunks, errorChunks) {
|
|
|
803
824
|
};
|
|
804
825
|
}
|
|
805
826
|
if (/^\$W[0-9a-f]+$/i.test(value)) {
|
|
806
|
-
const decoded = decodeReactFlightChunk(value.slice(2), modelChunks, errorChunks);
|
|
827
|
+
const decoded = decodeReactFlightChunk(value.slice(2), modelChunks, errorChunks, depth + 1, context);
|
|
807
828
|
return {
|
|
808
829
|
kind: "set",
|
|
809
830
|
values: Array.isArray(decoded) ? decoded : [],
|
|
810
831
|
};
|
|
811
832
|
}
|
|
812
833
|
if (/^\$K[0-9a-f]+$/i.test(value)) {
|
|
813
|
-
const decoded = decodeReactFlightChunk(value.slice(2), modelChunks, errorChunks);
|
|
834
|
+
const decoded = decodeReactFlightChunk(value.slice(2), modelChunks, errorChunks, depth + 1, context);
|
|
814
835
|
const entries = Array.isArray(decoded)
|
|
815
836
|
? decoded.flatMap((entry) => Array.isArray(entry) && typeof entry[0] === "string"
|
|
816
837
|
? [[entry[0], entry[1] ?? { kind: "undefined" }]]
|
|
@@ -822,7 +843,7 @@ function decodeReactFlightString(value, modelChunks, errorChunks) {
|
|
|
822
843
|
};
|
|
823
844
|
}
|
|
824
845
|
if (/^\$i[0-9a-f]+$/i.test(value)) {
|
|
825
|
-
const decoded = decodeReactFlightChunk(value.slice(2), modelChunks, errorChunks);
|
|
846
|
+
const decoded = decodeReactFlightChunk(value.slice(2), modelChunks, errorChunks, depth + 1, context);
|
|
826
847
|
return {
|
|
827
848
|
kind: "iterable",
|
|
828
849
|
values: Array.isArray(decoded) ? decoded : [],
|
|
@@ -839,11 +860,13 @@ function decodeReactFlightString(value, modelChunks, errorChunks) {
|
|
|
839
860
|
return { kind: "undefined" };
|
|
840
861
|
}
|
|
841
862
|
if (/^\$[0-9a-f]+$/i.test(value)) {
|
|
842
|
-
return decodeReactFlightChunk(value.slice(1), modelChunks, errorChunks);
|
|
863
|
+
return decodeReactFlightChunk(value.slice(1), modelChunks, errorChunks, depth + 1, context);
|
|
843
864
|
}
|
|
844
865
|
return value;
|
|
845
866
|
}
|
|
846
|
-
function decodeReactFlightChunk(id, modelChunks, errorChunks) {
|
|
867
|
+
function decodeReactFlightChunk(id, modelChunks, errorChunks, depth, context) {
|
|
868
|
+
if (depth > MAX_FLIGHT_DECODE_DEPTH)
|
|
869
|
+
flightTooDeep();
|
|
847
870
|
const numericId = parseReactFlightId(id);
|
|
848
871
|
const error = errorChunks.get(numericId);
|
|
849
872
|
if (error !== undefined) {
|
|
@@ -855,7 +878,16 @@ function decodeReactFlightChunk(id, modelChunks, errorChunks) {
|
|
|
855
878
|
id: numericId,
|
|
856
879
|
};
|
|
857
880
|
}
|
|
858
|
-
|
|
881
|
+
if (context.inProgressChunkIds.has(numericId)) {
|
|
882
|
+
flightCycle(numericId);
|
|
883
|
+
}
|
|
884
|
+
context.inProgressChunkIds.add(numericId);
|
|
885
|
+
try {
|
|
886
|
+
return decodeReactFlightModel(modelChunks.get(numericId), modelChunks, errorChunks, depth, context);
|
|
887
|
+
}
|
|
888
|
+
finally {
|
|
889
|
+
context.inProgressChunkIds.delete(numericId);
|
|
890
|
+
}
|
|
859
891
|
}
|
|
860
892
|
function decodeReactFlightElementType(value) {
|
|
861
893
|
if (value === "$Sreact.fragment") {
|
|
@@ -869,12 +901,12 @@ function decodeReactFlightElementType(value) {
|
|
|
869
901
|
}
|
|
870
902
|
return typeof value === "string" ? value : String(value);
|
|
871
903
|
}
|
|
872
|
-
function decodeReactFlightProps(value, modelChunks, errorChunks, depth = 0) {
|
|
904
|
+
function decodeReactFlightProps(value, modelChunks, errorChunks, depth = 0, context = createFlightDecodeContext()) {
|
|
873
905
|
if (depth > MAX_FLIGHT_DECODE_DEPTH)
|
|
874
906
|
flightTooDeep();
|
|
875
907
|
return Object.fromEntries(Object.entries(value).map(([key, child]) => [
|
|
876
908
|
key,
|
|
877
|
-
decodeReactFlightModel(child, modelChunks, errorChunks, depth + 1),
|
|
909
|
+
decodeReactFlightModel(child, modelChunks, errorChunks, depth + 1, context),
|
|
878
910
|
]));
|
|
879
911
|
}
|
|
880
912
|
function isReactFlightBinaryModel(value) {
|