From cc125b475f7035cb793d59382a56ac2597224964 Mon Sep 17 00:00:00 2001 From: Kai Tamkun <13513421+heimskr@users.noreply.github.com> Date: Fri, 6 Dec 2024 23:59:47 -0800 Subject: [PATCH] Fix missing "readable" events (#15629) --- src/js/node/stream.ts | 12 +++++++++--- test/js/node/stream/node-stream.test.js | 23 +++++++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/js/node/stream.ts b/src/js/node/stream.ts index 874031f49ed3ad..26ba3188a60bb4 100644 --- a/src/js/node/stream.ts +++ b/src/js/node/stream.ts @@ -5371,14 +5371,18 @@ function createNativeStreamReadable(Readable) { } if (isClosed) { - nativeReadable.push(null); + ProcessNextTick(() => { + nativeReadable.push(null); + }); } return remainder.byteLength > 0 ? remainder : undefined; } if (isClosed) { - nativeReadable.push(null); + ProcessNextTick(() => { + nativeReadable.push(null); + }); } return view; @@ -5390,7 +5394,9 @@ function createNativeStreamReadable(Readable) { } if (isClosed) { - nativeReadable.push(null); + ProcessNextTick(() => { + nativeReadable.push(null); + }); } return view; diff --git a/test/js/node/stream/node-stream.test.js b/test/js/node/stream/node-stream.test.js index 287aaf8f74cc4b..934b4a92bc1ebe 100644 --- a/test/js/node/stream/node-stream.test.js +++ b/test/js/node/stream/node-stream.test.js @@ -544,3 +544,26 @@ it("should emit prefinish on current tick", done => { done(); }); }); + +for (const size of [0x10, 0xffff, 0x10000, 0x1f000, 0x20000, 0x20010, 0x7ffff, 0x80000, 0xa0000, 0xa0010]) { + it(`should emit 'readable' with null data and 'close' exactly once each, 0x${size.toString(16)} bytes`, async () => { + const path = `${tmpdir()}/${Date.now()}.readable_and_close.txt`; + writeFileSync(path, new Uint8Array(size)); + const stream = createReadStream(path); + const close_resolvers = Promise.withResolvers(); + const readable_resolvers = Promise.withResolvers(); + + stream.on("close", () => { + close_resolvers.resolve(); + }); + + stream.on("readable", () => { + const data = stream.read(); + if (data === null) { + readable_resolvers.resolve(); + } + }); + + await Promise.all([close_resolvers.promise, readable_resolvers.promise]); + }); +}