current commit
260718.5 · stream: resume flow when an errored pipe destination is removed
'use strict';
const common = require('../common');

// Regression test for https://github.com/nodejs/node/issues/53185
// When a source is piped to multiple destinations and one destination errors
// synchronously in `_write`, the source must keep flowing to the remaining
// healthy destination(s) instead of stalling forever.

const assert = require('assert');
const { PassThrough, Writable, finished } = require('stream');

const source = new PassThrough({ highWaterMark: 16 * 1024 });

// A destination that errors synchronously on its first write.
const failing = new Writable({
  highWaterMark: 16 * 1024,
  write(chunk, encoding, callback) {
    callback(new Error('boom'));
  },
});
failing.on('error', common.mustCall());

// A healthy destination that counts everything it receives.
let received = 0;
const healthy = new Writable({
  highWaterMark: 16 * 1024,
  write(chunk, encoding, callback) {
    received += chunk.length;
    callback();
  },
});

source.pipe(failing);
source.pipe(healthy);

// Two chunks each larger than the highWaterMark so that `write()` returns
// false and the source is paused awaiting a drain.
const chunk = Buffer.alloc(20000, 'a');
source.write(chunk);
source.write(chunk);
source.end();

finished(healthy, common.mustSucceed(() => {
  // Without the fix, the errored destination stays in the source's
  // awaitDrainWriters set, the source never resumes, and `healthy` only
  // receives the first chunk.
  assert.strictEqual(received, chunk.length * 2);
}));