Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support array and fragment during SSR #1503

Merged
merged 7 commits into from
Jan 28, 2020
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,43 @@ describe('SSR Creation Queue Streams - (non-JSX)', () => {
</div>
),
result: '<div><br></div>'
},
{
description: 'You should be able to render an array',
template: () => (
[
<p>1</p>,
<p>2</p>,
<p>3</p>
]
),
result: '<p>1</p><p>2</p><p>3</p>'
},
{
description: 'You should be able to render an empty array',
template: () => [],
result: '<!--!-->'
},
{
description: 'You should be able to render a fragment',
template: () => (
<>
<p>1</p>
<p>2</p>
<p>3</p>
</> /* reset syntax highlighting */
),
result: '<p>1</p><p>2</p><p>3</p>'
},
{
description: 'You should be able to render an empty fragment',
template: () => (<></>), /* reset syntax highlighting */
result: '<!--!-->'
},
{
description: 'You should be able to render fragment with single child',
template: () => (<><p>1</p></>), /* reset syntax highlighting */
result: '<p>1</p>'
}
];

Expand Down
37 changes: 37 additions & 0 deletions packages/inferno-server/__tests__/creation-stream.spec.server.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,43 @@ describe('SSR Creation Streams - (non-JSX)', () => {
</div>
),
result: '<div><br></div>'
},
{
description: 'You should be able to render an array',
template: () => (
[
<p>1</p>,
<p>2</p>,
<p>3</p>
]
),
result: '<p>1</p><p>2</p><p>3</p>'
},
{
description: 'You should be able to render an empty array',
template: () => [],
result: '<!--!-->'
},
{
description: 'You should be able to render a fragment',
template: () => (
<>
<p>1</p>
<p>2</p>
<p>3</p>
</> /* reset syntax highlighting */
),
result: '<p>1</p><p>2</p><p>3</p>'
},
{
description: 'You should be able to render an empty fragment',
template: () => (<></>), /* reset syntax highlighting */
result: '<!--!-->'
},
{
description: 'You should be able to render fragment with single child',
template: () => (<><p>1</p></>), /* reset syntax highlighting */
result: '<p>1</p>'
}
];

Expand Down
37 changes: 37 additions & 0 deletions packages/inferno-server/__tests__/creation.spec.server.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,43 @@ describe('SSR Creation (JSX)', () => {
</div>
),
result: '<div><br></div>'
},
{
description: 'You should be able to render an array',
template: () => (
[
<p>1</p>,
<p>2</p>,
<p>3</p>
]
),
result: '<p>1</p><p>2</p><p>3</p>'
},
{
description: 'You should be able to render an empty array',
template: () => [],
result: '<!--!-->'
},
{
description: 'You should be able to render a fragment',
template: () => (
<>
<p>1</p>
<p>2</p>
<p>3</p>
</> /* reset syntax highlighting */
),
result: '<p>1</p><p>2</p><p>3</p>'
},
{
description: 'You should be able to render an empty fragment',
template: () => (<></>), /* reset syntax highlighting */
result: '<!--!-->'
},
{
description: 'You should be able to render fragment with single child',
template: () => (<><p>1</p></>), /* reset syntax highlighting */
result: '<p>1</p>'
}
];

Expand Down
15 changes: 15 additions & 0 deletions packages/inferno-server/src/renderToString.queuestream.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {EMPTY_OBJ} from 'inferno';
import {
combineFrom,
isArray,
isFunction,
isInvalid,
isNull,
Expand Down Expand Up @@ -281,6 +282,20 @@ export class RenderQueueStream extends Readable {
// Push text directly to queue
} else if ((flags & VNodeFlags.Text) > 0) {
this.addToQueue(children === '' ? ' ' : escapeText(children), position);
// Handle fragments and arrays
} else if (isArray(vNode) || (flags & VNodeFlags.Fragment) !== 0) {
const childFlags = vNode.childFlags;

if (childFlags === ChildFlags.HasVNodeChildren || (isArray(vNode) && vNode.length === 0)) {
this.addToQueue ('<!--!-->', position);
} else if (childFlags & ChildFlags.MultipleChildren || isArray(vNode)) {
const tmpChildren = isArray(vNode) ? vNode : vNode.children;

for (let i = 0, len = tmpChildren.length; i < len; ++i) {
this.renderVNodeToQueue(tmpChildren[i], context, position);
}
return;
}
// Handle errors
} else {
if (process.env.NODE_ENV !== 'production') {
Expand Down
22 changes: 21 additions & 1 deletion packages/inferno-server/src/renderToString.stream.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {combineFrom, isFunction, isInvalid, isNull, isNullOrUndef, isNumber, isString} from 'inferno-shared';
import {combineFrom, isArray, isFunction, isInvalid, isNull, isNullOrUndef, isNumber, isString} from 'inferno-shared';
import {ChildFlags, VNodeFlags} from 'inferno-vnode-flags';
import {Readable} from 'stream';
import {renderStylesToString} from './prop-renderers';
Expand Down Expand Up @@ -43,10 +43,30 @@ export class RenderStream extends Readable {
if ((flags & VNodeFlags.Element) > 0) {
return this.renderElement(vNode, context);
}
if (isArray(vNode) || (flags & VNodeFlags.Fragment) !== 0) {
return this.renderArrayOrFragment(vNode, context)
}


return this.renderText(vNode);
}

public renderArrayOrFragment(vNode, context) {
const childFlags = vNode.childFlags;

if (childFlags === ChildFlags.HasVNodeChildren || (isArray(vNode) && vNode.length === 0)) {
return this.push('<!--!-->');
} else if (childFlags & ChildFlags.MultipleChildren || isArray(vNode)) {
const children = isArray(vNode) ? vNode : vNode.children;

return (children as VNode[]).reduce((p, child) => {
return p.then(() => {
return Promise.resolve(this.renderNode(child, context)).then(() => !!(child.flags & VNodeFlags.Text));
});
}, Promise.resolve(false));
}
}

public renderComponent(vComponent, context, isClass) {
const type = vComponent.type;
const props = vComponent.props;
Expand Down
16 changes: 9 additions & 7 deletions packages/inferno-server/src/renderToString.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {EMPTY_OBJ} from 'inferno';
import {
combineFrom,
isArray,
isFunction,
isInvalid,
isNull,
Expand Down Expand Up @@ -180,16 +181,17 @@ function renderVNodeToString(vNode, parent, context): string {
return renderedString;
} else if ((flags & VNodeFlags.Text) !== 0) {
return children === '' ? ' ' : escapeText(children);
} else if ((flags & VNodeFlags.Fragment) !== 0) {
} else if (isArray(vNode) || (flags & VNodeFlags.Fragment) !== 0) {
const childFlags = vNode.childFlags;

if (childFlags === ChildFlags.HasVNodeChildren) {
if (childFlags === ChildFlags.HasVNodeChildren || (isArray(vNode) && vNode.length === 0)) {
return '<!--!-->';
} else if (childFlags & ChildFlags.MultipleChildren) {
} else if (childFlags & ChildFlags.MultipleChildren || isArray(vNode)) {
const tmpNodes = isArray(vNode) ? vNode : children;
let renderedString = '';

for (let i = 0, len = children.length; i < len; ++i) {
renderedString += renderVNodeToString(children[i], vNode, context);
for (let i = 0, len = tmpNodes.length; i < len; ++i) {
renderedString += renderVNodeToString(tmpNodes[i], vNode, context);
}

return renderedString;
Expand Down