Add separator comment between text nodes (#21099)

This is needed to avoid mutating the DOM during hydration. This *always*
adds it even when it's just text children.

We need to avoid this overhead but it's a somewhat tricky problem to solve
so we defer the optimization to later.
This commit is contained in:
Sebastian Markbåge
2021-03-25 08:48:39 -07:00
committed by GitHub
parent 148f8e497c
commit 6a589ad711
3 changed files with 19 additions and 8 deletions
@@ -55,7 +55,7 @@ describe('ReactDOMFizzServer', () => {
<div>hello world</div>,
);
const result = await readResult(stream);
expect(result).toBe('<div>hello world</div>');
expect(result).toMatchInlineSnapshot(`"<div>hello world<!-- --></div>"`);
});
// @gate experimental
@@ -93,7 +93,9 @@ describe('ReactDOMFizzServer', () => {
expect(isComplete).toBe(true);
const result = await readResult(stream);
expect(result).toBe('<div><!--$-->Done<!--/$--></div>');
expect(result).toMatchInlineSnapshot(
`"<div><!--$-->Done<!-- --><!--/$--></div>"`,
);
});
// @gate experimental
@@ -65,7 +65,9 @@ describe('ReactDOMFizzServer', () => {
);
startWriting();
jest.runAllTimers();
expect(output.result).toBe('<div>hello world</div>');
expect(output.result).toMatchInlineSnapshot(
`"<div>hello world<!-- --></div>"`,
);
});
// @gate experimental
@@ -81,8 +83,8 @@ describe('ReactDOMFizzServer', () => {
'<!doctype html><html><head><title>test</title><head><body>';
// Then React starts writing.
startWriting();
expect(output.result).toBe(
'<!doctype html><html><head><title>test</title><head><body><div>hello world</div>',
expect(output.result).toMatchInlineSnapshot(
`"<!doctype html><html><head><title>test</title><head><body><div>hello world<!-- --></div>"`,
);
});
@@ -129,8 +131,8 @@ describe('ReactDOMFizzServer', () => {
'<!doctype html><html><head><title>test</title><head><body>';
// Then React starts writing.
startWriting();
expect(output.result).toBe(
'<!doctype html><html><head><title>test</title><head><body><div><!--$-->Done<!--/$--></div>',
expect(output.result).toMatchInlineSnapshot(
`"<!doctype html><html><head><title>test</title><head><body><div><!--$-->Done<!-- --><!--/$--></div>"`,
);
});
@@ -104,6 +104,8 @@ export function pushEmpty(
}
}
const textSeparator = stringToPrecomputedChunk('<!-- -->');
export function pushTextInstance(
target: Array<Chunk | PrecomputedChunk>,
text: string,
@@ -113,7 +115,12 @@ export function pushTextInstance(
if (assignID !== null) {
pushDummyNodeWithID(target, responseState, assignID);
}
target.push(stringToChunk(encodeHTMLTextNode(text)));
if (text === '') {
// Empty text doesn't have a DOM node representation and the hydration is aware of this.
return;
}
// TODO: Avoid adding a text separator in common cases.
target.push(stringToChunk(encodeHTMLTextNode(text)), textSeparator);
}
const startTag1 = stringToPrecomputedChunk('<');