Skip to content

Commit be9f90e

Browse files
committed
stream: defer readable async iterator listener
Defer installing the readable listener for async iteration until read() returns null. This avoids listener dispatch on the common path where data is already buffered while preserving end-of-stream error handling. Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Assisted-by: openai:gpt-5.5
1 parent 13feb34 commit be9f90e

1 file changed

Lines changed: 9 additions & 2 deletions

File tree

lib/internal/streams/readable.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1380,6 +1380,7 @@ function streamToAsyncIterator(stream, options) {
13801380

13811381
async function* createAsyncIterator(stream, options) {
13821382
let callback = nop;
1383+
let isListening = false;
13831384

13841385
function next(resolve) {
13851386
if (this === stream) {
@@ -1390,15 +1391,18 @@ async function* createAsyncIterator(stream, options) {
13901391
}
13911392
}
13921393

1393-
stream.on('readable', next);
1394-
13951394
let error;
13961395
const cleanup = eos(stream, { writable: false }, (err) => {
13971396
error = err ? aggregateTwoErrors(error, err) : null;
13981397
callback();
13991398
callback = nop;
14001399
});
14011400

1401+
function setupReadable() {
1402+
isListening = true;
1403+
stream.on('readable', next);
1404+
}
1405+
14021406
try {
14031407
while (true) {
14041408
const chunk = stream.destroyed ? null : stream.read();
@@ -1409,6 +1413,9 @@ async function* createAsyncIterator(stream, options) {
14091413
} else if (error === null) {
14101414
return;
14111415
} else {
1416+
if (!isListening) {
1417+
setupReadable();
1418+
}
14121419
await new Promise(next);
14131420
}
14141421
}

0 commit comments

Comments
 (0)