@@ -30,8 +30,10 @@ EventEmitter.init = function() {
30
30
}
31
31
}
32
32
33
- if ( ! this . _events || this . _events === Object . getPrototypeOf ( this ) . _events )
33
+ if ( ! this . _events || this . _events === Object . getPrototypeOf ( this ) . _events ) {
34
34
this . _events = { } ;
35
+ this . _eventsCount = 0 ;
36
+ }
35
37
36
38
this . _maxListeners = this . _maxListeners || undefined ;
37
39
} ;
@@ -115,15 +117,18 @@ function emitMany(handler, isFn, self, args) {
115
117
EventEmitter . prototype . emit = function emit ( type ) {
116
118
var er , handler , len , args , i , events , domain ;
117
119
var needDomainExit = false ;
120
+ var doError = ( type === 'error' ) ;
118
121
119
122
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 ;
122
127
123
128
domain = this . domain ;
124
129
125
130
// If there is no 'error' event listener then throw.
126
- if ( type === 'error' && ! events . error ) {
131
+ if ( doError ) {
127
132
er = arguments [ 1 ] ;
128
133
if ( domain ) {
129
134
if ( ! er )
@@ -189,39 +194,47 @@ EventEmitter.prototype.addListener = function addListener(type, listener) {
189
194
throw new TypeError ( 'listener must be a function' ) ;
190
195
191
196
events = this . _events ;
192
- if ( ! events )
197
+ if ( ! events ) {
193
198
events = this . _events = { } ;
194
- else {
199
+ this . _eventsCount = 0 ;
200
+ } else {
195
201
// To avoid recursion in the case that type === "newListener"! Before
196
202
// adding it to the listeners, first emit "newListener".
197
203
if ( events . newListener ) {
198
204
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 ;
201
210
}
202
211
existing = events [ type ] ;
203
212
}
204
213
205
- if ( ! existing )
214
+ if ( ! existing ) {
206
215
// Optimize the case of one listener. Don't need the extra array object.
207
216
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
+ }
225
238
}
226
239
}
227
240
@@ -254,7 +267,7 @@ EventEmitter.prototype.once = function once(type, listener) {
254
267
// emits a 'removeListener' event iff the listener was removed
255
268
EventEmitter . prototype . removeListener =
256
269
function removeListener ( type , listener ) {
257
- var list , events , position , length , i ;
270
+ var list , events , position , i ;
258
271
259
272
if ( typeof listener !== 'function' )
260
273
throw new TypeError ( 'listener must be a function' ) ;
@@ -267,17 +280,18 @@ EventEmitter.prototype.removeListener =
267
280
if ( ! list )
268
281
return this ;
269
282
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
+ }
279
291
} else if ( typeof list !== 'function' ) {
280
- for ( i = length ; i -- > 0 ; ) {
292
+ position = - 1 ;
293
+
294
+ for ( i = list . length ; i -- > 0 ; ) {
281
295
if ( list [ i ] === listener ||
282
296
( list [ i ] . listener && list [ i ] . listener === listener ) ) {
283
297
position = i ;
@@ -289,8 +303,12 @@ EventEmitter.prototype.removeListener =
289
303
return this ;
290
304
291
305
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 ] ;
294
312
} else {
295
313
spliceOne ( list , position ) ;
296
314
}
@@ -312,10 +330,15 @@ EventEmitter.prototype.removeAllListeners =
312
330
313
331
// not listening for removeListener, no need to emit
314
332
if ( ! events . removeListener ) {
315
- if ( arguments . length === 0 )
333
+ if ( arguments . length === 0 ) {
316
334
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
+ }
319
342
return this ;
320
343
}
321
344
@@ -329,19 +352,20 @@ EventEmitter.prototype.removeAllListeners =
329
352
}
330
353
this . removeAllListeners ( 'removeListener' ) ;
331
354
this . _events = { } ;
355
+ this . _eventsCount = 0 ;
332
356
return this ;
333
357
}
334
358
335
359
listeners = events [ type ] ;
336
360
337
361
if ( typeof listeners === 'function' ) {
338
362
this . removeListener ( type , listeners ) ;
339
- } else if ( Array . isArray ( listeners ) ) {
363
+ } else if ( listeners ) {
340
364
// LIFO order
341
- while ( listeners . length )
365
+ do {
342
366
this . removeListener ( type , listeners [ listeners . length - 1 ] ) ;
367
+ } while ( listeners [ 0 ] ) ;
343
368
}
344
- delete events [ type ] ;
345
369
346
370
return this ;
347
371
} ;
0 commit comments