Skip to content

stream: use state.ending to see if stream called end()

Calling writable.end() will probably synchronously call writable.write(), in such a situation the state.ended is false and writable.write() doesn't trigger writeAfterEnd().

There is an example as below:

const { Writable } = require('stream');

let data = '';
const w = new Writable({
  write: function(chunk, encoding, cb) {
    process.nextTick(() => {
      data += chunk;
      cb();
    });
  },
});

w.on('prefinish', () => {
  // w.write('prefinish');
});
w.on('finish', () => {
  w.write('finish');
});

w.end(() => {
  console.log(data);
});

when 'prefinish' listener doesn't call w.write(), w.end() will synchronously emit 'finish' event. The console's output is: finish. when 'prefinish' listener calls w.write(), the 'finish' event will be asynchronously emitted. The w.write() that called by the 'finish' listener will trigger writeAfterEnd() and throw a Error.

I think using state.ended to decide whether to trigger writeAfterEnd is diffcult to understand and is somewhat unreasonable.

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • commit message follows commit guidelines
Affected core subsystem(s)

stream

Merge request reports

Loading