Skip to content

Commit 5b26439

Browse files
araujoguiaduh95
authored andcommitted
lib: lazily initialize kEvents and kHandlers maps
Signed-off-by: Guilherme Araújo <arauujogui@gmail.com> PR-URL: #63702 Reviewed-By: Stephen Belanger <admin@stephenbelanger.com> Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
1 parent 2f567ed commit 5b26439

3 files changed

Lines changed: 79 additions & 17 deletions

File tree

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
'use strict';
2+
3+
constcommon=require('../common.js');
4+
constassert=require('node:assert');
5+
6+
constbench=common.createBenchmark(main,{
7+
n: [1e6],
8+
kind: ['AbortController','AbortSignal.timeout'],
9+
});
10+
11+
functionmain({ n, kind }){
12+
letresult;
13+
14+
switch(kind){
15+
case'AbortController':
16+
bench.start();
17+
for(leti=0;i<n;i++)
18+
result=newAbortController().signal;// AbortSignal is created lazily on first .signal access
19+
bench.end(n);
20+
break;
21+
case'AbortSignal.timeout':
22+
bench.start();
23+
for(leti=0;i<n;i++)
24+
result=AbortSignal.timeout(1);
25+
bench.end(n);
26+
break;
27+
default:
28+
thrownewError('Invalid kind');
29+
}
30+
31+
// Avoid V8 dead code elimination
32+
assert.ok(result);
33+
}

