diff --git a/source/event-emitter.ts b/source/event-emitter.ts index 5ea4070..8544fca 100644 --- a/source/event-emitter.ts +++ b/source/event-emitter.ts @@ -117,11 +117,17 @@ export class EventEmitter { * @param type - The event type. * @param listener - The listener function. */ - off(type: K, listener: Listener): void { + off(type: K, listener?: Listener): void { // Get the listeners for the event type. const listeners = this.#listeners.get(type); if (!listeners) return; + // If no listener is provided, remove all listeners for the event type. + if (!listener) { + this.#listeners.delete(type); + return; + } + // Find the listener entry. const listenerEntry = Array.from(listeners).find((entry) => entry.listener === listener || entry.wrappedListener === listener); diff --git a/test/event-emitter.test.ts b/test/event-emitter.test.ts index b0b0e81..11d6a3e 100644 --- a/test/event-emitter.test.ts +++ b/test/event-emitter.test.ts @@ -124,6 +124,21 @@ const testEventEmitterOffRemovesListenerByReference = (): void => { expect(listener).not.toHaveBeenCalled(); }; +/** + * Tests that off() removes all listeners for an event type when no listener is provided. + */ +const testEventEmitterOffRemovesAllListenersForEventType = (): void => { + const emitter = new EventEmitter(); + const listener = vi.fn(); + + emitter.on('message', listener); + emitter.off('message'); + + expect(listener).not.toHaveBeenCalled(); + expect(emitter.emit('message', 'hello')).toBe(false); + expect(emitter.emit('count', 42)).toBe(false); +}; + /** * Tests that off() does nothing when given an unknown listener reference. */ @@ -484,6 +499,7 @@ const runTests = async (): Promise => { test('EventEmitter: returns true when emitting with listeners', testEventEmitterEmitReturnsTrueWithListeners); test('EventEmitter: stops calling a listener after its off callback is invoked', testEventEmitterOffCallbackRemovesListener); test('EventEmitter: removes a listener when off is called with the same reference', testEventEmitterOffRemovesListenerByReference); + test('EventEmitter: removes all listeners for an event type when off is called with no listener', testEventEmitterOffRemovesAllListenersForEventType); test('EventEmitter: ignores off when the listener reference is unknown', testEventEmitterOffIgnoresUnknownListener); test('EventEmitter: ignores off for an event type with no listeners', testEventEmitterOffIgnoresUnregisteredEventType); test('EventEmitter: calls a once listener only one time', testEventEmitterOnceListenerFiresOnce);