diff --git a/lib/internal/streams/destroy.js b/lib/internal/streams/destroy.js index 06c74db830ed02..2f543f2d36bace 100644 --- a/lib/internal/streams/destroy.js +++ b/lib/internal/streams/destroy.js @@ -285,10 +285,14 @@ function constructNT(stream) { then.call( result, function() { - process.nextTick(onConstruct, null); + if (!called) { + process.nextTick(onConstruct, null); + } }, function(err) { - process.nextTick(onConstruct, err); + if (!called) { + process.nextTick(onConstruct, err); + } }); } } diff --git a/lib/internal/streams/writable.js b/lib/internal/streams/writable.js index f41cc183f0939a..d0d4e7fb615205 100644 --- a/lib/internal/streams/writable.js +++ b/lib/internal/streams/writable.js @@ -698,10 +698,14 @@ function callFinal(stream, state) { then.call( result, function() { - process.nextTick(onFinish, null); + if (!called) { + process.nextTick(onFinish, null); + } }, function(err) { - process.nextTick(onFinish, err); + if (!called) { + process.nextTick(onFinish, err); + } }); } } diff --git a/test/parallel/test-stream-construct-async-error.js b/test/parallel/test-stream-construct-async-error.js index 8101ec93fc0d74..c8ca293f1b08e3 100644 --- a/test/parallel/test-stream-construct-async-error.js +++ b/test/parallel/test-stream-construct-async-error.js @@ -9,26 +9,6 @@ const { const { setTimeout } = require('timers/promises'); const assert = require('assert'); -{ - class Foo extends Duplex { - async _construct(cb) { - // eslint-disable-next-line no-restricted-syntax - await setTimeout(common.platformTimeout(1)); - cb(); - throw new Error('boom'); - } - } - - const foo = new Foo(); - foo.on('error', common.expectsError({ - message: 'boom' - })); - foo.on('close', common.mustCall(() => { - assert(foo._writableState.constructed); - assert(foo._readableState.constructed); - })); -} - { class Foo extends Duplex { async _destroy(err, cb) { @@ -98,9 +78,7 @@ const assert = require('assert'); const foo = new Foo(); foo.write('test', common.mustCall()); - foo.on('error', common.expectsError({ - code: 'ERR_MULTIPLE_CALLBACK' - })); + foo.on('error', common.mustNotCall()); } { diff --git a/test/parallel/test-stream-writable-final-async.js b/test/parallel/test-stream-writable-final-async.js new file mode 100644 index 00000000000000..5571b794fd4fbd --- /dev/null +++ b/test/parallel/test-stream-writable-final-async.js @@ -0,0 +1,26 @@ +'use strict'; + +const common = require('../common'); +const { + Duplex, +} = require('stream'); +const { setTimeout } = require('timers/promises'); + +{ + class Foo extends Duplex { + async _final(callback) { + // eslint-disable-next-line no-restricted-syntax + await setTimeout(common.platformTimeout(1)); + callback(); + } + + _read() {} + } + + const foo = new Foo(); + foo._write = common.mustCall((chunk, encoding, cb) => { + cb(); + }); + foo.end('test', common.mustCall()); + foo.on('error', common.mustNotCall()); +}