Skip to content

fix: improve streaming and WebSocket WHATWG compatibility - #25

Merged
StopMakingThatBigFace merged 1 commit into
mainfrom
fix/whatwg-streaming-websocket
Aug 3, 2026
Merged

fix: improve streaming and WebSocket WHATWG compatibility#25
StopMakingThatBigFace merged 1 commit into
mainfrom
fix/whatwg-streaming-websocket

Conversation

@StopMakingThatBigFace

@StopMakingThatBigFace StopMakingThatBigFace commented Aug 3, 2026

Copy link
Copy Markdown
Owner

Summary

This PR rolls up all changes since v3.0.0, with a focus on streaming request bodies, WHATWG compatibility, WebSocket lifecycle correctness, and native resource cleanup.

Changes since v3.0.0

Request, Response, and streaming bodies

  • stream Blob, ReadableStream, async iterable, and iterable request bodies through the native transport with backpressure instead of buffering them in JS
  • preserve content length and MIME type for streamed blobs
  • support aborts and source errors for raw and multipart upload streams
  • replay blob and multipart bodies across retries and body-preserving redirects, while rejecting retries or redirects for already-consumed one-shot streams
  • consume global Request bodies as streams instead of calling arrayBuffer()
  • align Request.body, bodyUsed, cloning, transfer, GET/HEAD body validation, URL parsing, credential rejection, and method normalization with Fetch behavior
  • preserve explicit Content-Type headers for FormData
  • expose MIME types from Request.blob() and Response.blob() and add bytes() readers
  • expand Headers compatibility with global headers, tuple validation, keys(), values(), and forEach()
  • expose Request as a named ESM export and add compile-time compatibility checks against the global Fetch types

WebSocket

  • support the standard new WebSocket(url, protocols) constructor form and convert http:/https: URLs to ws:/wss:
  • cancel an in-progress native handshake when close() is called during CONNECTING, preventing a later spurious open event
  • keep queued sends ordered and wait for them before starting the closing handshake
  • use a bounded native command channel and acknowledge writes after they reach the socket
  • snapshot mutable binary payloads at send() call time
  • align send() behavior in CONNECTING, CLOSING, and CLOSED states and improve bufferedAmount tracking
  • report close state from the actual peer handshake instead of synthesizing a clean close immediately
  • populate MessageEvent.origin, use WHATWG-style DOMException errors for protocol validation, and ignore invalid binaryType assignments
  • surface cookie jar failures through the normal error and close event path
  • clean up native WebSocket handles when event or command streams terminate

Native resource lifecycle

  • release stored response bodies when reading a body chunk fails, preventing leaked connections and pool slots (fix: release stored response body when a chunk read errors #23)
  • cancel intermediate response bodies discarded by redirects, retries, hooks, or response replacement
  • add finalizer-backed cleanup for abandoned native response streams
  • cover response and WebSocket store cleanup with Rust and integration tests

Tests and tooling

  • add coverage for raw and multipart streaming, aborts, stream failures, retries, redirects, Request/Response body lifecycle, ESM exports, and WHATWG type compatibility
  • add WebSocket coverage for connecting cancellation, queued send ordering, mutable payload snapshots, cookie errors, origin, protocols, and close semantics
  • update oxfmt from 0.60 to 0.61

New contributor

Special thanks to @chad-loder for identifying and fixing the failed response-body cleanup leak in #23. That fix prevents broken streamed responses from retaining a socket and exhausting the connection pool over time.

Validation

  • npm test — 116 tests passed
  • cargo test --manifest-path rust/Cargo.toml — 6 tests passed
  • npm run lint
  • npm run build:ts
  • npm run lint:rust
  • TypeScript and Rust formatting checks

@StopMakingThatBigFace
StopMakingThatBigFace merged commit d920571 into main Aug 3, 2026
16 checks passed
@StopMakingThatBigFace
StopMakingThatBigFace deleted the fix/whatwg-streaming-websocket branch August 3, 2026 12:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant