Testable Requirements - New Streams API

March 19, 2026 · View on GitHub

This document lists all testable requirements for the new streams API implementation.

Legend

  • ✅ Covered by existing tests
  • ⚠️ Partially covered
  • ❌ Not covered

1. Stream.push()

Creates a bonded writer and async iterable pair for push-based streaming.

1.1 Basic Operation

IDRequirementStatus
PUSH-001Returns object with writer and readable properties
PUSH-002Writer.write() accepts string (UTF-8 encoded)
PUSH-003Writer.write() accepts Uint8Array
PUSH-004Writer.writev() writes multiple chunks atomically
PUSH-005Writer.writeSync() returns boolean (true if accepted)
PUSH-006Writer.writevSync() returns boolean (true if accepted)
PUSH-007Writer.end() signals end of stream
PUSH-008Writer.end() returns total bytes written
PUSH-009Writer.endSync() returns total bytes written
PUSH-010Writer.fail() signals error to consumer
PUSH-011Writer.failSync() signals error synchronously
PUSH-012Readable yields Uint8Array[] batches

1.2 Backpressure - desiredSize

IDRequirementStatus
PUSH-020desiredSize reflects available buffer space
PUSH-021desiredSize is 0 when buffer is full
PUSH-022desiredSize is null after close
PUSH-023desiredSize is null after fail
PUSH-024desiredSize is always >= 0 (never negative)

1.3 Backpressure - highWaterMark

IDRequirementStatus
PUSH-030Default highWaterMark is 4
PUSH-031Custom highWaterMark is respected
PUSH-032highWaterMark is clamped to [1, implementation-defined max (>= 1024)]
PUSH-033writev counts as single slot for backpressure

1.4 Backpressure Policies

IDRequirementStatus
PUSH-040backpressure: 'strict' rejects async writes when buffer full
PUSH-041backpressure: 'strict' returns false for sync writes when buffer full
PUSH-042backpressure: 'block' waits for space on async writes
PUSH-043backpressure: 'block' returns false for sync writes when buffer full
PUSH-044backpressure: 'drop-oldest' discards oldest buffered data
PUSH-045backpressure: 'drop-newest' discards incoming data when buffer full

1.5 Consumer Termination

IDRequirementStatus
PUSH-050Consumer break closes writer (desiredSize becomes null)
PUSH-051writeSync returns false after consumer terminates
PUSH-052iterator.throw() propagates error to writer

1.6 AbortSignal

IDRequirementStatus
PUSH-060signal option aborts stream when signaled
PUSH-061Already-aborted signal creates errored stream
PUSH-062Write blocked on backpressure rejects on signal abort��

1.7 Transforms

IDRequirementStatus
PUSH-070Accepts transforms as arguments
PUSH-071Multiple transforms are applied in order
PUSH-072Transforms are applied lazily (on pull)

1.8 Edge Cases

IDRequirementStatus
PUSH-080Handles empty writes
PUSH-081Reading from already-closed stream returns done
PUSH-082Second end() call rejects with TypeError
PUSH-083Batches synchronously available chunks
PUSH-084Handles concurrent writes and reads

1.9 Drainable Protocol

IDRequirementStatus
PUSH-090Writer implements drainable protocol
PUSH-091ondrain returns resolved Promise when desiredSize > 0
PUSH-092ondrain returns null when desiredSize is null (writer closed)
PUSH-093ondrain returns null when desiredSize is null (writer failed)
PUSH-094ondrain returns pending Promise when desiredSize === 0
PUSH-095ondrain Promise resolves with false when writer closes while waiting
PUSH-096ondrain Promise rejects when writer fails while waiting
PUSH-097Multiple drain waiters all resolve together
PUSH-098ondrain returns null for non-drainable objects
PUSH-099ondrain works with event source pattern

2. Stream.from() / Stream.fromSync()

Creates iterables from various input sources.

2.1 ByteInput Handling

