@reckona/mreact-server 0.0.138 → 0.0.139
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/html-helpers.js
CHANGED
|
@@ -80,7 +80,12 @@ function appendReactNodeList(sink, nodes, state) {
|
|
|
80
80
|
let chain;
|
|
81
81
|
for (const node of nodes) {
|
|
82
82
|
if (chain !== undefined) {
|
|
83
|
-
|
|
83
|
+
const buffered = renderReactNodeToBufferedString(node, state);
|
|
84
|
+
chain = chain.then(async () => {
|
|
85
|
+
await buffered.result;
|
|
86
|
+
await buffered.sink.drain();
|
|
87
|
+
sink.append(buffered.sink.toString());
|
|
88
|
+
});
|
|
84
89
|
continue;
|
|
85
90
|
}
|
|
86
91
|
const result = appendReactNode(sink, node, state);
|
|
@@ -90,6 +95,13 @@ function appendReactNodeList(sink, nodes, state) {
|
|
|
90
95
|
}
|
|
91
96
|
return chain;
|
|
92
97
|
}
|
|
98
|
+
function renderReactNodeToBufferedString(node, state) {
|
|
99
|
+
const sink = createStringSink();
|
|
100
|
+
return {
|
|
101
|
+
result: appendReactNode(sink, node, state),
|
|
102
|
+
sink,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
93
105
|
function appendReactElement(sink, element, state) {
|
|
94
106
|
if (typeof element.type === "string") {
|
|
95
107
|
return appendHostElement(sink, element, state);
|
|
@@ -155,7 +167,12 @@ function appendRawTextNodeList(sink, nodes) {
|
|
|
155
167
|
let chain;
|
|
156
168
|
for (const node of nodes) {
|
|
157
169
|
if (chain !== undefined) {
|
|
158
|
-
|
|
170
|
+
const buffered = renderRawTextNodeToBufferedString(node);
|
|
171
|
+
chain = chain.then(async () => {
|
|
172
|
+
await buffered.result;
|
|
173
|
+
await buffered.sink.drain();
|
|
174
|
+
sink.append(buffered.sink.toString());
|
|
175
|
+
});
|
|
159
176
|
continue;
|
|
160
177
|
}
|
|
161
178
|
const result = appendRawTextNode(sink, node);
|
|
@@ -165,6 +182,13 @@ function appendRawTextNodeList(sink, nodes) {
|
|
|
165
182
|
}
|
|
166
183
|
return chain;
|
|
167
184
|
}
|
|
185
|
+
function renderRawTextNodeToBufferedString(node) {
|
|
186
|
+
const sink = createStringSink();
|
|
187
|
+
return {
|
|
188
|
+
result: appendRawTextNode(sink, node),
|
|
189
|
+
sink,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
168
192
|
function appendSuspenseElement(sink, element, state) {
|
|
169
193
|
const rendered = renderReactNodeChildrenToString(element.props.children, state);
|
|
170
194
|
if (!isPromiseLikeString(rendered)) {
|
|
@@ -236,13 +260,17 @@ function renderHtmlAttribute(name, value) {
|
|
|
236
260
|
name === "ref" ||
|
|
237
261
|
value === null ||
|
|
238
262
|
value === undefined ||
|
|
239
|
-
typeof value === "function"
|
|
263
|
+
typeof value === "function" ||
|
|
264
|
+
/^on/i.test(name)) {
|
|
240
265
|
return "";
|
|
241
266
|
}
|
|
242
267
|
const attributeName = toHtmlAttributeName(name);
|
|
243
268
|
if (!VALID_ATTRIBUTE_NAME.test(attributeName)) {
|
|
244
269
|
return "";
|
|
245
270
|
}
|
|
271
|
+
if (/^on/i.test(attributeName)) {
|
|
272
|
+
return "";
|
|
273
|
+
}
|
|
246
274
|
if (value === false && !isBooleanishStringAttribute(attributeName)) {
|
|
247
275
|
return "";
|
|
248
276
|
}
|
|
@@ -301,16 +329,34 @@ const HTML_ATTRIBUTE_ALIASES = {
|
|
|
301
329
|
useMap: "usemap",
|
|
302
330
|
};
|
|
303
331
|
function isBooleanishStringAttribute(name) {
|
|
304
|
-
const attributeName =
|
|
305
|
-
|
|
332
|
+
const attributeName = name;
|
|
333
|
+
if (attributeName.startsWith("aria-") ||
|
|
306
334
|
attributeName.startsWith("data-") ||
|
|
307
|
-
BOOLEANISH_STRING_ATTRIBUTES.has(attributeName))
|
|
335
|
+
BOOLEANISH_STRING_ATTRIBUTES.has(attributeName)) {
|
|
336
|
+
return true;
|
|
337
|
+
}
|
|
338
|
+
if (!hasAsciiUppercase(attributeName)) {
|
|
339
|
+
return false;
|
|
340
|
+
}
|
|
341
|
+
const lowerAttributeName = attributeName.toLowerCase();
|
|
342
|
+
return (lowerAttributeName.startsWith("aria-") ||
|
|
343
|
+
lowerAttributeName.startsWith("data-") ||
|
|
344
|
+
BOOLEANISH_STRING_ATTRIBUTES.has(lowerAttributeName));
|
|
308
345
|
}
|
|
309
346
|
const BOOLEANISH_STRING_ATTRIBUTES = new Set([
|
|
310
347
|
"contenteditable",
|
|
311
348
|
"draggable",
|
|
312
349
|
"spellcheck",
|
|
313
350
|
]);
|
|
351
|
+
function hasAsciiUppercase(value) {
|
|
352
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
353
|
+
const code = value.charCodeAt(index);
|
|
354
|
+
if (code >= 65 && code <= 90) {
|
|
355
|
+
return true;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
return false;
|
|
359
|
+
}
|
|
314
360
|
function isPromiseLikeNode(value) {
|
|
315
361
|
return isPromiseLikeUnknown(value);
|
|
316
362
|
}
|
package/dist/html-helpers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"html-helpers.js","sourceRoot":"","sources":["../src/html-helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Fragment,\n Suspense as ReactCompatSuspense,\n isValidElement,\n type ReactCompatElement,\n type ReactCompatNode,\n} from \"@reckona/mreact-compat\";\nimport type { HtmlSink } from \"@reckona/mreact-shared/compiler-contract\";\nimport { escapeHtmlText as escapeHtml } from \"@reckona/mreact-shared/html-escape\";\nimport { isVoidHtmlElement } from \"@reckona/mreact-shared\";\nimport {\n renderReactSuspenseBoundary,\n renderReactSuspenseOutOfOrderBoundary,\n type HydrationScriptOptions,\n} from \"./boundary.js\";\nimport {\n isDangerousHtmlAttribute,\n isDangerousHtmlOptIn,\n isUnsafeMetaRefreshContent,\n isUnsafeUrlAttribute,\n} from \"./url-safety.js\";\nimport {\n escapeAttribute,\n isPromiseLikeUnknown,\n renderNonceAttribute,\n serializeScriptJson,\n} from \"./html-internals.js\";\nimport { createStringSink, hasDeferredTasks, type StreamRender } from \"./sink.js\";\nimport { renderToReadableStream } from \"./stream.js\";\n\nexport interface ScriptAssetOptions {\n src: string;\n nonce?: string;\n integrity?: string;\n crossOrigin?: \"anonymous\" | \"use-credentials\";\n}\n\nexport interface EventHydrationEntry {\n id: string;\n event: string;\n handler: string;\n}\n\nexport interface EventHydrationManifest {\n version: 1;\n events: EventHydrationEntry[];\n}\n\nexport interface HtmlResponseOptions {\n headers?: HeadersInit;\n status?: number;\n statusText?: string;\n}\n\nexport function serializeSsrState(value: unknown): string {\n return serializeScriptJson(value);\n}\n\nexport function renderSsrState(\n sink: HtmlSink,\n value: unknown,\n options: HydrationScriptOptions = {},\n): void {\n sink.append(\n `<script type=\"application/json\" data-mreact-ssr-state${renderNonceAttribute(options.nonce)}>${serializeSsrState(value)}</script>`,\n );\n}\n\nexport function createEventHydrationManifest(\n events: readonly EventHydrationEntry[],\n): EventHydrationManifest {\n return {\n version: 1,\n events: events.map((event) => ({ ...event })),\n };\n}\n\nexport function renderEventHydrationManifest(\n sink: HtmlSink,\n manifest: EventHydrationManifest,\n options: HydrationScriptOptions = {},\n): void {\n sink.append(\n `<script type=\"application/json\" data-mreact-event-manifest${renderNonceAttribute(options.nonce)}>${serializeSsrState(manifest)}</script>`,\n );\n}\n\nexport function renderScriptAsset(sink: HtmlSink, options: ScriptAssetOptions): void {\n const integrityAttribute =\n options.integrity === undefined ? \"\" : ` integrity=\"${escapeAttribute(options.integrity)}\"`;\n const crossOrigin =\n options.integrity === undefined ? options.crossOrigin : (options.crossOrigin ?? \"anonymous\");\n const crossOriginAttribute =\n crossOrigin === undefined ? \"\" : ` crossorigin=\"${escapeAttribute(crossOrigin)}\"`;\n\n sink.append(\n `<script src=\"${escapeAttribute(options.src)}\"${renderNonceAttribute(options.nonce)}${integrityAttribute}${crossOriginAttribute}></script>`,\n );\n}\n\nexport function html(node: unknown, options: HtmlResponseOptions = {}): Response {\n const headers = new Headers(options.headers);\n const responseOptions: ResponseInit = { headers };\n\n if (!headers.has(\"content-type\")) {\n headers.set(\"content-type\", \"text/html; charset=utf-8\");\n }\n\n if (options.status !== undefined) {\n responseOptions.status = options.status;\n }\n\n if (options.statusText !== undefined) {\n responseOptions.statusText = options.statusText;\n }\n\n return new Response(\n renderToReadableStream((sink) => {\n const state: HtmlRenderState = { suspenseId: 0 };\n return appendReactNode(sink, node, state);\n }),\n responseOptions,\n );\n}\n\nexport async function renderToString(render: StreamRender): Promise<string> {\n const sink = createStringSink();\n\n await render(sink);\n await sink.drain();\n\n return sink.toString();\n}\n\nexport async function renderReactNodeToString(node: unknown): Promise<string> {\n const sink = createStringSink();\n const state: HtmlRenderState = { suspenseId: 0 };\n\n await appendReactNode(sink, node, state);\n await sink.drain();\n\n return sink.toString();\n}\n\ninterface HtmlRenderState {\n suspenseId: number;\n}\n\nfunction appendReactNode(\n sink: HtmlSink,\n node: unknown,\n state: HtmlRenderState,\n): void | PromiseLike<void> {\n if (isPromiseLikeNode(node)) {\n return node.then((resolved) => appendReactNode(sink, resolved, state));\n }\n\n if (node === null || node === undefined || typeof node === \"boolean\") {\n return;\n }\n\n if (typeof node === \"string\" || typeof node === \"number\") {\n sink.append(escapeHtml(node));\n return;\n }\n\n if (Array.isArray(node)) {\n return appendReactNodeList(sink, node, state);\n }\n\n if (!isValidElement(node)) {\n return;\n }\n\n return appendReactElement(sink, node, state);\n}\n\nfunction appendReactNodeList(\n sink: HtmlSink,\n nodes: readonly unknown[],\n state: HtmlRenderState,\n): void | PromiseLike<void> {\n let chain: PromiseLike<void> | undefined;\n\n for (const node of nodes) {\n if (chain !== undefined) {\n chain = chain.then(() => appendReactNode(sink, node, state));\n continue;\n }\n\n const result = appendReactNode(sink, node, state);\n\n if (isPromiseLike(result)) {\n chain = result;\n }\n }\n\n return chain;\n}\n\nfunction appendReactElement(\n sink: HtmlSink,\n element: ReactCompatElement,\n state: HtmlRenderState,\n): void | PromiseLike<void> {\n if (typeof element.type === \"string\") {\n return appendHostElement(sink, element, state);\n }\n\n if (element.type === Fragment) {\n return appendReactNode(sink, element.props.children, state);\n }\n\n if (element.type === ReactCompatSuspense) {\n return appendSuspenseElement(sink, element, state);\n }\n\n if (isClassComponentType(element.type)) {\n const instance = new element.type(element.props);\n return appendReactNode(sink, instance.render(), state);\n }\n\n if (typeof element.type === \"function\") {\n return appendReactNode(sink, element.type(element.props), state);\n }\n}\n\nfunction isClassComponentType(\n value: unknown,\n): value is new (props: Record<string, unknown>) => { render(): ReactCompatNode } {\n return typeof value === \"function\" && value.prototype?.render !== undefined;\n}\n\nfunction appendHostElement(\n sink: HtmlSink,\n element: ReactCompatElement,\n state: HtmlRenderState,\n): void | PromiseLike<void> {\n const tagName = element.type as string;\n const innerHtml = (element.props as { dangerouslySetInnerHTML?: { __html?: unknown } })\n .dangerouslySetInnerHTML;\n sink.append(`<${tagName}${renderHtmlAttributes(element.props)}>`);\n\n if (isVoidHtmlElement(tagName)) {\n return;\n }\n\n if (innerHtml !== undefined) {\n sink.append(String(innerHtml.__html ?? \"\"));\n sink.append(`</${tagName}>`);\n return;\n }\n\n const result = isRawTextElement(tagName)\n ? appendRawTextNode(sink, element.props.children)\n : appendReactNode(sink, element.props.children, state);\n\n if (isPromiseLike(result)) {\n return result.then(() => {\n sink.append(`</${tagName}>`);\n });\n }\n\n sink.append(`</${tagName}>`);\n}\n\nfunction isRawTextElement(tagName: string): boolean {\n return tagName === \"script\" || tagName === \"style\";\n}\n\nfunction appendRawTextNode(sink: HtmlSink, node: unknown): void | PromiseLike<void> {\n if (isPromiseLikeNode(node)) {\n return node.then((resolved) => appendRawTextNode(sink, resolved));\n }\n\n if (node === null || node === undefined || typeof node === \"boolean\") {\n return;\n }\n\n if (Array.isArray(node)) {\n return appendRawTextNodeList(sink, node);\n }\n\n if (typeof node === \"string\" || typeof node === \"number\") {\n sink.append(String(node));\n }\n}\n\nfunction appendRawTextNodeList(\n sink: HtmlSink,\n nodes: readonly unknown[],\n): void | PromiseLike<void> {\n let chain: PromiseLike<void> | undefined;\n\n for (const node of nodes) {\n if (chain !== undefined) {\n chain = chain.then(() => appendRawTextNode(sink, node));\n continue;\n }\n\n const result = appendRawTextNode(sink, node);\n\n if (isPromiseLike(result)) {\n chain = result;\n }\n }\n\n return chain;\n}\n\nfunction appendSuspenseElement(\n sink: HtmlSink,\n element: ReactCompatElement,\n state: HtmlRenderState,\n): void {\n const rendered = renderReactNodeChildrenToString(element.props.children, state);\n\n if (!isPromiseLikeString(rendered)) {\n renderReactSuspenseBoundary(sink, (boundarySink) => {\n boundarySink.append(rendered);\n });\n return;\n }\n\n const id = state.suspenseId;\n state.suspenseId += 1;\n renderReactSuspenseOutOfOrderBoundary(\n sink,\n `B:${id}`,\n `S:${id}`,\n rendered,\n (boundarySink, renderedHtml) => {\n boundarySink.append(renderedHtml);\n },\n {\n fallback(boundarySink) {\n const fallback = renderReactNodeChildrenToString(\n (element.props as { fallback?: ReactCompatNode }).fallback,\n state,\n );\n\n if (isPromiseLikeString(fallback)) {\n return fallback.then((html) => {\n boundarySink.append(html);\n });\n }\n\n boundarySink.append(fallback);\n },\n },\n );\n}\n\nfunction renderReactNodeChildrenToString(\n node: unknown,\n state: HtmlRenderState,\n): string | PromiseLike<string> {\n const sink = createStringSink();\n const result = appendReactNode(sink, node, state);\n const finish = () =>\n hasDeferredTasks(sink) ? sink.drain().then(() => sink.toString()) : sink.toString();\n\n if (isPromiseLike(result)) {\n return result.then(finish);\n }\n\n return finish();\n}\n\nfunction renderHtmlAttributes(props: Record<string, unknown>): string {\n // Issue 078: <meta http-equiv=\"refresh\" content=\"0;url=javascript:...\">\n // is URL-bearing only when http-equiv is \"refresh\", so we need both\n // attributes in scope to make the call. Strip the unsafe content\n // before per-attribute rendering.\n const sanitizedProps = sanitizeMetaRefreshProps(props);\n return Object.entries(sanitizedProps)\n .map(([name, value]) => renderHtmlAttribute(name, value))\n .filter((attribute) => attribute !== \"\")\n .join(\"\");\n}\n\nfunction sanitizeMetaRefreshProps(\n props: Record<string, unknown>,\n): Record<string, unknown> {\n const httpEquiv = props[\"http-equiv\"] ?? props.httpEquiv;\n const content = props[\"content\"];\n if (typeof httpEquiv !== \"string\" || typeof content !== \"string\") return props;\n if (!isUnsafeMetaRefreshContent(httpEquiv, content)) return props;\n // Drop only `content`; keep http-equiv so the developer's intent is\n // still visible in the rendered HTML (debugging hint).\n const sanitized = { ...props };\n delete sanitized[\"content\"];\n return sanitized;\n}\n\n// Mirrors `isAttributeNameSafe` in react-dom: an attribute name must start with\n// an ASCII letter (or underscore) and contain only word chars, dot, hyphen, or\n// colon. Anything else is dropped to prevent SSR XSS via spread props\n// (`<div {...userControlled} />`). See docs/issues/resolved Issue 060.\nconst VALID_ATTRIBUTE_NAME = /^[A-Za-z_][\\w.\\-:]*$/;\n\n// URL scheme allow/block list is shared with the compiler emit paths\n// (Issues 062 / 073). See packages/server/src/url-safety.ts.\n\nfunction renderHtmlAttribute(name: string, value: unknown): string {\n if (\n name === \"children\" ||\n name === \"dangerouslySetInnerHTML\" ||\n name === \"key\" ||\n name === \"ref\" ||\n value === null ||\n value === undefined ||\n typeof value === \"function\"\n ) {\n return \"\";\n }\n\n const attributeName = toHtmlAttributeName(name);\n\n if (!VALID_ATTRIBUTE_NAME.test(attributeName)) {\n return \"\";\n }\n\n if (value === false && !isBooleanishStringAttribute(attributeName)) {\n return \"\";\n }\n\n // Issue 077: HTML-bearing attributes (`srcdoc`) require the explicit\n // `{ __html: \"...\" }` opt-in. A plain string value -- even if escaped\n // for the attribute syntax -- decodes back to executable HTML inside\n // the iframe document with the parent's origin.\n if (isDangerousHtmlAttribute(attributeName)) {\n if (!isDangerousHtmlOptIn(value)) {\n return \"\";\n }\n return ` ${attributeName}=\"${escapeAttribute(value.__html)}\"`;\n }\n\n if (value === true) {\n if (isBooleanishStringAttribute(attributeName)) {\n return ` ${attributeName}=\"true\"`;\n }\n return ` ${attributeName}`;\n }\n\n if (value === false) {\n return ` ${attributeName}=\"false\"`;\n }\n\n const stringValue = String(value);\n\n if (isUnsafeUrlAttribute(attributeName, stringValue)) {\n return \"\";\n }\n\n return ` ${attributeName}=\"${escapeAttribute(stringValue)}\"`;\n}\n\nfunction toHtmlAttributeName(name: string): string {\n return HTML_ATTRIBUTE_ALIASES[name] ?? name;\n}\n\nconst HTML_ATTRIBUTE_ALIASES: Record<string, string> = {\n acceptCharset: \"accept-charset\",\n autoFocus: \"autofocus\",\n autoPlay: \"autoplay\",\n charSet: \"charset\",\n className: \"class\",\n colSpan: \"colspan\",\n contentEditable: \"contenteditable\",\n crossOrigin: \"crossorigin\",\n encType: \"enctype\",\n formAction: \"formaction\",\n frameBorder: \"frameborder\",\n htmlFor: \"for\",\n httpEquiv: \"http-equiv\",\n maxLength: \"maxlength\",\n minLength: \"minlength\",\n noValidate: \"novalidate\",\n playsInline: \"playsinline\",\n readOnly: \"readonly\",\n rowSpan: \"rowspan\",\n spellCheck: \"spellcheck\",\n srcDoc: \"srcdoc\",\n srcSet: \"srcset\",\n tabIndex: \"tabindex\",\n useMap: \"usemap\",\n};\n\nfunction isBooleanishStringAttribute(name: string): boolean {\n const attributeName = toHtmlAttributeName(name).toLowerCase();\n return (\n attributeName.startsWith(\"aria-\") ||\n attributeName.startsWith(\"data-\") ||\n BOOLEANISH_STRING_ATTRIBUTES.has(attributeName)\n );\n}\n\nconst BOOLEANISH_STRING_ATTRIBUTES = new Set<string>([\n \"contenteditable\",\n \"draggable\",\n \"spellcheck\",\n]);\n\nfunction isPromiseLikeNode(value: unknown): value is PromiseLike<unknown> {\n return isPromiseLikeUnknown(value);\n}\n\nfunction isPromiseLikeString(value: unknown): value is PromiseLike<string> {\n return isPromiseLikeUnknown(value);\n}\n\nfunction isPromiseLike(value: unknown): value is PromiseLike<void> {\n return isPromiseLikeUnknown(value);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"html-helpers.js","sourceRoot":"","sources":["../src/html-helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Fragment,\n Suspense as ReactCompatSuspense,\n isValidElement,\n type ReactCompatElement,\n type ReactCompatNode,\n} from \"@reckona/mreact-compat\";\nimport type { HtmlSink } from \"@reckona/mreact-shared/compiler-contract\";\nimport { escapeHtmlText as escapeHtml } from \"@reckona/mreact-shared/html-escape\";\nimport { isVoidHtmlElement } from \"@reckona/mreact-shared\";\nimport {\n renderReactSuspenseBoundary,\n renderReactSuspenseOutOfOrderBoundary,\n type HydrationScriptOptions,\n} from \"./boundary.js\";\nimport {\n isDangerousHtmlAttribute,\n isDangerousHtmlOptIn,\n isUnsafeMetaRefreshContent,\n isUnsafeUrlAttribute,\n} from \"./url-safety.js\";\nimport {\n escapeAttribute,\n isPromiseLikeUnknown,\n renderNonceAttribute,\n serializeScriptJson,\n} from \"./html-internals.js\";\nimport { createStringSink, hasDeferredTasks, type StreamRender } from \"./sink.js\";\nimport { renderToReadableStream } from \"./stream.js\";\n\nexport interface ScriptAssetOptions {\n src: string;\n nonce?: string;\n integrity?: string;\n crossOrigin?: \"anonymous\" | \"use-credentials\";\n}\n\nexport interface EventHydrationEntry {\n id: string;\n event: string;\n handler: string;\n}\n\nexport interface EventHydrationManifest {\n version: 1;\n events: EventHydrationEntry[];\n}\n\nexport interface HtmlResponseOptions {\n headers?: HeadersInit;\n status?: number;\n statusText?: string;\n}\n\nexport function serializeSsrState(value: unknown): string {\n return serializeScriptJson(value);\n}\n\nexport function renderSsrState(\n sink: HtmlSink,\n value: unknown,\n options: HydrationScriptOptions = {},\n): void {\n sink.append(\n `<script type=\"application/json\" data-mreact-ssr-state${renderNonceAttribute(options.nonce)}>${serializeSsrState(value)}</script>`,\n );\n}\n\nexport function createEventHydrationManifest(\n events: readonly EventHydrationEntry[],\n): EventHydrationManifest {\n return {\n version: 1,\n events: events.map((event) => ({ ...event })),\n };\n}\n\nexport function renderEventHydrationManifest(\n sink: HtmlSink,\n manifest: EventHydrationManifest,\n options: HydrationScriptOptions = {},\n): void {\n sink.append(\n `<script type=\"application/json\" data-mreact-event-manifest${renderNonceAttribute(options.nonce)}>${serializeSsrState(manifest)}</script>`,\n );\n}\n\nexport function renderScriptAsset(sink: HtmlSink, options: ScriptAssetOptions): void {\n const integrityAttribute =\n options.integrity === undefined ? \"\" : ` integrity=\"${escapeAttribute(options.integrity)}\"`;\n const crossOrigin =\n options.integrity === undefined ? options.crossOrigin : (options.crossOrigin ?? \"anonymous\");\n const crossOriginAttribute =\n crossOrigin === undefined ? \"\" : ` crossorigin=\"${escapeAttribute(crossOrigin)}\"`;\n\n sink.append(\n `<script src=\"${escapeAttribute(options.src)}\"${renderNonceAttribute(options.nonce)}${integrityAttribute}${crossOriginAttribute}></script>`,\n );\n}\n\nexport function html(node: unknown, options: HtmlResponseOptions = {}): Response {\n const headers = new Headers(options.headers);\n const responseOptions: ResponseInit = { headers };\n\n if (!headers.has(\"content-type\")) {\n headers.set(\"content-type\", \"text/html; charset=utf-8\");\n }\n\n if (options.status !== undefined) {\n responseOptions.status = options.status;\n }\n\n if (options.statusText !== undefined) {\n responseOptions.statusText = options.statusText;\n }\n\n return new Response(\n renderToReadableStream((sink) => {\n const state: HtmlRenderState = { suspenseId: 0 };\n return appendReactNode(sink, node, state);\n }),\n responseOptions,\n );\n}\n\nexport async function renderToString(render: StreamRender): Promise<string> {\n const sink = createStringSink();\n\n await render(sink);\n await sink.drain();\n\n return sink.toString();\n}\n\nexport async function renderReactNodeToString(node: unknown): Promise<string> {\n const sink = createStringSink();\n const state: HtmlRenderState = { suspenseId: 0 };\n\n await appendReactNode(sink, node, state);\n await sink.drain();\n\n return sink.toString();\n}\n\ninterface HtmlRenderState {\n suspenseId: number;\n}\n\nfunction appendReactNode(\n sink: HtmlSink,\n node: unknown,\n state: HtmlRenderState,\n): void | PromiseLike<void> {\n if (isPromiseLikeNode(node)) {\n return node.then((resolved) => appendReactNode(sink, resolved, state));\n }\n\n if (node === null || node === undefined || typeof node === \"boolean\") {\n return;\n }\n\n if (typeof node === \"string\" || typeof node === \"number\") {\n sink.append(escapeHtml(node));\n return;\n }\n\n if (Array.isArray(node)) {\n return appendReactNodeList(sink, node, state);\n }\n\n if (!isValidElement(node)) {\n return;\n }\n\n return appendReactElement(sink, node, state);\n}\n\nfunction appendReactNodeList(\n sink: HtmlSink,\n nodes: readonly unknown[],\n state: HtmlRenderState,\n): void | PromiseLike<void> {\n let chain: PromiseLike<void> | undefined;\n\n for (const node of nodes) {\n if (chain !== undefined) {\n const buffered = renderReactNodeToBufferedString(node, state);\n chain = chain.then(async () => {\n await buffered.result;\n await buffered.sink.drain();\n sink.append(buffered.sink.toString());\n });\n continue;\n }\n\n const result = appendReactNode(sink, node, state);\n\n if (isPromiseLike(result)) {\n chain = result;\n }\n }\n\n return chain;\n}\n\nfunction renderReactNodeToBufferedString(\n node: unknown,\n state: HtmlRenderState,\n): { result: void | PromiseLike<void>; sink: ReturnType<typeof createStringSink> } {\n const sink = createStringSink();\n\n return {\n result: appendReactNode(sink, node, state),\n sink,\n };\n}\n\nfunction appendReactElement(\n sink: HtmlSink,\n element: ReactCompatElement,\n state: HtmlRenderState,\n): void | PromiseLike<void> {\n if (typeof element.type === \"string\") {\n return appendHostElement(sink, element, state);\n }\n\n if (element.type === Fragment) {\n return appendReactNode(sink, element.props.children, state);\n }\n\n if (element.type === ReactCompatSuspense) {\n return appendSuspenseElement(sink, element, state);\n }\n\n if (isClassComponentType(element.type)) {\n const instance = new element.type(element.props);\n return appendReactNode(sink, instance.render(), state);\n }\n\n if (typeof element.type === \"function\") {\n return appendReactNode(sink, element.type(element.props), state);\n }\n}\n\nfunction isClassComponentType(\n value: unknown,\n): value is new (props: Record<string, unknown>) => { render(): ReactCompatNode } {\n return typeof value === \"function\" && value.prototype?.render !== undefined;\n}\n\nfunction appendHostElement(\n sink: HtmlSink,\n element: ReactCompatElement,\n state: HtmlRenderState,\n): void | PromiseLike<void> {\n const tagName = element.type as string;\n const innerHtml = (element.props as { dangerouslySetInnerHTML?: { __html?: unknown } })\n .dangerouslySetInnerHTML;\n sink.append(`<${tagName}${renderHtmlAttributes(element.props)}>`);\n\n if (isVoidHtmlElement(tagName)) {\n return;\n }\n\n if (innerHtml !== undefined) {\n sink.append(String(innerHtml.__html ?? \"\"));\n sink.append(`</${tagName}>`);\n return;\n }\n\n const result = isRawTextElement(tagName)\n ? appendRawTextNode(sink, element.props.children)\n : appendReactNode(sink, element.props.children, state);\n\n if (isPromiseLike(result)) {\n return result.then(() => {\n sink.append(`</${tagName}>`);\n });\n }\n\n sink.append(`</${tagName}>`);\n}\n\nfunction isRawTextElement(tagName: string): boolean {\n return tagName === \"script\" || tagName === \"style\";\n}\n\nfunction appendRawTextNode(sink: HtmlSink, node: unknown): void | PromiseLike<void> {\n if (isPromiseLikeNode(node)) {\n return node.then((resolved) => appendRawTextNode(sink, resolved));\n }\n\n if (node === null || node === undefined || typeof node === \"boolean\") {\n return;\n }\n\n if (Array.isArray(node)) {\n return appendRawTextNodeList(sink, node);\n }\n\n if (typeof node === \"string\" || typeof node === \"number\") {\n sink.append(String(node));\n }\n}\n\nfunction appendRawTextNodeList(\n sink: HtmlSink,\n nodes: readonly unknown[],\n): void | PromiseLike<void> {\n let chain: PromiseLike<void> | undefined;\n\n for (const node of nodes) {\n if (chain !== undefined) {\n const buffered = renderRawTextNodeToBufferedString(node);\n chain = chain.then(async () => {\n await buffered.result;\n await buffered.sink.drain();\n sink.append(buffered.sink.toString());\n });\n continue;\n }\n\n const result = appendRawTextNode(sink, node);\n\n if (isPromiseLike(result)) {\n chain = result;\n }\n }\n\n return chain;\n}\n\nfunction renderRawTextNodeToBufferedString(\n node: unknown,\n): { result: void | PromiseLike<void>; sink: ReturnType<typeof createStringSink> } {\n const sink = createStringSink();\n\n return {\n result: appendRawTextNode(sink, node),\n sink,\n };\n}\n\nfunction appendSuspenseElement(\n sink: HtmlSink,\n element: ReactCompatElement,\n state: HtmlRenderState,\n): void {\n const rendered = renderReactNodeChildrenToString(element.props.children, state);\n\n if (!isPromiseLikeString(rendered)) {\n renderReactSuspenseBoundary(sink, (boundarySink) => {\n boundarySink.append(rendered);\n });\n return;\n }\n\n const id = state.suspenseId;\n state.suspenseId += 1;\n renderReactSuspenseOutOfOrderBoundary(\n sink,\n `B:${id}`,\n `S:${id}`,\n rendered,\n (boundarySink, renderedHtml) => {\n boundarySink.append(renderedHtml);\n },\n {\n fallback(boundarySink) {\n const fallback = renderReactNodeChildrenToString(\n (element.props as { fallback?: ReactCompatNode }).fallback,\n state,\n );\n\n if (isPromiseLikeString(fallback)) {\n return fallback.then((html) => {\n boundarySink.append(html);\n });\n }\n\n boundarySink.append(fallback);\n },\n },\n );\n}\n\nfunction renderReactNodeChildrenToString(\n node: unknown,\n state: HtmlRenderState,\n): string | PromiseLike<string> {\n const sink = createStringSink();\n const result = appendReactNode(sink, node, state);\n const finish = () =>\n hasDeferredTasks(sink) ? sink.drain().then(() => sink.toString()) : sink.toString();\n\n if (isPromiseLike(result)) {\n return result.then(finish);\n }\n\n return finish();\n}\n\nfunction renderHtmlAttributes(props: Record<string, unknown>): string {\n // Issue 078: <meta http-equiv=\"refresh\" content=\"0;url=javascript:...\">\n // is URL-bearing only when http-equiv is \"refresh\", so we need both\n // attributes in scope to make the call. Strip the unsafe content\n // before per-attribute rendering.\n const sanitizedProps = sanitizeMetaRefreshProps(props);\n return Object.entries(sanitizedProps)\n .map(([name, value]) => renderHtmlAttribute(name, value))\n .filter((attribute) => attribute !== \"\")\n .join(\"\");\n}\n\nfunction sanitizeMetaRefreshProps(\n props: Record<string, unknown>,\n): Record<string, unknown> {\n const httpEquiv = props[\"http-equiv\"] ?? props.httpEquiv;\n const content = props[\"content\"];\n if (typeof httpEquiv !== \"string\" || typeof content !== \"string\") return props;\n if (!isUnsafeMetaRefreshContent(httpEquiv, content)) return props;\n // Drop only `content`; keep http-equiv so the developer's intent is\n // still visible in the rendered HTML (debugging hint).\n const sanitized = { ...props };\n delete sanitized[\"content\"];\n return sanitized;\n}\n\n// Mirrors `isAttributeNameSafe` in react-dom: an attribute name must start with\n// an ASCII letter (or underscore) and contain only word chars, dot, hyphen, or\n// colon. Anything else is dropped to prevent SSR XSS via spread props\n// (`<div {...userControlled} />`). See docs/issues/resolved Issue 060.\nconst VALID_ATTRIBUTE_NAME = /^[A-Za-z_][\\w.\\-:]*$/;\n\n// URL scheme allow/block list is shared with the compiler emit paths\n// (Issues 062 / 073). See packages/server/src/url-safety.ts.\n\nfunction renderHtmlAttribute(name: string, value: unknown): string {\n if (\n name === \"children\" ||\n name === \"dangerouslySetInnerHTML\" ||\n name === \"key\" ||\n name === \"ref\" ||\n value === null ||\n value === undefined ||\n typeof value === \"function\" ||\n /^on/i.test(name)\n ) {\n return \"\";\n }\n\n const attributeName = toHtmlAttributeName(name);\n\n if (!VALID_ATTRIBUTE_NAME.test(attributeName)) {\n return \"\";\n }\n\n if (/^on/i.test(attributeName)) {\n return \"\";\n }\n\n if (value === false && !isBooleanishStringAttribute(attributeName)) {\n return \"\";\n }\n\n // Issue 077: HTML-bearing attributes (`srcdoc`) require the explicit\n // `{ __html: \"...\" }` opt-in. A plain string value -- even if escaped\n // for the attribute syntax -- decodes back to executable HTML inside\n // the iframe document with the parent's origin.\n if (isDangerousHtmlAttribute(attributeName)) {\n if (!isDangerousHtmlOptIn(value)) {\n return \"\";\n }\n return ` ${attributeName}=\"${escapeAttribute(value.__html)}\"`;\n }\n\n if (value === true) {\n if (isBooleanishStringAttribute(attributeName)) {\n return ` ${attributeName}=\"true\"`;\n }\n return ` ${attributeName}`;\n }\n\n if (value === false) {\n return ` ${attributeName}=\"false\"`;\n }\n\n const stringValue = String(value);\n\n if (isUnsafeUrlAttribute(attributeName, stringValue)) {\n return \"\";\n }\n\n return ` ${attributeName}=\"${escapeAttribute(stringValue)}\"`;\n}\n\nfunction toHtmlAttributeName(name: string): string {\n return HTML_ATTRIBUTE_ALIASES[name] ?? name;\n}\n\nconst HTML_ATTRIBUTE_ALIASES: Record<string, string> = {\n acceptCharset: \"accept-charset\",\n autoFocus: \"autofocus\",\n autoPlay: \"autoplay\",\n charSet: \"charset\",\n className: \"class\",\n colSpan: \"colspan\",\n contentEditable: \"contenteditable\",\n crossOrigin: \"crossorigin\",\n encType: \"enctype\",\n formAction: \"formaction\",\n frameBorder: \"frameborder\",\n htmlFor: \"for\",\n httpEquiv: \"http-equiv\",\n maxLength: \"maxlength\",\n minLength: \"minlength\",\n noValidate: \"novalidate\",\n playsInline: \"playsinline\",\n readOnly: \"readonly\",\n rowSpan: \"rowspan\",\n spellCheck: \"spellcheck\",\n srcDoc: \"srcdoc\",\n srcSet: \"srcset\",\n tabIndex: \"tabindex\",\n useMap: \"usemap\",\n};\n\nfunction isBooleanishStringAttribute(name: string): boolean {\n const attributeName = name;\n\n if (\n attributeName.startsWith(\"aria-\") ||\n attributeName.startsWith(\"data-\") ||\n BOOLEANISH_STRING_ATTRIBUTES.has(attributeName)\n ) {\n return true;\n }\n\n if (!hasAsciiUppercase(attributeName)) {\n return false;\n }\n\n const lowerAttributeName = attributeName.toLowerCase();\n return (\n lowerAttributeName.startsWith(\"aria-\") ||\n lowerAttributeName.startsWith(\"data-\") ||\n BOOLEANISH_STRING_ATTRIBUTES.has(lowerAttributeName)\n );\n}\n\nconst BOOLEANISH_STRING_ATTRIBUTES = new Set<string>([\n \"contenteditable\",\n \"draggable\",\n \"spellcheck\",\n]);\n\nfunction hasAsciiUppercase(value: string): boolean {\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code >= 65 && code <= 90) {\n return true;\n }\n }\n\n return false;\n}\n\nfunction isPromiseLikeNode(value: unknown): value is PromiseLike<unknown> {\n return isPromiseLikeUnknown(value);\n}\n\nfunction isPromiseLikeString(value: unknown): value is PromiseLike<string> {\n return isPromiseLikeUnknown(value);\n}\n\nfunction isPromiseLike(value: unknown): value is PromiseLike<void> {\n return isPromiseLikeUnknown(value);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"html-internals.d.ts","sourceRoot":"","sources":["../src/html-internals.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"html-internals.d.ts","sourceRoot":"","sources":["../src/html-internals.ts"],"names":[],"mappings":"AAGA,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAO1D;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAEtE;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAAC,OAAO,CAAC,CAOlF"}
|
package/dist/html-internals.js
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
|
+
const attributeEscapePattern = /["&<>]/;
|
|
2
|
+
const scriptJsonEscapePattern = /[<\u2028\u2029]/;
|
|
1
3
|
export function escapeAttribute(value) {
|
|
2
|
-
return value
|
|
3
|
-
.replaceAll("&", "&")
|
|
4
|
-
.replaceAll('"', """)
|
|
5
|
-
.replaceAll("<", "<")
|
|
6
|
-
.replaceAll(">", ">");
|
|
4
|
+
return escapeString(value, attributeEscapePattern, attributeReplacement);
|
|
7
5
|
}
|
|
8
6
|
export function serializeScriptJson(value) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
const json = JSON.stringify(value);
|
|
8
|
+
if (json === undefined) {
|
|
9
|
+
throw new TypeError("Cannot serialize undefined as script JSON");
|
|
10
|
+
}
|
|
11
|
+
return escapeString(json, scriptJsonEscapePattern, scriptJsonReplacement);
|
|
13
12
|
}
|
|
14
13
|
export function renderNonceAttribute(nonce) {
|
|
15
14
|
return nonce === undefined ? "" : ` nonce="${escapeAttribute(nonce)}"`;
|
|
@@ -20,4 +19,51 @@ export function isPromiseLikeUnknown(value) {
|
|
|
20
19
|
"then" in value &&
|
|
21
20
|
typeof value.then === "function");
|
|
22
21
|
}
|
|
22
|
+
function escapeString(value, pattern, replacementForCode) {
|
|
23
|
+
const match = pattern.exec(value);
|
|
24
|
+
if (match === null) {
|
|
25
|
+
return value;
|
|
26
|
+
}
|
|
27
|
+
let escaped = "";
|
|
28
|
+
let lastIndex = 0;
|
|
29
|
+
let index = match.index;
|
|
30
|
+
for (; index < value.length; index += 1) {
|
|
31
|
+
const replacement = replacementForCode(value.charCodeAt(index));
|
|
32
|
+
if (replacement === undefined) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (lastIndex !== index) {
|
|
36
|
+
escaped += value.substring(lastIndex, index);
|
|
37
|
+
}
|
|
38
|
+
escaped += replacement;
|
|
39
|
+
lastIndex = index + 1;
|
|
40
|
+
}
|
|
41
|
+
return lastIndex === index ? escaped : escaped + value.substring(lastIndex, index);
|
|
42
|
+
}
|
|
43
|
+
function attributeReplacement(code) {
|
|
44
|
+
switch (code) {
|
|
45
|
+
case 34:
|
|
46
|
+
return """;
|
|
47
|
+
case 38:
|
|
48
|
+
return "&";
|
|
49
|
+
case 60:
|
|
50
|
+
return "<";
|
|
51
|
+
case 62:
|
|
52
|
+
return ">";
|
|
53
|
+
default:
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function scriptJsonReplacement(code) {
|
|
58
|
+
switch (code) {
|
|
59
|
+
case 60:
|
|
60
|
+
return "\\u003c";
|
|
61
|
+
case 8232:
|
|
62
|
+
return "\\u2028";
|
|
63
|
+
case 8233:
|
|
64
|
+
return "\\u2029";
|
|
65
|
+
default:
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
23
69
|
//# sourceMappingURL=html-internals.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"html-internals.js","sourceRoot":"","sources":["../src/html-internals.ts"],"names":[],"mappings":"AAAA,MAAM,
|
|
1
|
+
{"version":3,"file":"html-internals.js","sourceRoot":"","sources":["../src/html-internals.ts"],"names":[],"mappings":"AAAA,MAAM,sBAAsB,GAAG,QAAQ,CAAC;AACxC,MAAM,uBAAuB,GAAG,iBAAiB,CAAC;AAElD,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,OAAO,YAAY,CAAC,KAAK,EAAE,sBAAsB,EAAE,oBAAoB,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,KAAc;IAChD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,MAAM,IAAI,SAAS,CAAC,2CAA2C,CAAC,CAAC;IACnE,CAAC;IAED,OAAO,YAAY,CAAC,IAAI,EAAE,uBAAuB,EAAE,qBAAqB,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAyB;IAC5D,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAc;IACjD,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,MAAM,IAAI,KAAK;QACf,OAAQ,KAA4B,CAAC,IAAI,KAAK,UAAU,CACzD,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CACnB,KAAa,EACb,OAAe,EACf,kBAAwD;IAExD,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAElC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IAExB,OAAO,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACxC,MAAM,WAAW,GAAG,kBAAkB,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;QAEhE,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,SAAS;QACX,CAAC;QAED,IAAI,SAAS,KAAK,KAAK,EAAE,CAAC;YACxB,OAAO,IAAI,KAAK,CAAC,SAAS,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAC/C,CAAC;QAED,OAAO,IAAI,WAAW,CAAC;QACvB,SAAS,GAAG,KAAK,GAAG,CAAC,CAAC;IACxB,CAAC;IAED,OAAO,SAAS,KAAK,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;AACrF,CAAC;AAED,SAAS,oBAAoB,CAAC,IAAY;IACxC,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,EAAE;YACL,OAAO,QAAQ,CAAC;QAClB,KAAK,EAAE;YACL,OAAO,OAAO,CAAC;QACjB,KAAK,EAAE;YACL,OAAO,MAAM,CAAC;QAChB,KAAK,EAAE;YACL,OAAO,MAAM,CAAC;QAChB;YACE,OAAO,SAAS,CAAC;IACrB,CAAC;AACH,CAAC;AAED,SAAS,qBAAqB,CAAC,IAAY;IACzC,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,EAAE;YACL,OAAO,SAAS,CAAC;QACnB,KAAK,IAAI;YACP,OAAO,SAAS,CAAC;QACnB,KAAK,IAAI;YACP,OAAO,SAAS,CAAC;QACnB;YACE,OAAO,SAAS,CAAC;IACrB,CAAC;AACH,CAAC","sourcesContent":["const attributeEscapePattern = /[\"&<>]/;\nconst scriptJsonEscapePattern = /[<\\u2028\\u2029]/;\n\nexport function escapeAttribute(value: string): string {\n return escapeString(value, attributeEscapePattern, attributeReplacement);\n}\n\nexport function serializeScriptJson(value: unknown): string {\n const json = JSON.stringify(value);\n if (json === undefined) {\n throw new TypeError(\"Cannot serialize undefined as script JSON\");\n }\n\n return escapeString(json, scriptJsonEscapePattern, scriptJsonReplacement);\n}\n\nexport function renderNonceAttribute(nonce: string | undefined): string {\n return nonce === undefined ? \"\" : ` nonce=\"${escapeAttribute(nonce)}\"`;\n}\n\nexport function isPromiseLikeUnknown(value: unknown): value is PromiseLike<unknown> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"then\" in value &&\n typeof (value as { then?: unknown }).then === \"function\"\n );\n}\n\nfunction escapeString(\n value: string,\n pattern: RegExp,\n replacementForCode: (code: number) => string | undefined,\n): string {\n const match = pattern.exec(value);\n\n if (match === null) {\n return value;\n }\n\n let escaped = \"\";\n let lastIndex = 0;\n let index = match.index;\n\n for (; index < value.length; index += 1) {\n const replacement = replacementForCode(value.charCodeAt(index));\n\n if (replacement === undefined) {\n continue;\n }\n\n if (lastIndex !== index) {\n escaped += value.substring(lastIndex, index);\n }\n\n escaped += replacement;\n lastIndex = index + 1;\n }\n\n return lastIndex === index ? escaped : escaped + value.substring(lastIndex, index);\n}\n\nfunction attributeReplacement(code: number): string | undefined {\n switch (code) {\n case 34:\n return \""\";\n case 38:\n return \"&\";\n case 60:\n return \"<\";\n case 62:\n return \">\";\n default:\n return undefined;\n }\n}\n\nfunction scriptJsonReplacement(code: number): string | undefined {\n switch (code) {\n case 60:\n return \"\\\\u003c\";\n case 8232:\n return \"\\\\u2028\";\n case 8233:\n return \"\\\\u2029\";\n default:\n return undefined;\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reckona/mreact-server",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.139",
|
|
4
4
|
"description": "Server rendering, streaming, hydration, and Flight primitives for mreact.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"flight",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"access": "public"
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
|
-
"@reckona/mreact-
|
|
65
|
-
"@reckona/mreact-
|
|
64
|
+
"@reckona/mreact-shared": "0.0.139",
|
|
65
|
+
"@reckona/mreact-compat": "0.0.139"
|
|
66
66
|
}
|
|
67
67
|
}
|
package/src/boundary.ts
CHANGED
|
@@ -77,6 +77,7 @@ export async function renderAsyncBoundary<T>(
|
|
|
77
77
|
// "you're sending a lot of data" hint pattern used by other frameworks.
|
|
78
78
|
const AWAIT_PAYLOAD_WARN_BYTES = 100 * 1024;
|
|
79
79
|
const AWAIT_PAYLOAD_ERROR_BYTES = 1024 * 1024;
|
|
80
|
+
const textEncoder = typeof TextEncoder !== "undefined" ? new TextEncoder() : undefined;
|
|
80
81
|
|
|
81
82
|
function isProductionMode(): boolean {
|
|
82
83
|
// `process` may not exist in cross-runtime environments (Cloudflare/Deno).
|
|
@@ -160,8 +161,11 @@ function containsNonSerializableSurface(value: unknown): boolean {
|
|
|
160
161
|
}
|
|
161
162
|
|
|
162
163
|
function reportAwaitPayloadSize(json: string, awaitId: string): void {
|
|
163
|
-
|
|
164
|
-
|
|
164
|
+
if (json.length * 3 < AWAIT_PAYLOAD_WARN_BYTES) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const byteLength = textEncoder?.encode(json).length ?? json.length;
|
|
165
169
|
|
|
166
170
|
if (byteLength > AWAIT_PAYLOAD_ERROR_BYTES) {
|
|
167
171
|
console.error(
|
package/src/buffer-sink.ts
CHANGED
|
@@ -213,11 +213,7 @@ export function createBufferSink(options: BufferSinkOptions = {}): BufferSink {
|
|
|
213
213
|
return {
|
|
214
214
|
append(chunk) {
|
|
215
215
|
if (typeof chunk === "string") {
|
|
216
|
-
|
|
217
|
-
// can encode in a single `write()` call without a measurement
|
|
218
|
-
// pass; the actual encoded length is returned by `write()`.
|
|
219
|
-
const upperBound = chunk.length * 4;
|
|
220
|
-
ensure(upperBound);
|
|
216
|
+
ensure(Buffer.byteLength(chunk, "utf8"));
|
|
221
217
|
offset += buffer.write(chunk, offset, "utf8");
|
|
222
218
|
return;
|
|
223
219
|
}
|
package/src/flight.ts
CHANGED
|
@@ -738,7 +738,11 @@ function resolveFlightPromiseChunks(
|
|
|
738
738
|
model: FlightModel,
|
|
739
739
|
modelChunks: ReadonlyMap<number, unknown>,
|
|
740
740
|
errorChunks: ReadonlyMap<number, FlightErrorModel>,
|
|
741
|
+
depth = 0,
|
|
742
|
+
context: FlightDecodeContext = createFlightDecodeContext(),
|
|
741
743
|
): FlightModel {
|
|
744
|
+
if (depth > MAX_FLIGHT_DECODE_DEPTH) flightTooDeep();
|
|
745
|
+
|
|
742
746
|
if (
|
|
743
747
|
model === null ||
|
|
744
748
|
typeof model === "string" ||
|
|
@@ -749,7 +753,9 @@ function resolveFlightPromiseChunks(
|
|
|
749
753
|
}
|
|
750
754
|
|
|
751
755
|
if (Array.isArray(model)) {
|
|
752
|
-
return model.map((item) =>
|
|
756
|
+
return model.map((item) =>
|
|
757
|
+
resolveFlightPromiseChunks(item, modelChunks, errorChunks, depth + 1, context),
|
|
758
|
+
);
|
|
753
759
|
}
|
|
754
760
|
|
|
755
761
|
if (model.kind === "promise") {
|
|
@@ -760,7 +766,22 @@ function resolveFlightPromiseChunks(
|
|
|
760
766
|
}
|
|
761
767
|
|
|
762
768
|
if (modelChunks.has(model.id)) {
|
|
763
|
-
|
|
769
|
+
if (context.inProgressChunkIds.has(model.id)) {
|
|
770
|
+
flightCycle(model.id);
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
context.inProgressChunkIds.add(model.id);
|
|
774
|
+
try {
|
|
775
|
+
return decodeReactFlightModel(
|
|
776
|
+
modelChunks.get(model.id),
|
|
777
|
+
modelChunks,
|
|
778
|
+
errorChunks,
|
|
779
|
+
depth + 1,
|
|
780
|
+
context,
|
|
781
|
+
);
|
|
782
|
+
} finally {
|
|
783
|
+
context.inProgressChunkIds.delete(model.id);
|
|
784
|
+
}
|
|
764
785
|
}
|
|
765
786
|
|
|
766
787
|
return model;
|
|
@@ -772,7 +793,7 @@ function resolveFlightPromiseChunks(
|
|
|
772
793
|
props: Object.fromEntries(
|
|
773
794
|
Object.entries(model.props).map(([key, value]) => [
|
|
774
795
|
key,
|
|
775
|
-
resolveFlightPromiseChunks(value, modelChunks, errorChunks),
|
|
796
|
+
resolveFlightPromiseChunks(value, modelChunks, errorChunks, depth + 1, context),
|
|
776
797
|
]),
|
|
777
798
|
),
|
|
778
799
|
};
|
|
@@ -782,8 +803,8 @@ function resolveFlightPromiseChunks(
|
|
|
782
803
|
return {
|
|
783
804
|
...model,
|
|
784
805
|
entries: model.entries.map(([key, value]): [FlightModel, FlightModel] => [
|
|
785
|
-
resolveFlightPromiseChunks(key, modelChunks, errorChunks),
|
|
786
|
-
resolveFlightPromiseChunks(value, modelChunks, errorChunks),
|
|
806
|
+
resolveFlightPromiseChunks(key, modelChunks, errorChunks, depth + 1, context),
|
|
807
|
+
resolveFlightPromiseChunks(value, modelChunks, errorChunks, depth + 1, context),
|
|
787
808
|
]),
|
|
788
809
|
};
|
|
789
810
|
}
|
|
@@ -791,7 +812,9 @@ function resolveFlightPromiseChunks(
|
|
|
791
812
|
if (model.kind === "set") {
|
|
792
813
|
return {
|
|
793
814
|
...model,
|
|
794
|
-
values: model.values.map((value) =>
|
|
815
|
+
values: model.values.map((value) =>
|
|
816
|
+
resolveFlightPromiseChunks(value, modelChunks, errorChunks, depth + 1, context),
|
|
817
|
+
),
|
|
795
818
|
};
|
|
796
819
|
}
|
|
797
820
|
|
|
@@ -802,7 +825,9 @@ function resolveFlightPromiseChunks(
|
|
|
802
825
|
return Object.fromEntries(
|
|
803
826
|
Object.entries(model).map(([key, value]) => [
|
|
804
827
|
key,
|
|
805
|
-
value === undefined
|
|
828
|
+
value === undefined
|
|
829
|
+
? undefined
|
|
830
|
+
: resolveFlightPromiseChunks(value, modelChunks, errorChunks, depth + 1, context),
|
|
806
831
|
]),
|
|
807
832
|
);
|
|
808
833
|
}
|
|
@@ -1252,11 +1277,26 @@ function flightTooDeep(): never {
|
|
|
1252
1277
|
);
|
|
1253
1278
|
}
|
|
1254
1279
|
|
|
1280
|
+
function flightCycle(id: number): never {
|
|
1281
|
+
throw new FlightDecodeError(`MR_FLIGHT_CYCLE: cyclic chunk reference ${id}`);
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
interface FlightDecodeContext {
|
|
1285
|
+
inProgressChunkIds: Set<number>;
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
function createFlightDecodeContext(): FlightDecodeContext {
|
|
1289
|
+
return {
|
|
1290
|
+
inProgressChunkIds: new Set(),
|
|
1291
|
+
};
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1255
1294
|
function decodeReactFlightModel(
|
|
1256
1295
|
value: unknown,
|
|
1257
1296
|
modelChunks: ReadonlyMap<number, unknown> = new Map(),
|
|
1258
1297
|
errorChunks: ReadonlyMap<number, FlightErrorModel> = new Map(),
|
|
1259
1298
|
depth = 0,
|
|
1299
|
+
context: FlightDecodeContext = createFlightDecodeContext(),
|
|
1260
1300
|
): FlightModel {
|
|
1261
1301
|
if (depth > MAX_FLIGHT_DECODE_DEPTH) flightTooDeep();
|
|
1262
1302
|
if (
|
|
@@ -1268,7 +1308,7 @@ function decodeReactFlightModel(
|
|
|
1268
1308
|
}
|
|
1269
1309
|
|
|
1270
1310
|
if (typeof value === "string") {
|
|
1271
|
-
return decodeReactFlightString(value, modelChunks, errorChunks);
|
|
1311
|
+
return decodeReactFlightString(value, modelChunks, errorChunks, depth, context);
|
|
1272
1312
|
}
|
|
1273
1313
|
|
|
1274
1314
|
if (Array.isArray(value)) {
|
|
@@ -1282,12 +1322,13 @@ function decodeReactFlightModel(
|
|
|
1282
1322
|
modelChunks,
|
|
1283
1323
|
errorChunks,
|
|
1284
1324
|
depth + 1,
|
|
1325
|
+
context,
|
|
1285
1326
|
),
|
|
1286
1327
|
};
|
|
1287
1328
|
}
|
|
1288
1329
|
|
|
1289
1330
|
return value.map((item) =>
|
|
1290
|
-
decodeReactFlightModel(item, modelChunks, errorChunks, depth + 1),
|
|
1331
|
+
decodeReactFlightModel(item, modelChunks, errorChunks, depth + 1, context),
|
|
1291
1332
|
);
|
|
1292
1333
|
}
|
|
1293
1334
|
|
|
@@ -1296,7 +1337,7 @@ function decodeReactFlightModel(
|
|
|
1296
1337
|
}
|
|
1297
1338
|
|
|
1298
1339
|
if (valueIsObject(value)) {
|
|
1299
|
-
return decodeReactFlightProps(value, modelChunks, errorChunks, depth + 1);
|
|
1340
|
+
return decodeReactFlightProps(value, modelChunks, errorChunks, depth + 1, context);
|
|
1300
1341
|
}
|
|
1301
1342
|
|
|
1302
1343
|
return { kind: "undefined" };
|
|
@@ -1306,6 +1347,8 @@ function decodeReactFlightString(
|
|
|
1306
1347
|
value: string,
|
|
1307
1348
|
modelChunks: ReadonlyMap<number, unknown>,
|
|
1308
1349
|
errorChunks: ReadonlyMap<number, FlightErrorModel>,
|
|
1350
|
+
depth: number,
|
|
1351
|
+
context: FlightDecodeContext,
|
|
1309
1352
|
): FlightModel {
|
|
1310
1353
|
if (value === "$undefined" || value === "$u") {
|
|
1311
1354
|
return { kind: "undefined" };
|
|
@@ -1340,7 +1383,7 @@ function decodeReactFlightString(
|
|
|
1340
1383
|
}
|
|
1341
1384
|
|
|
1342
1385
|
if (/^\$[AOoUSsLlGgMmV][0-9a-f]+$/.test(value)) {
|
|
1343
|
-
return decodeReactFlightChunk(value.slice(2), modelChunks, errorChunks);
|
|
1386
|
+
return decodeReactFlightChunk(value.slice(2), modelChunks, errorChunks, depth + 1, context);
|
|
1344
1387
|
}
|
|
1345
1388
|
|
|
1346
1389
|
if (value.startsWith("$S")) {
|
|
@@ -1369,7 +1412,7 @@ function decodeReactFlightString(
|
|
|
1369
1412
|
}
|
|
1370
1413
|
|
|
1371
1414
|
if (/^\$Q[0-9a-f]+$/i.test(value)) {
|
|
1372
|
-
const decoded = decodeReactFlightChunk(value.slice(2), modelChunks, errorChunks);
|
|
1415
|
+
const decoded = decodeReactFlightChunk(value.slice(2), modelChunks, errorChunks, depth + 1, context);
|
|
1373
1416
|
const entries = Array.isArray(decoded)
|
|
1374
1417
|
? decoded.map((entry): [FlightModel, FlightModel] =>
|
|
1375
1418
|
Array.isArray(entry) ? [entry[0] ?? { kind: "undefined" }, entry[1] ?? { kind: "undefined" }] : [entry, { kind: "undefined" }],
|
|
@@ -1383,7 +1426,7 @@ function decodeReactFlightString(
|
|
|
1383
1426
|
}
|
|
1384
1427
|
|
|
1385
1428
|
if (/^\$W[0-9a-f]+$/i.test(value)) {
|
|
1386
|
-
const decoded = decodeReactFlightChunk(value.slice(2), modelChunks, errorChunks);
|
|
1429
|
+
const decoded = decodeReactFlightChunk(value.slice(2), modelChunks, errorChunks, depth + 1, context);
|
|
1387
1430
|
|
|
1388
1431
|
return {
|
|
1389
1432
|
kind: "set",
|
|
@@ -1392,7 +1435,7 @@ function decodeReactFlightString(
|
|
|
1392
1435
|
}
|
|
1393
1436
|
|
|
1394
1437
|
if (/^\$K[0-9a-f]+$/i.test(value)) {
|
|
1395
|
-
const decoded = decodeReactFlightChunk(value.slice(2), modelChunks, errorChunks);
|
|
1438
|
+
const decoded = decodeReactFlightChunk(value.slice(2), modelChunks, errorChunks, depth + 1, context);
|
|
1396
1439
|
const entries = Array.isArray(decoded)
|
|
1397
1440
|
? decoded.flatMap((entry): [string, FlightModel][] =>
|
|
1398
1441
|
Array.isArray(entry) && typeof entry[0] === "string"
|
|
@@ -1408,7 +1451,7 @@ function decodeReactFlightString(
|
|
|
1408
1451
|
}
|
|
1409
1452
|
|
|
1410
1453
|
if (/^\$i[0-9a-f]+$/i.test(value)) {
|
|
1411
|
-
const decoded = decodeReactFlightChunk(value.slice(2), modelChunks, errorChunks);
|
|
1454
|
+
const decoded = decodeReactFlightChunk(value.slice(2), modelChunks, errorChunks, depth + 1, context);
|
|
1412
1455
|
|
|
1413
1456
|
return {
|
|
1414
1457
|
kind: "iterable",
|
|
@@ -1429,7 +1472,7 @@ function decodeReactFlightString(
|
|
|
1429
1472
|
}
|
|
1430
1473
|
|
|
1431
1474
|
if (/^\$[0-9a-f]+$/i.test(value)) {
|
|
1432
|
-
return decodeReactFlightChunk(value.slice(1), modelChunks, errorChunks);
|
|
1475
|
+
return decodeReactFlightChunk(value.slice(1), modelChunks, errorChunks, depth + 1, context);
|
|
1433
1476
|
}
|
|
1434
1477
|
|
|
1435
1478
|
return value;
|
|
@@ -1439,7 +1482,10 @@ function decodeReactFlightChunk(
|
|
|
1439
1482
|
id: string,
|
|
1440
1483
|
modelChunks: ReadonlyMap<number, unknown>,
|
|
1441
1484
|
errorChunks: ReadonlyMap<number, FlightErrorModel>,
|
|
1485
|
+
depth: number,
|
|
1486
|
+
context: FlightDecodeContext,
|
|
1442
1487
|
): FlightModel {
|
|
1488
|
+
if (depth > MAX_FLIGHT_DECODE_DEPTH) flightTooDeep();
|
|
1443
1489
|
const numericId = parseReactFlightId(id);
|
|
1444
1490
|
const error = errorChunks.get(numericId);
|
|
1445
1491
|
|
|
@@ -1454,7 +1500,22 @@ function decodeReactFlightChunk(
|
|
|
1454
1500
|
};
|
|
1455
1501
|
}
|
|
1456
1502
|
|
|
1457
|
-
|
|
1503
|
+
if (context.inProgressChunkIds.has(numericId)) {
|
|
1504
|
+
flightCycle(numericId);
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
context.inProgressChunkIds.add(numericId);
|
|
1508
|
+
try {
|
|
1509
|
+
return decodeReactFlightModel(
|
|
1510
|
+
modelChunks.get(numericId),
|
|
1511
|
+
modelChunks,
|
|
1512
|
+
errorChunks,
|
|
1513
|
+
depth,
|
|
1514
|
+
context,
|
|
1515
|
+
);
|
|
1516
|
+
} finally {
|
|
1517
|
+
context.inProgressChunkIds.delete(numericId);
|
|
1518
|
+
}
|
|
1458
1519
|
}
|
|
1459
1520
|
|
|
1460
1521
|
function decodeReactFlightElementType(value: unknown): FlightElementModel["type"] {
|
|
@@ -1477,12 +1538,13 @@ function decodeReactFlightProps(
|
|
|
1477
1538
|
modelChunks: ReadonlyMap<number, unknown>,
|
|
1478
1539
|
errorChunks: ReadonlyMap<number, FlightErrorModel>,
|
|
1479
1540
|
depth = 0,
|
|
1541
|
+
context: FlightDecodeContext = createFlightDecodeContext(),
|
|
1480
1542
|
): Record<string, FlightModel> {
|
|
1481
1543
|
if (depth > MAX_FLIGHT_DECODE_DEPTH) flightTooDeep();
|
|
1482
1544
|
return Object.fromEntries(
|
|
1483
1545
|
Object.entries(value).map(([key, child]) => [
|
|
1484
1546
|
key,
|
|
1485
|
-
decodeReactFlightModel(child, modelChunks, errorChunks, depth + 1),
|
|
1547
|
+
decodeReactFlightModel(child, modelChunks, errorChunks, depth + 1, context),
|
|
1486
1548
|
]),
|
|
1487
1549
|
);
|
|
1488
1550
|
}
|