Skip to content

Commit 8709a40

Browse files
ronagTrott
authored andcommitted
stream: use more accurate end-of-stream writable and readable detection
The value of stream.readable and stream.writable should not be used to detect whether a stream is Writable or Readable. Refs: #29395 PR-URL: #29409 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 872d803 commit 8709a40

File tree

2 files changed

+64
-2
lines changed

2 files changed

+64
-2
lines changed

lib/internal/streams/end-of-stream.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,18 @@ function isRequest(stream) {
1313
return stream.setHeader && typeof stream.abort === 'function';
1414
}
1515

16+
function isReadable(stream) {
17+
return typeof stream.readable === 'boolean' ||
18+
typeof stream.readableEnded === 'boolean' ||
19+
!!stream._readableState;
20+
}
21+
22+
function isWritable(stream) {
23+
return typeof stream.writable === 'boolean' ||
24+
typeof stream.writableEnded === 'boolean' ||
25+
!!stream._writableState;
26+
}
27+
1628
function eos(stream, opts, callback) {
1729
if (arguments.length === 2) {
1830
callback = opts;
@@ -47,8 +59,10 @@ function eos(stream, opts, callback) {
4759
};
4860
}
4961

50-
let readable = opts.readable || (opts.readable !== false && stream.readable);
51-
let writable = opts.writable || (opts.writable !== false && stream.writable);
62+
let readable = opts.readable ||
63+
(opts.readable !== false && isReadable(stream));
64+
let writable = opts.writable ||
65+
(opts.writable !== false && isWritable(stream));
5266

5367
const onlegacyfinish = () => {
5468
if (!stream.writable) onfinish();

test/parallel/test-stream-finished.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,3 +318,51 @@ const { promisify } = require('util');
318318
}));
319319
r.destroy();
320320
}
321+
322+
{
323+
// Test is readable check through readable
324+
const streamLike = new EE();
325+
streamLike.readable = false;
326+
finished(streamLike, common.mustCall());
327+
streamLike.emit('end');
328+
}
329+
330+
{
331+
// Test is readable check through readableEnded
332+
const streamLike = new EE();
333+
streamLike.readableEnded = true;
334+
finished(streamLike, common.mustCall());
335+
streamLike.emit('end');
336+
}
337+
338+
{
339+
// Test is readable check through _readableState
340+
const streamLike = new EE();
341+
streamLike._readableState = {};
342+
finished(streamLike, common.mustCall());
343+
streamLike.emit('end');
344+
}
345+
346+
{
347+
// Test is writable check through writable
348+
const streamLike = new EE();
349+
streamLike.writable = false;
350+
finished(streamLike, common.mustCall());
351+
streamLike.emit('finish');
352+
}
353+
354+
{
355+
// Test is writable check through writableEnded
356+
const streamLike = new EE();
357+
streamLike.writableEnded = true;
358+
finished(streamLike, common.mustCall());
359+
streamLike.emit('finish');
360+
}
361+
362+
{
363+
// Test is writable check through _writableState
364+
const streamLike = new EE();
365+
streamLike._writableState = {};
366+
finished(streamLike, common.mustCall());
367+
streamLike.emit('finish');
368+
}

0 commit comments

Comments
 (0)