Skip to content

Commit 51d97bf

Browse files
committed
stream: ensure errorEmitted is always set
1 parent 885c644 commit 51d97bf

File tree

3 files changed

+48
-4
lines changed

3 files changed

+48
-4
lines changed

lib/_stream_writable.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -429,13 +429,11 @@ function onwriteError(stream, state, sync, er, cb) {
429429
// This can emit finish, and it will always happen
430430
// after error
431431
process.nextTick(finishMaybe, stream, state);
432-
stream._writableState.errorEmitted = true;
433432
errorOrDestroy(stream, er);
434433
} else {
435434
// The caller expect this to happen before if
436435
// it is async
437436
cb(er);
438-
stream._writableState.errorEmitted = true;
439437
errorOrDestroy(stream, er);
440438
// This can emit finish, but finish must
441439
// always follow error

lib/internal/streams/destroy.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,14 @@ function errorOrDestroy(stream, err) {
101101
const rState = stream._readableState;
102102
const wState = stream._writableState;
103103

104-
if ((rState && rState.autoDestroy) || (wState && wState.autoDestroy))
104+
if ((rState && rState.autoDestroy) || (wState && wState.autoDestroy)) {
105105
stream.destroy(err);
106-
else
106+
} else {
107+
if (wState) {
108+
wState.errorEmitted = true;
109+
}
107110
stream.emit('error', err);
111+
}
108112
}
109113

110114

test/parallel/test-stream2-writable.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,3 +402,45 @@ const helloWorldBuffer = Buffer.from('hello world');
402402
w.write(Buffer.allocUnsafe(1));
403403
w.end(Buffer.allocUnsafe(0));
404404
}
405+
406+
{
407+
// Verify that error is only emitted once when failing in _finish.
408+
const w = new W();
409+
410+
w._final = common.mustCall(function(cb) {
411+
cb(new Error('test'));
412+
});
413+
w._write = function(chunk, e, cb) {
414+
process.nextTick(cb);
415+
};
416+
w.once('error', common.mustCall((err) => {
417+
assert.strictEqual(w._writableState.errorEmitted, true);
418+
assert.strictEqual(err.message, 'test');
419+
w.on('error', common.mustNotCall());
420+
w.destroy(new Error());
421+
}));
422+
w.end();
423+
}
424+
425+
{
426+
// Verify that error is only emitted once when failing in write.
427+
const w = new W();
428+
w.on('error', common.mustCall((err) => {
429+
assert.strictEqual(w._writableState.errorEmitted, true);
430+
assert.strictEqual(err.code, 'ERR_STREAM_NULL_VALUES');
431+
}));
432+
w.write(null);
433+
w.destroy(new Error());
434+
}
435+
436+
{
437+
// Verify that error is only emitted once when failing in write after end.
438+
const w = new W();
439+
w.on('error', common.mustCall((err) => {
440+
assert.strictEqual(w._writableState.errorEmitted, true);
441+
assert.strictEqual(err.code, 'ERR_STREAM_WRITE_AFTER_END');
442+
}));
443+
w.end();
444+
w.write('hello');
445+
w.destroy(new Error());
446+
}

0 commit comments

Comments
 (0)