diff --git a/lib/internal/process/stdio.js b/lib/internal/process/stdio.js index bf5f6df15f123c..46c2ba4e9ca35d 100644 --- a/lib/internal/process/stdio.js +++ b/lib/internal/process/stdio.js @@ -2,7 +2,26 @@ exports.getMainThreadStdio = getMainThreadStdio; -function dummyDestroy(err, cb) { cb(err); } +function dummyDestroy(err, cb) { + // SyncWriteStream does not use the stream + // destroy mechanism for some legacy reason. + // TODO(mcollina): remove when + // https://github.com/nodejs/node/pull/26690 lands. + if (typeof cb === 'function') { + cb(err); + } + + // We need to emit 'close' anyway so that the closing + // of the stream is observable. We just make sure we + // are not going to do it twice. + // The 'close' event is needed so that finished and + // pipeline work correctly. + if (!this._writableState.emitClose) { + process.nextTick(() => { + this.emit('close'); + }); + } +} function getMainThreadStdio() { var stdin; diff --git a/test/parallel/test-stdout-pipeline-destroy.js b/test/parallel/test-stdout-pipeline-destroy.js new file mode 100644 index 00000000000000..291579cf69d3d4 --- /dev/null +++ b/test/parallel/test-stdout-pipeline-destroy.js @@ -0,0 +1,31 @@ +'use strict'; + +const common = require('../common'); +const { Transform, Readable, pipeline } = require('stream'); +const assert = require('assert'); + +const reader = new Readable({ + read(size) { this.push('foo'); } +}); + +let count = 0; + +const err = new Error('this-error-gets-hidden'); + +const transform = new Transform({ + transform(chunk, enc, cb) { + if (count++ >= 5) + this.emit('error', err); + else + cb(null, count.toString() + '\n'); + } +}); + +pipeline( + reader, + transform, + process.stdout, + common.mustCall((e) => { + assert.strictEqual(e, err); + }) +);