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
Fixed a Maximum call stack exceeded
err in getAlternateSourceIdForPosition
#7785
Fixed a Maximum call stack exceeded
err in getAlternateSourceIdForPosition
#7785
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
@@ -153,15 +153,28 @@ function getUniqueAlternateSourceId( | |||
return { sourceId: alternateSourceId }; | |||
} | |||
|
|||
function min(arr: number[]) { | |||
if (arr.length === 0) { | |||
return Infinity; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this matches Math.min(...[])
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this as a temporary workaround and we can merge it now, but I think we should come up with an alternate implementation. I already made a couple tweaks to the "breakable positions" handling that use a normalized lookup table by line instead of searching a giant array in order to fix a couple perf hotspots, and this looks like another good candidate.
Why not function minOptimized(arr) {
const length = arr.length;
if (length === 0) {
return Infinity;
} else if (length === 1) {
return arr[0]
} else {
let lowest = arr[0];
for (let i = 1; i < length; ++i) {
(arr[i] < lowest) && (lowest = arr[i]);
if (lowest === 1) {
break
}
}
return lowest;
}
} |
Because this one is less readable, it looks like the microoptimization. It's also not correct: minOptimized([10, 1, -1]) // actual 1, expected -1 It could be thought of as correct for this very specific use case, but I didn't bother to overoptimize this for this case here (could be done though) |
You can have negative lines in a file? |
No, that’s why i’ve said that it would be OK here but i was just trying to replace the current implementation with the one that wouldnt blow up the stack. So i’ve wanted to match the previous code 1 to 1 and just went for a generic implementation for the |
Yeah you are right. Probably the best optimization would be let breakableLine = Infinity
const positionLine = position.line
for (let i = 0, il = lineLocations.length; i < il; ++i) {
const line = lineLocations[i].line
if (
line >= positionLine &&
line < breakableLine
) {
breakableLine = line
}
} |
Yeah, per comment above, I think the best improvement here is to already have a |
I don't have a ton of context here but I agree that we should avoid iterating over big arrays– especially in code that's hot. Looking forward to seeing what Mark has in mind 😁 |
I noticed this error in the console and reported it a couple of days ago on Discord:
I couldn't repro it in Replay (it only happens for me in Chrome) - I'm not sure what exactly leads to it. However, when asked by @bvaughn for some more details about this I started to dig deeper. I was able to confirm that this happens for a minified code line that looks like this:
and I was able to trace it back to this in the source code:
devtools/src/devtools/client/debugger/src/utils/sourceVisualizations.ts
Lines 163 to 165 in 8772827
The problem with
fn(...arr)
is that it pushes all array elements onto the stack and that can blow up the stack. Usually, this is not an issue but it turns out thato
is quite huge here:Note that on this screenshot we see both the original
o
and the result of thefilter
+map
- we can notice that their lengths are the same. This might indicate a bug - but I don't know what exactly those code lines are meant to do so I'm not sure.In case this isn't a bug on its own... I've prepared this simple fix that just doesn't rely on the spread.
You can also test the "issue" with spread by evaluating this in the Chrome's console:
Note that FF has a bigger allowed stack and it might be the reason why it doesn't happen in Replay. I've recorded the situation in Replay and added a comment to the call site receiving this huge array, you might find it helpful: https://app.replay.io/recording/max-call-stack-exceeded-in-replay-just-in-chrome--018c0ea7-1ffe-446e-8020-e7e45f14d228