Commit 89fef14f69a for nodejs

commit 89fef14f69afcd1532e711bb98530af7d9799c1d
Author: James M Snell <jasnell@gmail.com>
Date:   Sat Oct 3 15:13:47 2026 +0000

    doc: document stream/iter behaviors and Node.js extensions

    Document behaviors that were previously only visible in the code:

    - the writer "closing" state after end()/endSync(),
    - writes made from argument conversion being ordered first,
    - zero-length push() writes not being buffered,
    - broadcast.cancel() also closing the paired writer,
    - merge() not waiting for the other sources' cleanup on error,
    - the options argument passed to the tap() callback,
    - FileHandle writer() ordering of un-awaited writes, and the lazy
      locking of FileHandle pull() and pullSync().

    Also link the WinterTC Iterable Streams API draft and list the exports
    that are Node.js extensions to it.

    Assisted-by: OpenCode
    Signed-off-by: James M Snell <jasnell@gmail.com>
    PR-URL: https://github.com/nodejs/node/pull/66483
    Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>

diff --git a/doc/api/fs.md b/doc/api/fs.md
index f49e131ee7b..e327a330a14 100644
--- a/doc/api/fs.md
+++ b/doc/api/fs.md
@@ -412,8 +412,9 @@ Return the file contents as an async iterable using the
 chunks (default 128 KB). If transforms are provided, they are applied
 via [`stream/iter pull()`][].

-The file handle is locked while the iterable is being consumed and unlocked
-when iteration completes, an error occurs, or the consumer breaks.
+The file handle is locked from the first read of the iterable, and unlocked
+when iteration completes, an error occurs, or the consumer breaks. An iterable
+that is never read does not lock the file handle.

 This function is only available when the `--experimental-stream-iter` flag is
 enabled.
@@ -487,8 +488,8 @@ Synchronous counterpart of [`filehandle.pull()`][]. Returns a sync iterable
 that reads the file using synchronous I/O on the main thread. Reads are
 performed in `chunkSize`-byte chunks (default 128 KB).

-The file handle is locked while the iterable is being consumed. Unlike the
-async `pull()`, this method does not support `AbortSignal` since all
+The file handle is locked from the first read of the iterable until iteration
+ends, as with [`filehandle.pull()`][]. Unlike the async `pull()`, this method does not support `AbortSignal` since all
 operations are synchronous.

 This function is only available when the `--experimental-stream-iter` flag is
@@ -1134,6 +1135,11 @@ The writer supports both `Symbol.asyncDispose` and `Symbol.dispose`:
   for it to complete.
 * `using w = fh.writer()` — calls `fail()` unconditionally.

+Async writes (`write()` and `writev()`) that are started without awaiting the
+previous one are performed one at a time, in the order they were called, so
+they never overlap in the file. A queued write is not performed if the writer
+fails, or its `signal` aborts, before its turn.
+
 The `writeSync()` and `writevSync()` methods enable the try-sync fast path
 used by [`stream/iter pipeTo()`][]. When the reader's chunk size matches the
 writer's `chunkSize`, all writes in a `pipeTo()` pipeline complete
diff --git a/doc/api/stream_iter.md b/doc/api/stream_iter.md
index fb4a26a6cd6..0e78c64f202 100644
--- a/doc/api/stream_iter.md
+++ b/doc/api/stream_iter.md
@@ -18,6 +18,13 @@ functions or objects with a `transform` method.
 Data flows in **batches** ({Uint8Array\[]} per iteration) to amortize the cost
 of async operations.

