@@ -84,9 +84,12 @@ type InternalListenersMap<
8484> 
8585
8686export  type  TypedListenerOptions  =  { 
87+   once ?: boolean 
8788  signal ?: AbortSignal 
8889} 
8990
91+ const  kListenerOptions  =  Symbol ( 'kListenerOptions' ) 
92+ 
9093export  namespace  Emitter  { 
9194  /** 
9295   * Returns an appropriate `Event` type for the given event type. 
@@ -145,13 +148,9 @@ export namespace Emitter {
145148
146149export  class  Emitter < EventMap  extends  DefaultEventMap >  { 
147150  #listeners: InternalListenersMap < typeof  this ,  EventMap > 
148-   #listenerOptions: WeakMap < Function ,  AddEventListenerOptions > 
149-   #abortControllers: WeakMap < Function ,  AbortController > 
150151
151152  constructor ( )  { 
152153    this . #listeners =  { }  as  InternalListenersMap < typeof  this ,  EventMap > 
153-     this . #listenerOptions =  new  WeakMap ( ) 
154-     this . #abortControllers =  new  WeakMap ( ) 
155154  } 
156155
157156  /** 
@@ -163,17 +162,8 @@ export class Emitter<EventMap extends DefaultEventMap> {
163162    type : EventType , 
164163    listener : Emitter . ListenerType < typeof  this ,  EventType ,  EventMap > , 
165164    options ?: TypedListenerOptions , 
166-   ) : AbortController  { 
167-     this . #addListener( type ,  listener ) 
168- 
169-     const  abortController  =  this . #createAbortController( type ,  listener ) 
170-     this . #listenerOptions. set ( listener ,  { 
171-       signal : options ?. signal 
172-         ? AbortSignal . any ( [ abortController . signal ,  options . signal ] ) 
173-         : abortController . signal , 
174-     } ) 
175- 
176-     return  abortController 
165+   ) : typeof  this  { 
166+     return  this . #addListener( type ,  listener ,  options ) 
177167  } 
178168
179169  /** 
@@ -184,19 +174,9 @@ export class Emitter<EventMap extends DefaultEventMap> {
184174  public  once < EventType  extends  keyof  EventMap  &  string > ( 
185175    type : EventType , 
186176    listener : Emitter . ListenerType < typeof  this ,  EventType ,  EventMap > , 
187-     options ?: TypedListenerOptions , 
188-   ) : AbortController  { 
189-     this . #addListener( type ,  listener ) 
190- 
191-     const  abortController  =  this . #createAbortController( type ,  listener ) 
192-     this . #listenerOptions. set ( listener ,  { 
193-       once : true , 
194-       signal : options ?. signal 
195-         ? AbortSignal . any ( [ abortController . signal ,  options . signal ] ) 
196-         : abortController . signal , 
197-     } ) 
198- 
199-     return  abortController 
177+     options ?: Omit < TypedListenerOptions ,  'once' > , 
178+   ) : typeof  this  { 
179+     return  this . on ( type ,  listener ,  {  ...( options  ||  { } ) ,  once : true  } ) 
200180  } 
201181
202182  /** 
@@ -208,21 +188,8 @@ export class Emitter<EventMap extends DefaultEventMap> {
208188    type : EventType , 
209189    listener : Emitter . ListenerType < typeof  this ,  EventType ,  EventMap > , 
210190    options ?: TypedListenerOptions , 
211-   ) : AbortController  { 
212-     if  ( ! this . #listeners[ type ] )  { 
213-       this . #listeners[ type ]  =  [ ] 
214-     } 
215- 
216-     this . #listeners[ type ] . unshift ( listener ) 
217- 
218-     const  abortController  =  this . #createAbortController( type ,  listener ) 
219-     this . #listenerOptions. set ( listener ,  { 
220-       signal : options ?. signal 
221-         ? AbortSignal . any ( [ abortController . signal ,  options . signal ] ) 
222-         : abortController . signal , 
223-     } ) 
224- 
225-     return  abortController 
191+   ) : typeof  this  { 
192+     return  this . #addListener( type ,  listener ,  options ,  'prepend' ) 
226193  } 
227194
228195  /** 
@@ -231,19 +198,9 @@ export class Emitter<EventMap extends DefaultEventMap> {
231198  public  earlyOnce < EventType  extends  keyof  EventMap  &  string > ( 
232199    type : EventType , 
233200    listener : Emitter . ListenerType < typeof  this ,  EventType ,  EventMap > , 
234-     options ?: TypedListenerOptions , 
235-   ) : AbortController  { 
236-     this . earlyOn ( type ,  listener ) 
237- 
238-     const  abortController  =  this . #createAbortController( type ,  listener ) 
239-     this . #listenerOptions. set ( listener ,  { 
240-       once : true , 
241-       signal : options ?. signal 
242-         ? AbortSignal . any ( [ abortController . signal ,  options . signal ] ) 
243-         : abortController . signal , 
244-     } ) 
245- 
246-     return  abortController 
201+     options ?: Omit < TypedListenerOptions ,  'once' > , 
202+   ) : typeof  this  { 
203+     return  this . earlyOn ( type ,  listener ,  {  ...( options  ||  { } ) ,  once : true  } ) 
247204  } 
248205
249206  /** 
@@ -272,11 +229,7 @@ export class Emitter<EventMap extends DefaultEventMap> {
272229        break 
273230      } 
274231
275-       if  ( this . #listenerOptions. get ( listener ) . signal . aborted )  { 
276-         continue 
277-       } 
278- 
279-       this . #callListener( listener ,  proxiedEvent . event ) 
232+       this . #callListener( proxiedEvent . event ,  listener ) 
280233    } 
281234
282235    proxiedEvent . revoke ( ) 
@@ -318,13 +271,9 @@ export class Emitter<EventMap extends DefaultEventMap> {
318271        break 
319272      } 
320273
321-       if  ( this . #listenerOptions. get ( listener ) ?. signal ?. aborted )  { 
322-         continue 
323-       } 
324- 
325274      pendingListeners . push ( 
326275        // Awaiting individual listeners guarantees their call order. 
327-         await  Promise . resolve ( this . #callListener( listener ,   proxiedEvent . event ) ) , 
276+         await  Promise . resolve ( this . #callListener( proxiedEvent . event ,   listener ) ) , 
328277      ) 
329278    } 
330279
@@ -363,11 +312,7 @@ export class Emitter<EventMap extends DefaultEventMap> {
363312        break 
364313      } 
365314
366-       if  ( this . #listenerOptions. get ( listener ) ?. signal ?. aborted )  { 
367-         continue 
368-       } 
369- 
370-       yield  this . #callListener( listener ,  proxiedEvent . event ) 
315+       yield  this . #callListener( proxiedEvent . event ,  listener ) 
371316    } 
372317
373318    proxiedEvent . revoke ( ) 
@@ -389,13 +334,9 @@ export class Emitter<EventMap extends DefaultEventMap> {
389334    >  =  [ ] 
390335
391336    for  ( const  existingListener  of  this . #listeners[ type ] )  { 
392-       if  ( existingListener  ===  listener )  { 
393-         this . #listenerOptions. delete ( existingListener ) 
394-         this . #abortControllers. delete ( existingListener ) 
395-         continue 
337+       if  ( existingListener  !==  listener )  { 
338+         nextListeners . push ( existingListener ) 
396339      } 
397- 
398-       nextListeners . push ( existingListener ) 
399340    } 
400341
401342    this . #listeners[ type ]  =  nextListeners 
@@ -410,8 +351,6 @@ export class Emitter<EventMap extends DefaultEventMap> {
410351  ) : void   { 
411352    if  ( type  ==  null )  { 
412353      this . #listeners =  { }  as  InternalListenersMap < typeof  this > 
413-       this . #listenerOptions =  new  WeakMap ( ) 
414-       this . #abortControllers =  new  WeakMap ( ) 
415354      return 
416355    } 
417356
@@ -445,12 +384,36 @@ export class Emitter<EventMap extends DefaultEventMap> {
445384  #addListener< EventType  extends  keyof  EventMap  &  string > ( 
446385    type : EventType , 
447386    listener : Emitter . ListenerType < typeof  this ,  EventType ,  EventMap > , 
448-   )  { 
449-     if  ( ! this . #listeners[ type ] )  { 
450-       this . #listeners[ type ]  =  [ ] 
387+     options : TypedListenerOptions  |  undefined , 
388+     insertMode : 'append'  |  'prepend'  =  'append' , 
389+   ) : typeof  this  { 
390+     this . #listeners[ type ]  ??=  [ ] 
391+ 
392+     if  ( insertMode  ===  'prepend' )  { 
393+       this . #listeners[ type ] . unshift ( listener ) 
394+     }  else  { 
395+       this . #listeners[ type ] . push ( listener ) 
396+     } 
397+ 
398+     if  ( options )  { 
399+       Object . defineProperty ( listener ,  kListenerOptions ,  { 
400+         value : options , 
401+         enumerable : false , 
402+         writable : false , 
403+       } ) 
404+ 
405+       if  ( options . signal )  { 
406+         options . signal . addEventListener ( 
407+           'abort' , 
408+           ( )  =>  { 
409+             this . removeListener ( type ,  listener ) 
410+           } , 
411+           {  once : true  } , 
412+         ) 
413+       } 
451414    } 
452415
453-     this . #listeners [ type ] . push ( listener ) 
416+     return   this 
454417  } 
455418
456419  #proxyEvent< Event  extends  TypedEvent > ( 
@@ -474,31 +437,17 @@ export class Emitter<EventMap extends DefaultEventMap> {
474437  } 
475438
476439  #callListener< EventType  extends  keyof  EventMap  &  string > ( 
477-     listener : Emitter . ListenerType < typeof  this ,  EventType ,  EventMap > , 
478440    event : Event , 
441+     listener : Emitter . ListenerType < typeof  this ,  EventType ,  EventMap >  &  { 
442+       [ kListenerOptions ] ?: TypedListenerOptions 
443+     } , 
479444  )  { 
480445    const  returnValue  =  listener . call ( this ,  event ) 
481446
482-     if  ( this . #listenerOptions . get ( listener ) ?. once )  { 
447+     if  ( listener [ kListenerOptions ] ?. once )  { 
483448      this . removeListener ( event . type ,  listener ) 
484449    } 
485450
486451    return  returnValue 
487452  } 
488- 
489-   #createAbortController< EventType  extends  keyof  EventMap  &  string > ( 
490-     type : EventType , 
491-     listener : Emitter . ListenerType < typeof  this ,  EventType ,  EventMap > , 
492-   ) : AbortController  { 
493-     const  abortController  =  new  AbortController ( ) 
494- 
495-     // Since we are emitting events manually, aborting the controller 
496-     // won't do anything by itself. We need to teach the class what to do. 
497-     abortController . signal . addEventListener ( 'abort' ,  ( )  =>  { 
498-       this . removeListener ( type ,  listener ) 
499-     } ) 
500- 
501-     this . #abortControllers. set ( listener ,  abortController ) 
502-     return  abortController 
503-   } 
504453} 
0 commit comments