Repository navigation
Conversation
mrgoonie
force-pushed
the
fix/5-sse-crlf
branch
from
October 12, 2026 02:09
873c2a9 to
09ead18
Compare
A `\r` at the end of one chunk ended the line, and a `\n` opening the next chunk was then read as a second, empty line, which dispatched the event early. The parser now remembers a trailing `\r` and skips a `\n` that immediately follows it in the next chunk, as the WHATWG event-stream format requires. Lone `\r` line endings still work, and the buffer cap, failed state and end-of-stream flush are unchanged. Closes #5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pin three cases: an empty chunk between the CR and LF of a split CRLF, an LF that opens the next chunk (one frame, not two), and CR CR followed by LF (one frame, nothing more). Note why the empty-chunk return must come before the endedWithCr update. Refs #5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The LF that ends a CRLF split across chunks does not count toward the next line, so the cap still applies exactly, and the frame that LF completes is kept when the rest of the chunk passes the cap. Refs #5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mrgoonie
force-pushed
the
fix/5-sse-crlf
branch
from
October 12, 2026 02:15
09ead18 to
984b586
Compare
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Stacked on #4 (
fix/2-sse-buffer-cap), which is stacked on #3. Review and merge those first; this PR's diff is only the CRLF fix.Problem
SseParser.pushtreated a\rat the end of one chunk as a line ending and then read a\nopening the next chunk as a second, empty line. An empty line dispatches the event, so an event with onlyevent:set could be sent early with no data, and its real data arrived as a separate event.Fix (
src/protocol/sse-reader.ts)endedWithCrflag: set when a chunk ends with\r.\nand the flag is set, parsing starts at index 1, so the split CRLF counts as one line ending (WHATWG event-stream format).failedstate and the end-of-stream flush are unchanged. The line regex\r\n|\r|\nalways consumes a trailing\r, so the buffer never holds one.Tests (
tests/unit/protocol/sse-reader.test.ts)push('event: x\r')thenpush('\ndata: y\r\n\r\n')gives exactly one eventxwith datay.push('data: a\rdata: b\r\r')gives one event with dataa\nb.readSseFramesover'event: x\r'+'\ndata: y\r', then the stream ends, gives one eventx/y.startset back to0, the split-CRLF parser test and the stream test both fail (2 failed, 13 passed in the file). With the fix restored, all pass.Gates
pnpm lint: passpnpm typecheck: passpnpm test: 27 files, 390 tests passpnpm build: passpnpm test:e2e(no.env): 5 smoke tests pass, 16 live tests skippedCloses #5
🤖 Generated with Claude Code