Skip to content

Commit c96aa20

Browse files
EventEmitter fixed.
1 parent aa7e892 commit c96aa20

File tree

4 files changed

+225
-91
lines changed

4 files changed

+225
-91
lines changed

docs/TinyChain/Events.md

Lines changed: 0 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -75,93 +75,3 @@ This class defines all the event names used by `TinyChain` in the EventEmitter.
7575

7676
**Description:**
7777
Validates if a given event is one of the defined event names in the class.
78-
79-
---
80-
81-
### 📏 `setMaxListeners(max)`
82-
83-
Set the maximum number of listeners allowed for the internal event emitter.
84-
85-
* **Parameters:**
86-
87-
* `max` *(number)*: Maximum number of allowed listeners.
88-
89-
> 🧠 Useful for preventing memory leaks due to excessive listeners.
90-
91-
---
92-
93-
### 📣 `emit(event, ...args)`
94-
95-
Emit an event, triggering all listeners registered to it.
96-
97-
* **Parameters:**
98-
99-
* `event` *(string | symbol)*: Name of the event to emit.
100-
* `...args` *(any)*: Optional arguments passed to listeners.
101-
* **Returns:** `boolean``true` if the event had listeners, `false` otherwise.
102-
103-
> 🚀 Emits are synchronous and fire listeners in the order they were registered.
104-
105-
---
106-
107-
### 🎧 `on(event, listener)`
108-
109-
Register a listener for the specified event.
110-
111-
* **Parameters:**
112-
113-
* `event` *(string | symbol)*: The event name.
114-
* `listener` *(ListenerCallback)*: Function to invoke when the event is emitted.
115-
* **Returns:** `this` – Enables method chaining.
116-
117-
---
118-
119-
### ⏱️ `once(event, listener)`
120-
121-
Register a one-time listener for the event. It will be invoked once and then automatically removed.
122-
123-
* **Parameters:**
124-
125-
* `event` *(string | symbol)*: The event name.
126-
* `listener` *(ListenerCallback)*: The callback function.
127-
* **Returns:** `this`
128-
129-
---
130-
131-
### 🧹 `off(event, listener)`
132-
133-
Remove a specific listener from the given event.
134-
135-
* **Parameters:**
136-
137-
* `event` *(string | symbol)*: The event name.
138-
* `listener` *(ListenerCallback)*: The listener to remove.
139-
* **Returns:** `this`
140-
141-
---
142-
143-
### `addListener(event, listener)`
144-
145-
Alias for `.on()` – Register a listener for the specified event.
146-
147-
* **Parameters:**
148-
149-
* `event` *(string | symbol)*: The event name.
150-
* `listener` *(ListenerCallback)*: The callback function.
151-
* **Returns:** `this`
152-
153-
> 🔁 Use this if you prefer the more explicit naming convention.
154-
155-
---
156-
157-
### `removeListener(event, listener)`
158-
159-
Alias for `.off()` – Remove a listener from the event.
160-
161-
* **Parameters:**
162-
163-
* `event` *(string | symbol)*: The event name.
164-
* `listener` *(ListenerCallback)*: The listener to remove.
165-
* **Returns:** `this`
166-
167-
> 🧽 Perfect for cleaning up listeners dynamically.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "tiny-crypto-suite",
3-
"version": "1.5.1",
3+
"version": "1.5.2",
44
"description": "Tiny tools, big crypto — seamless encryption and certificate handling for modern web and Node apps.",
55
"scripts": {
66
"test": "npm run test:mjs && npm run test:cjs && npm run test:js",

src/TinyChain/Instance.mjs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,86 @@ class TinyChainInstance {
195195
return this;
196196
}
197197

198+
/**
199+
* Removes all listeners for a specific event, or all events if no event is specified.
200+
* @param {string | symbol} [event] - The name of the event. If omitted, all listeners from all events will be removed.
201+
* @returns {this} The current class instance (for chaining).
202+
*/
203+
removeAllListeners(event) {
204+
this.#events.removeAllListeners(event);
205+
return this;
206+
}
207+
208+
/**
209+
* Returns the number of times the given `listener` is registered for the specified `event`.
210+
* If no `listener` is passed, returns how many listeners are registered for the `event`.
211+
* @param {string | symbol} eventName - The name of the event.
212+
* @param {Function} [listener] - Optional listener function to count.
213+
* @returns {number} Number of matching listeners.
214+
*/
215+
listenerCount(eventName, listener) {
216+
return this.#events.listenerCount(eventName, listener);
217+
}
218+
219+
/**
220+
* Adds a listener function to the **beginning** of the listeners array for the specified event.
221+
* The listener is called every time the event is emitted.
222+
* @param {string | symbol} eventName - The event name.
223+
* @param {ListenerCallback} listener - The callback function.
224+
* @returns {this} The current class instance (for chaining).
225+
*/
226+
prependListener(eventName, listener) {
227+
this.#events.prependListener(eventName, listener);
228+
return this;
229+
}
230+
231+
/**
232+
* Adds a **one-time** listener function to the **beginning** of the listeners array.
233+
* The next time the event is triggered, this listener is removed and then invoked.
234+
* @param {string | symbol} eventName - The event name.
235+
* @param {ListenerCallback} listener - The callback function.
236+
* @returns {this} The current class instance (for chaining).
237+
*/
238+
prependOnceListener(eventName, listener) {
239+
this.#events.prependOnceListener(eventName, listener);
240+
return this;
241+
}
242+
243+
/**
244+
* Returns an array of event names for which listeners are currently registered.
245+
* @returns {(string | symbol)[]} Array of event names.
246+
*/
247+
eventNames() {
248+
return this.#events.eventNames();
249+
}
250+
251+
/**
252+
* Gets the current maximum number of listeners allowed for any single event.
253+
* @returns {number} The max listener count.
254+
*/
255+
getMaxListeners() {
256+
return this.#events.getMaxListeners();
257+
}
258+
259+
/**
260+
* Returns a copy of the listeners array for the specified event.
261+
* @param {string | symbol} eventName - The event name.
262+
* @returns {Function[]} An array of listener functions.
263+
*/
264+
listeners(eventName) {
265+
return this.#events.listeners(eventName);
266+
}
267+
268+
/**
269+
* Returns a copy of the internal listeners array for the specified event,
270+
* including wrapper functions like those used by `.once()`.
271+
* @param {string | symbol} eventName - The event name.
272+
* @returns {Function[]} An array of raw listener functions.
273+
*/
274+
rawListeners(eventName) {
275+
return this.#events.rawListeners(eventName);
276+
}
277+
198278
/**
199279
* Important instance used to make request queue.
200280
* @type {TinyPromiseQueue}
@@ -1745,6 +1825,20 @@ class TinyChainInstance {
17451825
getBlockSizeLimit() {
17461826
return this.#blockSizeLimit;
17471827
}
1828+
1829+
/**
1830+
* Destroys the current instance by resetting all internal state.
1831+
*
1832+
* This method clears the chain data, resets all balances,
1833+
* and removes all attached listeners from both internal and system event emitters.
1834+
* It should be called when the instance is no longer needed to free up memory and avoid leaks.
1835+
*/
1836+
destroy() {
1837+
this.chain = [];
1838+
this.balances = {};
1839+
this.#events.removeAllListeners();
1840+
this.#sysEvents.removeAllListeners();
1841+
}
17481842
}
17491843

