diff --git a/packages/react-dom-bindings/src/server/ReactDOMLegacyServerStreamConfig.js b/packages/react-dom-bindings/src/server/ReactDOMLegacyServerStreamConfig.js
index 4b940731b99b0..b9b5d741d796a 100644
--- a/packages/react-dom-bindings/src/server/ReactDOMLegacyServerStreamConfig.js
+++ b/packages/react-dom-bindings/src/server/ReactDOMLegacyServerStreamConfig.js
@@ -66,9 +66,9 @@ export function typedArrayToBinaryChunk(
throw new Error('Not implemented.');
}
-export function byteLengthOfChunk(chunk: Chunk | PrecomputedChunk): number {
- throw new Error('Not implemented.');
-}
+export const byteLengthOfChunk:
+ | null
+ | ((chunk: Chunk | PrecomputedChunk) => number) = null;
export function byteLengthOfBinaryChunk(chunk: BinaryChunk): number {
throw new Error('Not implemented.');
diff --git a/packages/react-html/src/__tests__/ReactHTMLClient-test.js b/packages/react-html/src/__tests__/ReactHTMLClient-test.js
index 92fb762c8ca1b..02cef97c2d82f 100644
--- a/packages/react-html/src/__tests__/ReactHTMLClient-test.js
+++ b/packages/react-html/src/__tests__/ReactHTMLClient-test.js
@@ -38,6 +38,17 @@ if (!__EXPERIMENTAL__) {
expect(html).toBe('
hello world
');
});
+ it('should be able to render a large string', async () => {
+ function Component() {
+ return {'hello '.repeat(200)}world
;
+ }
+
+ const html = await ReactHTML.renderToMarkup(
+ React.createElement(Component),
+ );
+ expect(html).toBe('' + ('hello '.repeat(200) + 'world') + '
');
+ });
+
it('should prefix html tags with a doctype', async () => {
const html = await ReactHTML.renderToMarkup(
diff --git a/packages/react-html/src/__tests__/ReactHTMLServer-test.js b/packages/react-html/src/__tests__/ReactHTMLServer-test.js
index f97b5aa92d60e..236c2b0f4021c 100644
--- a/packages/react-html/src/__tests__/ReactHTMLServer-test.js
+++ b/packages/react-html/src/__tests__/ReactHTMLServer-test.js
@@ -61,6 +61,18 @@ if (!__EXPERIMENTAL__) {
expect(html).toBe('hello world
');
});
+ it('should be able to render a large string', async () => {
+ function Component() {
+ // We can't use JSX because that's client-JSX in our tests.
+ return React.createElement('div', null, 'hello '.repeat(200) + 'world');
+ }
+
+ const html = await ReactHTML.renderToMarkup(
+ React.createElement(Component),
+ );
+ expect(html).toBe('' + ('hello '.repeat(200) + 'world') + '
');
+ });
+
it('should prefix html tags with a doctype', async () => {
const html = await ReactHTML.renderToMarkup(
// We can't use JSX because that's client-JSX in our tests.
diff --git a/packages/react-server/src/ReactFlightServer.js b/packages/react-server/src/ReactFlightServer.js
index 9987c689f2aa8..7ff1e47897299 100644
--- a/packages/react-server/src/ReactFlightServer.js
+++ b/packages/react-server/src/ReactFlightServer.js
@@ -2541,7 +2541,7 @@ function renderModelDestructive(
return serializeDateFromDateJSON(value);
}
}
- if (value.length >= 1024) {
+ if (value.length >= 1024 && byteLengthOfChunk !== null) {
// For large strings, we encode them outside the JSON payload so that we
// don't have to double encode and double parse the strings. This can also
// be more compact in case the string has a lot of escaped characters.
@@ -2892,6 +2892,12 @@ function emitTypedArrayChunk(
}
function emitTextChunk(request: Request, id: number, text: string): void {
+ if (byteLengthOfChunk === null) {
+ // eslint-disable-next-line react-internal/prod-error-codes
+ throw new Error(
+ 'Existence of byteLengthOfChunk should have already been checked. This is a bug in React.',
+ );
+ }
request.pendingChunks++; // Extra chunk for the header.
const textChunk = stringToChunk(text);
const binaryLength = byteLengthOfChunk(textChunk);
@@ -3289,7 +3295,7 @@ function emitChunk(
const id = task.id;
// For certain types we have special types, we typically outlined them but
// we can emit them directly for this row instead of through an indirection.
- if (typeof value === 'string') {
+ if (typeof value === 'string' && byteLengthOfChunk !== null) {
if (enableTaint) {
const tainted = TaintRegistryValues.get(value);
if (tainted !== undefined) {