Skip to content

Commit 90d92e6

Browse files
Merge pull request #246 from preactjs/ignore-non-vnode-objects
Ignore non-VNode objects during rendering
2 parents 60075a5 + 203b79a commit 90d92e6

File tree

6 files changed

+39
-0
lines changed

6 files changed

+39
-0
lines changed

.changeset/curly-bananas-do.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'preact-render-to-string': patch
3+
---
4+
5+
Fix object and function children being rendered as `undefined`

src/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ function _renderToString(vnode, context, isSvgMode, selectValue, parent) {
195195

196196
// Text VNodes: escape as HTML
197197
if (typeof vnode !== 'object') {
198+
if (typeof vnode === 'function') return '';
198199
return encodeEntities(vnode);
199200
}
200201

@@ -210,6 +211,9 @@ function _renderToString(vnode, context, isSvgMode, selectValue, parent) {
210211
return rendered;
211212
}
212213

214+
// VNodes have {constructor:undefined} to prevent JSON injection:
215+
if (vnode.constructor !== undefined) return '';
216+
213217
vnode[PARENT] = parent;
214218
if (options[DIFF]) options[DIFF](vnode);
215219

src/pretty.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export function _renderToStringPretty(
2929

3030
// #text nodes
3131
if (typeof vnode !== 'object') {
32+
if (typeof vnode === 'function') return '';
3233
return encodeEntities(vnode);
3334
}
3435

@@ -53,6 +54,9 @@ export function _renderToStringPretty(
5354
return rendered;
5455
}
5556

57+
// VNodes have {constructor:undefined} to prevent JSON injection:
58+
if (vnode.constructor !== undefined) return '';
59+
5660
let nodeName = vnode.type,
5761
props = vnode.props,
5862
isComponent = false;

test/jsx.test.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,4 +163,12 @@ describe('jsx', () => {
163163
<meta charset="utf-8" />
164164
`);
165165
});
166+
167+
it('should prevent JSON injection', () => {
168+
expect(renderJsx(<div>{{ hello: 'world' }}</div>)).to.equal('<div></div>');
169+
});
170+
171+
it('should not render function children', () => {
172+
expect(renderJsx(<div>{() => {}}</div>)).to.equal('<div></div>');
173+
});
166174
});

test/pretty.test.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,4 +222,14 @@ describe('pretty', () => {
222222
</p>
223223
`);
224224
});
225+
226+
it('should prevent JSON injection', () => {
227+
expect(prettyRender(<div>{{ hello: 'world' }}</div>)).to.equal(
228+
'<div></div>'
229+
);
230+
});
231+
232+
it('should not render function children', () => {
233+
expect(prettyRender(<div>{() => {}}</div>)).to.equal('<div></div>');
234+
});
225235
});

test/render.test.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1260,4 +1260,12 @@ describe('render', () => {
12601260
'<select><option selected value="2">2</option></select>'
12611261
);
12621262
});
1263+
1264+
it('should prevent JSON injection', () => {
1265+
expect(render(<div>{{ hello: 'world' }}</div>)).to.equal('<div></div>');
1266+
});
1267+
1268+
it('should not render function children', () => {
1269+
expect(render(<div>{() => {}}</div>)).to.equal('<div></div>');
1270+
});
12631271
});

0 commit comments

Comments
 (0)