From ad35c4c931db37837761038d33ae71fa31ebc9e3 Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Mon, 12 Sep 2022 10:51:34 -0400 Subject: [PATCH 1/2] Ignore non-VNode objects during rendering This fixes #245. --- .changeset/curly-bananas-do.md | 5 +++++ src/index.js | 3 +++ src/pretty.js | 3 +++ test/jsx.test.js | 4 ++++ test/pretty.test.js | 6 ++++++ test/render.test.js | 4 ++++ 6 files changed, 25 insertions(+) create mode 100644 .changeset/curly-bananas-do.md diff --git a/.changeset/curly-bananas-do.md b/.changeset/curly-bananas-do.md new file mode 100644 index 00000000..19a81f08 --- /dev/null +++ b/.changeset/curly-bananas-do.md @@ -0,0 +1,5 @@ +--- +'preact-render-to-string': patch +--- + +Fix object children being rendered as `undefined` diff --git a/src/index.js b/src/index.js index 9892d218..206a1d67 100644 --- a/src/index.js +++ b/src/index.js @@ -210,6 +210,9 @@ function _renderToString(vnode, context, isSvgMode, selectValue, parent) { return rendered; } + // VNodes have {constructor:undefined} to prevent JSON injection: + if (vnode.constructor !== undefined) return ''; + vnode[PARENT] = parent; if (options[DIFF]) options[DIFF](vnode); diff --git a/src/pretty.js b/src/pretty.js index 4d85cbc7..de7e66d3 100644 --- a/src/pretty.js +++ b/src/pretty.js @@ -53,6 +53,9 @@ export function _renderToStringPretty( return rendered; } + // VNodes have {constructor:undefined} to prevent JSON injection: + if (vnode.constructor !== undefined) return ''; + let nodeName = vnode.type, props = vnode.props, isComponent = false; diff --git a/test/jsx.test.js b/test/jsx.test.js index 733ebaf4..e2969835 100644 --- a/test/jsx.test.js +++ b/test/jsx.test.js @@ -163,4 +163,8 @@ describe('jsx', () => { `); }); + + it('should prevent JSON injection', () => { + expect(renderJsx(
{{ hello: 'world' }}
)).to.equal('
'); + }); }); diff --git a/test/pretty.test.js b/test/pretty.test.js index 5c6b4410..9ddfecd1 100644 --- a/test/pretty.test.js +++ b/test/pretty.test.js @@ -222,4 +222,10 @@ describe('pretty', () => {

`); }); + + it('should prevent JSON injection', () => { + expect(prettyRender(
{{ hello: 'world' }}
)).to.equal( + '
' + ); + }); }); diff --git a/test/render.test.js b/test/render.test.js index 3783569c..0ca58827 100644 --- a/test/render.test.js +++ b/test/render.test.js @@ -1260,4 +1260,8 @@ describe('render', () => { '' ); }); + + it('should prevent JSON injection', () => { + expect(render(
{{ hello: 'world' }}
)).to.equal('
'); + }); }); From 203b79a45dfc55f8d0988be4f312f07959c9813c Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Tue, 4 Oct 2022 22:43:13 +0200 Subject: [PATCH 2/2] Ignore functions passed as children --- .changeset/curly-bananas-do.md | 2 +- src/index.js | 1 + src/pretty.js | 1 + test/jsx.test.js | 4 ++++ test/pretty.test.js | 4 ++++ test/render.test.js | 4 ++++ 6 files changed, 15 insertions(+), 1 deletion(-) diff --git a/.changeset/curly-bananas-do.md b/.changeset/curly-bananas-do.md index 19a81f08..4df000d9 100644 --- a/.changeset/curly-bananas-do.md +++ b/.changeset/curly-bananas-do.md @@ -2,4 +2,4 @@ 'preact-render-to-string': patch --- -Fix object children being rendered as `undefined` +Fix object and function children being rendered as `undefined` diff --git a/src/index.js b/src/index.js index 206a1d67..4f5e2831 100644 --- a/src/index.js +++ b/src/index.js @@ -195,6 +195,7 @@ function _renderToString(vnode, context, isSvgMode, selectValue, parent) { // Text VNodes: escape as HTML if (typeof vnode !== 'object') { + if (typeof vnode === 'function') return ''; return encodeEntities(vnode); } diff --git a/src/pretty.js b/src/pretty.js index de7e66d3..1c977987 100644 --- a/src/pretty.js +++ b/src/pretty.js @@ -29,6 +29,7 @@ export function _renderToStringPretty( // #text nodes if (typeof vnode !== 'object') { + if (typeof vnode === 'function') return ''; return encodeEntities(vnode); } diff --git a/test/jsx.test.js b/test/jsx.test.js index e2969835..403b888b 100644 --- a/test/jsx.test.js +++ b/test/jsx.test.js @@ -167,4 +167,8 @@ describe('jsx', () => { it('should prevent JSON injection', () => { expect(renderJsx(
{{ hello: 'world' }}
)).to.equal('
'); }); + + it('should not render function children', () => { + expect(renderJsx(
{() => {}}
)).to.equal('
'); + }); }); diff --git a/test/pretty.test.js b/test/pretty.test.js index 9ddfecd1..4ee901ea 100644 --- a/test/pretty.test.js +++ b/test/pretty.test.js @@ -228,4 +228,8 @@ describe('pretty', () => { '
' ); }); + + it('should not render function children', () => { + expect(prettyRender(
{() => {}}
)).to.equal('
'); + }); }); diff --git a/test/render.test.js b/test/render.test.js index 0ca58827..8f234821 100644 --- a/test/render.test.js +++ b/test/render.test.js @@ -1264,4 +1264,8 @@ describe('render', () => { it('should prevent JSON injection', () => { expect(render(
{{ hello: 'world' }}
)).to.equal('
'); }); + + it('should not render function children', () => { + expect(render(
{() => {}}
)).to.equal('
'); + }); });