@@ -30,8 +30,10 @@ EventEmitter.init = function() {
3030 }
3131 }
3232
33- if ( ! this . _events || this . _events === Object . getPrototypeOf ( this ) . _events )
33+ if ( ! this . _events || this . _events === Object . getPrototypeOf ( this ) . _events ) {
3434 this . _events = { } ;
35+ this . _eventsCount = 0 ;
36+ }
3537
3638 this . _maxListeners = this . _maxListeners || undefined ;
3739} ;
@@ -115,15 +117,18 @@ function emitMany(handler, isFn, self, args) {
115117EventEmitter . prototype . emit = function emit ( type ) {
116118 var er , handler , len , args , i , events , domain ;
117119 var needDomainExit = false ;
120+ var doError = ( type === 'error' ) ;
118121
119122 events = this . _events ;
120- if ( ! events )
121- events = this . _events = { } ;
123+ if ( events )
124+ doError = ( doError && events . error == null ) ;
125+ else if ( ! doError )
126+ return false ;
122127
123128 domain = this . domain ;
124129
125130 // If there is no 'error' event listener then throw.
126- if ( type === 'error' && ! events . error ) {
131+ if ( doError ) {
127132 er = arguments [ 1 ] ;
128133 if ( domain ) {
129134 if ( ! er )
@@ -189,39 +194,47 @@ EventEmitter.prototype.addListener = function addListener(type, listener) {
189194 throw new TypeError ( 'listener must be a function' ) ;
190195
191196 events = this . _events ;
192- if ( ! events )
197+ if ( ! events ) {
193198 events = this . _events = { } ;
194- else {
199+ this . _eventsCount = 0 ;
200+ } else {
195201 // To avoid recursion in the case that type === "newListener"! Before
196202 // adding it to the listeners, first emit "newListener".
197203 if ( events . newListener ) {
198204 this . emit ( 'newListener' , type ,
199- typeof listener . listener === 'function' ?
200- listener . listener : listener ) ;
205+ listener . listener ? listener . listener : listener ) ;
206+
207+ // Re-assign `events` because a newListener handler could have caused the
208+ // this._events to be assigned to a new object
209+ events = this . _events ;
201210 }
202211 existing = events [ type ] ;
203212 }
204213
205- if ( ! existing )
214+ if ( ! existing ) {
206215 // Optimize the case of one listener. Don't need the extra array object.
207216 existing = events [ type ] = listener ;
208- else if ( typeof existing !== 'function' )
209- // If we've already got an array, just append.
210- existing . push ( listener ) ;
211- else
212- // Adding the second element, need to change to array.
213- existing = events [ type ] = [ existing , listener ] ;
214-
215- // Check for listener leak
216- if ( typeof existing !== 'function' && ! existing . warned ) {
217- m = $getMaxListeners ( this ) ;
218- if ( m && m > 0 && existing . length > m ) {
219- existing . warned = true ;
220- console . error ( '(node) warning: possible EventEmitter memory ' +
221- 'leak detected. %d %s listeners added. ' +
222- 'Use emitter.setMaxListeners() to increase limit.' ,
223- existing . length , type ) ;
224- console . trace ( ) ;
217+ ++ this . _eventsCount ;
218+ } else {
219+ if ( typeof existing === 'function' ) {
220+ // Adding the second element, need to change to array.
221+ existing = events [ type ] = [ existing , listener ] ;
222+ } else {
223+ // If we've already got an array, just append.
224+ existing . push ( listener ) ;
225+ }
226+
227+ // Check for listener leak
228+ if ( ! existing . warned ) {
229+ m = $getMaxListeners ( this ) ;
230+ if ( m && m > 0 && existing . length > m ) {
231+ existing . warned = true ;
232+ console . error ( '(node) warning: possible EventEmitter memory ' +
233+ 'leak detected. %d %s listeners added. ' +
234+ 'Use emitter.setMaxListeners() to increase limit.' ,
235+ existing . length , type ) ;
236+ console . trace ( ) ;
237+ }
225238 }
226239 }
227240
@@ -254,7 +267,7 @@ EventEmitter.prototype.once = function once(type, listener) {
254267// emits a 'removeListener' event iff the listener was removed
255268EventEmitter . prototype . removeListener =
256269 function removeListener ( type , listener ) {
257- var list , events , position , length , i ;
270+ var list , events , position , i ;
258271
259272 if ( typeof listener !== 'function' )
260273 throw new TypeError ( 'listener must be a function' ) ;
@@ -267,17 +280,18 @@ EventEmitter.prototype.removeListener =
267280 if ( ! list )
268281 return this ;
269282
270- length = list . length ;
271- position = - 1 ;
272-
273- if ( list === listener ||
274- ( typeof list . listener === 'function' && list . listener === listener ) ) {
275- delete events [ type ] ;
276- if ( events . removeListener )
277- this . emit ( 'removeListener' , type , listener ) ;
278-
283+ if ( list === listener || ( list . listener && list . listener === listener ) ) {
284+ if ( -- this . _eventsCount === 0 )
285+ this . _events = { } ;
286+ else {
287+ delete events [ type ] ;
288+ if ( events . removeListener )
289+ this . emit ( 'removeListener' , type , listener ) ;
290+ }
279291 } else if ( typeof list !== 'function' ) {
280- for ( i = length ; i -- > 0 ; ) {
292+ position = - 1 ;
293+
294+ for ( i = list . length ; i -- > 0 ; ) {
281295 if ( list [ i ] === listener ||
282296 ( list [ i ] . listener && list [ i ] . listener === listener ) ) {
283297 position = i ;
@@ -289,8 +303,12 @@ EventEmitter.prototype.removeListener =
289303 return this ;
290304
291305 if ( list . length === 1 ) {
292- list . length = 0 ;
293- delete events [ type ] ;
306+ list [ 0 ] = undefined ;
307+ if ( -- this . _eventsCount === 0 ) {
308+ this . _events = { } ;
309+ return this ;
310+ } else
311+ delete events [ type ] ;
294312 } else {
295313 spliceOne ( list , position ) ;
296314 }
@@ -312,10 +330,15 @@ EventEmitter.prototype.removeAllListeners =
312330
313331 // not listening for removeListener, no need to emit
314332 if ( ! events . removeListener ) {
315- if ( arguments . length === 0 )
333+ if ( arguments . length === 0 ) {
316334 this . _events = { } ;
317- else if ( events [ type ] )
318- delete events [ type ] ;
335+ this . _eventsCount = 0 ;
336+ } else if ( events [ type ] ) {
337+ if ( -- this . _eventsCount === 0 )
338+ this . _events = { } ;
339+ else
340+ delete events [ type ] ;
341+ }
319342 return this ;
320343 }
321344
@@ -329,19 +352,20 @@ EventEmitter.prototype.removeAllListeners =
329352 }
330353 this . removeAllListeners ( 'removeListener' ) ;
331354 this . _events = { } ;
355+ this . _eventsCount = 0 ;
332356 return this ;
333357 }
334358
335359 listeners = events [ type ] ;
336360
337361 if ( typeof listeners === 'function' ) {
338362 this . removeListener ( type , listeners ) ;
339- } else if ( Array . isArray ( listeners ) ) {
363+ } else if ( listeners ) {
340364 // LIFO order
341- while ( listeners . length )
365+ do {
342366 this . removeListener ( type , listeners [ listeners . length - 1 ] ) ;
367+ } while ( listeners [ 0 ] ) ;
343368 }
344- delete events [ type ] ;
345369
346370 return this ;
347371 } ;
0 commit comments