IDRequirementStatus
FROM-001from() handles string input (UTF-8 encoded)
FROM-002from() handles Uint8Array input
FROM-003from() handles ArrayBuffer input
FROM-004fromSync() handles string input
FROM-005fromSync() handles Uint8Array input
FROM-006fromSync() handles ArrayBuffer input
FROM-007fromSync() handles ArrayBufferView (Int8Array, DataView)

2.2 Iterable Handling

IDRequirementStatus
FROM-010from() handles async generator
FROM-011from() handles sync generator
FROM-012from() handles array input
FROM-013fromSync() handles sync generator
FROM-014fromSync() handles array input
FROM-015from() flattens nested async iterables
FROM-016fromSync() flattens nested iterables
FROM-017fromSync() flattens arrays yielded by generators

2.3 Protocol Handling

IDRequirementStatus
FROM-020from() handles toAsyncStreamable returning promise
FROM-021from() handles toAsyncStreamable returning async iterable
FROM-022from() prefers toAsyncStreamable over toStreamable
FROM-023from() falls back to toStreamable when toAsyncStreamable absent
FROM-024fromSync() handles toStreamable returning string
FROM-025fromSync() handles toStreamable returning array
FROM-026fromSync() handles nested ToStreamable objects

2.4 String Coercion Fallback

IDRequirementStatus
FROM-030fromSync() handles URL (custom toString)
FROM-031fromSync() handles Date (custom toString)
FROM-032fromSync() handles objects with custom toString

2.5 Error Handling

IDRequirementStatus
FROM-040fromSync() rejects plain objects without custom toString
FROM-041fromSync() rejects null
FROM-042fromSync() rejects undefined
FROM-043fromSync() rejects numbers
FROM-044from() rejects non-iterable input
FROM-045from() propagates errors from async generators

2.6 Empty Inputs

IDRequirementStatus
FROM-050from() handles empty string
FROM-051from() handles empty async generator
FROM-052fromSync() handles empty string
FROM-053fromSync() handles empty generator
FROM-054fromSync() handles empty array

3. Stream.pull() / Stream.pullSync()

Creates pull-through pipelines with transforms.

3.1 Basic Operation

IDRequirementStatus
PULL-001pull() passes through source without transforms
PULL-002pull() works with sync source
PULL-003pullSync() passes through source without transforms
PULL-004pull() applies single transform
PULL-005pull() chains multiple transforms in order
PULL-006pullSync() applies single transform
PULL-007pullSync() chains multiple transforms

3.2 Transform Output Types

IDRequirementStatus
PULL-010Transform returning Uint8Array[] is passed through
PULL-011Transform returning string is UTF-8 encoded
PULL-012Transform returning nested iterables is flattened
PULL-013Transform returning null filters out batch

3.3 Async Transforms

IDRequirementStatus
PULL-020Handles async transform function
PULL-021Handles transform returning Promise
PULL-022Handles transform returning async generator

3.4 Stateful Transforms

IDRequirementStatus
PULL-030Supports stateful transform object
PULL-031Receives null flush signal at end
PULL-032Pipeline signal fires on transforms when error occurs

3.5 Options

IDRequirementStatus
PULL-040Accepts options as last argument
PULL-041Respects AbortSignal
PULL-042Handles already-aborted signal

4. Stream.pipeTo() / Stream.pipeToSync()

Consumes source and writes to a writer with optional transforms.

4.1 Basic Operation

IDRequirementStatus
PIPE-001pipeTo() writes source to writer without transforms
PIPE-002pipeTo() works with sync source
PIPE-003pipeTo() applies transforms before writing
PIPE-004pipeToSync() writes source to writer without transforms
PIPE-005pipeToSync() applies transforms before writing

4.2 Options

IDRequirementStatus
WRITE-010preventClose keeps writer open on completion
WRITE-011preventFail keeps writer from failing on error
WRITE-012Respects AbortSignal

4.3 Error Handling

IDRequirementStatus
WRITE-020Fails writer on source error
WRITE-021Throws if no writer provided
WRITE-025pipeTo passes signal to writer.write()
WRITE-026pipeTo passes signal to writer.end()

4.4 Special Cases

IDRequirementStatus
WRITE-030Handles writer that is also a transform

5. Consumer Functions

Terminal consumers that collect streams into memory.

