44'use strict';
55
66const {
7+ DisposableStack,
78 Promise,
89 PromisePrototypeThen,
910 SymbolDispose,
@@ -177,36 +178,38 @@ function eos(stream, options, callback) {
177178 callback.call(stream);
178179 };
179180
181+ const disposableStack = new DisposableStack();
182+
180183 const onrequest = () => {
181- stream.req.on ('finish', onfinish);
184+ disposableStack.use( stream.req.addDisposableListener ('finish', onfinish) );
182185 };
183186
184187 if (isRequest(stream)) {
185- stream.on ('complete', onfinish);
188+ disposableStack.use( stream.addDisposableListener ('complete', onfinish) );
186189 if (!willEmitClose) {
187- stream.on ('abort', onclose);
190+ disposableStack.use( stream.addDisposableListener ('abort', onclose) );
188191 }
189192 if (stream.req) {
190193 onrequest();
191194 } else {
192- stream.on ('request', onrequest);
195+ disposableStack.use( stream.addDisposableListener ('request', onrequest) );
193196 }
194197 } else if (writable && !wState) { // legacy streams
195- stream.on ('end', onlegacyfinish);
196- stream.on ('close', onlegacyfinish);
198+ disposableStack.use( stream.addDisposableListener ('end', onlegacyfinish) );
199+ disposableStack.use( stream.addDisposableListener ('close', onlegacyfinish) );
197200 }
198201
199202 // Not all streams will emit 'close' after 'aborted'.
200203 if (!willEmitClose && typeof stream.aborted === 'boolean') {
201- stream.on ('aborted', onclose);
204+ disposableStack.use( stream.addDisposableListener ('aborted', onclose) );
202205 }
203206
204- stream.on ('end', onend);
205- stream.on ('finish', onfinish);
207+ disposableStack.use( stream.addDisposableListener ('end', onend) );
208+ disposableStack.use( stream.addDisposableListener ('finish', onfinish) );
206209 if (options.error !== false) {
207- stream.on ('error', onerror);
210+ disposableStack.use( stream.addDisposableListener ('error', onerror) );
208211 }
209- stream.on ('close', onclose);
212+ disposableStack.use( stream.addDisposableListener ('close', onclose) );
210213
211214 if (closed) {
212215 process.nextTick(onclose);
@@ -233,18 +236,10 @@ function eos(stream, options, callback) {
233236
234237 const cleanup = () => {
235238 callback = nop;
236- stream.removeListener('aborted', onclose);
237- stream.removeListener('complete', onfinish);
238- stream.removeListener('abort', onclose);
239- stream.removeListener('request', onrequest);
240- if (stream.req) stream.req.removeListener('finish', onfinish);
241- stream.removeListener('end', onlegacyfinish);
242- stream.removeListener('close', onlegacyfinish);
243- stream.removeListener('finish', onfinish);
244- stream.removeListener('end', onend);
245- stream.removeListener('error', onerror);
246- stream.removeListener('close', onclose);
239+ disposableStack.dispose();
247240 };
241+ // Arrange for the cleanup function to call itself when disposed.
242+ cleanup[SymbolDispose] = cleanup;
248243
249244 if (options.signal && !closed) {
250245 const abort = () => {
0 commit comments