@@ -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 ] &&
@@ -644,45 +646,58 @@ class EventTarget {
644646 }
645647 }
646648
647- type = webidl . converters . DOMString ( type ) ;
648-
649- let root = this [ kEvents ] . get ( type ) ;
649+ if ( options === kEmptyObject && this . #fastHandlers != null ) {
650+ const entry = this . #fastHandlers. get ( type ) ;
651+ if ( entry === undefined ) {
652+ this . #fastHandlers. set ( type , listener ) ;
653+ } else if ( typeof entry === 'function' ) {
654+ this . #fastHandlers. set ( type , new Set ( [ entry , listener ] ) ) ;
655+ } else {
656+ entry . add ( listener ) ;
657+ }
658+ } else {
659+ // XXX: Convert fastMode to slowMode....
660+
661+ type = webidl . converters . DOMString ( type ) ;
662+
663+ let root = this [ kEvents ] . get ( type ) ;
664+
665+ if ( root === undefined ) {
666+ root = { size : 1 , next : undefined , resistStopPropagation : Boolean ( resistStopPropagation ) } ;
667+ // This is the first handler in our linked list.
668+ new Listener ( this , type , root , listener , once , capture , passive ,
669+ isNodeStyleListener , weak , resistStopPropagation ) ;
670+ this [ kNewListener ] (
671+ root . size ,
672+ type ,
673+ listener ,
674+ once ,
675+ capture ,
676+ passive ,
677+ weak ) ;
678+ this [ kEvents ] . set ( type , root ) ;
679+ return ;
680+ }
650681
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- }
682+ let handler = root . next ;
683+ let previous = root ;
667684
668- let handler = root . next ;
669- let previous = root ;
685+ // We have to walk the linked list to see if we have a match
686+ while ( handler !== undefined && ! handler . same ( listener , capture ) ) {
687+ previous = handler ;
688+ handler = handler . next ;
689+ }
670690
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- }
691+ if ( handler !== undefined ) { // Duplicate! Ignore
692+ return ;
693+ }
676694
677- if ( handler !== undefined ) { // Duplicate! Ignore
678- return ;
695+ new Listener ( this , type , previous , listener , once , capture , passive ,
696+ isNodeStyleListener , weak , resistStopPropagation ) ;
697+ root . size ++ ;
698+ root . resistStopPropagation ||= Boolean ( resistStopPropagation ) ;
699+ this [ kNewListener ] ( root . size , type , listener , once , capture , passive , weak ) ;
679700 }
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 ) ;
686701 }
687702
688703 /**
@@ -700,24 +715,37 @@ class EventTarget {
700715 if ( ! validateEventListener ( listener ) )
701716 return ;
702717
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 ;
709-
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 ;
718+ if ( options === kEmptyObject && this . #fastHandlers != null ) {
719+ const entry = this . #fastHandlers. get ( type ) ;
720+ if ( entry === undefined ) {
721+ // Do nothing
722+ } else if ( entry === listener ) {
723+ this . #fastHandlers. delete ( type ) ;
724+ } else {
725+ entry . delete ( listener ) ;
726+ }
727+ } else {
728+ // XXX: Convert fastMode to slowMode....
729+
730+ type = webidl . converters . DOMString ( type ) ;
731+ const capture = options ?. capture === true ;
732+
733+ const root = this [ kEvents ] . get ( type ) ;
734+ if ( root === undefined || root . next === undefined )
735+ return ;
736+
737+ let handler = root . next ;
738+ while ( handler !== undefined ) {
739+ if ( handler . same ( listener , capture ) ) {
740+ handler . remove ( ) ;
741+ root . size -- ;
742+ if ( root . size === 0 )
743+ this [ kEvents ] . delete ( type ) ;
744+ this [ kRemoveListener ] ( root . size , type , listener , capture ) ;
745+ break ;
746+ }
747+ handler = handler . next ;
719748 }
720- handler = handler . next ;
721749 }
722750 }
723751
@@ -764,77 +792,81 @@ class EventTarget {
764792 }
765793
766794 [ kHybridDispatch ] ( nodeValue , type , event ) {
767- const createEvent = ( ) => {
768- if ( event === undefined ) {
769- event = this [ kCreateEvent ] ( nodeValue , type ) ;
795+ if ( this . #fastHandlers != null ) {
796+ // XXX: Implement
797+ } else {
798+ const createEvent = ( ) => {
799+ if ( event === undefined ) {
800+ event = this [ kCreateEvent ] ( nodeValue , type ) ;
801+ event [ kTarget ] = this ;
802+ event [ kIsBeingDispatched ] = true ;
803+ }
804+ return event ;
805+ } ;
806+ if ( event !== undefined ) {
770807 event [ kTarget ] = this ;
771808 event [ kIsBeingDispatched ] = true ;
772809 }
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- }
786810
787- let handler = root . next ;
788- let next ;
789-
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 ) ;
811+ const root = this [ kEvents ] . get ( type ) ;
812+ if ( root === undefined || root . next === undefined ) {
813+ if ( event !== undefined )
814+ event [ kIsBeingDispatched ] = false ;
815+ return true ;
813816 }
814817
815- try {
816- let arg ;
817- if ( handler . isNodeStyleListener ) {
818- arg = nodeValue ;
819- } else {
820- arg = createEvent ( ) ;
818+ let handler = root . next ;
819+ let next ;
820+
821+ const iterationCondition = ( ) => {
822+ if ( handler === undefined ) {
823+ return false ;
824+ }
825+ return root . resistStopPropagation || handler . passive || event ?. [ kStop ] !== true ;
826+ } ;
827+ while ( iterationCondition ( ) ) {
828+ // Cache the next item in case this iteration removes the current one
829+ next = handler . next ;
830+
831+ if ( handler . removed || ( event ?. [ kStop ] === true && ! handler . resistStopPropagation ) ) {
832+ // Deal with the case an event is removed while event handlers are
833+ // Being processed (removeEventListener called from a listener)
834+ // And the case of event.stopImmediatePropagation() being called
835+ // For events not flagged as resistStopPropagation
836+ handler = next ;
837+ continue ;
838+ }
839+ if ( handler . once ) {
840+ handler . remove ( ) ;
841+ root . size -- ;
842+ const { listener, capture } = handler ;
843+ this [ kRemoveListener ] ( root . size , type , listener , capture ) ;
821844 }
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 ;
845+
846+ try {
847+ let arg ;
848+ if ( handler . isNodeStyleListener ) {
849+ arg = nodeValue ;
850+ } else {
851+ arg = createEvent ( ) ;
852+ }
853+ const callback = handler . weak ?
854+ handler . callback . deref ( ) : handler . callback ;
855+ let result ;
856+ if ( callback ) {
857+ result = FunctionPrototypeCall ( callback , this , arg ) ;
858+ if ( ! handler . isNodeStyleListener ) {
859+ arg [ kIsBeingDispatched ] = false ;
860+ }
829861 }
862+ if ( result !== undefined && result !== null )
863+ addCatch ( result ) ;
864+ } catch ( err ) {
865+ emitUncaughtException ( err ) ;
830866 }
831- if ( result !== undefined && result !== null )
832- addCatch ( result ) ;
833- } catch ( err ) {
834- emitUncaughtException ( err ) ;
835- }
836867
837- handler = next ;
868+ handler = next ;
869+ }
838870 }
839871
840872 if ( event !== undefined )
0 commit comments