UNPKG

react-on-rails

Version:

react-on-rails JavaScript for react_on_rails Ruby gem

81 lines 3.26 kB
import { remapSourceMappedStack } from "./errorUtils.js"; export { convertToError } from "./errorUtils.js"; export function buildRenderMetadata(consoleReplayScript, renderState) { return { consoleReplayScript, clientProps: renderState.clientProps, hasErrors: renderState.hasErrors, renderingError: renderState.error && { message: renderState.error.message, stack: remapSourceMappedStack(renderState.error.stack), }, isShellReady: 'isShellReady' in renderState ? renderState.isShellReady : undefined, }; } /** * Returns the UTF-8 byte length of a string. * Uses native Buffer.byteLength when available (Node.js, Pro node renderer). * Falls back to a pure-JS implementation for environments without Buffer (mini_racer). */ function utf8ByteLength(str) { if (typeof Buffer !== 'undefined' && typeof Buffer.byteLength === 'function') { return Buffer.byteLength(str, 'utf-8'); } let bytes = 0; for (let i = 0; i < str.length; i += 1) { const code = str.charCodeAt(i); if (code <= 0x7f) { bytes += 1; } else if (code <= 0x7ff) { bytes += 2; } else if (code >= 0xd800 && code <= 0xdbff) { const next = i + 1 < str.length ? str.charCodeAt(i + 1) : 0; if (next >= 0xdc00 && next <= 0xdfff) { bytes += 4; // valid surrogate pair i += 1; } else { bytes += 3; // lone high surrogate → U+FFFD } } else { bytes += 3; // BMP char (0x800-0xFFFF) or lone low surrogate } } return bytes; } /** * Builds a length-prefixed result string from html content and render state. * Format: <metadata JSON>\t<content byte length hex>\n<raw html content> * * Used by the non-streaming rendering path. The streaming path uses * buildRenderMetadata directly with Buffer operations for efficiency. */ export function buildLengthPrefixedResult(html, consoleReplayScript, renderState) { // payloadType tells Ruby how to interpret the content bytes: // "string" — raw HTML, use as-is (the common case) // "object" — JSON-serialized value, needs JSON.parse (ServerRenderHash or null) const metadataObj = buildRenderMetadata(consoleReplayScript, renderState); let htmlStr; if (typeof html === 'string') { metadataObj.payloadType = 'string'; htmlStr = html; } else { // Handles null, ServerRenderHashRenderedHtml objects, etc. // JSON.stringify(null) → "null", which Ruby will JSON.parse back. metadataObj.payloadType = 'object'; htmlStr = JSON.stringify(html); } const metadata = JSON.stringify(metadataObj); const byteLength = utf8ByteLength(htmlStr); return `${metadata}\t${byteLength.toString(16).padStart(8, '0')}\n${htmlStr}`; } export function validateComponent(componentObj, componentName) { if (componentObj.isRenderer) { throw new Error(`Detected a renderer while server rendering component '${componentName}'. See https://github.com/shakacode/react_on_rails#renderer-functions`); } } //# sourceMappingURL=serverRenderUtils.js.map