‎lib/events.js‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -927,7 +927,7 @@ function getEventListeners(emitterOrTarget, type) {
927927
// Require event target lazily to avoid always loading it
928928
const{ isEventTarget, kEvents }=require('internal/event_target');
929929
if(isEventTarget(emitterOrTarget)){
930-
constroot=emitterOrTarget[kEvents].get(type);
930+
constroot=emitterOrTarget[kEvents]?.get(type);
931931
constlisteners=[];
932932
lethandler=root?.next;
933933
while(handler?.listener!==undefined){
@@ -972,7 +972,7 @@ function listenerCount(emitterOrTarget, type) {
972972
}
973973
const{ isEventTarget, kEvents }=require('internal/event_target');
974974
if(isEventTarget(emitterOrTarget)){
975-
returnemitterOrTarget[kEvents].get(type)?.size??0;
975+
returnemitterOrTarget[kEvents]?.get(type)?.size??0;
976976
}
977977
thrownewERR_INVALID_ARG_TYPE('emitter',
978978
['EventEmitter','EventTarget'],

‎lib/internal/event_target.js‎

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -551,10 +551,16 @@ class Listener {
551551
}
552552

553553
functioninitEventTarget(self){
554-
self[kEvents]=newSafeMap();
554+
self[kEvents]=undefined;
555555
self[kMaxEventTargetListeners]=EventEmitter.defaultMaxListeners;
556556
self[kMaxEventTargetListenersWarned]=false;
557-
self[kHandlers]=newSafeMap();
557+
self[kHandlers]=undefined;
558+
}
559+
560+
functiongetEventsMap(self){
561+
if(self[kEvents]===undefined)
562+
self[kEvents]=newSafeMap();
563+
returnself[kEvents];
558564
}
559565

560566
classEventTarget{
@@ -660,7 +666,8 @@ class EventTarget {
660666

661667
type=webidl.converters.DOMString(type);
662668

663-
letroot=this[kEvents].get(type);
669+
consteventsMap=getEventsMap(this);
670+
letroot=eventsMap.get(type);
664671

665672
if(root===undefined){
666673
root={size: 1,next: undefined,resistStopPropagation: Boolean(resistStopPropagation)};
@@ -675,7 +682,7 @@ class EventTarget {
675682
capture,
676683
passive,
677684
weak);
678-
this[kEvents].set(type,root);
685+
eventsMap.set(type,root);
679686
return;
680687
}
681688

@@ -717,6 +724,9 @@ class EventTarget {
717724
type=webidl.converters.DOMString(type);
718725
constcapture=options?.capture===true;
719726

727+
if(this[kEvents]===undefined)
728+
return;
729+
720730
constroot=this[kEvents].get(type);
721731
if(root===undefined||root.next===undefined)
722732
return;
@@ -736,6 +746,9 @@ class EventTarget {
736746
}
737747

738748
[kRemoveWeakListenerHelper](type,listener){
749+
if(this[kEvents]===undefined)
750+
return;
751+
739752
constroot=this[kEvents].get(type);
740753
if(root===undefined||root.next===undefined)
741754
return;
@@ -791,7 +804,7 @@ class EventTarget {
791804
event[kIsBeingDispatched]=true;
792805
}
793806

794-
constroot=this[kEvents].get(type);
807+
constroot=this[kEvents]?.get(type);
795808
if(root===undefined||root.next===undefined){
796809
if(event!==undefined)
797810
event[kIsBeingDispatched]=false;
@@ -927,6 +940,8 @@ class NodeEventTarget extends EventTarget {
927940
eventNames(){
928941
if(!isNodeEventTarget(this))
929942
thrownewERR_INVALID_THIS('NodeEventTarget');
943+
if(this[kEvents]===undefined)
944+
return[];
930945
returnArrayFrom(this[kEvents].keys());
931946
}
932947

@@ -937,6 +952,8 @@ class NodeEventTarget extends EventTarget {
937952
listenerCount(type){
938953
if(!isNodeEventTarget(this))
939954
thrownewERR_INVALID_THIS('NodeEventTarget');
955+
if(this[kEvents]===undefined)
956+
return0;
940957
constroot=this[kEvents].get(String(type));
941958
returnroot!==undefined ? root.size : 0;
942959
}
@@ -1029,11 +1046,12 @@ class NodeEventTarget extends EventTarget {
10291046
removeAllListeners(type){
10301047
if(!isNodeEventTarget(this))
10311048
thrownewERR_INVALID_THIS('NodeEventTarget');
1032-
if(type!==undefined){
1049+
if(this[kEvents]===undefined)
1050+
returnthis;
1051+
if(type!==undefined)
10331052
this[kEvents].delete(String(type));
1034-
}else{
1053+
else
10351054
this[kEvents].clear();
1036-
}
10371055

10381056
returnthis;
10391057
}
@@ -1145,18 +1163,29 @@ function defineEventHandler(emitter, name, event = name) {
11451163

11461164
functionset(value){
11471165
validateThisInternalField(this,kHandlers,'EventTarget');
1148-
letwrappedHandler=this[kHandlers]?.get(event);
1166+
if(this[kHandlers]===undefined)
1167+
this[kHandlers]=newSafeMap();
1168+
letwrappedHandler=this[kHandlers].get(event);
11491169
if(wrappedHandler){
1170+
consteventsMap=getEventsMap(this);
11501171
if(typeofwrappedHandler.handler==='function'){
1151-
this[kEvents].get(event).size--;
1152-
constsize=this[kEvents].get(event).size;
1153-
this[kRemoveListener](size,event,wrappedHandler.handler,false);
1172+
constroot=eventsMap.get(event);
1173+
if(root!==undefined){
1174+
root.size--;
1175+
this[kRemoveListener](root.size,event,wrappedHandler.handler,false);
1176+
}
11541177
}
11551178
wrappedHandler.handler=value;
11561179
if(typeofwrappedHandler.handler==='function'){
1157-
this[kEvents].get(event).size++;
1158-
constsize=this[kEvents].get(event).size;
1159-
this[kNewListener](size,event,value,false,false,false,false);
1180+
constroot=eventsMap.get(event);
1181+
if(root!==undefined){
1182+
root.size++;
1183+
this[kNewListener](root.size,event,value,false,false,false,false);
1184+
}else{
1185+
// The wrapper was externally removed from kEvents (e.g. via
1186+
// removeEventListener); re-register it so the handler fires.
1187+
this.addEventListener(event,wrappedHandler);
1188+
}
11601189
}
11611190
}else{
11621191
wrappedHandler=makeEventHandler(value);

0 commit comments

Comments
 (0)