diff --git a/lib/_stream_writable.js b/lib/_stream_writable.js index 916e9b87d9c17a..740e3c298bec83 100644 --- a/lib/_stream_writable.js +++ b/lib/_stream_writable.js @@ -185,6 +185,9 @@ function WritableState(options, stream, isDuplex) { // True if close has been emitted or would have been emitted // depending on emitClose. this.closeEmitted = false; + + // True indicates have invoked error callback + this.invokeError = false; } function resetBuffer(state) { @@ -320,6 +323,7 @@ Writable.prototype.write = function(chunk, encoding, cb) { } if (err) { + this.invokeError = true; process.nextTick(cb, err); errorOrDestroy(this, err, true); return false; @@ -587,7 +591,8 @@ Writable.prototype.end = function(chunk, encoding, cb) { } if (chunk !== null && chunk !== undefined) - this.write(chunk, encoding); + !state.ending ? this.write(chunk, encoding) : + this.write(chunk, encoding, cb); // .end() fully uncorks. if (state.corked) { @@ -610,7 +615,7 @@ Writable.prototype.end = function(chunk, encoding, cb) { err = new ERR_STREAM_DESTROYED('end'); } - if (typeof cb === 'function') { + if (typeof cb === 'function' && !this.invokeError) { if (err || state.finished) process.nextTick(cb, err); else diff --git a/test/parallel/test-stream-write-propagate-end-cb.js b/test/parallel/test-stream-write-propagate-end-cb.js new file mode 100644 index 00000000000000..eac297218f6a9b --- /dev/null +++ b/test/parallel/test-stream-write-propagate-end-cb.js @@ -0,0 +1,16 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const { Writable } = require('stream'); +{ + const w = new Writable(); + w.end(); + + w.end('asd', common.mustCall((err) => { + assert.strictEqual(err.code, 'ERR_STREAM_WRITE_AFTER_END'); + })); + + w.on('error', common.mustCall((err) => { + assert.strictEqual(err.code, 'ERR_STREAM_WRITE_AFTER_END'); + })); +}