@@ -32,6 +32,8 @@ function isWritableFinished(stream) {
32
32
return wState . finished || ( wState . ended && wState . length === 0 ) ;
33
33
}
34
34
35
+ function nop ( ) { }
36
+
35
37
function eos ( stream , opts , callback ) {
36
38
if ( arguments . length === 2 ) {
37
39
callback = opts ;
@@ -52,20 +54,23 @@ function eos(stream, opts, callback) {
52
54
let writable = opts . writable ||
53
55
( opts . writable !== false && isWritable ( stream ) ) ;
54
56
57
+ const wState = stream . _writableState ;
58
+ const rState = stream . _readableState ;
59
+
55
60
const onlegacyfinish = ( ) => {
56
61
if ( ! stream . writable ) onfinish ( ) ;
57
62
} ;
58
63
59
64
let writableFinished = stream . writableFinished ||
60
- ( stream . _writableState && stream . _writableState . finished ) ;
65
+ ( rState && rState . finished ) ;
61
66
const onfinish = ( ) => {
62
67
writable = false ;
63
68
writableFinished = true ;
64
69
if ( ! readable ) callback . call ( stream ) ;
65
70
} ;
66
71
67
72
let readableEnded = stream . readableEnded ||
68
- ( stream . _readableState && stream . _readableState . endEmitted ) ;
73
+ ( rState && rState . endEmitted ) ;
69
74
const onend = ( ) => {
70
75
readable = false ;
71
76
readableEnded = true ;
@@ -79,7 +84,7 @@ function eos(stream, opts, callback) {
79
84
const onclose = ( ) => {
80
85
let err ;
81
86
if ( readable && ! readableEnded ) {
82
- if ( ! stream . _readableState || ! stream . _readableState . ended )
87
+ if ( ! rState || ! rState . ended )
83
88
err = new ERR_STREAM_PREMATURE_CLOSE ( ) ;
84
89
return callback . call ( stream , err ) ;
85
90
}
@@ -99,7 +104,7 @@ function eos(stream, opts, callback) {
99
104
stream . on ( 'abort' , onclose ) ;
100
105
if ( stream . req ) onrequest ( ) ;
101
106
else stream . on ( 'request' , onrequest ) ;
102
- } else if ( writable && ! stream . _writableState ) { // legacy streams
107
+ } else if ( writable && ! wState ) { // legacy streams
103
108
stream . on ( 'end' , onlegacyfinish ) ;
104
109
stream . on ( 'close' , onlegacyfinish ) ;
105
110
}
@@ -114,7 +119,24 @@ function eos(stream, opts, callback) {
114
119
if ( opts . error !== false ) stream . on ( 'error' , onerror ) ;
115
120
stream . on ( 'close' , onclose ) ;
116
121
122
+ const closed = ( wState && wState . closed ) || ( rState && rState . closed ) ||
123
+ ( wState && wState . errorEmitted ) || ( rState && rState . errorEmitted ) ||
124
+ ( wState && wState . finished ) || ( rState && rState . endEmitted ) ||
125
+ ( rState && stream . req && stream . aborted ) ;
126
+
127
+ if ( closed ) {
128
+ // TODO(ronag): Re-throw error if errorEmitted?
129
+ // TODO(ronag): Throw premature close as if finished was called?
130
+ // before being closed? i.e. if closed but not errored, ended or finished.
131
+ // TODO(ronag): Throw some kind of error? Does it make sense
132
+ // to call finished() on a "finished" stream?
133
+ process . nextTick ( ( ) => {
134
+ callback ( ) ;
135
+ } ) ;
136
+ }
137
+
117
138
return function ( ) {
139
+ callback = nop ;
118
140
stream . removeListener ( 'aborted' , onclose ) ;
119
141
stream . removeListener ( 'complete' , onfinish ) ;
120
142
stream . removeListener ( 'abort' , onclose ) ;
0 commit comments