Repository navigation
wrpc v2.0.1: fix route binary stream chunks through the worker proxy - #7
Merged
Merged
Conversation
Behind WrpcClientProxy both directions of a binary stream arrived empty: the stream packets were forwarded, the chunks between them were not. - Page to server: the proxy treated any bytes that were not an attachments frame as junk and dropped them, so an upload reached the server's handler as an announcement and an end with no bytes. - Server to page: the worker's upstream client handed the stream packets to the proxy but read every chunk itself, found no such stream, and logged "Stream … is not initialized"; the tab's readable got nothing. A chunk carries only its stream id, so the proxy now routes it by the stream's announcement: an upload's chunks go up only from the page that announced it, a server stream's chunks go down wherever its stream packet went (the page waiting on the id, or every page). The upstream client hands a chunk over synchronously, so it keeps its place between the stream packets it is routed by. A page that leaves mid-upload has its stream terminated upstream (the server waited for the rest of the bytes forever), a lost upstream terminates the server streams the pages were reading, and a page's stream end releases the pending slot its announcement took. +235 B min+gzip in the shared client core: the main browser entry stays under its 28 KB (28,636 B), the sse entry crossed its 29 KB (29,753 B), so its budget goes to 30 with the reason in scripts/size.js; the size tables in README, the browser guide and llms.txt follow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- package.json and the docs nav label to 2.0.1 (npm has 1.0.0 and 2.0.0; [Unreleased] carries no breaking change, so a patch). - CHANGELOG: the worker-proxy stream fix moves under [2.0.1] - 2026-10-08, with a fresh empty [Unreleased] and its empty Changed (breaking) above. - The size tables in README and the browser guide refreshed from `pnpm size`. Checked per CONTRIBUTING's release checklist: lint, format:check, test:coverage (2996 pass, 0 fail, 46 skipped), test:coverage:floors, test:types, size and docs:build green; `npm publish --dry-run` lists every root shim and .d.ts, bin/ and src/, and none of docs/tests/bench/scripts/ examples/coverage; the packed tarball installs and resolves under CJS, ESM, `wrpc --version` and a bundler-resolution tsc. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This branch was successfully deployed
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.
Summary
Binary streams were broken behind
WrpcClientProxy, the worker that holds one connection for every tab (theeventtransport). In both directions thestreampackets got through but the bytes between them did not:ctx.client.createStream()): the worker's upstream client passed the stream packets on to the proxy but tried to read each chunk itself. It had no such stream, so it loggedStream … is not initializedfor every chunk, and the tab's readable got nothing.This releases the fix as 2.0.1.
The fix
A chunk carries only its stream id, so the proxy now routes it by the stream's announcement:
streampacket went: the one tab waiting on that id, or every tab.Cleanup that came with it:
terminateupstream. The server used to wait for the rest of the bytes forever.terminatefor every server stream a tab was reading, so those readables end instead of hanging.Bundle size
The fix adds +235 B min+gzip to the shared client core.
@alexify/wrpc/ssebrowserThe sse entry went over its budget, so the budget is raised, with the reason recorded in
scripts/size.jsas earlier raises were. The size tables in README,docs/guide/browser.mdandllms.txtare updated to match.Release prep (CONTRIBUTING › Release checklist)
package.json→2.0.1. npm has1.0.0and2.0.0.CHANGELOG.md: the fix moved under## [2.0.1] - 2026-10-08, with a fresh empty[Unreleased]and its empty### Changed (breaking)above itv2.0.1pnpm sizeVerification
tests/proxy.test.js: download, upload (including chunks from another tab and after the end), a tab leaving mid-upload, and a lost upstream. Each one failed before the fix.pnpm lint && pnpm format:check && pnpm test:coverage && pnpm test:coverage:floors && pnpm test:types && pnpm size && pnpm docs:build: all green. 3042 tests: 2996 pass, 0 fail, 46 skipped (integration, skip-guarded). Line coverage 98.02%.npm publish --dry-run: 203 files. Every root entry file and.d.ts,bin/andsrc/are in.docs/,tests/,bench/,scripts/,examples/andcoverage/are out.requireworksimportworkswrpc --versionprints2.0.1tsc --moduleResolution bundlertype-checks a Node consumer (with@types/node) and a browser-condition consumer (no Node types at all)Notes for reviewers
proxyclient option now also gets a third argument,chunk.client.d.tsis left unchanged on purpose:tests/index.test-d.tsrequires a callback typed(data: string) => voidto stay assignable to the option.streampackets are exactly what they were.After merge
main, not the branch commit (a squash merge changes the SHA):git tag v2.0.1 && git push --follow-tagsnpm publish🤖 Generated with Claude Code