+The module implements the WinterTC [Iterable Streams API][] draft. The
+classic stream interop functions ([`fromReadable()`][], [`fromWritable()`][],
+[`toReadable()`][], [`toReadableSync()`][] and [`toWritable()`][]),
+[`Broadcast.from()`][], [`Share.from()`][], [`SyncShare.fromSync()`][] and the
+protocol symbols exported by `Stream` are Node.js extensions that are not part
+of the draft.
+
 ```mjs
 import { from, pull, text } from 'node:stream/iter';
 import { compressGzip, decompressGzip } from 'node:zlib/iter';
@@ -407,6 +414,18 @@ converted to a `USVString` and then UTF-8 encoded. `writev()` and
 chunks. Writer option dictionaries treat `null` as an empty dictionary and
 ignore unknown members.

+Arguments are converted before the write itself starts. If the conversion runs
+user code (for example a `toString()` method, or the iterator of a `writev()`
+argument) that writes to the same writer, those writes are ordered before the
+write whose argument is being converted, and they count against the same
+backpressure limits.
+
+After `end()` or `endSync()` has been called, and until all buffered data has
+been consumed, the writer is _closing_. While closing, `canWrite` is `null`,
+`write()` and `writev()` reject with a `TypeError`, `writeSync()` and
+`writevSync()` return `false`, `endSync()` returns `-1`, and calling `end()`
+again returns the same promise as the first call.
+
 Each async method has a synchronous `*Sync` counterpart designed for a
 try-fallback pattern: attempt the fast synchronous path first, and fall back
 to the async version only when the synchronous call indicates it could not
@@ -869,6 +888,10 @@ run().catch(console.error);

 The writer returned by `push()` conforms to the \[Writer interface]\[].

+Zero-length chunks are accepted without being buffered: they are not delivered
+to the consumer, and `writeSync()` and `write()` report success for them even
+when backpressure is active.
+
 ## Duplex channels

 ### `duplex([options])`
@@ -1275,7 +1298,12 @@ added:

 Merge multiple async iterables by yielding batches in temporal order
 (whichever source produces data first). All sources are consumed
-concurrently.
+concurrently, with at most one pending `next()` call per source.
+
+If a source fails, the returned iterable rejects with its error. `merge()`
+calls `return()` on the other sources but does not wait for it to settle: an
+async generator source that is suspended in an `await` only runs its cleanup
+once that `await` completes.

 ```mjs
 import { from, merge, text } from 'node:stream/iter';
@@ -1303,8 +1331,9 @@ added:
  - v24.20.0
 -->

-* `callback` {Function} `(chunks) => void` Called with each batch and with
-  `null` when the source ends.
+* `callback` {Function} `(chunks, options) => void` Called with each batch and
+  with `null` when the source ends. `options.signal` is the pipeline's
+  {AbortSignal}.
 * Returns: {Function} A stateless transform.

 Create a pass-through transform that observes batches without modifying them.
@@ -1433,6 +1462,10 @@ run().catch(console.error);
 Cancel the broadcast. If `reason` is provided, all consumers reject with that
 exact reason. If it is omitted, consumers complete normally.

+Cancelling also closes the paired writer: afterwards its `canWrite` is `null`
+and `write()` rejects with a `TypeError`. This lets a [`Broadcast.from()`][]
+pump stop pulling from its source.
+
 #### `broadcast.consumerCount`

 * {number}
@@ -2342,13 +2375,19 @@ const stream = fromSync(new Greeting('world'));
 console.log(textSync(stream)); // 'hello world'
 ```

+[Iterable Streams API]: https://iter-streams.proposal.wintertc.org/
 [`--experimental-stream-iter`]: cli.md#--experimental-stream-iter
+[`Broadcast.from()`]: #broadcastfrominput-options
+[`Share.from()`]: #static-method-sharefrominput-options
+[`SyncShare.fromSync()`]: #static-method-syncsharefromsyncinput-options
 [`array()`]: #arraysource-options
 [`arrayBuffer()`]: #arraybuffersource-options
 [`bytes()`]: #bytessource-options
 [`dump()`]: #drainsource-options
 [`from()`]: #frominput
+[`fromReadable()`]: #fromreadablereadable
 [`fromSync()`]: #fromsyncinput
+[`fromWritable()`]: #fromwritablewritable-options
 [`node:zlib/iter`]: zlib.md#iterable-compression
 [`ondrain()`]: #ondraindrainable
 [`pipeTo()`]: #pipetosource-transforms-writer-options
@@ -2360,3 +2399,6 @@ console.log(textSync(stream)); // 'hello world'
 [`tap()`]: #tapcallback
 [`text()`]: #textsource-options
 [`toAsyncStreamable`]: #streamtoasyncstreamable
+[`toReadable()`]: #toreadablesource-options
+[`toReadableSync()`]: #toreadablesyncsource-options
+[`toWritable()`]: #towritablewriter