You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A drained stdio reader retains the previous allocation through an empty buffer view. Clear that reference when no bytes remain so idle transports release the storage and the next append avoids Buffer.concat(). Non-empty remainders are preserved.
V1 counterpart to #2540, using its proposed empty-remainder handling.
All nine CI checks pass, including the build, unit and end-to-end tests on Node 18 and 24, and client/server conformance.
Locally on Node 24.21.0, npm run check and npm run build pass; 1,855 unit tests pass with two workers.
The consumed-storage and next-chunk-copy regressions fail on base a8cf503 and pass here. The partial-message control passes on both.
All seven stdio end-to-end tests pass. With one worker, all 1,135 end-to-end assertions pass on both base and patch, but both commands exit nonzero with the same unhandled 200 ms protocol timeout. An initial two-worker run also hit an SSE max-total timing assertion.
Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.
I found one remaining storage-retention case in this fix.
readMessage() now drops _buffer when the consumed line ends exactly at the buffer boundary, which fixes the fully-drained case. But when a large backing allocation contains a complete message followed by a tiny partial next message, this line still keeps a view into the original allocation:
Because Buffer.subarray() shares the same ArrayBuffer, a few trailing bytes can pin the entire large allocation until more input arrives. The new partial-message test uses a normally-sized Buffer.from(...), so it doesn't exercise that retention case.
A regression test could allocate (for example) 64 KiB, place message + "\n" + partialNextMessage at the front, append a subarray of that allocation, consume the first message, and verify the retained remainder no longer shares/pins the 64 KiB backing store. One option is to compact/copy the remainder when the consumed prefix dominates the allocation, while keeping the zero-copy path for normal cases.
AI assistance was used to inspect the patch; this comment is scoped to the concrete backing-store retention behavior above.
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
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.
A drained stdio reader retains the previous allocation through an empty buffer view. Clear that reference when no bytes remain so idle transports release the storage and the next append avoids
Buffer.concat(). Non-empty remainders are preserved.V1 counterpart to #2540, using its proposed empty-remainder handling.
Related to #2536.
Validation:
npm run checkandnpm run buildpass; 1,855 unit tests pass with two workers.a8cf503and pass here. The partial-message control passes on both.max-totaltiming assertion.AI-assisted with Codex.