Skip to content

Commit

Permalink
Adjacent text nodes in SSR should have comments between them despite …
Browse files Browse the repository at this point in the history
…components (#11109)

* Add a failing test for text nodes within components

* Reset the text node flag only when emitting tags

This ensures we don't reset it when we exit components that return strings.

* Add a failing test for a more complex tree

* Also reset text flag when emitting a footer

This fixes the {'a'}</div>{'b'} case and prevents an unnecessary comment before 'b'.
  • Loading branch information
gaearon committed Oct 5, 2017
1 parent 7d3b44b commit 32ec797
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1117,6 +1117,79 @@ describe('ReactDOMServerIntegration', () => {
expectTextNode(e.childNodes[1], 'bar');
}
});

itRenders(
'a component returning text node between two text nodes',
async render => {
const B = () => 'b';
const e = await render(<div>{'a'}<B />{'c'}</div>);
if (
render === serverRender ||
render === clientRenderOnServerString ||
render === streamRender
) {
// In the server render output there's a comment between them.
expect(e.childNodes.length).toBe(5);
expectTextNode(e.childNodes[0], 'a');
expectTextNode(e.childNodes[2], 'b');
expectTextNode(e.childNodes[4], 'c');
} else {
expect(e.childNodes.length).toBe(3);
expectTextNode(e.childNodes[0], 'a');
expectTextNode(e.childNodes[1], 'b');
expectTextNode(e.childNodes[2], 'c');
}
},
);

itRenders('a tree with sibling host and text nodes', async render => {
class X extends React.Component {
render() {
return [null, [<Y key="1" />], false];
}
}

function Y() {
return [<Z key="1" />, ['c']];
}

function Z() {
return null;
}

const e = await render(
<div>
{[['a'], 'b']}
<div>
<X key="1" />
d
</div>
e
</div>,
);
if (
render === serverRender ||
render === clientRenderOnServerString ||
render === streamRender
) {
// In the server render output there's comments between text nodes.
expect(e.childNodes.length).toBe(5);
expectTextNode(e.childNodes[0], 'a');
expectTextNode(e.childNodes[2], 'b');
expect(e.childNodes[3].childNodes.length).toBe(3);
expectTextNode(e.childNodes[3].childNodes[0], 'c');
expectTextNode(e.childNodes[3].childNodes[2], 'd');
expectTextNode(e.childNodes[4], 'e');
} else {
expect(e.childNodes.length).toBe(4);
expectTextNode(e.childNodes[0], 'a');
expectTextNode(e.childNodes[1], 'b');
expect(e.childNodes[2].childNodes.length).toBe(2);
expectTextNode(e.childNodes[2].childNodes[0], 'c');
expectTextNode(e.childNodes[2].childNodes[1], 'd');
expectTextNode(e.childNodes[3], 'e');
}
});
});

describe('number children', function() {
Expand Down
8 changes: 6 additions & 2 deletions src/renderers/shared/server/ReactPartialRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -475,8 +475,11 @@ class ReactDOMServerRenderer {
}
var frame = this.stack[this.stack.length - 1];
if (frame.childIndex >= frame.children.length) {
out += frame.footer;
this.previousWasTextNode = false;
var footer = frame.footer;
out += footer;
if (footer !== '') {
this.previousWasTextNode = false;
}
this.stack.pop();
if (frame.tag === 'select') {
this.currentSelectValue = null;
Expand Down Expand Up @@ -827,6 +830,7 @@ class ReactDOMServerRenderer {
frame.debugElementStack = [];
}
this.stack.push(frame);
this.previousWasTextNode = false;
return out;
}
}
Expand Down

0 comments on commit 32ec797

Please sign in to comment.