@@ -4,6 +4,53 @@ const common = require('../common');
44const { once, EventEmitter } = require ( 'events' ) ;
55const { strictEqual, deepStrictEqual } = require ( 'assert' ) ;
66
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+
754async function onceAnEvent ( ) {
855 const ee = new EventEmitter ( ) ;
956
@@ -84,10 +131,48 @@ async function onceError() {
84131 strictEqual ( ee . listenerCount ( 'myevent' ) , 0 ) ;
85132}
86133
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+
87169Promise . all ( [
88170 onceAnEvent ( ) ,
89171 onceAnEventWithTwoArgs ( ) ,
90172 catchesErrors ( ) ,
91173 stopListeningAfterCatchingError ( ) ,
92- onceError ( )
174+ onceError ( ) ,
175+ onceWithEventTarget ( ) ,
176+ onceWithEventTargetTwoArgs ( ) ,
177+ onceWithEventTargetError ( ) ,
93178] ) . then ( common . mustCall ( ) ) ;
0 commit comments