Skip to content

Commit bca23b9

Browse files
ronagBridgeAR
authored andcommitted
stream: reset flowing state if no 'readable' or 'data' listeners
If we don't have any 'readable' or 'data' listeners and we are not about to resume. Then reset flowing state to initial null state. PR-URL: #31036Fixes: #24474 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com>
1 parent 1463214 commit bca23b9

3 files changed

Lines changed: 58 additions & 5 deletions

File tree

‎lib/_stream_readable.js‎

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const {
2828
ObjectDefineProperty,
2929
ObjectSetPrototypeOf,
3030
SymbolAsyncIterator,
31+
Symbol
3132
}=primordials;
3233

3334
module.exports=Readable;
@@ -51,6 +52,8 @@ const {
5152
ERR_STREAM_UNSHIFT_AFTER_END_EVENT
5253
}=require('internal/errors').codes;
5354

55+
constkPaused=Symbol('kPaused');
56+
5457
// Lazy loaded to improve the startup performance.
5558
letStringDecoder;
5659
letcreateReadableStreamAsyncIterator;
@@ -126,7 +129,7 @@ function ReadableState(options, stream, isDuplex) {
126129
this.emittedReadable=false;
127130
this.readableListening=false;
128131
this.resumeScheduled=false;
129-
this.paused=true;
132+
this[kPaused]=null;
130133

131134
// True if the error was already emitted and should not be thrown again
132135
this.errorEmitted=false;
@@ -170,6 +173,16 @@ ObjectDefineProperty(ReadableState.prototype, 'pipesCount', {
170173
}
171174
});
172175

176+
// Legacy property for `paused`
177+
ObjectDefineProperty(ReadableState.prototype,'paused',{
178+
get(){
179+
returnthis[kPaused]!==false;
180+
},
181+
set(value){
182+
this[kPaused]=!!value;
183+
}
184+
});
185+
173186
functionReadable(options){
174187
if(!(thisinstanceofReadable))
175188
returnnewReadable(options);
@@ -365,7 +378,8 @@ function chunkInvalid(state, chunk) {
365378

366379

367380
Readable.prototype.isPaused=function(){
368-
returnthis._readableState.flowing===false;
381+
conststate=this._readableState;
382+
returnstate[kPaused]===true||state.flowing===false;
369383
};
370384

371385
// Backwards compatibility.
@@ -962,14 +976,16 @@ function updateReadableListening(self) {
962976
conststate=self._readableState;
963977
state.readableListening=self.listenerCount('readable')>0;
964978

965-
if(state.resumeScheduled&&!state.paused){
979+
if(state.resumeScheduled&&state[kPaused]===false){
966980
// Flowing needs to be set to true now, otherwise
967981
// the upcoming resume will not flow.
968982
state.flowing=true;
969983

970984
// Crude way to check if we should resume
971985
}elseif(self.listenerCount('data')>0){
972986
self.resume();
987+
}elseif(!state.readableListening){
988+
state.flowing=null;
973989
}
974990
}
975991

@@ -990,7 +1006,7 @@ Readable.prototype.resume = function() {
9901006
state.flowing=!state.readableListening;
9911007
resume(this,state);
9921008
}
993-
state.paused=false;
1009+
state[kPaused]=false;
9941010
returnthis;
9951011
};
9961012

@@ -1021,7 +1037,7 @@ Readable.prototype.pause = function() {
10211037
this._readableState.flowing=false;
10221038
this.emit('pause');
10231039
}
1024-
this._readableState.paused=true;
1040+
this._readableState[kPaused]=true;
10251041
returnthis;
10261042
};
10271043

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
'use strict';
2+
constcommon=require('../common');
3+
4+
const{ Readable }=require('stream');
5+
6+
constreadable=newReadable({
7+
read(){}
8+
});
9+
10+
functionread(){}
11+
12+
readable.setEncoding('utf8');
13+
readable.on('readable',read);
14+
readable.removeListener('readable',read);
15+
16+
process.nextTick(function(){
17+
readable.on('data',common.mustCall());
18+
readable.push('hello');
19+
});

‎test/parallel/test-stream-readable-pause-and-resume.js‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22

33
constcommon=require('../common');
4+
constassert=require('assert');
45
const{ Readable }=require('stream');
56

67
letticks=18;
@@ -38,3 +39,20 @@ function readAndPause() {
3839

3940
rs.on('data',ondata);
4041
}
42+
43+
{
44+
constreadable=newReadable({
45+
read(){}
46+
});
47+
48+
functionread(){}
49+
50+
readable.setEncoding('utf8');
51+
readable.on('readable',read);
52+
readable.removeListener('readable',read);
53+
readable.pause();
54+
55+
process.nextTick(function(){
56+
assert(readable.isPaused());
57+
});
58+
}

0 commit comments

Comments
 (0)