Commit 82563d8c395 for nodejs

commit 82563d8c3959e6b4b845b42073b4bd2c0dc3abfd
Author: James M Snell <jasnell@gmail.com>
Date:   Sun Oct 4 01:33:51 2026 +0000

    stream: keep long-lived stream/iter objects in fast mode

    Object literals with `__proto__: null` are created in V8 dictionary
    mode. Create the objects that live as long as a stream and are used for
    every chunk with ObjectSetPrototypeOf() instead, as was done for the
    share and broadcast consumer state, so that they keep fast properties:

    - the iterators returned by push(), pull(), share(), shareSync() and
      broadcast() consumers, and the pull() consumer-cleanup wrapper,
    - the iterators and the cancellation context used by from()
      normalization,
    - the async wrapper share() uses for sync sources.

    Objects created per call or per chunk (iterator results, options bags,
    promise resolver records, single-use iterables) keep the literal form:
    for those, setting the prototype after creation costs more than it
    saves, about 2x slower in a create-and-read microbenchmark. The
    fromWritable() writer is also unchanged, since V8 keeps object literals
    with accessors in dictionary mode regardless.

    With 200,000 16-byte chunks, pipeTo() is about 3.5% faster and pull()
    with a transform or a signal about 1-1.5% faster. In
    benchmark/streams/iter-throughput-share*.js, share() and shareSync()
    improve by 1-4.5%; no benchmark regressed significantly.

    Assisted-by: OpenCode
    Signed-off-by: James M Snell <jasnell@gmail.com>
    PR-URL: https://github.com/nodejs/node/pull/66648
    Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
    Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>

