Web Streams polyfill and ponyfill implementation based on the WHATWG specification
npx @tessl/cli install tessl/npm-web-streams-polyfill@4.2.0Web Streams Polyfill provides a comprehensive Web Streams polyfill and ponyfill implementation based on the WHATWG specification. It offers multiple variants including modern ES2015+ and legacy ES5+ versions, both as polyfills that replace global stream implementations and as ponyfills that provide stream implementations without modifying globals.
npm install web-streams-polyfillPonyfill (recommended):
import {
ReadableStream,
WritableStream,
TransformStream,
CountQueuingStrategy,
ByteLengthQueuingStrategy
} from "web-streams-polyfill";ES5 Ponyfill:
import {
ReadableStream,
WritableStream,
TransformStream
} from "web-streams-polyfill/es5";Polyfill (modifies globals):
import "web-streams-polyfill/polyfill";
// Now ReadableStream, WritableStream, TransformStream are available globallyCommonJS:
const {
ReadableStream,
WritableStream,
TransformStream
} = require("web-streams-polyfill");import {
ReadableStream,
WritableStream,
TransformStream,
CountQueuingStrategy
} from "web-streams-polyfill";
// Create a simple readable stream
const readable = new ReadableStream({
start(controller) {
controller.enqueue("Hello");
controller.enqueue("World");
controller.close();
}
});
// Create a transform stream that uppercases text
const upperCaseTransform = new TransformStream({
transform(chunk, controller) {
controller.enqueue(chunk.toString().toUpperCase());
}
});
// Create a writable stream that logs output
const writable = new WritableStream({
write(chunk) {
console.log("Output:", chunk);
}
});
// Pipe data through the transform to the writable
await readable
.pipeThrough(upperCaseTransform)
.pipeTo(writable);
// Output: HELLO
// Output: WORLDWeb Streams Polyfill is built around several key components that follow the WHATWG Streams Standard:
ReadableStream, WritableStream, and TransformStream implementationsReadableStreamDefaultReader, WritableStreamDefaultWriter, etc.)CountQueuingStrategy and ByteLengthQueuingStrategyCore readable stream functionality for creating data sources that can be read from, with support for both default and byte streams, async iteration, and BYOB (Bring Your Own Buffer) reading.
class ReadableStream<R = any> {
constructor(underlyingSource?: UnderlyingSource<R>, strategy?: QueuingStrategy<R>);
constructor(underlyingSource: UnderlyingByteSource, strategy?: { highWaterMark?: number; size?: undefined });
readonly locked: boolean;
cancel(reason?: any): Promise<void>;
getReader(): ReadableStreamDefaultReader<R>;
getReader(options: { mode: 'byob' }): ReadableStreamBYOBReader;
pipeThrough<RS extends ReadableStream>(transform: ReadableWritablePair<R, RS>, options?: StreamPipeOptions): RS;
pipeTo(destination: WritableStream<R>, options?: StreamPipeOptions): Promise<void>;
tee(): [ReadableStream<R>, ReadableStream<R>];
values(options?: ReadableStreamIteratorOptions): ReadableStreamAsyncIterator<R>;
[Symbol.asyncIterator](options?: ReadableStreamIteratorOptions): ReadableStreamAsyncIterator<R>;
static from<R>(asyncIterable: Iterable<R> | AsyncIterable<R> | ReadableStreamLike<R>): ReadableStream<R>;
}
interface UnderlyingSource<R = any> {
start?: (controller: ReadableStreamDefaultController<R>) => void | PromiseLike<void>;
pull?: (controller: ReadableStreamDefaultController<R>) => void | PromiseLike<void>;
cancel?: (reason: any) => void | PromiseLike<void>;
type?: undefined;
}
interface UnderlyingByteSource {
start?: (controller: ReadableByteStreamController) => void | PromiseLike<void>;
pull?: (controller: ReadableByteStreamController) => void | PromiseLike<void>;
cancel?: (reason: any) => void | PromiseLike<void>;
type: 'bytes';
autoAllocateChunkSize?: number;
}Writable stream functionality for creating data destinations that can be written to, with backpressure support and error handling.
class WritableStream<W = any> {
constructor(underlyingSink?: UnderlyingSink<W>, strategy?: QueuingStrategy<W>);
readonly locked: boolean;
abort(reason?: any): Promise<void>;
close(): Promise<void>;
getWriter(): WritableStreamDefaultWriter<W>;
}
interface UnderlyingSink<W = any> {
start?: (controller: WritableStreamDefaultController<W>) => void | PromiseLike<void>;
write?: (chunk: W, controller: WritableStreamDefaultController<W>) => void | PromiseLike<void>;
close?: () => void | PromiseLike<void>;
abort?: (reason: any) => void | PromiseLike<void>;
type?: undefined;
}Transform stream functionality that connects a writable side to a readable side, allowing data to be transformed as it flows through.
class TransformStream<I = any, O = any> {
constructor(
transformer?: Transformer<I, O>,
writableStrategy?: QueuingStrategy<I>,
readableStrategy?: QueuingStrategy<O>
);
readonly readable: ReadableStream<O>;
readonly writable: WritableStream<I>;
}
interface Transformer<I = any, O = any> {
start?: (controller: TransformStreamDefaultController<O>) => void | PromiseLike<void>;
transform?: (chunk: I, controller: TransformStreamDefaultController<O>) => void | PromiseLike<void>;
flush?: (controller: TransformStreamDefaultController<O>) => void | PromiseLike<void>;
cancel?: (reason: any) => void | PromiseLike<void>;
readableType?: undefined;
writableType?: undefined;
}Backpressure management through queuing strategies that control how data is buffered within streams.
class CountQueuingStrategy {
constructor(options: { highWaterMark: number });
readonly highWaterMark: number;
readonly size: (chunk: any) => 1;
}
class ByteLengthQueuingStrategy {
constructor(options: { highWaterMark: number });
readonly highWaterMark: number;
readonly size: (chunk: ArrayBufferView) => number;
}
interface QueuingStrategy<T = any> {
highWaterMark?: number;
size?: (chunk: T) => number;
}
interface QueuingStrategyInit {
highWaterMark: number;
}interface ReadableWritablePair<R, W> {
readable: ReadableStream<R>;
writable: WritableStream<W>;
}
interface StreamPipeOptions {
preventAbort?: boolean;
preventCancel?: boolean;
preventClose?: boolean;
signal?: AbortSignal;
}
interface ReadableStreamIteratorOptions {
preventCancel?: boolean;
}
type ReadableStreamDefaultReadResult<T> =
| { done: false; value: T }
| { done: true; value: undefined };
type ReadableStreamBYOBReadResult<T extends ArrayBufferView> =
| { done: false; value: T }
| { done: true; value: T | undefined };
interface AbortSignal {
readonly aborted: boolean;
readonly reason?: any;
addEventListener(type: 'abort', listener: () => void): void;
removeEventListener(type: 'abort', listener: () => void): void;
}