From 1fc6382942db5f177305836168c6baba45f8c82c Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Sat, 10 Jul 2021 00:37:09 +0200 Subject: [PATCH] stream: don't emit prefinish after error or close PR-URL: https://github.com/nodejs/node/pull/39332 Reviewed-By: Matteo Collina Reviewed-By: James M Snell --- lib/internal/streams/writable.js | 10 ++++----- .../test-stream-writable-final-destroy.js | 21 +++++++++++++++++++ 2 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 test/parallel/test-stream-writable-final-destroy.js diff --git a/lib/internal/streams/writable.js b/lib/internal/streams/writable.js index 03f63b16bd04ff..91d1230f1c7d9a 100644 --- a/lib/internal/streams/writable.js +++ b/lib/internal/streams/writable.js @@ -654,7 +654,9 @@ function needFinish(state) { !state.errored && state.buffered.length === 0 && !state.finished && - !state.writing); + !state.writing && + !state.errorEmitted && + !state.closeEmitted); } function callFinal(stream, state) { @@ -685,7 +687,7 @@ function callFinal(stream, state) { then.call( result, function() { - if (state.prefinished) + if (state.prefinished || !needFinish(state)) return; state.prefinish = true; process.nextTick(() => stream.emit('prefinish')); @@ -735,10 +737,6 @@ function finishMaybe(stream, state, sync) { function finish(stream, state) { state.pendingcb--; - // TODO (ronag): Unify with needFinish. - if (state.errorEmitted || state.closeEmitted) - return; - state.finished = true; const onfinishCallbacks = state[kOnFinished].splice(0); diff --git a/test/parallel/test-stream-writable-final-destroy.js b/test/parallel/test-stream-writable-final-destroy.js new file mode 100644 index 00000000000000..8d3bf72c89126f --- /dev/null +++ b/test/parallel/test-stream-writable-final-destroy.js @@ -0,0 +1,21 @@ +'use strict'; +const common = require('../common'); + +const { Writable } = require('stream'); + +{ + const w = new Writable({ + write(chunk, encoding, callback) { + callback(null); + }, + final(callback) { + queueMicrotask(callback); + } + }); + w.end(); + w.destroy(); + + w.on('prefinish', common.mustNotCall()); + w.on('finish', common.mustNotCall()); + w.on('close', common.mustCall()); +}