diff --git a/packages/inferno-server/__tests__/creation-queuestream.spec.server.jsx b/packages/inferno-server/__tests__/creation-queuestream.spec.server.jsx index 5f8711c44..9ecad8324 100644 --- a/packages/inferno-server/__tests__/creation-queuestream.spec.server.jsx +++ b/packages/inferno-server/__tests__/creation-queuestream.spec.server.jsx @@ -377,6 +377,43 @@ describe('SSR Creation Queue Streams - (non-JSX)', () => { ), result: '

' + }, + { + description: 'You should be able to render an array', + template: () => ( + [ +

1

, +

2

, +

3

+ ] + ), + result: '

1

2

3

' + }, + { + description: 'You should be able to render an empty array', + template: () => [], + result: '' + }, + { + description: 'You should be able to render a fragment', + template: () => ( + <> +

1

+

2

+

3

+ /* reset syntax highlighting */ + ), + result: '

1

2

3

' + }, + { + 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: () => (<>

1

), /* reset syntax highlighting */ + result: '

1

' } ]; diff --git a/packages/inferno-server/__tests__/creation-stream.spec.server.jsx b/packages/inferno-server/__tests__/creation-stream.spec.server.jsx index e524a94b3..ba424251a 100644 --- a/packages/inferno-server/__tests__/creation-stream.spec.server.jsx +++ b/packages/inferno-server/__tests__/creation-stream.spec.server.jsx @@ -290,6 +290,43 @@ describe('SSR Creation Streams - (non-JSX)', () => { ), result: '

' + }, + { + description: 'You should be able to render an array', + template: () => ( + [ +

1

, +

2

, +

3

+ ] + ), + result: '

1

2

3

' + }, + { + description: 'You should be able to render an empty array', + template: () => [], + result: '' + }, + { + description: 'You should be able to render a fragment', + template: () => ( + <> +

1

+

2

+

3

+ /* reset syntax highlighting */ + ), + result: '

1

2

3

' + }, + { + 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: () => (<>

1

), /* reset syntax highlighting */ + result: '

1

' } ]; diff --git a/packages/inferno-server/__tests__/creation.spec.server.jsx b/packages/inferno-server/__tests__/creation.spec.server.jsx index bfdb14073..d16912391 100644 --- a/packages/inferno-server/__tests__/creation.spec.server.jsx +++ b/packages/inferno-server/__tests__/creation.spec.server.jsx @@ -152,6 +152,43 @@ describe('SSR Creation (JSX)', () => { ), result: '

' + }, + { + description: 'You should be able to render an array', + template: () => ( + [ +

1

, +

2

, +

3

+ ] + ), + result: '

1

2

3

' + }, + { + description: 'You should be able to render an empty array', + template: () => [], + result: '' + }, + { + description: 'You should be able to render a fragment', + template: () => ( + <> +

1

+

2

+

3

+ /* reset syntax highlighting */ + ), + result: '

1

2

3

' + }, + { + 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: () => (<>

1

), /* reset syntax highlighting */ + result: '

1

' } ]; diff --git a/packages/inferno-server/src/renderToString.queuestream.ts b/packages/inferno-server/src/renderToString.queuestream.ts index 551d7dd1e..db6785406 100644 --- a/packages/inferno-server/src/renderToString.queuestream.ts +++ b/packages/inferno-server/src/renderToString.queuestream.ts @@ -1,6 +1,7 @@ import {EMPTY_OBJ} from 'inferno'; import { combineFrom, + isArray, isFunction, isInvalid, isNull, @@ -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') { diff --git a/packages/inferno-server/src/renderToString.stream.ts b/packages/inferno-server/src/renderToString.stream.ts index 56e6daf09..8f841f1c3 100644 --- a/packages/inferno-server/src/renderToString.stream.ts +++ b/packages/inferno-server/src/renderToString.stream.ts @@ -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'; @@ -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; diff --git a/packages/inferno-server/src/renderToString.ts b/packages/inferno-server/src/renderToString.ts index 320a9ebce..8c246bdc0 100644 --- a/packages/inferno-server/src/renderToString.ts +++ b/packages/inferno-server/src/renderToString.ts @@ -1,6 +1,7 @@ import {EMPTY_OBJ} from 'inferno'; import { combineFrom, + isArray, isFunction, isInvalid, isNull, @@ -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;