-
Notifications
You must be signed in to change notification settings - Fork 29.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
"inconvenient" stack overflow when using spread operator - changing stack size does not work #16870
Comments
/cc @nodejs/v8 for the question about |
Thanks 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 |
This is working as intended. The spread operator simply pushes all array elements onto the stack. You essentially have the same restrictions as
|
How about using array spread instead? someArray = [...someArray, ...someOtherArray]; |
Yeah this is one of the ways in which spread calls are surprising in JS. There is some more discussion about it on this bug.
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. |
@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! |
A customer cannot scan their project with a supposedly very large dependency graph because as soon as it reaches our back-end, we get a stack overflow error. It was identified that the error is due to the combination of Array.push() and the spread operator. For reference: nodejs/node#16870 To reproduce, create an array of size 2^17 then do [].push(...myArray);. This fix replaces all uses of push() and spread with a simple loop.
A customer cannot scan their project with a supposedly very large dependency graph because as soon as it reaches our back-end, we get a stack overflow error. It was identified that the error is due to the combination of Array.push() and the spread operator. For reference: nodejs/node#16870 To reproduce, create an array of size 2^17 then do [].push(...myArray);. This fix replaces all uses of push() and spread with a simple loop.
A customer cannot scan their project with a supposedly very large dependency graph because as soon as it reaches our back-end, we get a stack overflow error. It was identified that the error is due to the combination of Array.push() and the spread operator. For reference: nodejs/node#16870 To reproduce, create an array of size 2^17 then do [].push(...myArray); This fix replaces all uses of push() and spread with a simple loop.
workaround for nodejs/node#16870
Howdy! I'm bringing this PR over from the decidedly dead vultix/ts-results repo. This PR adds non-spread variants of `Result.all` and `Result.any` which should be preferred over the parameter spread variants. For instances where `Result.all` or `Result.any` are invoked with very large arrays, the spread operation could lead to stack overflows (nodejs/node#16870 (comment)). Additionally, speaking from personal experience in an enterprise environment; the usage of `Result.all` via a spread array (`Result.all(...myResults)`) grossly exceeds the usage of `Result.all` with multiple parameters. I'd imagine this is the same for others as well. This new behavior has been added as an overload of `Result.all` to offer backwards compatibility for those spreading arrays in, or passing each argument individually. Though based on the stack overflow issue mentioned above, I'd recommend users migrate from array spreading to just passing the array.
Using the spread operator with large arrays can trigger a stack overflow in Chrome/V8. For example, see: - nodejs/node#16870 In a highlighting context, we can have 10k-100k occurrences in a file, so let's avoid using the spread operator. Fixes https://linear.app/sourcegraph/issue/GRAPH-772 ## Test plan Manually tested against sample file. ![](https://github.com/user-attachments/assets/e096c664-063e-44ed-a991-72629af36651) ## Changelog - Fixes a Chrome-specific stack overflow when highlighting large files.
Using the spread operator with large arrays can trigger a stack overflow in Chrome/V8. For example, see: - nodejs/node#16870 In a highlighting context, we can have 10k-100k occurrences in a file, so let's avoid using the spread operator. Fixes https://linear.app/sourcegraph/issue/GRAPH-772 ## Test plan Manually tested against sample file. ![](https://github.com/user-attachments/assets/e096c664-063e-44ed-a991-72629af36651) ## Changelog - Fixes a Chrome-specific stack overflow when highlighting large files. (cherry picked from commit 2644e24)
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_size
parameter, but setting that to anything significantly larger than1000
on 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 🙂
The text was updated successfully, but these errors were encountered: