@@ -85,6 +85,7 @@ const {
8585 validateString,
8686} = require ( 'internal/validators' ) ;
8787
88+ const kEvents = Symbol ( 'kEvents' ) ;
8889const kCapture = Symbol ( 'kCapture' ) ;
8990const kErrorMonitor = Symbol ( 'events.errorMonitor' ) ;
9091const kMaxEventTargetListeners = Symbol ( 'events.maxEventTargetListeners' ) ;
@@ -262,8 +263,7 @@ ObjectDefineProperty(EventEmitter.prototype, kCapture, {
262263 enumerable : false ,
263264} ) ;
264265
265- EventEmitter . prototype . _events = undefined ;
266- EventEmitter . prototype . _eventsCount = 0 ;
266+ EventEmitter . prototype [ kEvents ] = undefined ;
267267EventEmitter . prototype . _maxListeners = undefined ;
268268
269269// By default EventEmitters will print a warning if more than 10 listeners are
@@ -287,6 +287,40 @@ ObjectDefineProperty(EventEmitter, 'defaultMaxListeners', {
287287 } ,
288288} ) ;
289289
290+ // _events and _eventsCount are Legacy
291+ ObjectDefineProperty ( EventEmitter , '_events' , {
292+ __proto__ : null ,
293+ enumerable : true ,
294+ get : function ( ) {
295+ // TODO - maybe in order to not break the ecosystem, create a Proxy that will update the events map
296+ const events = this [ kEvents ] ;
297+ if ( events === undefined ) {
298+ return undefined ;
299+ }
300+
301+ return Object . fromEntries ( events . entries ( ) ) ;
302+ } ,
303+ set : function ( events ) {
304+ this [ kEvents ] = new Map ( events ) ;
305+ } ,
306+ } ) ;
307+
308+ ObjectDefineProperty ( EventEmitter , '_eventsCount' , {
309+ __proto__ : null ,
310+ enumerable : true ,
311+ get : function ( ) {
312+ const events = this [ kEvents ] ;
313+ if ( events === undefined ) {
314+ return 0 ;
315+ }
316+
317+ return events . size ;
318+ } ,
319+ set : function ( ) {
320+ // TODO - throw, this is not supported
321+ } ,
322+ } ) ;
323+
290324ObjectDefineProperties ( EventEmitter , {
291325 kMaxEventTargetListeners : {
292326 __proto__ : null ,
@@ -339,11 +373,9 @@ EventEmitter.setMaxListeners =
339373// If you're updating this function definition, please also update any
340374// re-definitions, such as the one in the Domain module (lib/domain.js).
341375EventEmitter . init = function ( opts ) {
342-
343- if ( this . _events === undefined ||
344- this . _events === ObjectGetPrototypeOf ( this ) . _events ) {
345- this . _events = { } ;
346- this . _eventsCount = 0 ;
376+ if ( this [ kEvents ] === undefined ||
377+ this [ kEvents ] === ObjectGetPrototypeOf ( this ) [ kEvents ] ) {
378+ this [ kEvents ] = new Map ( )
347379 }
348380
349381 this . _maxListeners = this . _maxListeners || undefined ;
@@ -462,11 +494,11 @@ function enhanceStackTrace(err, own) {
462494EventEmitter . prototype . emit = function emit ( type , ...args ) {
463495 let doError = ( type === 'error' ) ;
464496
465- const events = this . _events ;
497+ const events = this [ kEvents ] ;
466498 if ( events !== undefined ) {
467- if ( doError && events [ kErrorMonitor ] !== undefined )
499+ if ( doError && events . has ( kErrorMonitor ) )
468500 this . emit ( kErrorMonitor , ...args ) ;
469- doError = ( doError && events . error === undefined ) ;
501+ doError = ( doError && ! events . has ( ' error' ) ) ;
470502 } else if ( ! doError )
471503 return false ;
472504
@@ -506,7 +538,7 @@ EventEmitter.prototype.emit = function emit(type, ...args) {
506538 throw err ; // Unhandled 'error' event
507539 }
508540
509- const handler = events [ type ] ;
541+ const handler = events . get ( type ) ;
510542
511543 if ( handler === undefined )
512544 return false ;
@@ -547,10 +579,9 @@ function _addListener(target, type, listener, prepend) {
547579
548580 checkListener ( listener ) ;
549581
550- events = target . _events ;
582+ events = target [ kEvents ] ;
551583 if ( events === undefined ) {
552- events = target . _events = { __proto__ : null } ;
553- target . _eventsCount = 0 ;
584+ events = target [ kEvents ] = new Map ( ) ;
554585 } else {
555586 // To avoid recursion in the case that type === "newListener"! Before
556587 // adding it to the listeners, first emit "newListener".
@@ -559,21 +590,20 @@ function _addListener(target, type, listener, prepend) {
559590 listener . listener ?? listener ) ;
560591
561592 // Re-assign `events` because a newListener handler could have caused the
562- // this._events to be assigned to a new object
563- events = target . _events ;
593+ // this[kEvents] to be assigned to a new object
594+ events = target [ kEvents ] ;
564595 }
565- existing = events [ type ] ;
596+ existing = events . get ( type ) ;
566597 }
567598
568599 if ( existing === undefined ) {
569600 // Optimize the case of one listener. Don't need the extra array object.
570- events [ type ] = listener ;
571- ++ target . _eventsCount ;
601+ events . set ( type , listener ) ;
572602 } else {
573603 if ( typeof existing === 'function' ) {
574604 // Adding the second element, need to change to array.
575- existing = events [ type ] =
576- prepend ? [ listener , existing ] : [ existing , listener ] ;
605+ existing = prepend ? [ listener , existing ] : [ existing , listener ] ;
606+ events . set ( type , existing ) ;
577607 // If we've already got an array, just append.
578608 } else if ( prepend ) {
579609 existing . unshift ( listener ) ;
@@ -677,20 +707,22 @@ EventEmitter.prototype.removeListener =
677707 function removeListener ( type , listener ) {
678708 checkListener ( listener ) ;
679709
680- const events = this . _events ;
710+ const events = this [ kEvents ] ;
681711 if ( events === undefined )
682712 return this ;
683713
684- const list = events [ type ] ;
714+ const list = events . get ( type ) ;
685715 if ( list === undefined )
686716 return this ;
687717
688718 if ( list === listener || list . listener === listener ) {
689- if ( -- this . _eventsCount === 0 )
690- this . _events = { __proto__ : null } ;
719+ if ( this [ kEvents ] . size === 1 )
720+ // TODO - this is no longer creating new objects
721+ // this[kEvents].clear();
722+ this [ kEvents ] = new Map ( ) ;
691723 else {
692- delete events [ type ] ;
693- if ( events . removeListener )
724+ events . delete ( type ) ;
725+ if ( events . has ( ' removeListener' ) )
694726 this . emit ( 'removeListener' , type , list . listener || listener ) ;
695727 }
696728 } else if ( typeof list !== 'function' ) {
@@ -715,9 +747,9 @@ EventEmitter.prototype.removeListener =
715747 }
716748
717749 if ( list . length === 1 )
718- events [ type ] = list [ 0 ] ;
750+ events . set ( type , list [ 0 ] ) ;
719751
720- if ( events . removeListener !== undefined )
752+ if ( events . has ( ' removeListener' ) )
721753 this . emit ( 'removeListener' , type , listener ) ;
722754 }
723755
@@ -735,37 +767,38 @@ EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
735767 */
736768EventEmitter . prototype . removeAllListeners =
737769 function removeAllListeners ( type ) {
738- const events = this . _events ;
770+ const events = this [ kEvents ] ;
739771 if ( events === undefined )
740772 return this ;
741773
742774 // Not listening for removeListener, no need to emit
743- if ( events . removeListener === undefined ) {
775+ if ( ! events . has ( ' removeListener' ) ) {
744776 if ( arguments . length === 0 ) {
745- this . _events = { __proto__ : null } ;
746- this . _eventsCount = 0 ;
747- } else if ( events [ type ] !== undefined ) {
748- if ( -- this . _eventsCount === 0 )
749- this . _events = { __proto__ : null } ;
777+ // this[kEvents].clear();
778+ this [ kEvents ] = new Map ( ) ;
779+ } else if ( events . has ( type ) ) {
780+ if ( this [ kEvents ] . size === 1 )
781+ // this[kEvents].clear();
782+ this [ kEvents ] = new Map ( ) ;
750783 else
751- delete events [ type ] ;
784+ this [ kEvents ] . delete ( type ) ;
752785 }
753786 return this ;
754787 }
755788
756789 // Emit removeListener for all listeners on all events
757790 if ( arguments . length === 0 ) {
758- for ( const key of ReflectOwnKeys ( events ) ) {
791+ for ( const key of events . keys ( ) ) {
759792 if ( key === 'removeListener' ) continue ;
760793 this . removeAllListeners ( key ) ;
761794 }
762795 this . removeAllListeners ( 'removeListener' ) ;
763- this . _events = { __proto__ : null } ;
764- this . _eventsCount = 0 ;
796+ // this[kEvents].clear() ;
797+ this [ kEvents ] = new Map ( ) ;
765798 return this ;
766799 }
767800
768- const listeners = events [ type ] ;
801+ const listeners = events . get ( type ) ;
769802
770803 if ( typeof listeners === 'function' ) {
771804 this . removeListener ( type , listeners ) ;
@@ -780,12 +813,12 @@ EventEmitter.prototype.removeAllListeners =
780813 } ;
781814
782815function _listeners ( target , type , unwrap ) {
783- const events = target . _events ;
816+ const events = target [ kEvents ] ;
784817
785818 if ( events === undefined )
786819 return [ ] ;
787820
788- const evlistener = events [ type ] ;
821+ const evlistener = events . get ( type ) ;
789822 if ( evlistener === undefined )
790823 return [ ] ;
791824
@@ -841,10 +874,10 @@ EventEmitter.prototype.listenerCount = listenerCount;
841874 * @returns {number }
842875 */
843876function listenerCount ( type , listener ) {
844- const events = this . _events ;
877+ const events = this [ kEvents ] ;
845878
846879 if ( events !== undefined ) {
847- const evlistener = events [ type ] ;
880+ const evlistener = events . get ( type ) ;
848881
849882 if ( typeof evlistener === 'function' ) {
850883 if ( listener != null ) {
@@ -878,7 +911,7 @@ function listenerCount(type, listener) {
878911 * @returns {any[] }
879912 */
880913EventEmitter . prototype . eventNames = function eventNames ( ) {
881- return this . _eventsCount > 0 ? ReflectOwnKeys ( this . _events ) : [ ] ;
914+ return this [ kEvents ] . size > 0 ? Array . from ( this [ kEvents ] . keys ( ) ) : [ ] ;
882915} ;
883916
884917function arrayClone ( arr ) {
0 commit comments