Skip to content
Commit Detail

Commit 8f84ad2

Author
James M Snell <jsnell@cloudflare.com> 2025-09-04 15:55:33 -0700
Parents
910d7ec
Tree
6ad5f12
Add readable-source/writable-sink adapters

This is the first step towards a significant refactoring of the
streams implementation with the goal of making it safer and more
performance.

This commits adds four new classes:

* `ReadableStreamSourceKjAdapter`: Adapts a ReadableStream to the
  `ReadableStreamSource` API, fully encapsulating the JS interactions
  behind the KJ-friendly interface.
* `ReadableStreamSourceJsAdapter`: Adapts a `ReadableStreamSource`
  to a more friendly JS interface.
* `WritableStreamSinkKjAdapter`: Adapts a WritableStream to the
  `WritableStreamSink` API, fully encapsulating the JS interactions
  behind the KJ-friendly interface.
* `WritableStreamSinkJsAdapter`: Adapts a `WritableStreamSink`
  to a more friendly JS interface.

Also adds tests.

This commit does not update any existing code to use these adapters
yet, that will come in follow-up commits.

There are several key goals for this refactoring:

* Make the streams implementation safer by using the new checked
  Queue for buffering operations and removing direct reliance on
  raw references.
* Reducing the overall complexity of the streams implementation
  through better encapsulation and separation of concerns.

These require very careful review to ensure the behavior is correct
before we start switching existing code over to use these adapters.
In future commits I will be incrementally removing the old code
and switching to use these adapters.

Based on Harris' feedback, I've updated the implementation
of the ReadableStreamSourceKjAdapter to include a minimum
read policy. When the policy is IMMEDIATE, the adapter will
always return immediately after minimally fulfilling the
minimum read, even if more data is available and there is
more room in buffer we're reading into. If the policy is
OPPORTUNISTIC, then the adapter will attempt to fill the
buffer as much as possible (up until there is <= 512
bytes remaining in the buffer or we hit maxBytes) while
we are holding the isolate lock. The default policy is
OPPORTUNISTIC, with the idea being that we should do as
much work as possible while we have the isolate lock
before returning to the kj event loop.

Files changed