Skip to content

Commit

Permalink
events: add listener argument to listenerCount
Browse files Browse the repository at this point in the history
PR-URL: #46523
Reviewed-By: Robert Nagy <ronagy@icloud.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
  • Loading branch information
ShogunPanda authored and danielleadams committed Apr 5, 2023
1 parent 45fccc9 commit cc6deea
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 5 deletions.
2 changes: 1 addition & 1 deletion doc/api/deprecations.md
Original file line number Diff line number Diff line change
Expand Up @@ -3364,7 +3364,7 @@ In a future version of Node.js, [`message.headers`][],
[`dnsPromises.lookup()`]: dns.md#dnspromiseslookuphostname-options
[`domain`]: domain.md
[`ecdh.setPublicKey()`]: crypto.md#ecdhsetpublickeypublickey-encoding
[`emitter.listenerCount(eventName)`]: events.md#emitterlistenercounteventname
[`emitter.listenerCount(eventName)`]: events.md#emitterlistenercounteventname-listener
[`events.listenerCount(emitter, eventName)`]: events.md#eventslistenercountemitter-eventname
[`fs.FileHandle`]: fs.md#class-filehandle
[`fs.access()`]: fs.md#fsaccesspath-mode-callback
Expand Down
13 changes: 10 additions & 3 deletions doc/api/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -646,16 +646,23 @@ Returns the current max listener value for the `EventEmitter` which is either
set by [`emitter.setMaxListeners(n)`][] or defaults to
[`events.defaultMaxListeners`][].

### `emitter.listenerCount(eventName)`
### `emitter.listenerCount(eventName[, listener])`

<!-- YAML
added: v3.2.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/46523
description: Added the `listener` argument.
-->

* `eventName` {string|symbol} The name of the event being listened for
* `listener` {Function} The event handler function
* Returns: {integer}

Returns the number of listeners listening to the event named `eventName`.
Returns the number of listeners listening for the event named `eventName`.
If `listener` is provided, it will return how many times the listener is found
in the list of the listeners of the event.

### `emitter.listeners(eventName)`

Expand Down Expand Up @@ -2462,7 +2469,7 @@ to the `EventTarget`.
[`EventTarget` error handling]: #eventtarget-error-handling
[`Event` Web API]: https://dom.spec.whatwg.org/#event
[`domain`]: domain.md
[`emitter.listenerCount()`]: #emitterlistenercounteventname
[`emitter.listenerCount()`]: #emitterlistenercounteventname-listener
[`emitter.removeListener()`]: #emitterremovelistenereventname-listener
[`emitter.setMaxListeners(n)`]: #emittersetmaxlistenersn
[`event.defaultPrevented`]: #eventdefaultprevented
Expand Down
19 changes: 18 additions & 1 deletion lib/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -835,17 +835,34 @@ EventEmitter.prototype.listenerCount = listenerCount;
* Returns the number of listeners listening to event name
* specified as `type`.
* @param {string | symbol} type
* @param {Function} listener
* @returns {number}
*/
function listenerCount(type) {
function listenerCount(type, listener) {
const events = this._events;

if (events !== undefined) {
const evlistener = events[type];

if (typeof evlistener === 'function') {
if (listener != null) {
return listener === evlistener ? 1 : 0;
}

return 1;
} else if (evlistener !== undefined) {
if (listener != null) {
let matching = 0;

for (let i = 0, l = evlistener.length; i < l; i++) {
if (evlistener[i] === listener || evlistener[i].listener === listener) {
matching++;
}
}

return matching;
}

return evlistener.length;
}
}
Expand Down
53 changes: 53 additions & 0 deletions test/parallel/test-events-listener-count-with-listener.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
'use strict';

const common = require('../common');
const EventEmitter = require('events');
const assert = require('assert');

const EE = new EventEmitter();
const handler = common.mustCall(undefined, 3);
const anotherHandler = common.mustCall();

assert.strictEqual(EE.listenerCount('event'), 0);
assert.strictEqual(EE.listenerCount('event', handler), 0);
assert.strictEqual(EE.listenerCount('event', anotherHandler), 0);

EE.on('event', handler);

assert.strictEqual(EE.listenerCount('event'), 1);
assert.strictEqual(EE.listenerCount('event', handler), 1);
assert.strictEqual(EE.listenerCount('event', anotherHandler), 0);

EE.once('event', anotherHandler);

assert.strictEqual(EE.listenerCount('event'), 2);
assert.strictEqual(EE.listenerCount('event', handler), 1);
assert.strictEqual(EE.listenerCount('event', anotherHandler), 1);

assert.strictEqual(EE.listenerCount('another-event'), 0);
assert.strictEqual(EE.listenerCount('another-event', handler), 0);
assert.strictEqual(EE.listenerCount('another-event', anotherHandler), 0);

EE.once('event', handler);

assert.strictEqual(EE.listenerCount('event'), 3);
assert.strictEqual(EE.listenerCount('event', handler), 2);
assert.strictEqual(EE.listenerCount('event', anotherHandler), 1);

EE.emit('event');

assert.strictEqual(EE.listenerCount('event'), 1);
assert.strictEqual(EE.listenerCount('event', handler), 1);
assert.strictEqual(EE.listenerCount('event', anotherHandler), 0);

EE.emit('event');

assert.strictEqual(EE.listenerCount('event'), 1);
assert.strictEqual(EE.listenerCount('event', handler), 1);
assert.strictEqual(EE.listenerCount('event', anotherHandler), 0);

EE.off('event', handler);

assert.strictEqual(EE.listenerCount('event'), 0);
assert.strictEqual(EE.listenerCount('event', handler), 0);
assert.strictEqual(EE.listenerCount('event', anotherHandler), 0);

0 comments on commit cc6deea

Please sign in to comment.