Repository navigation
fix: accept \r as line ending in alert/confirm/prompt for REPL compatibility #27544
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
Closed
Closed
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
🔴 The
_ = reader.takeByte() catch {}after reading\r(line 58, and 5 other locations) performs a blocking read. In raw terminal mode (the REPL scenario this PR fixes), Enter sends only\rwith no trailing\n, so this read blocks until the user presses a second key — partially defeating the fix. The follow-up read should only consume the next byte if data is already buffered (non-blocking peek), not issue an unconditional blocking read.Extended reasoning...
What the bug is
The PR adds
_ = reader.takeByte() catch {}(orreadByte) after every\rdetection to consume an optional trailing\nfor Windows CRLF line endings. However,takeByte()andreadByte()are blocking calls — they issue aread()syscall that blocks until at least one byte is available. In raw terminal mode (the exact REPL scenario this PR is designed to fix), pressing Enter sends only\rwith no trailing\n, so the follow-up read blocks waiting for the next byte from stdin.The specific code path
In
alert()at lines 56-60:The reader wraps a
std.fs.File(stdin) viareaderStreamingwith a 1-byte buffer. When all buffered data has been consumed (only\rwas available),takeByte()calls the underlyingread()syscall. Thecatch {}only handles read errors (e.g., EOF on a pipe), not blocking — a blocking read simply never returns.Why the REPL triggers this
The REPL puts the terminal in raw mode at startup (
bun.tty.setMode(0, .raw)in repl.zig:757). The raw mode configuration setsVMIN=1, VTIME=0(confirmed in wtf-bindings.cpp:90), meaningread()blocks until at least 1 byte is available. When the user presses Enter in raw mode, only\ris sent — there is no trailing\n. So after consuming\r, thetakeByte()call blocks indefinitely waiting for the next keystroke.Step-by-step proof
bun repl(terminal enters raw mode)alert("hello")and submits ithello [Enter]and waits for input\r(just one byte in raw mode)whileloop reads byte =\rat line 54if (byte == )branch at line 56_ = reader.takeByte() catch {}issues a blockingread()syscall\r), soread()blocksBefore this PR,
alert()hung indefinitely (infinite loop waiting for\n). After this PR, it hangs until a second keypress — an improvement but still broken.Why the tests pass
All tests use piped stdin with
proc.stdin.end()after writing\r. When the pipe is closed, the follow-uptakeByte()gets EOF, which is caught bycatch {}. But in a real REPL session, stdin is an open terminal file descriptor — it never returns EOF, so the read blocks.How to fix
The fix should only consume the next byte if it is already available in the reader's internal buffer (a non-blocking peek). For example, after reading
\r, check if the streaming reader has any buffered data before attempting to read the trailing byte. If no data is buffered, skip the read. This handles both cases correctly: bare\rin raw REPL mode (no blocking read) and\r\nin Windows cooked mode (consumes the\nfrom the buffer since both bytes arrive together). The same fix is needed at all six locations: alert() line 58, confirm() lines 121/137/147, both readUntilDelimiter helpers at lines 176/199, and prompt() at line 289.