5.1 Stream.bytes() / Stream.bytesSync()

IDRequirementStatus
BYTES-001bytes() collects all bytes from async source
BYTES-002bytes() collects all bytes from sync source
BYTES-003bytesSync() collects all bytes from source
BYTES-004bytesSync() handles multiple chunks
BYTES-005bytesSync() handles empty source
BYTES-006bytes() respects AbortSignal
BYTES-007bytes() respects byte limit
BYTES-008bytesSync() respects byte limit
BYTES-009bytesSync() allows data within limit

5.2 Stream.text() / Stream.textSync()

IDRequirementStatus
TEXT-001text() decodes UTF-8 by default
TEXT-002text() handles multi-byte UTF-8 characters
TEXT-003text() respects AbortSignal
TEXT-004textSync() decodes UTF-8 by default
TEXT-005textSync() handles multi-byte UTF-8 characters
TEXT-006textSync() respects encoding option
TEXT-007textSync() throws on invalid UTF-8 (fatal mode)
TEXT-008textSync() respects byte limit

5.3 Stream.arrayBuffer() / Stream.arrayBufferSync()

IDRequirementStatus
ARRAYBUF-001arrayBuffer() returns ArrayBuffer
ARRAYBUF-002arrayBuffer() respects AbortSignal
ARRAYBUF-003arrayBufferSync() returns ArrayBuffer
ARRAYBUF-004arrayBufferSync() respects byte limit

5.4 Stream.array() / Stream.arraySync()

IDRequirementStatus
ARRAY-001array() collects all chunks from async source
ARRAY-002array() collects all chunks from sync source
ARRAY-003arraySync() collects all chunks from source
ARRAY-004arraySync() handles single chunk
ARRAY-005arraySync() handles empty source
ARRAY-006arraySync() respects byte limit
ARRAY-007arraySync() allows data within limit
ARRAY-008array() respects AbortSignal
ARRAY-009array() respects byte limit
ARRAY-010array() preserves chunk boundaries

6. Stream.broadcast()

Push-model multi-consumer streaming.

6.1 Basic Operation

IDRequirementStatus
BCAST-001Creates writer and broadcast pair
BCAST-002Single consumer receives data
BCAST-003Multiple consumers receive same data
BCAST-004Tracks consumer count
BCAST-005Late subscribers receive new data

6.2 Buffer Management

IDRequirementStatus
BCAST-010Respects buffer limit
BCAST-011Trims buffer as consumers advance
BCAST-012Uses drop-oldest policy
BCAST-013Uses drop-newest policy

6.3 Writer Operations

IDRequirementStatus
BCAST-020Tracks total bytes written
BCAST-021Supports writev
BCAST-022Propagates errors via fail

6.4 Cancel

IDRequirementStatus
BCAST-030cancel() cancels all consumers without error
BCAST-031cancel(reason) cancels all consumers with error
BCAST-032cancel() is idempotent

6.5 Symbol.dispose

IDRequirementStatus
BCAST-040Symbol.dispose cancels broadcast

6.6 AbortSignal

IDRequirementStatus
BCAST-050Respects already-aborted signal
BCAST-051Cancels on signal abort

6.7 Transforms

IDRequirementStatus
BCAST-070Applies single transform to consumer
BCAST-071Applies multiple transforms in order
BCAST-072Allows different transforms per consumer

6.9 Drainable Protocol

IDRequirementStatus
BCAST-080Writer implements drainable protocol
BCAST-081ondrain returns resolved Promise when desiredSize > 0
BCAST-082ondrain returns null when desiredSize is null (writer closed)
BCAST-083ondrain returns null when desiredSize is null (writer failed)
BCAST-084ondrain returns pending Promise when desiredSize === 0
BCAST-085ondrain Promise resolves with false when writer closes while waiting
BCAST-086ondrain Promise rejects when writer fails while waiting
BCAST-087Multiple drain waiters all resolve together

7. Stream.share() / Stream.shareSync()

Pull-model multi-consumer streaming.

7.1 Basic Operation

