@creejs/commons-events 2.0.2 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,373 +0,0 @@
1
- // 3rd
2
- // internal
3
- import { TypeUtils, TypeAssert } from '@creejs/commons-lang'
4
-
5
- // owned
6
- import Event from './event.js'
7
- // eslint-disable-next-line no-unused-vars
8
- import Listener from './listener.js'
9
-
10
- // module vars
11
- const { isNil } = TypeUtils
12
- const {
13
- assertString, assertFunction, assertNumber,
14
- assertStringOrSymbol, assertNotNil
15
- } = TypeAssert
16
-
17
- /**
18
- * methods allowed to mixin other objects
19
- */
20
- const MixinMethods = [
21
- 'on', 'once', 'addListener', 'prependListener', 'prependOnceListener',
22
- 'off', 'offAll', 'offOwner', 'removeAllListeners', 'removeListener',
23
- 'emit', 'setMaxListeners', 'getMaxListeners', 'hasOwner',
24
- 'listeners', 'listenerCount', 'eventNames', 'rawListeners'
25
- ]
26
- let DefaultMaxListeners = 10
27
- /**
28
- * 1. An EventEmitter follows the API of NodeJS EventEmitter.
29
- * 2. Enhancement:
30
- * * Listeners are grouped by "owner".
31
- * * Operation via "owner"
32
- * * Duplicate listeners are filtered out. Only unique One kept.
33
- */
34
- export default class EventEmitter {
35
- /**
36
- * Mixes EventEmitter methods into the given object.
37
- * @template T
38
- * @param {T} obj - The target object to mix methods into.
39
- * @returns {T} The modified object with EventEmitter methods.
40
- */
41
- static mixin (obj) {
42
- const emitter = new EventEmitter()
43
- // @ts-ignore
44
- obj.__emitter = emitter
45
- for (const name of MixinMethods) {
46
- // @ts-ignore
47
- const method = emitter[name]
48
- // @ts-ignore
49
- obj[name] = method.bind(emitter)
50
- }
51
- return obj
52
- }
53
-
54
- static get defaultMaxListeners () {
55
- return DefaultMaxListeners
56
- }
57
-
58
- static set defaultMaxListeners (maxListeners) {
59
- assertNumber(maxListeners)
60
- DefaultMaxListeners = maxListeners ?? 10
61
- }
62
-
63
- /**
64
- */
65
- constructor () {
66
- /**
67
- * @type {Map<string|Symbol, Event>}
68
- */
69
- this._name2Event = new Map()
70
- this._maxListeners = DefaultMaxListeners
71
- }
72
-
73
- /**
74
- * Alias of {@linkcode EventEmitter.addListener}
75
- * @param {string|Symbol} eventName
76
- * @param {function} listener
77
- * @param {*} [owner]
78
- * @returns {this}
79
- */
80
- addListener (eventName, listener, owner) {
81
- return this.on(eventName, listener, owner)
82
- }
83
-
84
- /**
85
- * Adds the listener function to the beginning of the listeners array for the event named eventName.
86
- * @param {string|Symbol} eventName
87
- * @param {function} listener
88
- * @param {*} [owner]
89
- * @returns {this}
90
- */
91
- prependListener (eventName, listener, owner) {
92
- assertString(eventName)
93
- assertFunction(listener)
94
- this._checkMaxListeners(eventName)
95
-
96
- const event = this._getOrCreateEvent(eventName)
97
- event.prependListener(listener, owner)
98
- return this
99
- }
100
-
101
- /**
102
- * Adds a one-time listener function for the event named eventName to the beginning of the listeners array.
103
- * @param {string|Symbol} eventName
104
- * @param {function} listener
105
- * @param {*} [owner]
106
- * @returns {this}
107
- */
108
- prependOnceListener (eventName, listener, owner) {
109
- assertString(eventName)
110
- assertFunction(listener)
111
- this._checkMaxListeners(eventName)
112
-
113
- const event = this._getOrCreateEvent(eventName)
114
- event.prependOnceListener(listener, owner)
115
- return this
116
- }
117
-
118
- /**
119
- * Synchronously calls each of the listeners registered for the event named eventName,
120
- * in the order they were registered, passing the supplied arguments to each.
121
- * Returns true if the event had listeners, false otherwise.
122
- * @param {string|Symbol} eventName - The name of the event.
123
- * @param {...*} args arguments to pass to the listeners.
124
- * @returns {boolean}
125
- */
126
- emit (eventName, ...args) {
127
- const event = this._name2Event.get(eventName)
128
- if (event == null || event.isEmpty()) {
129
- return false
130
- }
131
- event.emit(...args)
132
- return true
133
- }
134
-
135
- /**
136
- * Returns an array listing the events for which the emitter has registered listeners.
137
- * @returns {Array<string|Symbol>} An array of event names.
138
- */
139
- eventNames () {
140
- return [...this._name2Event.keys()]
141
- }
142
-
143
- getMaxListeners () {
144
- return this._maxListeners
145
- }
146
-
147
- /**
148
- * Returns the number of listeners listening for the event named eventName.
149
- * If listener is provided, it will return how many times the listener is found
150
- * in the list of the listeners of the event.
151
- * @param {string|Symbol} eventName - The name of the event to check
152
- * @param {function} [listener] - Optional specific listener to count
153
- * @returns {number} The number of listeners for the event
154
- */
155
- listenerCount (eventName, listener) {
156
- assertStringOrSymbol(eventName, 'eventName')
157
- const event = this._name2Event.get(eventName)
158
- if (event == null || event.isEmpty()) {
159
- return 0
160
- }
161
- return event.listenerCount(listener)
162
- }
163
-
164
- /**
165
- * Returns a copy of the array of listeners for the event named eventName.
166
- * 1. if a callback function added multiple times, it will be returned multiple times.
167
- * @param {string} eventName
168
- * @returns {Array<function>}
169
- */
170
- listeners (eventName) {
171
- assertStringOrSymbol(eventName, 'eventName')
172
- const event = this._name2Event.get(eventName)
173
- if (event == null || event.isEmpty()) {
174
- return []
175
- }
176
- return event.callbacks()
177
- }
178
-
179
- /**
180
- * Removes a callback function from a specific event.
181
- * 1. If the event doesn't exist or has no listeners, do nothing
182
- * 2. if one callback function added multiple times, all of them will be removed.
183
- * * !!! This is different from the behavior of Node.js EventEmitter.
184
- *
185
- * @param {string} eventName - The name of the event to remove callback from
186
- * @param {function} callback - The callback function to remove
187
- * @returns {EventEmitter} Returns the emitter instance for chaining
188
- */
189
- off (eventName, callback) {
190
- const event = this._name2Event.get(eventName)
191
- if (event == null) {
192
- return this
193
- }
194
- event.removeListener(callback)
195
- if (event.isEmpty()) {
196
- this._name2Event.delete(eventName)
197
- return this
198
- }
199
- return this
200
- }
201
-
202
- /**
203
- * Removes all listeners for the specified event.
204
- * if owner is limited, only the listeners of the owner will be removed.
205
- *
206
- * @param {string|Symbol} eventName - The name of the event to clear listeners for.
207
- * @param {*} owner - The owner whose listeners should be removed.
208
- * @returns {EventEmitter} The emitter instance for chaining.
209
- */
210
- offAll (eventName, owner) {
211
- assertStringOrSymbol(eventName, 'eventName')
212
- const event = this._name2Event.get(eventName)
213
- if (event == null) {
214
- return this
215
- }
216
- event.removeAllListeners(owner)
217
- if (event.isEmpty()) {
218
- this._name2Event.delete(eventName)
219
- return this
220
- }
221
- return this
222
- }
223
-
224
- /**
225
- * Removes all event listeners belonging to the specified owner.
226
- * @param {*} owner - The owner whose listeners should be removed.
227
- * @returns {this}
228
- */
229
- offOwner (owner) {
230
- assertNotNil(owner, 'owner')
231
- const events = [...this._name2Event.values()]
232
- for (const event of events) {
233
- event.removeAllListeners(owner)
234
- if (event.isEmpty()) {
235
- this._name2Event.delete(event.name)
236
- }
237
- }
238
- return this
239
- }
240
-
241
- /**
242
- * Adds the listener function to the end of the listeners array for the event named eventName.
243
- * @param {string|Symbol} eventName
244
- * @param {function} callback
245
- * @param {*} [owner]
246
- * @returns {this}
247
- */
248
- on (eventName, callback, owner) {
249
- assertString(eventName)
250
- assertFunction(callback)
251
- this._checkMaxListeners(eventName)
252
-
253
- const event = this._getOrCreateEvent(eventName)
254
- event.addListener(callback, owner)
255
- return this
256
- }
257
-
258
- /**
259
- * Checks if the number of listeners for the given event exceeds the maximum allowed.
260
- * Emits a warning if the listener count reaches or exceeds the maxListeners threshold.
261
- * @private
262
- * @param {string|Symbol} eventName - The name of the event to check
263
- * @returns {void}
264
- */
265
- _checkMaxListeners (eventName) {
266
- let listenerCount = 0
267
- if (this._maxListeners !== 0 && this._maxListeners !== Infinity && (listenerCount = this.listenerCount(eventName)) >= this._maxListeners) {
268
- console.warn(`maxlistenersexceededwarning: Possible EventEmitter memory leak detected. ${listenerCount} ${eventName} listeners added to [${this}]. Use emitter.setMaxListeners() to increase limit`)
269
- }
270
- }
271
-
272
- /**
273
- * Adds a listener that will be invoked only once for the event named eventName.SIGINT listeners added to [process]. Use emitter.setMaxListeners() to increase limit`)
274
- }
275
- }
276
-
277
- /**
278
- * Adds a one-time callback function for the specified event.
279
- * The callback is invoked only once and then automatically removed.
280
- *
281
- * @param {string} eventName - The name of the event to listen for.
282
- * @param {Function} callback - The callback function to execute when the event is emitted.
283
- * @param {*} [owner] - Optional owner used to group listener callbacks.
284
- * @returns {EventEmitter} Returns the emitter instance for chaining.
285
- */
286
- once (eventName, callback, owner) {
287
- assertString(eventName)
288
- assertFunction(callback)
289
-
290
- const event = this._getOrCreateEvent(eventName)
291
- event.addOnceListener(callback, owner)
292
- return this
293
- }
294
-
295
- /**
296
- * Returns a copy of the array of listeners for the event named eventName,
297
- * including any wrappers (such as those created by .once()).
298
- * @param {string} eventName - The name of the event.
299
- * @returns {Listener[]} An array of raw listener functions, or empty array if none exist.
300
- */
301
- rawListeners (eventName) {
302
- return this._name2Event.get(eventName)?.rawListeners() || []
303
- }
304
-
305
- /**
306
- * Alias of {@linkcode EventEmitter.offAll}
307
- * @param {string|Symbol} eventName - The name of the event to remove listeners for.
308
- * @param {*} owner - The owner of the listeners to be removed.
309
- * @returns {EventEmitter} The emitter instance for chaining.
310
- */
311
- removeAllListeners (eventName, owner) {
312
- return this.offAll(eventName, owner)
313
- }
314
-
315
- /**
316
- * Alias of {@linkcode EventEmitter.off}
317
- * @param {string} eventName - The name of the event.
318
- * @param {Function} callback - The callback function to remove.
319
- * @returns {EventEmitter} The emitter instance for chaining.
320
- */
321
- removeListener (eventName, callback) {
322
- return this.off(eventName, callback)
323
- }
324
-
325
- /**
326
- * Sets the maximum number of listeners that can be added to this event emitter.
327
- * @param {number} max - The maximum number of listeners.
328
- * @returns {this} The set maximum number of listeners.
329
- */
330
- setMaxListeners (max) {
331
- assertNumber(max)
332
- if (max < 0) {
333
- throw new RangeError('maxListeners must >=0')
334
- }
335
- this._maxListeners = max
336
- return this
337
- }
338
-
339
- /**
340
- * Gets an existing event by name or creates a new one if it doesn't exist.
341
- * @private
342
- * @param {string|Symbol} eventName - The name of the event to get or create.
343
- * @returns {Event} The existing or newly created Event instance.
344
- */
345
- _getOrCreateEvent (eventName) {
346
- if (this._name2Event.has(eventName)) {
347
- // @ts-ignore
348
- return this._name2Event.get(eventName)
349
- }
350
- const event = new Event(eventName)
351
- this._name2Event.set(eventName, event)
352
- return event
353
- }
354
-
355
- /**
356
- * Checks if the specified owner has any registered events.
357
- * @param {Object} owner - The owner object to check for registered events.
358
- * @returns {boolean} True if the owner has any registered events, false otherwise.
359
- */
360
- hasOwner (owner) {
361
- if (isNil(owner)) {
362
- return false
363
- }
364
- for (const event of this._name2Event.values()) {
365
- if (event.hasOwner(owner)) {
366
- return true
367
- }
368
- }
369
- return false
370
- }
371
- }
372
-
373
- export { EventEmitter as EventEmitterType }