-
Notifications
You must be signed in to change notification settings - Fork 33
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
Maximum call stack size exceeded
error happens with a long string literal
#42
Comments
First finding: It’s the Identifier regex that throws this errors when there’s a very long identifier. To reproduce (8388575 is the smallest number of “f”s that triggers it, both in Node.js, Chrome and Firefox): /(\x23?)(?=[$_\p{ID_Start}\\])(?:[$_\u200C\u200D\p{ID_Continue}]|\\u[\da-fA-F]{4}|\\u\{[\da-fA-F]+\})+/yu.test('f'.repeat(8388575)) Interestingly, Safari does not throw an error. It just returns Next up: Trying to reduce that regex to make an even smaller reproduction and narrow down exactly when it happens. |
Ok, so this seems to be enough to make Chrome’s and Firefox’s regex engine sad: /(?:a|b)+/.test('a'.repeat(8388575)) However, Safari manages that one. Maybe it has some optimization that kicks in for that simple case, but not the real, more complicated one. This works though: /[ab]+/.test('a'.repeat(8388575)) (Maybe Safari automatically optimizes to that.) And adding one plus sign to the original regex makes that pass: /(\x23?)(?=[$_\p{ID_Start}\\])(?:[$_\u200C\u200D\p{ID_Continue}]+|\\u[\da-fA-F]{4}|\\u\{[\da-fA-F]+\})+/yu.test('f'.repeat(8388575))
// ^ added! That works because it’s optimizing for the common case. A very long identifier of alternating > /(\x23?)(?=[$_\p{ID_Start}\\])(?:[$_\u200C\u200D\p{ID_Continue}]+|\\u[\da-fA-F]{4}|\\u\{[\da-fA-F]+\})+/yu.test('f\\u1234'.repeat(838857))
true Luckily, having escapes in identifiers is very rare. Next up: Seeing what other regexes might need a similar optimization, and how to document regex engine limitations. |
@sapphi-red (Edit: I now realize the original post literally mentions ”long string literal”, and the provided example code does create a string literal. Reading more carefully helps 🤦 ) |
Yes, that's just the smallest way. |
Released in v8.0.3. |
Thanks 💚 |
When a long string literal is contained in the input code, js-tokens throws
Maximum call stack size exceeded
error.Reproduction: https://github.com/sapphi-red-repros/js-tokens-maximum-call-stack-size-exceeded-repro
It happens with
as well.
Original issue: vitejs/vite#15703
The text was updated successfully, but these errors were encountered: