Skip to content

Commit 0e841b4

Browse files
committed
stream: don't emit 'data' after 'error' or 'close'
As per doc we should not emit further events after 'close' and only 'close' after 'error'. Fixes: #39630 PR-URL: #39639 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Antoine du Hamel <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
1 parent 8bfb4b9 commit 0e841b4

File tree

2 files changed

+86
-1
lines changed

2 files changed

+86
-1
lines changed

lib/internal/streams/readable.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,8 @@ function readableAddChunk(stream, chunk, encoding, addToFront) {
276276
if (addToFront) {
277277
if (state.endEmitted)
278278
errorOrDestroy(stream, new ERR_STREAM_UNSHIFT_AFTER_END_EVENT());
279+
else if (state.destroyed || state.errored)
280+
return false;
279281
else
280282
addChunk(stream, state, chunk, true);
281283
} else if (state.ended) {
@@ -316,6 +318,7 @@ function addChunk(stream, state, chunk, addToFront) {
316318
} else {
317319
state.awaitDrainWriters = null;
318320
}
321+
319322
state.dataEmitted = true;
320323
stream.emit('data', chunk);
321324
} else {
@@ -542,7 +545,7 @@ Readable.prototype.read = function(n) {
542545
endReadable(this);
543546
}
544547

545-
if (ret !== null) {
548+
if (ret !== null && !state.errorEmitted && !state.closeEmitted) {
546549
state.dataEmitted = true;
547550
this.emit('data', ret);
548551
}

test/parallel/test-stream-readable-destroy.js

+82
Original file line numberDiff line numberDiff line change
@@ -319,3 +319,85 @@ const assert = require('assert');
319319
})(), /AbortError/);
320320
setTimeout(() => controller.abort(), 0);
321321
}
322+
323+
{
324+
const read = new Readable({
325+
read() {
326+
},
327+
});
328+
329+
read.on('data', common.mustNotCall());
330+
read.on('error', common.mustCall((e) => {
331+
read.push('asd');
332+
read.read();
333+
}));
334+
read.on('close', common.mustCall((e) => {
335+
read.push('asd');
336+
read.read();
337+
}));
338+
read.destroy(new Error('asd'));
339+
}
340+
341+
{
342+
const read = new Readable({
343+
read() {
344+
},
345+
});
346+
347+
read.on('data', common.mustNotCall());
348+
read.on('close', common.mustCall((e) => {
349+
read.push('asd');
350+
read.read();
351+
}));
352+
read.destroy();
353+
}
354+
355+
{
356+
const read = new Readable({
357+
read() {
358+
},
359+
});
360+
361+
read.on('data', common.mustNotCall());
362+
read.on('close', common.mustCall((e) => {
363+
read.push('asd');
364+
read.unshift('asd');
365+
}));
366+
read.destroy();
367+
}
368+
369+
{
370+
const read = new Readable({
371+
read() {
372+
},
373+
});
374+
375+
read.on('data', common.mustNotCall());
376+
read.destroy();
377+
read.unshift('asd');
378+
}
379+
380+
{
381+
const read = new Readable({
382+
read() {
383+
},
384+
});
385+
386+
read.resume();
387+
read.on('data', common.mustNotCall());
388+
read.on('close', common.mustCall((e) => {
389+
read.push('asd');
390+
}));
391+
read.destroy();
392+
}
393+
394+
{
395+
const read = new Readable({
396+
read() {
397+
},
398+
});
399+
400+
read.on('data', common.mustNotCall());
401+
read.destroy();
402+
read.push('asd');
403+
}

0 commit comments

Comments
 (0)