17501844
export default TinyChainInstance;

src/TinyOlm/Instance.mjs

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,46 @@ class TinyOlmInstance {
5050
*/
5151
#events = new EventEmitter();
5252

53+
/**
54+
* Important instance used to make system event emitter.
55+
* @type {EventEmitter}
56+
*/
57+
#sysEvents = new EventEmitter();
58+
#sysEventsUsed = false;
59+
5360
/**
5461
* Emits an event with optional arguments to all system emit.
5562
* @param {string | symbol} event - The name of the event to emit.
5663
* @param {...any} args - Arguments passed to event listeners.
5764
*/
5865
#emit(event, ...args) {
5966
this.#events.emit(event, ...args);
67+
if (this.#sysEventsUsed) this.#sysEvents.emit(event, ...args);
68+
}
69+
70+
/**
71+
* Provides access to a secure internal EventEmitter for subclass use only.
72+
*
73+
* This method exposes a dedicated EventEmitter instance intended specifically for subclasses
74+
* that extend the main class. It prevents subclasses from accidentally or intentionally using
75+
* the primary class's public event system (`emit`), which could lead to unpredictable behavior
76+
* or interference in the base class's event flow.
77+
*
78+
* For security and consistency, this method is designed to be accessed only once.
79+
* Multiple accesses are blocked to avoid leaks or misuse of the internal event bus.
80+
*
81+
* @returns {EventEmitter} A special internal EventEmitter instance for subclass use.
82+
* @throws {Error} If the method is called more than once.
83+
*/
84+
getSysEvents() {
85+
if (this.#sysEventsUsed)
86+
throw new Error(
87+
'Access denied: getSysEvents() can only be called once. ' +
88+
'This restriction ensures subclass event isolation and prevents accidental interference ' +
89+
'with the main class event emitter.',
90+
);
91+
this.#sysEventsUsed = true;
92+
return this.#sysEvents;
6093
}
6194

6295
/**
@@ -138,6 +171,86 @@ class TinyOlmInstance {
138171
return this;
139172
}
140173

174+
/**
175+
* Removes all listeners for a specific event, or all events if no event is specified.
176+
* @param {string | symbol} [event] - The name of the event. If omitted, all listeners from all events will be removed.
177+
* @returns {this} The current class instance (for chaining).
178+
*/
179+
removeAllListeners(event) {
180+
this.#events.removeAllListeners(event);
181+
return this;
182+
}
183+
184+
/**
185+
* Returns the number of times the given `listener` is registered for the specified `event`.
186+
* If no `listener` is passed, returns how many listeners are registered for the `event`.
187+
* @param {string | symbol} eventName - The name of the event.
188+
* @param {Function} [listener] - Optional listener function to count.
189+
* @returns {number} Number of matching listeners.
190+
*/
191+
listenerCount(eventName, listener) {
192+
return this.#events.listenerCount(eventName, listener);
193+
}
194+
195+
/**
196+
* Adds a listener function to the **beginning** of the listeners array for the specified event.
197+
* The listener is called every time the event is emitted.
198+
* @param {string | symbol} eventName - The event name.
199+
* @param {ListenerCallback} listener - The callback function.
200+
* @returns {this} The current class instance (for chaining).
201+
*/
202+
prependListener(eventName, listener) {
203+
this.#events.prependListener(eventName, listener);
204+
return this;
205+
}
206+
207+
/**
208+
* Adds a **one-time** listener function to the **beginning** of the listeners array.
209+
* The next time the event is triggered, this listener is removed and then invoked.
210+
* @param {string | symbol} eventName - The event name.
211+
* @param {ListenerCallback} listener - The callback function.
212+
* @returns {this} The current class instance (for chaining).
213+
*/
214+
prependOnceListener(eventName, listener) {
215+
this.#events.prependOnceListener(eventName, listener);
216+
return this;
217+
}
218+
219+
/**
220+
* Returns an array of event names for which listeners are currently registered.
221+
* @returns {(string | symbol)[]} Array of event names.
222+
*/
223+
eventNames() {
224+
return this.#events.eventNames();
225+
}
226+
227+
/**
228+
* Gets the current maximum number of listeners allowed for any single event.
229+
* @returns {number} The max listener count.
230+
*/
231+
getMaxListeners() {
232+
return this.#events.getMaxListeners();
233+
}
234+
235+
/**
236+
* Returns a copy of the listeners array for the specified event.
237+
* @param {string | symbol} eventName - The event name.
238+
* @returns {Function[]} An array of listener functions.
239+
*/
240+
listeners(eventName) {
241+
return this.#events.listeners(eventName);
242+
}
243+
244+
/**
245+
* Returns a copy of the internal listeners array for the specified event,
246+
* including wrapper functions like those used by `.once()`.
247+
* @param {string | symbol} eventName - The event name.
248+
* @returns {Function[]} An array of raw listener functions.
249+
*/
250+
rawListeners(eventName) {
251+
return this.#events.rawListeners(eventName);
252+
}
253+
141254
/**
142255
* Important instance used to validate values.
143256
* @type {TinyCryptoParser}
@@ -1730,6 +1843,23 @@ class TinyOlmInstance {
17301843
}
17311844
});
17321845
}
1846+
1847+
/**
1848+
* Destroys the instance by disposing internal resources and removing all event listeners.
1849+
*
1850+
* This method ensures a clean shutdown of the instance by first calling `dispose()`—which is expected
1851+
* to release external or internal resources (such as timers or memory references)—and then
1852+
* removes all listeners from both `#events` and `#sysEvents` to prevent memory leaks or unintended behavior.
1853+
*
1854+
* It should be called when the instance is no longer needed.
1855+
*
1856+
* @returns {Promise<void>} Resolves when cleanup is complete.
1857+
*/
1858+
async destroy() {
1859+
await this.dispose();
1860+
this.#events.removeAllListeners();
1861+
this.#sysEvents.removeAllListeners();
1862+
}
17331863
}
17341864

17351865
export default TinyOlmInstance;

0 commit comments

Comments
 (0)