preactjs / preact-devtools

Browser extension for inspection Preact applications

Home Page:https://preactjs.github.io/preact-devtools/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

RangeError (stack overflow) when enough "operations" happen in a single render

ashvinsrivatsa opened this issue · comments

Consider this code:

<html>
        <head>
                <script type="module">
import "https://esm.sh/preact/debug";
import { h, render } from "https://esm.sh/preact";
import { useState } from "https://esm.sh/preact/hooks";
import htm from "https://esm.sh/htm";

const html = htm.bind(h);

const App = () => {
        const [showTree, setShowTree] = useState(false);
        if (showTree) {
                return html`<${Tree} depth=${14} />`;
        } else {
                return html`<button onClick=${() => setShowTree(true)}>Show Tree</button>`;
        }
};

const Tree = ({ depth }) => {
        if (depth === 0) {
                return null;
        } else {
                return html`<div>${depth}<${Tree} depth=${depth-1} /><${Tree} depth=${depth-1} /></div>`;
        }
};

render(html`<${App} />`, document.body);
                </script>
        </head>
        <body></body>
</html>

When the user clicks the "Show Tree" button, Preact is able to render the large Tree component without issue. But if the Preact Devtools (v4.7.1) are attached, the browser tab will crash:

RangeError: Maximum call stack size exceeded

Specifically, it crashes here:

msg.push(...operations);

In the above example, operations.length === 294907 here, which exceeds the number of arguments that may be passed to a function (at least on Chrome M123; the exact limit varies depending on browser).

(The <Tree depth={14} /> component here is comparable in size to a component our codebase actually contains; the component in question renders in a way that has operations.length around 200,000. This precludes the use of Preact Devtools when working on this component.)