Skip to content

Commit 536d088

Browse files
Stewart Addisontargos
Stewart Addison
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 Backport-PR-URL: #31345 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 4fd4a73 commit 536d088

File tree

2 files changed

+65
-2
lines changed

2 files changed

+65
-2
lines changed

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

+16-2
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;
@@ -28,8 +40,10 @@ function eos(stream, opts, callback) {
2840

2941
callback = once(callback);
3042

31-
let readable = opts.readable || (opts.readable !== false && stream.readable);
32-
let writable = opts.writable || (opts.writable !== false && stream.writable);
43+
let readable = opts.readable ||
44+
(opts.readable !== false && isReadable(stream));
45+
let writable = opts.writable ||
46+
(opts.writable !== false && isWritable(stream));
3347

3448
const onlegacyfinish = () => {
3549
if (!stream.writable) onfinish();

test/parallel/test-stream-finished.js

+49
Original file line numberDiff line numberDiff line change
@@ -184,3 +184,52 @@ const { promisify } = require('util');
184184
finished(streamLike, common.mustCall);
185185
streamLike.emit('close');
186186
}
187+
188+
189+
{
190+
// Test is readable check through readable
191+
const streamLike = new EE();
192+
streamLike.readable = false;
193+
finished(streamLike, common.mustCall());
194+
streamLike.emit('end');
195+
}
196+
197+
{
198+
// Test is readable check through readableEnded
199+
const streamLike = new EE();
200+
streamLike.readableEnded = true;
201+
finished(streamLike, common.mustCall());
202+
streamLike.emit('end');
203+
}
204+
205+
{
206+
// Test is readable check through _readableState
207+
const streamLike = new EE();
208+
streamLike._readableState = {};
209+
finished(streamLike, common.mustCall());
210+
streamLike.emit('end');
211+
}
212+
213+
{
214+
// Test is writable check through writable
215+
const streamLike = new EE();
216+
streamLike.writable = false;
217+
finished(streamLike, common.mustCall());
218+
streamLike.emit('finish');
219+
}
220+
221+
{
222+
// Test is writable check through writableEnded
223+
const streamLike = new EE();
224+
streamLike.writableEnded = true;
225+
finished(streamLike, common.mustCall());
226+
streamLike.emit('finish');
227+
}
228+
229+
{
230+
// Test is writable check through _writableState
231+
const streamLike = new EE();
232+
streamLike._writableState = {};
233+
finished(streamLike, common.mustCall());
234+
streamLike.emit('finish');
235+
}

0 commit comments

Comments
 (0)