-
Notifications
You must be signed in to change notification settings - Fork 29.8k
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
.load
infinite loop in REPL
#46731
Comments
The behavior is the same with v18.14.1 and v18.13.0, but works fine with v18.12.1. The only relevant change I can see between the two is from #45539, but I'm not sure why that would be causing this issue. It's also a little too in the weeds for me to spend much more time on it right now, unfortunately. Hopefully this information helps at least. |
I did some testing and this seems to also relate to newline characters:
Note that even without the ending newline character, the output between v20.0.0-pre and 18.12.0 is different. |
I'm confused by the new line situation. For one, you can see that without the newline it's not even reading the last line, apparently. Actually, this is interesting:
i.e., the repl is left in editor mode. That seems like a separate issue, however, so I'd be happy to open another issue if so. |
Minimum reproduce code: $ node
> fs.writeFileSync('foo.js', ` \n}\n`)
> .load foo.js
|
I found the Problem! ProblemThe Detailed Description
|
Since the lineEnding Regular Expression is declared on the module scope, recursive invocations of its `[kTtyWrite]` method share one instance of this Regular Expression. Since the state of a RegExp is managed by instance, alternately calling RegExpPrototypeExec with the same RegExp on different strings can lead to the state changing unexpectedly. This is the root cause of this infinite loop bug when calling .load on javascript files of certain shapes. PR-URL: #46742 Fixes: #46731 Reviewed-By: Kohei Ueno <[email protected]> Reviewed-By: Antoine du Hamel <[email protected]>
Since the lineEnding Regular Expression is declared on the module scope, recursive invocations of its `[kTtyWrite]` method share one instance of this Regular Expression. Since the state of a RegExp is managed by instance, alternately calling RegExpPrototypeExec with the same RegExp on different strings can lead to the state changing unexpectedly. This is the root cause of this infinite loop bug when calling .load on javascript files of certain shapes. PR-URL: #46742 Fixes: #46731 Reviewed-By: Kohei Ueno <[email protected]> Reviewed-By: Antoine du Hamel <[email protected]>
Since the lineEnding Regular Expression is declared on the module scope, recursive invocations of its `[kTtyWrite]` method share one instance of this Regular Expression. Since the state of a RegExp is managed by instance, alternately calling RegExpPrototypeExec with the same RegExp on different strings can lead to the state changing unexpectedly. This is the root cause of this infinite loop bug when calling .load on javascript files of certain shapes. PR-URL: #46742 Fixes: #46731 Reviewed-By: Kohei Ueno <[email protected]> Reviewed-By: Antoine du Hamel <[email protected]>
Since the lineEnding Regular Expression is declared on the module scope, recursive invocations of its `[kTtyWrite]` method share one instance of this Regular Expression. Since the state of a RegExp is managed by instance, alternately calling RegExpPrototypeExec with the same RegExp on different strings can lead to the state changing unexpectedly. This is the root cause of this infinite loop bug when calling .load on javascript files of certain shapes. PR-URL: #46742 Fixes: #46731 Reviewed-By: Kohei Ueno <[email protected]> Reviewed-By: Antoine du Hamel <[email protected]>
Version
v19.6.0
Platform
Darwin 22.3.0 Darwin Kernel Version 22.3.0: Mon Jan 30 20:38:43 PST 2023; root:xnu-8792.81.3~2/RELEASE_ARM64_T8112 arm64
Subsystem
repl
What steps will reproduce the bug?
This prints
function a(b) {
forever until killing the process (it doesn't respond toCtrl-c
)How often does it reproduce? Is there a required condition?
Every time, with the correct file.
What is the expected behavior?
What do you see instead?
Additional information
I'm struggling to figure out what's happening here. If the file contents don't include a new line after the first
{
, i.e.everything works fine. This lead me to believe it was somehow a parsing issue, but there are a number of iterations of the file that either do or do not work that don't seem to line up. The following files do work (separated by lines only containing //):
The following do not work:
I believe there were a few other weird things that worked and didn't work.
The odd thing is that reverting 6874aa1, lines 1554-1559 (6874aa1#diff-392b628f0a5eb047b1117351e6eedcefb8ec70a48933479e0e9bdc711a04f047L1554-L1559), seems to fix this. I tried a few other things, such as loading the file into a buffer before writing it out,
toString()
ing it afterBuffer.from()
ing it), changing the encoding, and changing the line endings. None of these worked.Also, the tests run fine, even when modifying them to include the text that breaks outside of the tests.
The text was updated successfully, but these errors were encountered: