@@ -552,6 +552,8 @@ class EventTarget {
552552 initEventTarget ( this ) ;
553553 }
554554
555+ #fastHandlers = new Map ( ) ;
556+
555557 [ kNewListener ] ( size , type , listener , once , capture , passive , weak ) {
556558 if ( this [ kMaxEventTargetListeners ] > 0 &&
557559 size > this [ kMaxEventTargetListeners ] &&
@@ -572,6 +574,27 @@ class EventTarget {
572574 }
573575 [ kRemoveListener ] ( size , type , listener , capture ) { }
574576
577+ #toSlowMode ( ) {
578+ if ( this . #fastHandlers == null ) {
579+ return ;
580+ }
581+
582+ const handlers = this . #fastHandlers;
583+
584+ this . #fastHandlers = null ;
585+ for ( const [ type , listeners ] of handlers ) {
586+ if ( listeners == null ) {
587+ // Do nothing..
588+ } else if ( typeof listeners === 'function' ) {
589+ this . addEventListener ( type , listeners ) ;
590+ } else {
591+ for ( const listener of listeners ) {
592+ this . addEventListener ( type , listener ) ;
593+ }
594+ }
595+ }
596+ }
597+
575598 /**
576599 * @callback EventTargetCallback
577600 * @param {Event } event
@@ -644,45 +667,60 @@ class EventTarget {
644667 }
645668 }
646669
647- type = webidl . converters . DOMString ( type ) ;
670+ if ( options === kEmptyObject && this . #fastHandlers != null ) {
671+ const entry = this . #fastHandlers. get ( type ) ;
672+ if ( entry == null ) {
673+ this . #fastHandlers. set ( type , listener ) ;
674+ } else if ( typeof entry === 'function' ) {
675+ this . #fastHandlers. set ( type , new Set ( [ entry , listener ] ) ) ;
676+ } else {
677+ entry . add ( listener ) ;
678+ }
679+ } else {
680+ if ( this . #fastHandlers != null ) {
681+ this . #toSlowMode( ) ;
682+ }
648683
649- let root = this [ kEvents ] . get ( type ) ;
684+ type = webidl . converters . DOMString ( type ) ;
685+
686+ let root = this [ kEvents ] . get ( type ) ;
687+
688+ if ( root === undefined ) {
689+ root = { size : 1 , next : undefined , resistStopPropagation : Boolean ( resistStopPropagation ) } ;
690+ // This is the first handler in our linked list.
691+ new Listener ( this , type , root , listener , once , capture , passive ,
692+ isNodeStyleListener , weak , resistStopPropagation ) ;
693+ this [ kNewListener ] (
694+ root . size ,
695+ type ,
696+ listener ,
697+ once ,
698+ capture ,
699+ passive ,
700+ weak ) ;
701+ this [ kEvents ] . set ( type , root ) ;
702+ return ;
703+ }
650704
651- if ( root === undefined ) {
652- root = { size : 1 , next : undefined , resistStopPropagation : Boolean ( resistStopPropagation ) } ;
653- // This is the first handler in our linked list.
654- new Listener ( this , type , root , listener , once , capture , passive ,
655- isNodeStyleListener , weak , resistStopPropagation ) ;
656- this [ kNewListener ] (
657- root . size ,
658- type ,
659- listener ,
660- once ,
661- capture ,
662- passive ,
663- weak ) ;
664- this [ kEvents ] . set ( type , root ) ;
665- return ;
666- }
705+ let handler = root . next ;
706+ let previous = root ;
667707
668- let handler = root . next ;
669- let previous = root ;
708+ // We have to walk the linked list to see if we have a match
709+ while ( handler !== undefined && ! handler . same ( listener , capture ) ) {
710+ previous = handler ;
711+ handler = handler . next ;
712+ }
670713
671- // We have to walk the linked list to see if we have a match
672- while ( handler !== undefined && ! handler . same ( listener , capture ) ) {
673- previous = handler ;
674- handler = handler . next ;
675- }
714+ if ( handler !== undefined ) { // Duplicate! Ignore
715+ return ;
716+ }
676717
677- if ( handler !== undefined ) { // Duplicate! Ignore
678- return ;
718+ new Listener ( this , type , previous , listener , once , capture , passive ,
719+ isNodeStyleListener , weak , resistStopPropagation ) ;
720+ root . size ++ ;
721+ root . resistStopPropagation ||= Boolean ( resistStopPropagation ) ;
722+ this [ kNewListener ] ( root . size , type , listener , once , capture , passive , weak ) ;
679723 }
680-
681- new Listener ( this , type , previous , listener , once , capture , passive ,
682- isNodeStyleListener , weak , resistStopPropagation ) ;
683- root . size ++ ;
684- root . resistStopPropagation ||= Boolean ( resistStopPropagation ) ;
685- this [ kNewListener ] ( root . size , type , listener , once , capture , passive , weak ) ;
686724 }
687725
688726 /**
@@ -700,24 +738,39 @@ class EventTarget {
700738 if ( ! validateEventListener ( listener ) )
701739 return ;
702740
703- type = webidl . converters . DOMString ( type ) ;
704- const capture = options ?. capture === true ;
705-
706- const root = this [ kEvents ] . get ( type ) ;
707- if ( root === undefined || root . next === undefined )
708- return ;
741+ if ( options === kEmptyObject && this . #fastHandlers != null ) {
742+ const entry = this . #fastHandlers. get ( type ) ;
743+ if ( entry == null ) {
744+ // Do nothing
745+ } else if ( entry === listener ) {
746+ this . #fastHandlers. delete ( type ) ;
747+ } else {
748+ entry . delete ( listener ) ;
749+ }
750+ } else {
751+ if ( this . #fastHandlers != null ) {
752+ this . #toSlowMode( ) ;
753+ }
709754
710- let handler = root . next ;
711- while ( handler !== undefined ) {
712- if ( handler . same ( listener , capture ) ) {
713- handler . remove ( ) ;
714- root . size -- ;
715- if ( root . size === 0 )
716- this [ kEvents ] . delete ( type ) ;
717- this [ kRemoveListener ] ( root . size , type , listener , capture ) ;
718- break ;
755+ type = webidl . converters . DOMString ( type ) ;
756+ const capture = options ?. capture === true ;
757+
758+ const root = this [ kEvents ] . get ( type ) ;
759+ if ( root === undefined || root . next === undefined )
760+ return ;
761+
762+ let handler = root . next ;
763+ while ( handler !== undefined ) {
764+ if ( handler . same ( listener , capture ) ) {
765+ handler . remove ( ) ;
766+ root . size -- ;
767+ if ( root . size === 0 )
768+ this [ kEvents ] . delete ( type ) ;
769+ this [ kRemoveListener ] ( root . size , type , listener , capture ) ;
770+ break ;
771+ }
772+ handler = handler . next ;
719773 }
720- handler = handler . next ;
721774 }
722775 }
723776
@@ -764,77 +817,81 @@ class EventTarget {
764817 }
765818
766819 [ kHybridDispatch ] ( nodeValue , type , event ) {
767- const createEvent = ( ) => {
768- if ( event === undefined ) {
769- event = this [ kCreateEvent ] ( nodeValue , type ) ;
820+ if ( this . #fastHandlers != null ) {
821+ // XXX: Implement
822+ } else {
823+ const createEvent = ( ) => {
824+ if ( event === undefined ) {
825+ event = this [ kCreateEvent ] ( nodeValue , type ) ;
826+ event [ kTarget ] = this ;
827+ event [ kIsBeingDispatched ] = true ;
828+ }
829+ return event ;
830+ } ;
831+ if ( event !== undefined ) {
770832 event [ kTarget ] = this ;
771833 event [ kIsBeingDispatched ] = true ;
772834 }
773- return event ;
774- } ;
775- if ( event !== undefined ) {
776- event [ kTarget ] = this ;
777- event [ kIsBeingDispatched ] = true ;
778- }
779-
780- const root = this [ kEvents ] . get ( type ) ;
781- if ( root === undefined || root . next === undefined ) {
782- if ( event !== undefined )
783- event [ kIsBeingDispatched ] = false ;
784- return true ;
785- }
786-
787- let handler = root . next ;
788- let next ;
789835
790- const iterationCondition = ( ) => {
791- if ( handler === undefined ) {
792- return false ;
793- }
794- return root . resistStopPropagation || handler . passive || event ?. [ kStop ] !== true ;
795- } ;
796- while ( iterationCondition ( ) ) {
797- // Cache the next item in case this iteration removes the current one
798- next = handler . next ;
799-
800- if ( handler . removed || ( event ?. [ kStop ] === true && ! handler . resistStopPropagation ) ) {
801- // Deal with the case an event is removed while event handlers are
802- // Being processed (removeEventListener called from a listener)
803- // And the case of event.stopImmediatePropagation() being called
804- // For events not flagged as resistStopPropagation
805- handler = next ;
806- continue ;
807- }
808- if ( handler . once ) {
809- handler . remove ( ) ;
810- root . size -- ;
811- const { listener, capture } = handler ;
812- this [ kRemoveListener ] ( root . size , type , listener , capture ) ;
836+ const root = this [ kEvents ] . get ( type ) ;
837+ if ( root === undefined || root . next === undefined ) {
838+ if ( event !== undefined )
839+ event [ kIsBeingDispatched ] = false ;
840+ return true ;
813841 }
814842
815- try {
816- let arg ;
817- if ( handler . isNodeStyleListener ) {
818- arg = nodeValue ;
819- } else {
820- arg = createEvent ( ) ;
843+ let handler = root . next ;
844+ let next ;
845+
846+ const iterationCondition = ( ) => {
847+ if ( handler === undefined ) {
848+ return false ;
821849 }
822- const callback = handler . weak ?
823- handler . callback . deref ( ) : handler . callback ;
824- let result ;
825- if ( callback ) {
826- result = FunctionPrototypeCall ( callback , this , arg ) ;
827- if ( ! handler . isNodeStyleListener ) {
828- arg [ kIsBeingDispatched ] = false ;
850+ return root . resistStopPropagation || handler . passive || event ?. [ kStop ] !== true ;
851+ } ;
852+ while ( iterationCondition ( ) ) {
853+ // Cache the next item in case this iteration removes the current one
854+ next = handler . next ;
855+
856+ if ( handler . removed || ( event ?. [ kStop ] === true && ! handler . resistStopPropagation ) ) {
857+ // Deal with the case an event is removed while event handlers are
858+ // Being processed (removeEventListener called from a listener)
859+ // And the case of event.stopImmediatePropagation() being called
860+ // For events not flagged as resistStopPropagation
861+ handler = next ;
862+ continue ;
863+ }
864+ if ( handler . once ) {
865+ handler . remove ( ) ;
866+ root . size -- ;
867+ const { listener, capture } = handler ;
868+ this [ kRemoveListener ] ( root . size , type , listener , capture ) ;
869+ }
870+
871+ try {
872+ let arg ;
873+ if ( handler . isNodeStyleListener ) {
874+ arg = nodeValue ;
875+ } else {
876+ arg = createEvent ( ) ;
829877 }
878+ const callback = handler . weak ?
879+ handler . callback . deref ( ) : handler . callback ;
880+ let result ;
881+ if ( callback ) {
882+ result = FunctionPrototypeCall ( callback , this , arg ) ;
883+ if ( ! handler . isNodeStyleListener ) {
884+ arg [ kIsBeingDispatched ] = false ;
885+ }
886+ }
887+ if ( result !== undefined && result !== null )
888+ addCatch ( result ) ;
889+ } catch ( err ) {
890+ emitUncaughtException ( err ) ;
830891 }
831- if ( result !== undefined && result !== null )
832- addCatch ( result ) ;
833- } catch ( err ) {
834- emitUncaughtException ( err ) ;
835- }
836892
837- handler = next ;
893+ handler = next ;
894+ }
838895 }
839896
840897 if ( event !== undefined )
0 commit comments