@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.
package/lib/event.js DELETED
@@ -1,362 +0,0 @@
1
- // 3rd
2
- // internal
3
- import { TypeUtils, TypeAssert } from '@creejs/commons-lang'
4
-
5
- // owned
6
- // eslint-disable-next-line no-unused-vars
7
- import Listener from './listener.js'
8
- import { DefaultOwner } from './constants.js'
9
-
10
- // module vars
11
- const { isFunction, isNil } = TypeUtils
12
- const { assertStringOrSymbol, assertFunction } = TypeAssert
13
-
14
- /**
15
- * An Event definition
16
- * 1. listeners are grouped by owner
17
- * * if not specified, group it into one Default owner
18
- * 2. one listener may belong to multiple owners
19
- * 3. one owner may have multiple listeners
20
- */
21
- export default class Event {
22
- static get DefaultOwner () {
23
- return DefaultOwner
24
- }
25
-
26
- /**
27
- * Creates a new Event instance with the specified name.
28
- * @param {string|Symbol} eventName - The name of the event.
29
- */
30
- constructor (eventName) {
31
- assertStringOrSymbol(eventName, 'eventName')
32
- this._name = eventName
33
- /**
34
- * use Set to store unique listeners
35
- * @type {Set<function>}
36
- */
37
- this._callbacks = new Set()
38
- /**
39
- * @type {Array<Listener>}
40
- */
41
- this._listeners = [] // user array to keep order
42
- /**
43
- * @type {Map<function, Set<Listener>>}
44
- */
45
- this._callback2Listeners = new Map()
46
- /**
47
- * use listener to index owners. One Listener Instance only belongs to one owner
48
- * @type {Map<Listener, *>}
49
- */
50
- this._listener2Owner = new Map()
51
- /**
52
- * use "owner" to group listeners; one owner may have multiple listeners
53
- * @type {Map<*, Set<Listener>>}
54
- */
55
- this._owner2Listeners = new Map()
56
- }
57
-
58
- /**
59
- * Name of the event.
60
- * @returns {string|Symbol}
61
- */
62
- get name () {
63
- return this._name
64
- }
65
-
66
- isEmpty () {
67
- return this._callbacks.size === 0
68
- }
69
-
70
- /**
71
- * Returns a copy of the raw listeners array.
72
- * @returns {Array<Listener>} A shallow copy of the listeners array.
73
- */
74
- rawListeners () {
75
- return [...this._listeners]
76
- }
77
-
78
- /**
79
- * Returns the number of listeners listening for the event.
80
- * If callback is provided, it will return how many times the callback is found in the list of the listeners
81
- * @param {Function} [callback] - The callback function to count
82
- * @returns {number}
83
- */
84
- listenerCount (callback) {
85
- if (callback == null) {
86
- return this._listeners.length
87
- }
88
- return this._callback2Listeners.get(callback)?.size ?? 0
89
- }
90
-
91
- /**
92
- * Returns a shallow copy of the registered callbacks array.
93
- * if one callback function is added multiple times, it will be returned multiple times.
94
- * @returns {Array<function>} A new array containing all registered callbacks.
95
- */
96
- callbacks () {
97
- return [...this.rawListeners().map(listener => listener.callback)]
98
- }
99
-
100
- /**
101
- * Emits current event, invoking all registered listeners by order.
102
- * @param {...*} args - Arguments to be passed to each listener.
103
- * @returns {boolean} True if the event had listeners, false otherwise.
104
- */
105
- emit (...args) {
106
- if (this._listeners.length === 0) {
107
- return false
108
- }
109
- // Clone _listeners, it may be changed during call listener
110
- for (const listener of [...this._listeners]) {
111
- listener.invoke(...args)
112
- }
113
- return true
114
- }
115
-
116
- /**
117
- * Checks if listener is registered with this event.
118
- * @param {function} callback - The listener function to check.
119
- * @returns {boolean} True if the listener is registered, false otherwise.
120
- */
121
- hasListener (callback) {
122
- if (!isFunction(callback)) {
123
- return false
124
- }
125
- return this._callbacks.has(callback)
126
- }
127
-
128
- /**
129
- * Checks if owner has any registered listeners.
130
- * @param {*} owner - The owner to check for registered listeners.
131
- * @returns {boolean} True if the owner has listeners, false otherwise.
132
- */
133
- hasOwner (owner) {
134
- if (isNil(owner)) {
135
- return false
136
- }
137
- return this._owner2Listeners.has(owner)
138
- }
139
-
140
- /**
141
- * Adds an event listener
142
- * @param {function} callback - The callback function to be invoked when the event occurs.
143
- * @param {*} [owner] - use "owner" to group listeners, then can remove all listeners for an owner.
144
- * @returns {boolean} true if added, false otherwise.
145
- */
146
- addListener (callback, owner) {
147
- return this._addListener(callback, owner, false, false)
148
- }
149
-
150
- /**
151
- * Prepends a listener callback to the beginning of the listeners array.
152
- * No checks are made to see if the listener has already been added.
153
- * Multiple calls passing the same combination of eventName and listener will result in the listener being added,
154
- * and called, multiple times.
155
- * @param {Function} callback - The callback function to be executed when the event is emitted.
156
- * @param {Object} owner - The owner object to which the listener belongs.
157
- * @returns {boolean}
158
- */
159
- prependListener (callback, owner) {
160
- return this._addListener(callback, owner, false, true)
161
- }
162
-
163
- /**
164
- * Adds a one-time listener for the event. The listener is automatically removed after being invoked once.
165
- * @param {Function} callback - The function to call when the event is triggered.
166
- * @param {Object} [owner] - The object that owns the callback (used for binding `this` context).
167
- * @returns {boolean}
168
- */
169
- addOnceListener (callback, owner) {
170
- return this._addListener(callback, owner, true, false)
171
- }
172
-
173
- /**
174
- * Adds a one-time event listener that will be automatically removed after being triggered once.
175
- * The listener will only be triggered if the event is pretended (simulated).
176
- * @param {Function} callback - The function to call when the event is triggered.
177
- * @param {Object} owner - The object that owns the listener (used for reference tracking).
178
- * @returns {boolean} The listener function that was added.
179
- */
180
- prependOnceListener (callback, owner) {
181
- return this._addListener(callback, owner, true, true)
182
- }
183
-
184
- /**
185
- * Adds a listener for the event.
186
- * @param {Function} callback - The callback function to be executed when the event occurs
187
- * @param {*} [owner] - The owner object that the listener belongs to (defaults to DeaultOwner)
188
- * @param {boolean} [isOnce=false] - Whether the listener should be removed after first invocation
189
- * @param {boolean} [isPrepend=false] - Whether the listener should be inert at the beginning of the listeners array
190
- * @returns {boolean} Returns true if listener was added successfully, false if callback is nil or duplicate
191
- * @protected
192
- */
193
- _addListener (callback, owner, isOnce, isPrepend) {
194
- if (isNil(callback)) {
195
- return false
196
- }
197
- assertFunction(callback)
198
- if (!this._callbacks.has(callback)) {
199
- this._callbacks.add(callback)
200
- }
201
- // a listener must belong to an owner
202
- owner = owner ?? DefaultOwner
203
-
204
- // use Listener to wrap callback
205
- const listener = new Listener(this, callback, isOnce)
206
- listener.owner = owner
207
- if (isPrepend) {
208
- this._listeners.unshift(listener)
209
- } else {
210
- this._listeners.push(listener)
211
- }
212
-
213
- // index, rapadly find one listener's owner
214
- this._listener2Owner.set(listener, owner)
215
-
216
- // one callback function may be registered many times
217
- let callbackListeners = this._callback2Listeners.get(callback)
218
- if (callbackListeners == null) {
219
- callbackListeners = new Set()
220
- this._callback2Listeners.set(callback, callbackListeners)
221
- }
222
- callbackListeners.add(listener)
223
-
224
- // group by owner
225
- let ownerListeners = this._owner2Listeners.get(owner)
226
- if (ownerListeners == null) {
227
- ownerListeners = new Set()
228
- this._owner2Listeners.set(owner, ownerListeners)
229
- }
230
- ownerListeners.add(listener)
231
-
232
- return true
233
- }
234
-
235
- /**
236
- * Removes a callback
237
- * @param {Function} callback - The callback function to remove.
238
- * @returns {boolean} true if removed, false otherwise.
239
- */
240
- removeListener (callback) {
241
- if (isNil(callback)) {
242
- return false
243
- }
244
- if (!this._callbacks.has(callback)) {
245
- return false
246
- }
247
- this._callbacks.delete(callback)
248
-
249
- const listeners = this._callback2Listeners.get(callback)
250
- if (listeners == null) { // should not happen
251
- return false
252
- }
253
- this._callback2Listeners.delete(callback)
254
- for (const listener of listeners) {
255
- // remove from global index
256
- const index = this._listeners.indexOf(listener)
257
- index !== -1 && this._listeners.splice(this._listeners.indexOf(listener), 1)
258
-
259
- // remove from owner index
260
- const owner = this._listener2Owner.get(listener)
261
- if (owner == null) {
262
- continue
263
- }
264
- this._listener2Owner.delete(listener)
265
- const ownerListeners = this._owner2Listeners.get(owner)
266
- if (ownerListeners == null) {
267
- continue
268
- }
269
- ownerListeners.delete(listener)
270
- if (ownerListeners.size === 0) {
271
- this._owner2Listeners.delete(owner)
272
- }
273
- }
274
- return true
275
- }
276
-
277
- /**
278
- * Removes a listener from both global and owner indexes.
279
- * @param {Listener} listener - The listener function to remove
280
- */
281
- _remove (listener) {
282
- // remove from global index
283
- const index = this._listeners.indexOf(listener)
284
- index !== -1 && this._listeners.splice(index, 1)
285
-
286
- // clean callback index
287
- const { callback } = listener
288
- const callbackListeners = this._callback2Listeners.get(callback)
289
- if (callbackListeners != null) {
290
- callbackListeners.delete(listener)
291
- if (callbackListeners.size === 0) {
292
- this._callback2Listeners.delete(callback)
293
- this._callbacks.delete(callback)
294
- }
295
- }
296
-
297
- // remove from owner index
298
- const owner = this._listener2Owner.get(listener)
299
- if (owner == null) {
300
- return
301
- }
302
- this._listener2Owner.delete(listener)
303
- const ownerListeners = this._owner2Listeners.get(owner)
304
- if (ownerListeners == null) {
305
- return
306
- }
307
- ownerListeners.delete(listener)
308
- if (ownerListeners.size === 0) {
309
- this._owner2Listeners.delete(owner)
310
- }
311
- }
312
-
313
- /**
314
- * Removes all event listeners
315
- * @param {*} [owner] - Without owner, all listeners will be removed; otherwise, only listeners of "owner" will be removed.
316
- * @returns {this}
317
- */
318
- removeAllListeners (owner) {
319
- // remove listeners of owner
320
- if (isNil(owner)) {
321
- // remove all Listeners
322
- this._callbacks.clear()
323
- this._listeners.length = 0
324
- this._callback2Listeners.clear()
325
- this._listener2Owner.clear()
326
- this._owner2Listeners.clear()
327
- return this
328
- }
329
- // all listeners of the owner
330
- const ownerListeners = this._owner2Listeners.get(owner)
331
- // no owner
332
- if (ownerListeners == null) {
333
- return this
334
- }
335
- // clear owner index
336
- this._owner2Listeners.delete(owner)
337
- // clearn listeners of owner one by one
338
- for (const listener of ownerListeners) {
339
- // remove from global index
340
- const index = this._listeners.indexOf(listener)
341
- index !== -1 && this._listeners.splice(this._listeners.indexOf(listener), 1)
342
-
343
- // clean listener-owner index
344
- this._listener2Owner.delete(listener)
345
-
346
- // one callback function may be registered many times, has many Listeners
347
- const { callback } = listener
348
- const callbackListeners = this._callback2Listeners.get(callback)
349
- if (callbackListeners == null) {
350
- continue
351
- }
352
- callbackListeners.delete(listener)
353
- if (callbackListeners.size === 0) {
354
- this._callback2Listeners.delete(callback)
355
- this._callbacks.delete(callback)
356
- }
357
- }
358
- return this
359
- }
360
- }
361
-
362
- export { Event as EventType }
package/lib/index.js DELETED
@@ -1,5 +0,0 @@
1
- import EventEmitter from './event-emitter.js'
2
-
3
- export default EventEmitter
4
-
5
- export { EventEmitter }
package/lib/listener.js DELETED
@@ -1,93 +0,0 @@
1
- // 3rd
2
- // internal
3
- import { TypeAssert } from '@creejs/commons-lang'
4
-
5
- // owned
6
- import { DefaultOwner } from './constants.js'
7
-
8
- // module vars
9
- const { assertFunction, assertNotNil } = TypeAssert
10
- /**
11
- * Wraps a function to be called when an event is fired.
12
- * @typedef {import('./event.js').default} Event
13
- * @class Listener
14
- */
15
- export default class Listener {
16
- /**
17
- * @param {Event} event
18
- * @param {function} callback - The function to be called when event is fired
19
- * @param {boolean} [isOnce=false] - is a one time listener?
20
- */
21
- constructor (event, callback, isOnce = false) {
22
- assertNotNil(event, 'event')
23
- assertFunction(callback, 'callback')
24
- this._event = event
25
- this._callback = callback
26
- this._isOnce = !!isOnce // is Once Listener?
27
- this._owner = undefined
28
- }
29
-
30
- /**
31
- * Sets the owner of this listener.
32
- * @param {*} owner - The owner object to be associated with this listener.
33
- */
34
- set owner (owner) {
35
- this._owner = owner
36
- }
37
-
38
- get owner () {
39
- return this._owner === DefaultOwner ? undefined : this._owner
40
- }
41
-
42
- get event () {
43
- return this._event
44
- }
45
-
46
- get isOnce () {
47
- return this._isOnce
48
- }
49
-
50
- /**
51
- * Checks if the provided function is the same as the listener's wrapped function.
52
- * @param {Function} callback - The function to compare against.
53
- * @returns {boolean} True if the functions are the same, false otherwise.
54
- */
55
- isSameCallback (callback) {
56
- return this._callback === callback
57
- }
58
-
59
- get callback () {
60
- return this._callback
61
- }
62
-
63
- /**
64
- * Invokes the stored function with the provided arguments.
65
- * @param {...*} args - Arguments to pass to the function.
66
- * @returns {*} The result of the function invocation.
67
- */
68
- invoke (...args) {
69
- try {
70
- return this._callback(...args)
71
- } finally {
72
- if (this._isOnce) {
73
- try {
74
- this._event._remove(this)
75
- } catch (err) {
76
- // do nothing
77
- console.warn(err)
78
- }
79
- }
80
- }
81
- }
82
-
83
- /**
84
- * Invokes the listener with the provided arguments.
85
- * Alias for {@linkcode Listener.invoke}
86
- * @param {...*} args - Arguments to be passed to the listener.
87
- * @returns {*} The result of the listener invocation.
88
- */
89
- listener (...args) {
90
- return this.invoke(...args)
91
- }
92
- }
93
- export { Listener as ListenerType }