WHATWG Streams

Readable, writable, transform, byte, and BYOB streams.

Elide exposes readable, writable, and transform streams with readers, writers, controllers, queuing strategies, piping, teeing, and async iteration.

ReadableStream

const stream = new ReadableStream({
  start(controller) {
    controller.enqueue("hello");
    controller.enqueue("world");
    controller.close();
  },
});

const reader = stream.getReader();
(await reader.read()).value; // "hello"
(await reader.read()).value; // "world"
(await reader.read()).done;  // true

Readable streams provide cancel(), getReader(), pipeThrough(), pipeTo(), tee(), async iteration, values(), and ReadableStream.from().

WritableStream and TransformStream

Writable streams provide abort(), close(), and getWriter(). Transform streams pair a writable input with a readable output.

const upper = new TransformStream({
  transform(chunk, controller) {
    controller.enqueue(chunk.toUpperCase());
  },
});

const source = ReadableStream.from(["hello"]);
const destination = new WritableStream({
  write(chunk) {
    console.log(chunk); // HELLO
  },
});

await source.pipeThrough(upper).pipeTo(destination);

Backpressure uses the configured highWaterMark and size algorithm. CountQueuingStrategy and ByteLengthQueuingStrategy are globals.

Byte and BYOB streams

const bytes = new ReadableStream({
  type: "bytes",
  start(controller) {
    controller.enqueue(new Uint8Array([1, 2, 3]));
    controller.close();
  },
});

const reader = bytes.getReader({ mode: "byob" });
const target = new Uint8Array(8);
const pending = reader.read(target);
target.buffer.byteLength; // 0: transferred immediately

const { value } = await pending;
Array.from(value); // [1, 2, 3]

BYOB operations transfer and detach the supplied buffer. Reusing the original view throws. Transferable streams are supported within the same realm; cross-worker transfer remains limited.

See Compression Streams for byte transforms.