The h/createElement function in Preact 10.0.0-rc.2 can generate a circular data structure, causing an infinite loop when the result is later passed to render.
Steps to reproduce
const { h, render } = require('preact');
const el = h('div', null, h('span', null), h('br', null));
console.log('VDOM node is', el);
Expected: Non-circular data structure
Actual: Circular data structure. This causes an infinite loop in toChildArray when rendering.
Slack discussion: https://preact.slack.com/archives/G9T60GUQ0/p1568062137383300
The problem is here: https://github.com/preactjs/preact/blob/9fb01cbb6a2e654bd0288fcec24ca70ddf94fa96/src/create-element.js#L12-L20
This bug is triggered when h gets more than three arguments (arguments.length > 3).
Because children is an argument then the statement children = [] is functionally equivalent to arguments[2] = []. Due to this the first iteration of the for-loop (children.push(arguments[2])) is functionally equivalent to children.push(children). This in turn causes the cyclical structure.
Temporal workarounds for people facing this issue:
Because it's about how arguments is handled by some modes, using esmodules should work. E.g. if you're using webpack,
alias: { preact$: 'preact/dist/preact.module.js' }
(make sure that file is not excluded in bundler/compiler)
cf: https://github.com/preactjs/preact/pull/1917#issuecomment-529694815
Most helpful comment
The problem is here: https://github.com/preactjs/preact/blob/9fb01cbb6a2e654bd0288fcec24ca70ddf94fa96/src/create-element.js#L12-L20
This bug is triggered when
hgets more than three arguments (arguments.length > 3).Because
childrenis an argument then the statementchildren = []is functionally equivalent toarguments[2] = []. Due to this the first iteration of the for-loop (children.push(arguments[2])) is functionally equivalent tochildren.push(children). This in turn causes the cyclical structure.