1- export class EventEmitter <
2- Events extends { [ name : string ] : ( ...args : any [ ] ) => any }
3- > {
4- private readonly _events : {
5- [ name in keyof Events ] ?: Array < Events [ name ] >
6- } = { }
1+ type ListenerFunction = {
2+ listener ?: Function ;
3+ } & Function
74
8- on ( event : keyof Events , listener : Events [ typeof event ] ) : ( ) => void {
9- if ( ! this . _hasEvent ( event ) ) this . _events [ event ] = [ ]
5+ export class EventEmitter {
6+ static defaultMaxListeners : number = 10 ;
7+ maxListeners : number | undefined ;
8+ events : Map < string | symbol , Function [ ] > ;
109
11- this . _events [ event ] . push ( listener )
12- return ( ) => this . removeListener ( event , listener )
10+ constructor ( ) {
11+ this . events = new Map ( ) ;
1312 }
1413
15- removeListener ( event : keyof Events , listener : Events [ typeof event ] ) : void {
16- if ( ! this . _hasEvent ( event ) ) return
14+ _addListener (
15+ eventName : string | symbol ,
16+ listener : Function ,
17+ prepend : boolean
18+ ) : this {
19+ this . emit ( "newListener" , eventName , listener ) ;
20+ if ( this . events . has ( eventName ) ) {
21+ const listeners = this . events . get ( eventName ) as Function [ ] ;
22+ if ( prepend ) {
23+ listeners . unshift ( listener ) ;
24+ } else {
25+ listeners . push ( listener ) ;
26+ }
27+ } else {
28+ this . events . set ( eventName , [ listener ] ) ;
29+ }
30+ const max = this . getMaxListeners ( ) ;
31+ if ( max > 0 && this . listenerCount ( eventName ) > max ) {
32+ const warning = new Error (
33+ `Possible EventEmitter memory leak detected.
34+ ${ this . listenerCount ( eventName ) } ${ eventName . toString ( ) } listeners.
35+ Use emitter.setMaxListeners() to increase limit`
36+ ) ;
37+ warning . name = "MaxListenersExceededWarning" ;
38+ console . warn ( warning ) ;
39+ }
1740
18- const index = this . _events [ event ] . indexOf ( listener )
19- if ( ~ index ) this . _events [ event ] . splice ( index , 1 )
41+ return this ;
2042 }
2143
22- emit ( event : keyof Events , ...args : Parameters < Events [ typeof event ] > ) : void {
23- if ( ! this . _hasEvent ( event ) ) return
44+ addListener ( eventName : string | symbol , listener : Function ) : this {
45+ return this . _addListener ( eventName , listener , false ) ;
46+ }
47+
48+ emit ( eventName : string | symbol , ...args : any [ ] ) : boolean {
49+ if ( this . events . has ( eventName ) ) {
50+ const listeners = ( this . events . get ( eventName ) as Function [ ] ) . slice ( ) ; // We copy with slice() so array is not mutated during emit
51+ for ( const listener of listeners ) {
52+ try {
53+ listener . apply ( this , args ) ;
54+ } catch ( err ) {
55+ this . emit ( "error" , err ) ;
56+ }
57+ }
58+ return true ;
59+ } else if ( eventName === "error" ) {
60+ const errMsg = args . length > 0 ? args [ 0 ] : Error ( "Unhandled error." ) ;
61+ throw errMsg ;
62+ }
63+ return false ;
64+ }
65+
66+ eventNames ( ) : [ string | symbol ] {
67+ return Array . from ( this . events . keys ( ) ) as [ string | symbol ] ;
68+ }
69+
70+ getMaxListeners ( ) : number {
71+ return this . maxListeners || EventEmitter . defaultMaxListeners ;
72+ }
73+
74+ listenerCount ( eventName : string | symbol ) : number {
75+ if ( this . events . has ( eventName ) ) {
76+ return ( this . events . get ( eventName ) as Function [ ] ) . length ;
77+ } else {
78+ return 0 ;
79+ }
80+ }
81+
82+ _listeners (
83+ target : EventEmitter ,
84+ eventName : string | symbol ,
85+ unwrap : boolean
86+ ) : Function [ ] {
87+ if ( ! target . events . has ( eventName ) ) {
88+ return [ ] ;
89+ }
90+
91+ const eventListeners : ListenerFunction [ ] = target . events . get (
92+ eventName
93+ ) as Function [ ] ;
94+
95+ return unwrap
96+ ? this . unwrapListeners ( eventListeners )
97+ : eventListeners . slice ( 0 ) ;
98+ }
99+
100+ unwrapListeners ( arr : ListenerFunction [ ] ) : Function [ ] {
101+ let unwrappedListeners : Function [ ] = new Array ( arr . length ) as Function [ ] ;
102+ for ( let i = 0 ; i < arr . length ; i ++ ) {
103+ unwrappedListeners [ i ] = arr [ i ] [ "listener" ] || arr [ i ] ;
104+ }
105+ return unwrappedListeners ;
106+ }
107+
108+ listeners ( eventName : string | symbol ) : Function [ ] {
109+ return this . _listeners ( this , eventName , true ) ;
110+ }
111+
112+ rawListeners ( eventName : string | symbol ) : Function [ ] {
113+ return this . _listeners ( this , eventName , false ) ;
114+ }
115+
116+ off ( eventName : string | symbol , listener : Function ) : this {
117+ return this . removeListener ( eventName , listener ) ;
118+ }
119+
120+ on ( eventName : string | symbol , listener : Function ) : this {
121+ return this . addListener ( eventName , listener ) ;
122+ }
123+
124+ once ( eventName : string | symbol , listener : Function ) : this {
125+ const wrapped : Function = this . onceWrap ( eventName , listener ) ;
126+ this . on ( eventName , wrapped ) ;
127+ return this ;
128+ }
129+
130+ // Wrapped function that calls EventEmitter.removeListener(eventName, self) on execution.
131+ onceWrap ( eventName : string | symbol , listener : Function ) : Function {
132+ const wrapper : ListenerFunction = function (
133+ this : {
134+ eventName : string | symbol ;
135+ listener : Function ;
136+ rawListener : Function ;
137+ context : EventEmitter ;
138+ } ,
139+ ...args : any [ ] // eslint-disable-line @typescript-eslint/no-explicit-any
140+ ) : void {
141+ this . context . removeListener ( this . eventName , this . rawListener ) ;
142+ this . listener . apply ( this . context , args ) ;
143+ } ;
144+ const wrapperContext = {
145+ eventName : eventName ,
146+ listener : listener ,
147+ rawListener : wrapper ,
148+ context : this
149+ } ;
150+ const wrapped = wrapper . bind ( wrapperContext ) ;
151+ wrapperContext . rawListener = wrapped ;
152+ wrapped . listener = listener ;
153+ return wrapped ;
154+ }
155+
156+ prependListener ( eventName : string | symbol , listener : Function ) : this {
157+ return this . _addListener ( eventName , listener , true ) ;
158+ }
159+
160+ prependOnceListener (
161+ eventName : string | symbol ,
162+ listener : Function
163+ ) : this {
164+ const wrapped : Function = this . onceWrap ( eventName , listener ) ;
165+ this . prependListener ( eventName , wrapped ) ;
166+ return this ;
167+ }
168+
169+ removeAllListeners ( eventName ?: string | symbol ) : this {
170+ if ( this . events === undefined ) {
171+ return this ;
172+ }
173+
174+ if ( eventName && this . events . has ( eventName ) ) {
175+ const listeners = ( this . events . get ( eventName ) as Function [ ] ) . slice ( ) ; // Create a copy; We use it AFTER it's deleted.
176+ this . events . delete ( eventName ) ;
177+ for ( const listener of listeners ) {
178+ this . emit ( "removeListener" , eventName , listener ) ;
179+ }
180+ } else {
181+ const eventList : [ string | symbol ] = this . eventNames ( ) ;
182+ eventList . map ( ( value : string | symbol ) => {
183+ this . removeAllListeners ( value ) ;
184+ } ) ;
185+ }
186+
187+ return this ;
188+ }
24189
25- this . _events [ event ] . map ( ( listener ) => listener . apply ( this , args ) )
190+ removeListener ( eventName : string | symbol , listener : Function ) : this {
191+ if ( this . events . has ( eventName ) ) {
192+ const arr : Function [ ] = this . events . get ( eventName ) as Function [ ] ;
193+ if ( arr . indexOf ( listener ) !== - 1 ) {
194+ arr . splice ( arr . indexOf ( listener ) , 1 ) ;
195+ this . emit ( "removeListener" , eventName , listener ) ;
196+ if ( arr . length === 0 ) {
197+ this . events . delete ( eventName ) ;
198+ }
199+ }
200+ }
201+ return this ;
26202 }
27203
28- private _hasEvent ( event : keyof Events ) {
29- return Array . isArray ( this . _events [ event ] )
204+ setMaxListeners ( n : number ) : this {
205+ this . maxListeners = n ;
206+ return this ;
30207 }
31- }
208+ }
0 commit comments