Maximum call stack size exceeded when component is rendered (but only when mounted by Router)
Describe the bug
I've been developing a rewrite of a react codebase for analyzing logs for Stardew Valley, and in trying to get something from my log rendering at all was experiencing Uncaught RangeError: Maximum call stack size exceeded errors.
And after making the reproduction found it only happens when Router is involved, directly rendering the component works fine
Your Example Website or App
https://playground.solidjs.com/anonymous/8571b506-158c-43ab-84a1-2c21de773f3e
Steps to Reproduce the Bug or Issue
- Wait a few seconds after the sandbox page loads
- Press the science button
Expected behavior
A bunch of logs from ./dataset.ts to be displayed.
Actual behaviour:
Uncaught RangeError: Maximum call stack size exceeded
at ye (esm.sh/[email protected]/es2022/solid-js.mjs:2:12476)
at Object.fn (esm.sh/[email protected]/es2022/solid-js.mjs:2:6719)
at Ie (esm.sh/[email protected]/es2022/solid-js.mjs:2:8342)
at H (esm.sh/[email protected]/es2022/solid-js.mjs:2:8122)
at Z (esm.sh/[email protected]/es2022/solid-js.mjs:2:9655)
at ze (esm.sh/[email protected]/es2022/solid-js.mjs:2:10505)
at pt (esm.sh/[email protected]/es2022/solid-js.mjs:2:9912)
at M (esm.sh/[email protected]/es2022/solid-js.mjs:2:9825)
at Tt (esm.sh/[email protected]/es2022/solid-js.mjs:2:5349)
at i (esm.sh/[email protected]/es2022/store.mjs:2:3258)
This error doesn't happen and renders as intended when Line56 is changed to mount <MainPage /> Directly as opposed to having it called via the router
Screenshots or Videos
Inside the Sandbox
Platform
- OS: Windows
- Browser: Edge
- Version: 140.0.3485.40
Additional context
In analyzing it, it is this line of code at fault https://github.com/solidjs/solid/blob/0af2c2b4dc5f7da8022c16563c25d0687f68aff3/packages/solid/src/reactive/signal.ts#L1749 where it is trying to use .apply to call push in bulk, but .apply doesn't work for large arrays due to how it puts the contents on the stack.
I genuinely don't know why this only blows up when Solid Router is involved and only found out when making the reproduction in the sandbox and it worked until I added it back in for the more 1:1 equivilent.
Thanks, what happens is that some components, like the Router (and some others), recursively resolve children/functions as for Context to have the right value, or for elements to be hoisted. In short, components won't return functions, it will recursively call any function before returning, even if the functions are in an array(aka partials/fragments). This is done by the children helper https://docs.solidjs.com/reference/component-apis/children which calls the function you are describing resolveChildren.
Illustrative pseudocode
<Context value="1">
<div>
<Context value="2">
{[
function fn1(){ return context.value },
function fn2(){ return context.value }
]}
</Context>
</div>
</Context>
If Context value="2" were to return the array without calling the functions it contains, then once the <div is created with the two children, it will have the wrong context value of 1.
As for the particular case, yes the problem is results.push.apply(results, result) is trying to push 149k arguments, crashing
- repro with just the children helper https://playground.solidjs.com/anonymous/631ec862-0d2a-4b2a-a70e-a9844d1fb821
- repro without solid https://playground.solidjs.com/anonymous/4894991e-31ac-48db-a00b-d271865f1c84
Think we can fix this by using the QUANTUM approach MDN is suggesting.
There are some considerations, I will send a PR for Ryan to review, and we discuss the considerations there.
PR in https://github.com/solidjs/solid/pull/2543