From b513a3332163ad89cdb459f5877ee181b40f91c5 Mon Sep 17 00:00:00 2001 From: Jeremiah Senkpiel Date: Wed, 2 Sep 2015 12:23:49 -0400 Subject: [PATCH] events,lib: don't require EE#listenerCount() Now parts of our public and public-ish APIs fall back to old-style listenerCount() if the emitter does not have a listenerCount function. Fixes: https://github.com/nodejs/node/issues/2655 Refs: 8f58fb92fff904a6ca58fd0df9ee5a1816e5b84e PR-URL: https://github.com/nodejs/node/pull/2661 Reviewed-By: Sakthipriyan Vairamani Reviewed-By: Colin Ihrig Reviewed-By: James M Snell --- lib/_http_server.js | 4 ++-- lib/_stream_readable.js | 4 ++-- lib/events.js | 9 +++++++-- lib/stream.js | 2 +- .../test-stream-pipe-without-listenerCount.js | 19 +++++++++++++++++++ 5 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 test/parallel/test-stream-pipe-without-listenerCount.js diff --git a/lib/_http_server.js b/lib/_http_server.js index dd787fa2f7ad99..16460fca35705d 100644 --- a/lib/_http_server.js +++ b/lib/_http_server.js @@ -374,7 +374,7 @@ function connectionListener(socket) { parser = null; var eventName = req.method === 'CONNECT' ? 'connect' : 'upgrade'; - if (self.listenerCount(eventName) > 0) { + if (EventEmitter.listenerCount(self, eventName) > 0) { debug('SERVER have listener for %s', eventName); var bodyHead = d.slice(bytesParsed, d.length); @@ -497,7 +497,7 @@ function connectionListener(socket) { (req.httpVersionMajor == 1 && req.httpVersionMinor == 1) && continueExpression.test(req.headers['expect'])) { res._expect_continue = true; - if (self.listenerCount('checkContinue') > 0) { + if (EventEmitter.listenerCount(self, 'checkContinue') > 0) { self.emit('checkContinue', req, res); } else { res.writeContinue(); diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js index 681c3eaec245be..c6bd0c16659d1e 100644 --- a/lib/_stream_readable.js +++ b/lib/_stream_readable.js @@ -537,7 +537,7 @@ Readable.prototype.pipe = function(dest, pipeOpts) { debug('onerror', er); unpipe(); dest.removeListener('error', onerror); - if (dest.listenerCount('error') === 0) + if (EE.listenerCount(dest, 'error') === 0) dest.emit('error', er); } // This is a brutally ugly hack to make sure that our error handler @@ -586,7 +586,7 @@ function pipeOnDrain(src) { debug('pipeOnDrain', state.awaitDrain); if (state.awaitDrain) state.awaitDrain--; - if (state.awaitDrain === 0 && src.listenerCount('data')) { + if (state.awaitDrain === 0 && EE.listenerCount(src, 'data')) { state.flowing = true; flow(src); } diff --git a/lib/events.js b/lib/events.js index 722b64537e109d..ea3f2831eb3bbc 100644 --- a/lib/events.js +++ b/lib/events.js @@ -395,10 +395,15 @@ EventEmitter.prototype.listeners = function listeners(type) { }; EventEmitter.listenerCount = function(emitter, type) { - return emitter.listenerCount(type); + if (typeof emitter.listenerCount === 'function') { + return emitter.listenerCount(type); + } else { + return listenerCount.call(emitter, type); + } }; -EventEmitter.prototype.listenerCount = function listenerCount(type) { +EventEmitter.prototype.listenerCount = listenerCount; +function listenerCount(type) { const events = this._events; if (events) { diff --git a/lib/stream.js b/lib/stream.js index 2e0cdfc3134065..8d3535dc4d2f0e 100644 --- a/lib/stream.js +++ b/lib/stream.js @@ -70,7 +70,7 @@ Stream.prototype.pipe = function(dest, options) { // don't leave dangling pipes when there are errors. function onerror(er) { cleanup(); - if (this.listenerCount('error') === 0) { + if (EE.listenerCount(this, 'error') === 0) { throw er; // Unhandled stream error in pipe. } } diff --git a/test/parallel/test-stream-pipe-without-listenerCount.js b/test/parallel/test-stream-pipe-without-listenerCount.js new file mode 100644 index 00000000000000..d7a6a6b653a6bf --- /dev/null +++ b/test/parallel/test-stream-pipe-without-listenerCount.js @@ -0,0 +1,19 @@ +'use strict'; +const common = require('../common'); +const stream = require('stream'); + +const r = new stream.Stream(); +r.listenerCount = undefined; + +const w = new stream.Stream(); +w.listenerCount = undefined; + +w.on('pipe', function() { + r.emit('error', new Error('Readable Error')); + w.emit('error', new Error('Writable Error')); +}); +r.on('error', common.mustCall(noop)); +w.on('error', common.mustCall(noop)); +r.pipe(w); + +function noop() {};