8
8
FunctionPrototypeCall,
9
9
NumberIsInteger,
10
10
ObjectAssign,
11
+ ObjectCreate,
11
12
ObjectDefineProperties,
12
13
ObjectDefineProperty,
13
14
ObjectGetOwnPropertyDescriptor,
@@ -39,6 +40,7 @@ const { customInspectSymbol } = require('internal/util');
39
40
const { inspect } = require ( 'util' ) ;
40
41
41
42
const kIsEventTarget = SymbolFor ( 'nodejs.event_target' ) ;
43
+ const kIsNodeEventTarget = Symbol ( 'kIsNodeEventTarget' ) ;
42
44
43
45
const EventEmitter = require ( 'events' ) ;
44
46
const {
@@ -80,6 +82,10 @@ const isTrusted = ObjectGetOwnPropertyDescriptor({
80
82
}
81
83
} , 'isTrusted' ) . get ;
82
84
85
+ function isEvent ( value ) {
86
+ return typeof value ?. [ kType ] === 'string' ;
87
+ }
88
+
83
89
class Event {
84
90
constructor ( type , options = null ) {
85
91
if ( arguments . length === 0 )
@@ -110,6 +116,8 @@ class Event {
110
116
}
111
117
112
118
[ customInspectSymbol ] ( depth , options ) {
119
+ if ( ! isEvent ( this ) )
120
+ throw new ERR_INVALID_THIS ( 'Event' ) ;
113
121
const name = this . constructor . name ;
114
122
if ( depth < 0 )
115
123
return name ;
@@ -127,46 +135,111 @@ class Event {
127
135
}
128
136
129
137
stopImmediatePropagation ( ) {
138
+ if ( ! isEvent ( this ) )
139
+ throw new ERR_INVALID_THIS ( 'Event' ) ;
130
140
this [ kStop ] = true ;
131
141
}
132
142
133
143
preventDefault ( ) {
144
+ if ( ! isEvent ( this ) )
145
+ throw new ERR_INVALID_THIS ( 'Event' ) ;
134
146
this [ kDefaultPrevented ] = true ;
135
147
}
136
148
137
- get target ( ) { return this [ kTarget ] ; }
138
- get currentTarget ( ) { return this [ kTarget ] ; }
139
- get srcElement ( ) { return this [ kTarget ] ; }
149
+ get target ( ) {
150
+ if ( ! isEvent ( this ) )
151
+ throw new ERR_INVALID_THIS ( 'Event' ) ;
152
+ return this [ kTarget ] ;
153
+ }
140
154
141
- get type ( ) { return this [ kType ] ; }
155
+ get currentTarget ( ) {
156
+ if ( ! isEvent ( this ) )
157
+ throw new ERR_INVALID_THIS ( 'Event' ) ;
158
+ return this [ kTarget ] ;
159
+ }
142
160
143
- get cancelable ( ) { return this [ kCancelable ] ; }
161
+ get srcElement ( ) {
162
+ if ( ! isEvent ( this ) )
163
+ throw new ERR_INVALID_THIS ( 'Event' ) ;
164
+ return this [ kTarget ] ;
165
+ }
166
+
167
+ get type ( ) {
168
+ if ( ! isEvent ( this ) )
169
+ throw new ERR_INVALID_THIS ( 'Event' ) ;
170
+ return this [ kType ] ;
171
+ }
172
+
173
+ get cancelable ( ) {
174
+ if ( ! isEvent ( this ) )
175
+ throw new ERR_INVALID_THIS ( 'Event' ) ;
176
+ return this [ kCancelable ] ;
177
+ }
144
178
145
179
get defaultPrevented ( ) {
180
+ if ( ! isEvent ( this ) )
181
+ throw new ERR_INVALID_THIS ( 'Event' ) ;
146
182
return this [ kCancelable ] && this [ kDefaultPrevented ] ;
147
183
}
148
184
149
- get timeStamp ( ) { return this [ kTimestamp ] ; }
185
+ get timeStamp ( ) {
186
+ if ( ! isEvent ( this ) )
187
+ throw new ERR_INVALID_THIS ( 'Event' ) ;
188
+ return this [ kTimestamp ] ;
189
+ }
150
190
151
191
152
192
// The following are non-op and unused properties/methods from Web API Event.
153
193
// These are not supported in Node.js and are provided purely for
154
194
// API completeness.
155
195
156
- composedPath ( ) { return this [ kIsBeingDispatched ] ? [ this [ kTarget ] ] : [ ] ; }
157
- get returnValue ( ) { return ! this . defaultPrevented ; }
158
- get bubbles ( ) { return this [ kBubbles ] ; }
159
- get composed ( ) { return this [ kComposed ] ; }
196
+ composedPath ( ) {
197
+ if ( ! isEvent ( this ) )
198
+ throw new ERR_INVALID_THIS ( 'Event' ) ;
199
+ return this [ kIsBeingDispatched ] ? [ this [ kTarget ] ] : [ ] ;
200
+ }
201
+
202
+ get returnValue ( ) {
203
+ if ( ! isEvent ( this ) )
204
+ throw new ERR_INVALID_THIS ( 'Event' ) ;
205
+ return ! this . defaultPrevented ;
206
+ }
207
+
208
+ get bubbles ( ) {
209
+ if ( ! isEvent ( this ) )
210
+ throw new ERR_INVALID_THIS ( 'Event' ) ;
211
+ return this [ kBubbles ] ;
212
+ }
213
+
214
+ get composed ( ) {
215
+ if ( ! isEvent ( this ) )
216
+ throw new ERR_INVALID_THIS ( 'Event' ) ;
217
+ return this [ kComposed ] ;
218
+ }
219
+
160
220
get eventPhase ( ) {
221
+ if ( ! isEvent ( this ) )
222
+ throw new ERR_INVALID_THIS ( 'Event' ) ;
161
223
return this [ kIsBeingDispatched ] ? Event . AT_TARGET : Event . NONE ;
162
224
}
163
- get cancelBubble ( ) { return this [ kPropagationStopped ] ; }
225
+
226
+ get cancelBubble ( ) {
227
+ if ( ! isEvent ( this ) )
228
+ throw new ERR_INVALID_THIS ( 'Event' ) ;
229
+ return this [ kPropagationStopped ] ;
230
+ }
231
+
164
232
set cancelBubble ( value ) {
233
+ if ( ! isEvent ( this ) )
234
+ throw new ERR_INVALID_THIS ( 'Event' ) ;
165
235
if ( value ) {
166
236
this . stopPropagation ( ) ;
167
237
}
168
238
}
239
+
169
240
stopPropagation ( ) {
241
+ if ( ! isEvent ( this ) )
242
+ throw new ERR_INVALID_THIS ( 'Event' ) ;
170
243
this [ kPropagationStopped ] = true ;
171
244
}
172
245
@@ -176,12 +249,34 @@ class Event {
176
249
static BUBBLING_PHASE = 3 ;
177
250
}
178
251
179
- ObjectDefineProperty ( Event . prototype , SymbolToStringTag , {
180
- writable : false ,
181
- enumerable : false ,
182
- configurable : true ,
183
- value : 'Event' ,
184
- } ) ;
252
+ const kEnumerableProperty = ObjectCreate ( null ) ;
253
+ kEnumerableProperty . enumerable = true ;
254
+
255
+ ObjectDefineProperties (
256
+ Event . prototype , {
257
+ [ SymbolToStringTag ] : {
258
+ writable : false ,
259
+ enumerable : false ,
260
+ configurable : true ,
261
+ value : 'Event' ,
262
+ } ,
263
+ stopImmediatePropagation : kEnumerableProperty ,
264
+ preventDefault : kEnumerableProperty ,
265
+ target : kEnumerableProperty ,
266
+ currentTarget : kEnumerableProperty ,
267
+ srcElement : kEnumerableProperty ,
268
+ type : kEnumerableProperty ,
269
+ cancelable : kEnumerableProperty ,
270
+ defaultPrevented : kEnumerableProperty ,
271
+ timeStamp : kEnumerableProperty ,
272
+ composedPath : kEnumerableProperty ,
273
+ returnValue : kEnumerableProperty ,
274
+ bubbles : kEnumerableProperty ,
275
+ composed : kEnumerableProperty ,
276
+ eventPhase : kEnumerableProperty ,
277
+ cancelBubble : kEnumerableProperty ,
278
+ stopPropagation : kEnumerableProperty ,
279
+ } ) ;
185
280
186
281
class NodeCustomEvent extends Event {
187
282
constructor ( type , options ) {
@@ -297,6 +392,8 @@ class EventTarget {
297
392
[ kRemoveListener ] ( size , type , listener , capture ) { }
298
393
299
394
addEventListener ( type , listener , options = { } ) {
395
+ if ( ! isEventTarget ( this ) )
396
+ throw new ERR_INVALID_THIS ( 'EventTarget' ) ;
300
397
if ( arguments . length < 2 )
301
398
throw new ERR_MISSING_ARGS ( 'type' , 'listener' ) ;
302
399
@@ -368,6 +465,8 @@ class EventTarget {
368
465
}
369
466
370
467
removeEventListener ( type , listener , options = { } ) {
468
+ if ( ! isEventTarget ( this ) )
469
+ throw new ERR_INVALID_THIS ( 'EventTarget' ) ;
371
470
if ( ! shouldAddListener ( listener ) )
372
471
return ;
373
472
@@ -393,12 +492,12 @@ class EventTarget {
393
492
}
394
493
395
494
dispatchEvent ( event ) {
396
- if ( ! ( event instanceof Event ) )
397
- throw new ERR_INVALID_ARG_TYPE ( 'event' , 'Event' , event ) ;
398
-
399
495
if ( ! isEventTarget ( this ) )
400
496
throw new ERR_INVALID_THIS ( 'EventTarget' ) ;
401
497
498
+ if ( ! ( event instanceof Event ) )
499
+ throw new ERR_INVALID_ARG_TYPE ( 'event' , 'Event' , event ) ;
500
+
402
501
if ( event [ kIsBeingDispatched ] )
403
502
throw new ERR_EVENT_RECURSION ( event . type ) ;
404
503
@@ -479,6 +578,8 @@ class EventTarget {
479
578
return new NodeCustomEvent ( type , { detail : nodeValue } ) ;
480
579
}
481
580
[ customInspectSymbol ] ( depth , options ) {
581
+ if ( ! isEventTarget ( this ) )
582
+ throw new ERR_INVALID_THIS ( 'EventTarget' ) ;
482
583
const name = this . constructor . name ;
483
584
if ( depth < 0 )
484
585
return name ;
@@ -492,22 +593,23 @@ class EventTarget {
492
593
}
493
594
494
595
ObjectDefineProperties ( EventTarget . prototype , {
495
- addEventListener : { enumerable : true } ,
496
- removeEventListener : { enumerable : true } ,
497
- dispatchEvent : { enumerable : true }
498
- } ) ;
499
- ObjectDefineProperty ( EventTarget . prototype , SymbolToStringTag , {
500
- writable : false ,
501
- enumerable : false ,
502
- configurable : true ,
503
- value : 'EventTarget' ,
596
+ addEventListener : kEnumerableProperty ,
597
+ removeEventListener : kEnumerableProperty ,
598
+ dispatchEvent : kEnumerableProperty ,
599
+ [ SymbolToStringTag ] : {
600
+ writable : false ,
601
+ enumerable : false ,
602
+ configurable : true ,
603
+ value : 'EventTarget' ,
604
+ }
504
605
} ) ;
505
606
506
607
function initNodeEventTarget ( self ) {
507
608
initEventTarget ( self ) ;
508
609
}
509
610
510
611
class NodeEventTarget extends EventTarget {
612
+ static [ kIsNodeEventTarget ] = true ;
511
613
static defaultMaxListeners = 10 ;
512
614
513
615
constructor ( ) {
@@ -516,55 +618,77 @@ class NodeEventTarget extends EventTarget {
516
618
}
517
619
518
620
setMaxListeners ( n ) {
621
+ if ( ! isNodeEventTarget ( this ) )
622
+ throw new ERR_INVALID_THIS ( 'NodeEventTarget' ) ;
519
623
EventEmitter . setMaxListeners ( n , this ) ;
520
624
}
521
625
522
626
getMaxListeners ( ) {
627
+ if ( ! isNodeEventTarget ( this ) )
628
+ throw new ERR_INVALID_THIS ( 'NodeEventTarget' ) ;
523
629
return this [ kMaxEventTargetListeners ] ;
524
630
}
525
631
526
632
eventNames ( ) {
633
+ if ( ! isNodeEventTarget ( this ) )
634
+ throw new ERR_INVALID_THIS ( 'NodeEventTarget' ) ;
527
635
return ArrayFrom ( this [ kEvents ] . keys ( ) ) ;
528
636
}
529
637
530
638
listenerCount ( type ) {
639
+ if ( ! isNodeEventTarget ( this ) )
640
+ throw new ERR_INVALID_THIS ( 'NodeEventTarget' ) ;
531
641
const root = this [ kEvents ] . get ( String ( type ) ) ;
532
642
return root !== undefined ? root . size : 0 ;
533
643
}
534
644
535
645
off ( type , listener , options ) {
646
+ if ( ! isNodeEventTarget ( this ) )
647
+ throw new ERR_INVALID_THIS ( 'NodeEventTarget' ) ;
536
648
this . removeEventListener ( type , listener , options ) ;
537
649
return this ;
538
650
}
539
651
540
652
removeListener ( type , listener , options ) {
653
+ if ( ! isNodeEventTarget ( this ) )
654
+ throw new ERR_INVALID_THIS ( 'NodeEventTarget' ) ;
541
655
this . removeEventListener ( type , listener , options ) ;
542
656
return this ;
543
657
}
544
658
545
659
on ( type , listener ) {
660
+ if ( ! isNodeEventTarget ( this ) )
661
+ throw new ERR_INVALID_THIS ( 'NodeEventTarget' ) ;
546
662
this . addEventListener ( type , listener , { [ kIsNodeStyleListener ] : true } ) ;
547
663
return this ;
548
664
}
549
665
550
666
addListener ( type , listener ) {
667
+ if ( ! isNodeEventTarget ( this ) )
668
+ throw new ERR_INVALID_THIS ( 'NodeEventTarget' ) ;
551
669
this . addEventListener ( type , listener , { [ kIsNodeStyleListener ] : true } ) ;
552
670
return this ;
553
671
}
554
672
emit ( type , arg ) {
673
+ if ( ! isNodeEventTarget ( this ) )
674
+ throw new ERR_INVALID_THIS ( 'NodeEventTarget' ) ;
555
675
validateString ( type , 'type' ) ;
556
676
const hadListeners = this . listenerCount ( type ) > 0 ;
557
677
this [ kHybridDispatch ] ( arg , type ) ;
558
678
return hadListeners ;
559
679
}
560
680
561
681
once ( type , listener ) {
682
+ if ( ! isNodeEventTarget ( this ) )
683
+ throw new ERR_INVALID_THIS ( 'NodeEventTarget' ) ;
562
684
this . addEventListener ( type , listener ,
563
685
{ once : true , [ kIsNodeStyleListener ] : true } ) ;
564
686
return this ;
565
687
}
566
688
567
689
removeAllListeners ( type ) {
690
+ if ( ! isNodeEventTarget ( this ) )
691
+ throw new ERR_INVALID_THIS ( 'NodeEventTarget' ) ;
568
692
if ( type !== undefined ) {
569
693
this [ kEvents ] . delete ( String ( type ) ) ;
570
694
} else {
@@ -576,17 +700,17 @@ class NodeEventTarget extends EventTarget {
576
700
}
577
701
578
702
ObjectDefineProperties ( NodeEventTarget . prototype , {
579
- setMaxListeners : { enumerable : true } ,
580
- getMaxListeners : { enumerable : true } ,
581
- eventNames : { enumerable : true } ,
582
- listenerCount : { enumerable : true } ,
583
- off : { enumerable : true } ,
584
- removeListener : { enumerable : true } ,
585
- on : { enumerable : true } ,
586
- addListener : { enumerable : true } ,
587
- once : { enumerable : true } ,
588
- emit : { enumerable : true } ,
589
- removeAllListeners : { enumerable : true } ,
703
+ setMaxListeners : kEnumerableProperty ,
704
+ getMaxListeners : kEnumerableProperty ,
705
+ eventNames : kEnumerableProperty ,
706
+ listenerCount : kEnumerableProperty ,
707
+ off : kEnumerableProperty ,
708
+ removeListener : kEnumerableProperty ,
709
+ on : kEnumerableProperty ,
710
+ addListener : kEnumerableProperty ,
711
+ once : kEnumerableProperty ,
712
+ emit : kEnumerableProperty ,
713
+ removeAllListeners : kEnumerableProperty ,
590
714
} ) ;
591
715
592
716
// EventTarget API
@@ -631,6 +755,10 @@ function isEventTarget(obj) {
631
755
return obj ?. constructor ?. [ kIsEventTarget ] ;
632
756
}
633
757
758
+ function isNodeEventTarget ( obj ) {
759
+ return obj ?. constructor ?. [ kIsNodeEventTarget ] ;
760
+ }
761
+
634
762
function addCatch ( promise ) {
635
763
const then = promise . then ;
636
764
if ( typeof then === 'function' ) {
0 commit comments