test: assert Bun 1.4 and Deno 2.9.6 stream behavior, bump @types and pnpm - #82
Conversation
Bun 1.4.0 changed fetch/serve behavior: cancelling a response body now closes the connection, a streaming request body is cancelled once the response has been received, and an errored response stream reaches the client as an error. The bun-fetch tests asserted the old broken behavior on purpose so a Bun fix would surface as a failure, which it did on Bun 1.4.1 in CI. Both adapters now propagate cancellation, so the gating sets and their else-branches are removed. The one remaining difference is kept behind a set: Bun.serve only aborts request.signal on client disconnect, not when the server itself closes the connection after its response stream errors.
@standardserver/aws-lambda
@standardserver/core
@standardserver/fastify
@standardserver/fetch
@standardserver/node
@standardserver/peer
@standardserver/shared
commit: |
Merging this PR will not alter performance
Comparing Footnotes
|
There was a problem hiding this comment.
✅ No new issues found.
The tests now assert Bun 1.4's fixed behavior, and every changed test passes on the current
bun 1in CI.
Reviewed changes
- Dropped the
REQUEST_STREAM_CANCEL_ADAPTERSandRESPONSE_STREAM_CANCEL_ADAPTERSgates — since Bun 1.4.0 bothbun-fetchandbun-wspropagate stream cancellation, so the.has(adapter)checks and bothelsebranches are gone and the cancel-path assertions are unconditional. - Introduced
RESPONSE_STREAM_ERROR_ABORT_ADAPTERS = {'bun-ws'}for the one remaining difference: in the response-stream-error test,bun-wsstill waits onserverSignal.aborted, whilebun-fetchasserts the server signal never aborts (the server tore the connection down itself;Bun.serveonly abortsrequest.signalon client disconnect).expect(error).toBeDefined()on the client read is now unconditional, matchingECONNRESETon 1.4.
The assertions are exact and each one fails loudly if Bun's behavior regresses — which is the stated convention, and it caught the 1.4.1 change in CI as intended. I verified the CI matrix output for this head: all tests/bun signal-and-cancel and data-transfer tests pass on both adapters (~26-37ms per cancel test, comfortably inside the 300ms bound).
One note for the record: the PR's red checks pre-date this change and are unrelated to it — lint_and_typecheck fails on the pre-existing ReadableWritablePair error in packages/core/src/event-stream/decoder.ts:146, and test_node_matrix fails on tests/deno flakes plus pnpm 11 requiring Node >= 22.13. None of these touch tests/bun.
DeepSeek Flash (default — pick a model for stronger reviews) | 𝕏
Drop the implements ReadableWritablePair clause on EventStreamDecoderStream. The name is a DOM lib global that @types/node only exposes under stream/web, so the clause leaked into the emitted declarations and failed to resolve for consumers type-checking against Node types alone. The class still exposes the same readable/writable pair structurally.
Deno 2.8.3 through 2.9.5 stopped delivering request body chunks to a Deno.serve handler once it started writing a streaming response, so the deno-fetch event stream echo tests deliberately asserted the stall. Deno 2.9.6 fixed it (denoland/deno#36629), which made those assertions fail in CI. Both Deno adapters are full-duplex now, so the FULL_DUPLEX_ADAPTERS gate and its stall branches are removed.
There was a problem hiding this comment.
✅ No new issues found.
The two new commits land the workspace-wide type bumps and a declaration cleanup in
EventStreamDecoderStream. The@types/node/@types/bunbumps are types-only — the lockfile is internally consistent (no leftover26.2.0/1.3.14references) and runtime deps likeundici-types@8.3.0are unchanged — and droppingimplements ReadableWritablePair<...>is a genuine fix: that name is module-scoped innode:stream/weband only a global under the DOM lib, so the clause failed the roottsc(lib ES2022, no DOM) with TS2304 and leaked a DOM-only name into emitted declarations. The class still satisfies the interface structurally, sopipeThrough(new EventStreamDecoderStream())callers are unaffected, andimplementsis erased at runtime.
Reviewed changes
- Bumped
@types/node^26.1.2 → ^26.4.1workspace-wide (root,aws-lambda,fastify,node,hono-node,node-http) and@types/bun^1.3.14 → ^1.4.0intests/bun, with a consistentpnpm-lock.yamland no runtime dependency changes. - Dropped
implements ReadableWritablePair<EventStreamMessage, string>fromEventStreamDecoderStream(packages/core/src/event-stream/decoder.ts), clearing the pre-existing TS2304 that red'dlint_and_typecheckon the prior commit — the class keeps itsreadable/writablemembers, so the conformance is preserved structurally.
Verified against the head's CI: lint_and_typecheck is now green (it was red at decoder.ts:146 on the prior commit), tests/bun runs 50 pass / 0 fail on Bun 1.4.1, and the remaining test_node_matrix failures are the known pre-existing tests/deno "event stream in parallel" flakes plus the Node 20 node:sqlite/pnpm issue — none are caused by this delta.
DeepSeek Flash (default — pick a model for stronger reviews) | 𝕏
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
✅ No new issues found.
The new commit updates
tests/deno/tests/data-transfer.test.tsfor Deno 2.9.6's full-duplex fix (denoland/deno#36629). Removing theFULL_DUPLEX_ADAPTERSgate and its stall branches is the right call — bothdeno-fetchanddeno-wsare full-duplex now — and the tests keep their exact parallel-delivery assertions (PARALLEL_THRESHOLD < 2 * CHUNK_DELAY), so a Deno regression to the old stalling behavior still fails loudly. This also clears the previously-red matrix legs.
Reviewed changes
- Removed the
FULL_DUPLEX_ADAPTERSset and both stall branches from the two event-stream echo tests intests/deno/tests/data-transfer.test.ts; both adapters now unconditionally assert that the second and third chunks are delivered in parallel, with a comment documenting theDeno >= 2.9.6requirement that the stall is gone.
Verified against the head's CI: lint_and_typecheck is green, and test_node_matrix now passes on Node 26/22/24 (previously red on the deno "event stream in parallel" tests) — only Node 20 remains red on the pre-existing node:sqlite/pnpm-11-requires-Node-≥22.13 issue, unrelated to this delta.
DeepSeek Flash (default — pick a model for stronger reviews) | 𝕏
pnpm 11 requires Node >= 22.13 and loads node:sqlite, so the Node 20 matrix job crashed inside pnpm before running any test. pnpm 12 supports Node >= 18. The lockfile gains pnpm 12's leading env document, which records the pinned pnpm version and its platform binaries.
There was a problem hiding this comment.
Important
The pnpm 12 upgrade breaks pnpm i — all six CI jobs on this head fail at the install step, a regression vs. the previous head (b1a9cd7, pnpm 11) where install worked. This directly defeats the commit's stated goal of unblocking the Node 20 leg.
Reviewed changes
Since the prior pullfrog review (b1a9cd7):
- Bumped
packageManagerfrompnpm@11.21.0topnpm@12.3.3and regeneratedpnpm-lock.yamlwith pnpm 12's leading env document —configDependencies/packageManagerDependenciesfor 12.3.3 plus@pnpm/exe.*platform-specific binaries.
Reproduction and root cause are anchored inline on package.json:6.
DeepSeek Flash (default — pick a model for stronger reviews) | 𝕏
There was a problem hiding this comment.
✅ No new issues found.
The new commit adds .npmrc declaring @jsr:registry=https://npm.jsr.io/, the exact fix the prior review's inline comment recommended for pnpm 12's @jsr/* metadata-fetch failure. Verified directly: pnpm install --frozen-lockfile under pnpm 12.3.3 now passes the 833-entry supply-chain policy check and completes, and this head's CI is green across lint_and_typecheck, all four test_node_matrix legs (including the Node 20 leg the pnpm bump targeted), publish_preview, and Continuous Releases — the install-step failure that red'd every job on 5d27d1e is gone.
Reviewed changes
- Added
.npmrc(repo root) with@jsr:registry=https://npm.jsr.io/, letting pnpm 12's supply-chain metadata fetch resolve the@jsr/*transitive deps that only exist onnpm.jsr.io— resolving the prior blocking finding and unblocking Node 20.
DeepSeek Flash (default — pick a model for stronger reviews) | 𝕏
1b60a5f to
01fdc59
Compare
There was a problem hiding this comment.
✅ No new issues found.
Since the last pullfrog review the branch was rewritten to abandon the pnpm 12 + .npmrc JSR-scope workaround entirely. The new head reverts to pnpm 11 via devEngines.packageManager (^11.0.0, resolves to 11.25.0), deletes .npmrc, and drops the EOL Node 20 leg from test_node_matrix. I verified the toolchain end-to-end:
devEngines.packageManageris a genuine pnpm v11.0.0+ feature, andpnpm/action-setup@v6reads it with priority overpackageManager, self-updating to the^11.0.0range (src/install-pnpm/run.ts) — consistent with the lockfile's recordedpnpm@11.25.0.- No stale
@jsr/*or pnpm 12 references remain, and noengines.nodefloor is declared anywhere, so dropping Node 20 (EOL, and pnpm 11 requires Node ≥ 22.13 anyway so it could never install) breaks no contract. - All CI on this head is green:
lint_and_typecheck,test_node_matrix(22/24/26),publish_preview,benchmarks,Continuous Releases, CodSpeed, codecov/patch.
Reviewed changes
- Reverted the pnpm 12.3.3 bump +
.npmrcJSR-scope workaround — replacedpackageManagerwithdevEngines.packageManager(pnpm@^11.0.0,onFail: download), deleted.npmrc, and regeneratedpnpm-lock.yamlfor pnpm 11 (recordspnpm@11.25.0). This resolves the earlier blocking install finding by the simpler supported path rather than a custom registry override. - Dropped Node 20 from
test_node_matrix(node-version: [26, 24, 22, 20]→[26, 24, 22]) — the EOL runtime that pnpm 11 can't even install on. - The Bun 1.4 (
signal-and-cancel.test.ts) and Deno 2.9.6 (data-transfer.test.ts) assertion changes are unchanged from the commits previously reviewed and approved; the rewrite touched onlyci.yaml, rootpackage.json, and the lockfile.
DeepSeek Flash (default — pick a model for stronger reviews) | 𝕏

Bun 1.4 and Deno 2.9.6 both fixed stream behavior that the Bun and Deno test suites deliberately asserted as broken, so CI on main has been red since Bun 1.4.0 landed and the Deno failures surfaced right after. The failures are runtime behavior changes, not standardserver bugs, and the tests now assert the fixed behavior instead of skipping anything. Alongside that,
@types/nodeand@types/bunare bumped,EventStreamDecoderStreamno longer declaresimplements ReadableWritablePair, pnpm is now declared throughdevEnginesso it self-provisions, and Node 20 is dropped from the CI matrix.Bun 1.4: stream cancellation now propagates
Pure-Bun repros with no standardserver code show the same change between Bun 1.3.14 and 1.4.0:
ECONNRESETerror instead of a clean end of body.Both Bun adapters propagate request and response cancellation, so the
REQUEST_STREAM_CANCEL_ADAPTERSandRESPONSE_STREAM_CANCEL_ADAPTERSgates and their else-branches are gone. One difference remains behind a newRESPONSE_STREAM_ERROR_ABORT_ADAPTERSset:Bun.serveonly abortsrequest.signalwhen the client goes away, not when the server itself closes the connection after its response stream errors. The test asserts that current behavior so a future Bun change surfaces as a failure, same convention as before.Deno 2.9.6: request body stays readable while streaming a response
Deno 2.8.3 through 2.9.5 stopped delivering request body chunks to a
Deno.servehandler once it started writing a streaming response, so thedeno-fetchevent stream echo tests asserted the stall. Deno 2.9.6 fixed it (denoland/deno#36629), and CI picks up the latest Deno 2, so those assertions started failing. Both Deno adapters are full-duplex now, so theFULL_DUPLEX_ADAPTERSgate and its stall branches are removed, with the minimum Deno version noted in the test.Types
@types/node26.1 → 26.4.1 across the workspace,@types/bun1.3 → 1.4.0 for the Bun tests.EventStreamDecoderStreamdropsimplements ReadableWritablePair. Node's types only expose that name understream/web, not as a global, so the clause failed to resolve for consumers type-checking against Node types alone. The class still exposes the samereadable/writablepair structurally, so nothing changes at runtime or for callers.Toolchain and CI
devEngines.packageManager(^11.0.0,onFail: download) instead of apackageManagerpin, so any pnpm on a contributor's machine or in CI provisions a compatible 11.x automatically. The lockfile records the resolved 11.25.0 and picks up refreshed resolutions within the existing dependency ranges.node:sqlitebefore running a single test on Node 20, and Node 20 reached end-of-life in April 2026. The matrix is now 22, 24 and 26.Testing
pnpm -w testpasses locally on the refreshed lockfile with pnpm 11.25.0: Bun 50 pass, Deno 4 suites / 50 steps pass, vitest 1076 tests across 59 files pass.bun teston Bun 1.4.1 anddeno teston Deno 2.9.6 each pass 3 of 3 repeated runs.pnpm run type:checkpasses for all 11 workspace projects with the new types.pnpm runtime set bun 1/deno 2).