@@ -4,6 +4,53 @@ const common = require('../common');
4
4
const { once, EventEmitter } = require ( 'events' ) ;
5
5
const { strictEqual, deepStrictEqual } = require ( 'assert' ) ;
6
6
7
+ class EventTargetMock {
8
+ constructor ( ) {
9
+ this . events = { } ;
10
+ }
11
+
12
+ addEventListener = common . mustCall ( function ( name , listener , options ) {
13
+ if ( ! ( name in this . events ) ) {
14
+ this . events [ name ] = { listeners : [ ] , options } ;
15
+ }
16
+ this . events [ name ] . listeners . push ( listener ) ;
17
+ } ) ;
18
+
19
+ removeEventListener = common . mustCall ( function ( name , callback ) {
20
+ if ( ! ( name in this . events ) ) {
21
+ return ;
22
+ }
23
+ const event = this . events [ name ] ;
24
+ const stack = event . listeners ;
25
+
26
+ for ( let i = 0 , l = stack . length ; i < l ; i ++ ) {
27
+ if ( stack [ i ] === callback ) {
28
+ stack . splice ( i , 1 ) ;
29
+ if ( stack . length === 0 ) {
30
+ Reflect . deleteProperty ( this . events , name ) ;
31
+ }
32
+ return ;
33
+ }
34
+ }
35
+ } ) ;
36
+
37
+ dispatchEvent = function ( name , ...arg ) {
38
+ if ( ! ( name in this . events ) ) {
39
+ return true ;
40
+ }
41
+ const event = this . events [ name ] ;
42
+ const stack = event . listeners . slice ( ) ;
43
+
44
+ for ( let i = 0 , l = stack . length ; i < l ; i ++ ) {
45
+ stack [ i ] . apply ( this , arg ) ;
46
+ if ( event . options . once ) {
47
+ this . removeEventListener ( name , stack [ i ] ) ;
48
+ }
49
+ }
50
+ return ! name . defaultPrevented ;
51
+ } ;
52
+ }
53
+
7
54
async function onceAnEvent ( ) {
8
55
const ee = new EventEmitter ( ) ;
9
56
@@ -84,10 +131,48 @@ async function onceError() {
84
131
strictEqual ( ee . listenerCount ( 'myevent' ) , 0 ) ;
85
132
}
86
133
134
+ async function onceWithEventTarget ( ) {
135
+ const et = new EventTargetMock ( ) ;
136
+
137
+ process . nextTick ( ( ) => {
138
+ et . dispatchEvent ( 'myevent' , 42 ) ;
139
+ } ) ;
140
+ const [ value ] = await once ( et , 'myevent' ) ;
141
+ strictEqual ( value , 42 ) ;
142
+ strictEqual ( Reflect . has ( et . events , 'myevent' ) , false ) ;
143
+ }
144
+
145
+ async function onceWithEventTargetTwoArgs ( ) {
146
+ const et = new EventTargetMock ( ) ;
147
+
148
+ process . nextTick ( ( ) => {
149
+ et . dispatchEvent ( 'myevent' , 42 , 24 ) ;
150
+ } ) ;
151
+
152
+ const value = await once ( et , 'myevent' ) ;
153
+ deepStrictEqual ( value , [ 42 , 24 ] ) ;
154
+ }
155
+
156
+ async function onceWithEventTargetError ( ) {
157
+ const et = new EventTargetMock ( ) ;
158
+
159
+ const expected = new Error ( 'kaboom' ) ;
160
+ process . nextTick ( ( ) => {
161
+ et . dispatchEvent ( 'error' , expected ) ;
162
+ } ) ;
163
+
164
+ const [ err ] = await once ( et , 'error' ) ;
165
+ strictEqual ( err , expected ) ;
166
+ strictEqual ( Reflect . has ( et . events , 'error' ) , false ) ;
167
+ }
168
+
87
169
Promise . all ( [
88
170
onceAnEvent ( ) ,
89
171
onceAnEventWithTwoArgs ( ) ,
90
172
catchesErrors ( ) ,
91
173
stopListeningAfterCatchingError ( ) ,
92
- onceError ( )
174
+ onceError ( ) ,
175
+ onceWithEventTarget ( ) ,
176
+ onceWithEventTargetTwoArgs ( ) ,
177
+ onceWithEventTargetError ( ) ,
93
178
] ) . then ( common . mustCall ( ) ) ;
0 commit comments