Repository navigation
"inconvenient" stack overflow when using spread operator - changing stack size does not work #16870
Description
Activity
- addedquestionIssues asking questions about Node.js.Issues asking questions about Node.js.v8 engineIssues and PRs related to the V8 dependency.Issues and PRs related to the V8 dependency.
on Nov 7, 2017 I read about the
--stack-size/--stack_sizeparameter, but setting that to anything significantly larger than1000on my Windows box caused the process to just silently crash instead of getting the nice stack overflow error.--stack-sizedoesn’t let you set the stack size; it tells V8 what to assume for the usable stack size. So when you set it to a value that exceed the actual size, V8 just runs past the end of the stack and crashes./cc @nodejs/v8 for the question about
.push(...array)Reacted by Anton Ivanov and Cesar Manuel Cruzata De la CruzThanks for the clarification about stack size - it felt that way given that it crashed silently 👍
Some refs that I have stumbled upon in a similar case:
https://stackoverflow.com/questions/22123769/rangeerror-maximum-call-stack-size-exceeded-why
Reacted by Johannes BaderThis is working as intended. The spread operator simply pushes all array elements onto the stack. You essentially have the same restrictions as
Function.prototype.apply. You are better served doing something likefor (let e of someOtherArray) someArray.push(e)Reacted by Ethan BowerHow about using array spread instead?
someArray = [...someArray, ...someOtherArray];
Reacted by Anton IvanovYeah this is one of the ways in which spread calls are surprising in JS. There is some more discussion about it on this bug.
- Is there a plan for allowing larger spreads?
Basically, no. In the bug above I mention a few things we thought about to enable that, but the benefits are kind of unclear and it won't be particularly easy. Other JS engines would also need to do the same thing to enable spread to be used widely in this way. I guess for node you know much more about the JS engine you are using, so it would be more useful there.
Unfortunately, the best advice I can give is to avoid spread calls unless you know something about the length of your array and thus the stack space it will use. It is still useful for some other things particularly in combination with rest parameters, but this style where you call Array push or Math max/min is a bit dangerous for exactly the reason you describe.
Reacted by Johannes Bader, aronfiechter, Flynn and Mathias Bynens@hashseed @bmeurer Absolutely, note that this was not about how to work around this issue, but whether there are plans to support large spreads in calls. We used them "accidentally" since they are super convenient and while it makes perfect sense that you're exploding the stack, it's easy to miss. Also, tons of online resources will suggest stuff like that as the "ES6-way" of doing things, so I was curious whether there are plans to, say, implement calls differently in the future to work around that.
@psmarshall Thanks for the insights, that makes perfect sense!
Reacted by josephrocca- added 2 commits that reference this issue
on Oct 23, 2019 - added a commit that references this issue
on Oct 24, 2019 - added a commit that references this issue
on Oct 2, 2021 - added a commit that references this issue
on Apr 24, 2024 - added a commit that references this issue
on Jul 25, 2024 - added a commit that references this issue
on Jul 25, 2024
Happy about recent ES features, we did stuff like
someArray.push(...someOtherArray)which turns out to be problematic for largesomeOtherArray(say, 1 million elements), causing a stack overflow presumably because of the huge number of "arguments". There is the obvious workaround of loop-pushing (...with some helper method, since it's ugly to do that in tons of places), but given that the spread array doesn't even have too large for this to happen, I was also investigating stack size. I read about the--stack-size/--stack_sizeparameter, but setting that to anything significantly larger than1000on my Windows box caused the process to just silently crash instead of getting the nice stack overflow error.I'm not expecting any magic, the error and its reason makes sense to me, I just wondered:
push(...LARGE_ARRAY)since I assume that's the pattern people will happily use these days, unaware of the caveatNow that I wrote this, I think maybe these questions make more sense on the V8 side, but maybe you have valuable insights/ideas to share 🙂