IDRequirementStatus
SHARE-001share() creates a share instance
SHARE-002share() allows single consumer to pull data
SHARE-003share() allows multiple consumers to share data
SHARE-004share() handles sync source
SHARE-005shareSync() creates a sync share instance
SHARE-006shareSync() allows single consumer to pull data
SHARE-007shareSync() allows interleaved iteration of multiple consumers

7.2 Buffer Management

IDRequirementStatus
SHARE-010Buffers data for slow consumers
SHARE-011share() respects buffer limit with strict policy (throws)
SHARE-012share() drops oldest with drop-oldest policy
SHARE-013shareSync() throws on buffer overflow with strict policy
SHARE-014shareSync() drops oldest with drop-oldest policy

7.3 Cancel

IDRequirementStatus
SHARE-020share() cancel() cancels all consumers without error
SHARE-021share() cancel(reason) cancels all consumers with error
SHARE-022share() cancel() closes source iterator
SHARE-023shareSync() cancel() cancels all consumers

7.4 Symbol.dispose

IDRequirementStatus
SHARE-030Symbol.dispose cancels share

7.5 AbortSignal

IDRequirementStatus
SHARE-040Respects already-aborted signal

7.6 Error Propagation

IDRequirementStatus
SHARE-050Propagates source errors to all consumers

7.7 Transforms

IDRequirementStatus
SHARE-070share() applies single transform to consumer
SHARE-071share() applies multiple transforms in order
SHARE-072share() allows different transforms per consumer
SHARE-073share() supports transforms with options
SHARE-074shareSync() applies single transform to sync consumer

8. Stream.duplex()

Creates a pair of connected duplex channels for bidirectional communication.

8.1 Basic Operation

IDRequirementStatus
DUPLEX-001Returns tuple of two DuplexChannel instances
DUPLEX-002Data written to A appears in B's readable
DUPLEX-003Data written to B appears in A's readable
DUPLEX-004Bidirectional communication works

8.2 Close Behavior

IDRequirementStatus
DUPLEX-005close() is idempotent
DUPLEX-006Symbol.asyncDispose works
DUPLEX-007Closing one channel doesn't affect the other direction

8.3 Options

IDRequirementStatus
DUPLEX-008Respects highWaterMark option
DUPLEX-009Respects backpressure option
DUPLEX-010Respects AbortSignal option
DUPLEX-013Respects per-direction options
DUPLEX-014Per-direction options override shared options

8.4 Real-World Patterns

IDRequirementStatus
DUPLEX-011Supports request-response pattern
DUPLEX-012Supports multiple message exchanges

9. Stream.merge()

Merges multiple async sources by temporal order.

IDRequirementStatus
MERGE-001Handles empty sources
MERGE-002Handles single source
MERGE-003Merges multiple sources
MERGE-004Yields in temporal order (first-come)
MERGE-005Respects AbortSignal
MERGE-006Handles source errors
MERGE-007Accepts options as last argument

10. Stream.tap() / Stream.tapSync()

Creates pass-through transforms for observation.

IDRequirementStatus
TAP-001tap() calls callback with chunks
TAP-002tap() supports async callback
TAP-003tapSync() calls callback with chunks
TAP-004tapSync() passes chunks through unchanged

11. Protocol Symbols

Symbols for custom type integration.

IDRequirementStatus
PROTO-001toStreamable symbol allows sync conversion
PROTO-002toAsyncStreamable symbol allows async conversion
PROTO-003broadcastProtocol symbol allows custom broadcast
PROTO-004shareProtocol symbol allows custom share
PROTO-005shareSyncProtocol symbol allows custom sync share
PROTO-006drainableProtocol symbol allows drain notification

Summary Statistics

CategoryTotalCovered
Stream.push()4645
Stream.from() / fromSync()2626
Stream.pull() / pullSync()1717
Stream.pipeTo() / pipeToSync()1210
Consumer Functions2727
Stream.broadcast()2626
Stream.share() / shareSync()2222
Stream.duplex()1414
Stream.merge()77
Stream.tap() / tapSync()44
Protocol Symbols66
Total207207

Coverage: 100% of specified requirements are tested.