From 02c76626d18117df7e932fbf55a37ea01f19fb8a Mon Sep 17 00:00:00 2001 From: jakecastelli <959672929@qq.com> Date: Thu, 13 Jun 2024 16:49:25 +0930 Subject: [PATCH 1/5] stream: callback should be called when pendingcb is 0 Fixes: https://github.com/nodejs/node/issues/46170 --- lib/internal/streams/end-of-stream.js | 4 +++- test/parallel/test-stream-finished.js | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/internal/streams/end-of-stream.js b/lib/internal/streams/end-of-stream.js index dd8e4e5d8a0c7e..ccf6f6bd6b8d11 100644 --- a/lib/internal/streams/end-of-stream.js +++ b/lib/internal/streams/end-of-stream.js @@ -215,7 +215,9 @@ function eos(stream, options, callback) { (!willEmitClose || isReadable(stream)) && (writableFinished || isWritable(stream) === false) ) { - process.nextTick(onclosed); + if (wState && wState.pendingcb === 0) { + process.nextTick(onclosed); + } } else if ( !writable && (!willEmitClose || isWritable(stream)) && diff --git a/test/parallel/test-stream-finished.js b/test/parallel/test-stream-finished.js index c7513805e7ac6f..82e5282ad452a4 100644 --- a/test/parallel/test-stream-finished.js +++ b/test/parallel/test-stream-finished.js @@ -679,5 +679,6 @@ testClosed((opts) => new Writable({ write() {}, ...opts })); finished(stream, { readable: false }, common.mustCall((err) => { assert(!err); + assert.strictEqual(stream._writableState.pendingcb, 0) })); } From 84580eda83a249de4e23652616a8ee4ce5b25d46 Mon Sep 17 00:00:00 2001 From: jakecastelli <959672929@qq.com> Date: Thu, 13 Jun 2024 17:03:55 +0930 Subject: [PATCH 2/5] fixup! linting --- lib/internal/streams/end-of-stream.js | 7 +++---- test/parallel/test-stream-finished.js | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/internal/streams/end-of-stream.js b/lib/internal/streams/end-of-stream.js index ccf6f6bd6b8d11..2b0eea0b0f98e9 100644 --- a/lib/internal/streams/end-of-stream.js +++ b/lib/internal/streams/end-of-stream.js @@ -213,11 +213,10 @@ function eos(stream, options, callback) { } else if ( !readable && (!willEmitClose || isReadable(stream)) && - (writableFinished || isWritable(stream) === false) + (writableFinished || isWritable(stream) === false) && + wState && wState.pendingcb === 0 ) { - if (wState && wState.pendingcb === 0) { - process.nextTick(onclosed); - } + process.nextTick(onclosed); } else if ( !writable && (!willEmitClose || isWritable(stream)) && diff --git a/test/parallel/test-stream-finished.js b/test/parallel/test-stream-finished.js index 82e5282ad452a4..d1b30079b7dd2c 100644 --- a/test/parallel/test-stream-finished.js +++ b/test/parallel/test-stream-finished.js @@ -679,6 +679,6 @@ testClosed((opts) => new Writable({ write() {}, ...opts })); finished(stream, { readable: false }, common.mustCall((err) => { assert(!err); - assert.strictEqual(stream._writableState.pendingcb, 0) + assert.strictEqual(stream._writableState.pendingcb, 0); })); } From b052a0cede9c058e85805c0891a45161b489319b Mon Sep 17 00:00:00 2001 From: jakecastelli <959672929@qq.com> Date: Thu, 13 Jun 2024 19:54:12 +0930 Subject: [PATCH 3/5] fixup! expand the test Make sure the callback in `write` is called before the callback in finished --- test/parallel/test-stream-finished.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/parallel/test-stream-finished.js b/test/parallel/test-stream-finished.js index d1b30079b7dd2c..010f953f099f8e 100644 --- a/test/parallel/test-stream-finished.js +++ b/test/parallel/test-stream-finished.js @@ -669,9 +669,13 @@ testClosed((opts) => new Writable({ write() {}, ...opts })); } { + let isCalld = false; const stream = new Duplex({ write(chunk, enc, cb) { - setImmediate(cb); + setImmediate(() => { + isCalld = true; + cb(); + }); } }); @@ -679,6 +683,7 @@ testClosed((opts) => new Writable({ write() {}, ...opts })); finished(stream, { readable: false }, common.mustCall((err) => { assert(!err); + assert.strictEqual(isCalld, true); assert.strictEqual(stream._writableState.pendingcb, 0); })); } From 39a543737215d73a74e1e7615f6aeb3d6f5e7279 Mon Sep 17 00:00:00 2001 From: jakecastelli <38635403+jakecastelli@users.noreply.github.com> Date: Thu, 13 Jun 2024 20:26:07 +0930 Subject: [PATCH 4/5] Update lib/internal/streams/end-of-stream.js Co-authored-by: Robert Nagy --- lib/internal/streams/end-of-stream.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/streams/end-of-stream.js b/lib/internal/streams/end-of-stream.js index 2b0eea0b0f98e9..723292faf5bd3a 100644 --- a/lib/internal/streams/end-of-stream.js +++ b/lib/internal/streams/end-of-stream.js @@ -214,7 +214,7 @@ function eos(stream, options, callback) { !readable && (!willEmitClose || isReadable(stream)) && (writableFinished || isWritable(stream) === false) && - wState && wState.pendingcb === 0 + (wState == null || wState.pendingcb === 0) ) { process.nextTick(onclosed); } else if ( From ce31bd07efee9f9210d2347165bd2a6e78d8de62 Mon Sep 17 00:00:00 2001 From: jakecastelli <959672929@qq.com> Date: Fri, 14 Jun 2024 13:48:40 +0930 Subject: [PATCH 5/5] fixup! typo --- test/parallel/test-stream-finished.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/parallel/test-stream-finished.js b/test/parallel/test-stream-finished.js index 010f953f099f8e..6820ac18cf4b5c 100644 --- a/test/parallel/test-stream-finished.js +++ b/test/parallel/test-stream-finished.js @@ -669,11 +669,11 @@ testClosed((opts) => new Writable({ write() {}, ...opts })); } { - let isCalld = false; + let isCalled = false; const stream = new Duplex({ write(chunk, enc, cb) { setImmediate(() => { - isCalld = true; + isCalled = true; cb(); }); } @@ -683,7 +683,7 @@ testClosed((opts) => new Writable({ write() {}, ...opts })); finished(stream, { readable: false }, common.mustCall((err) => { assert(!err); - assert.strictEqual(isCalld, true); + assert.strictEqual(isCalled, true); assert.strictEqual(stream._writableState.pendingcb, 0); })); }