@@ -27,7 +27,6 @@ const {
2727 ArrayPrototypeShift,
2828 ArrayPrototypeSlice,
2929 ArrayPrototypeSplice,
30- ArrayFrom,
3130 Boolean,
3231 Error,
3332 ErrorCaptureStackTrace,
@@ -64,7 +63,6 @@ const {
6463 ERR_UNHANDLED_ERROR
6564 } ,
6665} = require ( 'internal/errors' ) ;
67- const getLinkedMap = require ( 'internal/linkedMap' ) ;
6866
6967const {
7068 validateAbortSignal,
@@ -388,19 +386,30 @@ EventEmitter.prototype.emit = function emit(type, ...args) {
388386 if ( handler === undefined )
389387 return false ;
390388
391- const listeners = ArrayFrom ( handler ) ;
392- const len = handler . length ;
393- for ( let i = 0 ; i < len ; ++ i ) {
394- const result = listeners [ i ] . apply ( this , args ) ;
389+ if ( typeof handler === 'function' ) {
390+ const result = handler . apply ( this , args ) ;
395391
396392 // We check if result is undefined first because that
397393 // is the most common case so we do not pay any perf
398- // penalty.
399- // This code is duplicated because extracting it away
400- // would make it non-inlineable.
394+ // penalty
401395 if ( result !== undefined && result !== null ) {
402396 addCatch ( this , result , type , args ) ;
403397 }
398+ } else {
399+ const len = handler . length ;
400+ const listeners = arrayClone ( handler ) ;
401+ for ( let i = 0 ; i < len ; ++ i ) {
402+ const result = listeners [ i ] . apply ( this , args ) ;
403+
404+ // We check if result is undefined first because that
405+ // is the most common case so we do not pay any perf
406+ // penalty.
407+ // This code is duplicated because extracting it away
408+ // would make it non-inlineable.
409+ if ( result !== undefined && result !== null ) {
410+ addCatch ( this , result , type , args ) ;
411+ }
412+ }
404413 }
405414
406415 return true ;
@@ -433,29 +442,36 @@ function _addListener(target, type, listener, prepend) {
433442
434443 if ( existing === undefined ) {
435444 // Optimize the case of one listener. Don't need the extra array object.
436- existing = events [ type ] = getLinkedMap ( ) . push ( listener ) ;
445+ events [ type ] = listener ;
437446 ++ target . _eventsCount ;
438- } else if ( prepend ) {
439- existing . unshift ( listener ) ;
440447 } else {
441- existing . push ( listener ) ;
442- }
448+ if ( typeof existing === 'function' ) {
449+ // Adding the second element, need to change to array.
450+ existing = events [ type ] =
451+ prepend ? [ listener , existing ] : [ existing , listener ] ;
452+ // If we've already got an array, just append.
453+ } else if ( prepend ) {
454+ existing . unshift ( listener ) ;
455+ } else {
456+ existing . push ( listener ) ;
457+ }
443458
444- // Check for listener leak
445- m = _getMaxListeners ( target ) ;
446- if ( m > 0 && existing . length > m && ! existing . warned ) {
447- existing . warned = true ;
448- // No error code for this since it is a Warning
449- // eslint-disable-next-line no-restricted-syntax
450- const w = new Error ( 'Possible EventEmitter memory leak detected. ' +
451- `${ existing . length } ${ String ( type ) } listeners ` +
452- `added to ${ inspect ( target , { depth : - 1 } ) } . Use ` +
453- 'emitter.setMaxListeners() to increase limit' ) ;
454- w . name = 'MaxListenersExceededWarning' ;
455- w . emitter = target ;
456- w . type = type ;
457- w . count = existing . length ;
458- process . emitWarning ( w ) ;
459+ // Check for listener leak
460+ m = _getMaxListeners ( target ) ;
461+ if ( m > 0 && existing . length > m && ! existing . warned ) {
462+ existing . warned = true ;
463+ // No error code for this since it is a Warning
464+ // eslint-disable-next-line no-restricted-syntax
465+ const w = new Error ( 'Possible EventEmitter memory leak detected. ' +
466+ `${ existing . length } ${ String ( type ) } listeners ` +
467+ `added to ${ inspect ( target , { depth : - 1 } ) } . Use ` +
468+ 'emitter.setMaxListeners() to increase limit' ) ;
469+ w . name = 'MaxListenersExceededWarning' ;
470+ w . emitter = target ;
471+ w . type = type ;
472+ w . count = existing . length ;
473+ process . emitWarning ( w ) ;
474+ }
459475 }
460476
461477 return target ;
@@ -548,10 +564,39 @@ EventEmitter.prototype.removeListener =
548564 const list = events [ type ] ;
549565 if ( list === undefined )
550566 return this ;
551- if ( list ?. remove ( listener ) ) {
552- if ( list . length === 0 ) {
567+
568+ if ( list === listener || list . listener === listener ) {
569+ if ( -- this . _eventsCount === 0 )
570+ this . _events = ObjectCreate ( null ) ;
571+ else {
553572 delete events [ type ] ;
573+ if ( events . removeListener )
574+ this . emit ( 'removeListener' , type , list . listener || listener ) ;
575+ }
576+ } else if ( typeof list !== 'function' ) {
577+ let position = - 1 ;
578+
579+ for ( let i = list . length - 1 ; i >= 0 ; i -- ) {
580+ if ( list [ i ] === listener || list [ i ] . listener === listener ) {
581+ position = i ;
582+ break ;
583+ }
584+ }
585+
586+ if ( position < 0 )
587+ return this ;
588+
589+ if ( position === 0 )
590+ list . shift ( ) ;
591+ else {
592+ if ( spliceOne === undefined )
593+ spliceOne = require ( 'internal/util' ) . spliceOne ;
594+ spliceOne ( list , position ) ;
554595 }
596+
597+ if ( list . length === 1 )
598+ events [ type ] = list [ 0 ] ;
599+
555600 if ( events . removeListener !== undefined )
556601 this . emit ( 'removeListener' , type , listener ) ;
557602 }
@@ -675,7 +720,19 @@ EventEmitter.prototype.listenerCount = listenerCount;
675720 * @returns {number }
676721 */
677722function listenerCount ( type ) {
678- return this . _events ?. [ type ] ?. length || 0 ;
723+ const events = this . _events ;
724+
725+ if ( events !== undefined ) {
726+ const evlistener = events [ type ] ;
727+
728+ if ( typeof evlistener === 'function' ) {
729+ return 1 ;
730+ } else if ( evlistener !== undefined ) {
731+ return evlistener . length ;
732+ }
733+ }
734+
735+ return 0 ;
679736}
680737
681738/**
0 commit comments