diff --git a/lib/internal/streams/iter/broadcast.js b/lib/internal/streams/iter/broadcast.js
index cdf25021bbc..e862f8d2a7a 100644
--- a/lib/internal/streams/iter/broadcast.js
+++ b/lib/internal/streams/iter/broadcast.js
@@ -225,8 +225,7 @@ class BroadcastImpl {
     return {
       __proto__: null,
       [SymbolAsyncIterator]() {
-        return {
-          __proto__: null,
+        return ObjectSetPrototypeOf({
           next() {
             if (state.detached) {
               if (state.error !== kNoBroadcastError) {
@@ -284,7 +283,7 @@ class BroadcastImpl {
             detach();
             return kDone;
           },
-        };
+        }, null);
       },
     };
   }
diff --git a/lib/internal/streams/iter/from.js b/lib/internal/streams/iter/from.js
index e434ff9c253..9f39e0f614a 100644
--- a/lib/internal/streams/iter/from.js
+++ b/lib/internal/streams/iter/from.js
@@ -15,6 +15,7 @@ const {
   DataViewPrototypeGetByteLength,
   DataViewPrototypeGetByteOffset,
   FunctionPrototypeCall,
+  ObjectSetPrototypeOf,
   PromisePrototypeThen,
   PromiseResolve,
   PromiseWithResolvers,
@@ -68,13 +69,12 @@ const kNormalizationCancelled = Symbol('kNormalizationCancelled');
 const kFlushBatch = Symbol('kFlushBatch');

 function createNormalizationContext() {
-  return {
-    __proto__: null,
+  return ObjectSetPrototypeOf({
     cancelled: false,
     reason: undefined,
     resolve: null,
     suppressCleanup: false,
-  };
+  }, null);
 }

 function cancelNormalization(context, reason, suppressCleanup = false) {
@@ -112,8 +112,7 @@ async function waitForNormalization(value, context) {
 function createNormalizationIterator(createIterator) {
   const context = createNormalizationContext();
   const iterator = createIterator(context);
-  return {
-    __proto__: null,
+  return ObjectSetPrototypeOf({
     next(value) {
       return FunctionPrototypeCall(iterator.next, iterator, value);
     },
@@ -129,7 +128,7 @@ function createNormalizationIterator(createIterator) {
     [SymbolAsyncIterator]() {
       return this;
     },
-  };
+  }, null);
 }

 function createNormalizationSource(createIterator) {
@@ -386,8 +385,7 @@ function yieldNormalizationAbortable(source, context) {
         }
       }

-      return {
-        __proto__: null,
+      return ObjectSetPrototypeOf({
         async next() {
           if (completed) {
             return { __proto__: null, done: true, value: undefined };
@@ -433,7 +431,7 @@ function yieldNormalizationAbortable(source, context) {
         [SymbolAsyncIterator]() {
           return this;
         },
-      };
+      }, null);
     },
   };
 }
diff --git a/lib/internal/streams/iter/pull.js b/lib/internal/streams/iter/pull.js
index 176d8dbfc83..6dff97e42be 100644
--- a/lib/internal/streams/iter/pull.js
+++ b/lib/internal/streams/iter/pull.js
@@ -11,6 +11,7 @@ const {
   ArrayPrototypePush,
   ArrayPrototypeSlice,
   FunctionPrototypeCall,
+  ObjectSetPrototypeOf,
   PromisePrototypeThen,
   PromiseReject,
   PromiseResolve,
@@ -861,8 +862,7 @@ function pull(source, ...args) {
           yield* createAsyncPipeline(normalized, transforms, controller.signal);
         }
         const iterator = pipeline();
-        return {
-          __proto__: null,
+        return ObjectSetPrototypeOf({
           next(value) {
             return iterator.next(value);
           },
@@ -877,7 +877,7 @@ function pull(source, ...args) {
           [SymbolAsyncIterator]() {
             return this;
           },
-        };
+        }, null);
       }
       return createAbortablePullIterator(normalized, transforms, signal);
     },
@@ -907,8 +907,7 @@ function createAbortablePullIterator(source, transforms, signal) {
     throw error;
   }

-  return {
-    __proto__: null,
+  return ObjectSetPrototypeOf({
     next(value) {
       if (aborted) return PromiseReject(signal.reason);
       return PromisePrototypeThen(iterator.next(value), undefined, onRejected);
@@ -929,7 +928,7 @@ function createAbortablePullIterator(source, transforms, signal) {
     [SymbolAsyncIterator]() {
       return this;
     },
-  };
+  }, null);
 }

 // Keep ownership of a bonded consumer outside the transform pipeline so it can
@@ -986,8 +985,7 @@ function pullWithConsumerCleanup(source, transforms, signal) {
     __proto__: null,
     [SymbolAsyncIterator]() {
       const iterator = pipeline[SymbolAsyncIterator]();
-      return {
-        __proto__: null,
+      return ObjectSetPrototypeOf({
         next(value) {
           return PromisePrototypeThen(
             iterator.next(value),
@@ -1011,7 +1009,7 @@ function pullWithConsumerCleanup(source, transforms, signal) {
         [SymbolAsyncIterator]() {
           return this;
         },
-      };
+      }, null);
     },
   };
 }
diff --git a/lib/internal/streams/iter/push.js b/lib/internal/streams/iter/push.js
index 764a3afac92..039e6b9f39d 100644
--- a/lib/internal/streams/iter/push.js
+++ b/lib/internal/streams/iter/push.js
@@ -7,6 +7,7 @@

 const {
   ArrayPrototypePush,
+  ObjectSetPrototypeOf,
   PromisePrototypeThen,
   PromiseReject,
   PromiseResolve,
@@ -733,8 +734,7 @@ function createReadable(queue) {
   return {
     __proto__: null,
     [SymbolAsyncIterator]() {
-      return {
-        __proto__: null,
+      return ObjectSetPrototypeOf({
         async next() {
           return queue.read();
         },
@@ -746,7 +746,7 @@ function createReadable(queue) {
           queue.consumerThrow(error);
           throw error;
         },
-      };
+      }, null);
     },
   };
 }
diff --git a/lib/internal/streams/iter/share.js b/lib/internal/streams/iter/share.js
index 6e9881b682a..a61d4627ad5 100644
--- a/lib/internal/streams/iter/share.js
+++ b/lib/internal/streams/iter/share.js
@@ -235,8 +235,7 @@ class ShareImpl {
           }
         };

-        return {
-          __proto__: null,
+        return ObjectSetPrototypeOf({
           next() {
             const next = PromisePrototypeThen(
               state.pendingNext,
@@ -266,7 +265,7 @@ class ShareImpl {
             }
             return { __proto__: null, done: true, value: undefined };
           },
-        };
+        }, null);
       },
     };
   }
@@ -401,8 +400,7 @@ class ShareImpl {
           } else if (isSyncIterable(this.#source)) {
             const syncIterator =
               this.#source[SymbolIterator]();
-            this.#sourceIterator = {
-              __proto__: null,
+            this.#sourceIterator = ObjectSetPrototypeOf({
               async next() {
                 return syncIterator.next();
               },
@@ -410,7 +408,7 @@ class ShareImpl {
                 return syncIterator.return?.() ??
                        { __proto__: null, done: true, value: undefined };
               },
-            };
+            }, null);
           } else {
             throw new ERR_INVALID_ARG_TYPE(
               'source', ['AsyncIterable', 'Iterable'], this.#source);
@@ -592,8 +590,7 @@ class SyncShareImpl {
     return {
       __proto__: null,
       [SymbolIterator]() {
-        return {
-          __proto__: null,
+        return ObjectSetPrototypeOf({
           next() {
             if (state.detached) {
               if (state.error !== kNoShareError) throw state.error;
@@ -710,7 +707,7 @@ class SyncShareImpl {
             }
             return { __proto__: null, done: true, value: undefined };
           },
-        };
+        }, null);
       },
     };
   }