Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 567f8d8

Browse filesBrowse files
benjamingrdanielleadams
authored andcommitted
events: getEventListeners static
PR-URL: #35991 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
1 parent b7aa5e2 commit 567f8d8
Copy full SHA for 567f8d8

File tree

Expand file treeCollapse file tree

4 files changed

+97
-1
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

4 files changed

+97
-1
lines changed
Open diff view settings
Collapse file

‎doc/api/events.md‎

Copy file name to clipboardExpand all lines: doc/api/events.md
+34Lines changed: 34 additions & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,40 @@ class MyClass extends EventEmitter {
829829
}
830830
```
831831

832+
## `events.getEventListeners(emitterOrTarget, eventName)`
833+
<!-- YAML
834+
added:
835+
- REPLACEME
836+
-->
837+
* `emitterOrTarget` {EventEmitter|EventTarget}
838+
* `eventName` {string|symbol}
839+
* Returns: {Function[]}
840+
841+
Returns a copy of the array of listeners for the event named `eventName`.
842+
843+
For `EventEmitter`s this behaves exactly the same as calling `.listeners` on
844+
the emitter.
845+
846+
For `EventTarget`s this is the only way to get the event listeners for the
847+
event target. This is useful for debugging and diagnostic purposes.
848+
849+
```js
850+
const { getEventListeners, EventEmitter } = require('events');
851+
852+
{
853+
const ee = new EventEmitter();
854+
const listener = () => console.log('Events are fun');
855+
ee.on('foo', listener);
856+
getEventListeners(ee, 'foo'); // [listener]
857+
}
858+
{
859+
const et = new EventTarget();
860+
const listener = () => console.log('Events are fun');
861+
ee.addEventListener('foo', listener);
862+
getEventListeners(ee, 'foo'); // [listener]
863+
}
864+
```
865+
832866
## `events.once(emitter, name[, options])`
833867
<!-- YAML
834868
added:
Collapse file

‎lib/events.js‎

Copy file name to clipboardExpand all lines: lib/events.js
+25-1Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
'use strict';
2323

2424
const {
25+
ArrayPrototypePush,
2526
Boolean,
2627
Error,
2728
ErrorCaptureStackTrace,
@@ -74,13 +75,14 @@ const lazyDOMException = hideStackFrames((message, name) => {
7475
return new DOMException(message, name);
7576
});
7677

78+
7779
function EventEmitter(opts) {
7880
EventEmitter.init.call(this, opts);
7981
}
8082
module.exports = EventEmitter;
8183
module.exports.once = once;
8284
module.exports.on = on;
83-
85+
module.exports.getEventListeners = getEventListeners;
8486
// Backwards-compat with node 0.10.x
8587
EventEmitter.EventEmitter = EventEmitter;
8688

@@ -634,6 +636,28 @@ function unwrapListeners(arr) {
634636
return ret;
635637
}
636638

639+
function getEventListeners(emitterOrTarget, type) {
640+
// First check if EventEmitter
641+
if (typeof emitterOrTarget.listeners === 'function') {
642+
return emitterOrTarget.listeners(type);
643+
}
644+
// Require event target lazily to avoid always loading it
645+
const { isEventTarget, kEvents } = require('internal/event_target');
646+
if (isEventTarget(emitterOrTarget)) {
647+
const root = emitterOrTarget[kEvents].get(type);
648+
const listeners = [];
649+
let handler = root?.next;
650+
while (handler?.listener !== undefined) {
651+
ArrayPrototypePush(listeners, handler.listener);
652+
handler = handler.next;
653+
}
654+
return listeners;
655+
}
656+
throw new ERR_INVALID_ARG_TYPE('emitter',
657+
['EventEmitter', 'EventTarget'],
658+
emitterOrTarget);
659+
}
660+
637661
async function once(emitter, name, options = {}) {
638662
const signal = options ? options.signal : undefined;
639663
validateAbortSignal(signal, 'options.signal');
Collapse file

‎lib/internal/event_target.js‎

Copy file name to clipboardExpand all lines: lib/internal/event_target.js
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,4 +636,6 @@ module.exports = {
636636
kNewListener,
637637
kTrustEvent,
638638
kRemoveListener,
639+
kEvents,
640+
isEventTarget,
639641
};
Collapse file
+36Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
5+
const {
6+
deepStrictEqual,
7+
} = require('assert');
8+
9+
const { getEventListeners, EventEmitter } = require('events');
10+
11+
// Test getEventListeners on EventEmitter
12+
{
13+
const fn1 = common.mustNotCall();
14+
const fn2 = common.mustNotCall();
15+
const emitter = new EventEmitter();
16+
emitter.on('foo', fn1);
17+
emitter.on('foo', fn2);
18+
emitter.on('baz', fn1);
19+
emitter.on('baz', fn1);
20+
deepStrictEqual(getEventListeners(emitter, 'foo'), [fn1, fn2]);
21+
deepStrictEqual(getEventListeners(emitter, 'bar'), []);
22+
deepStrictEqual(getEventListeners(emitter, 'baz'), [fn1, fn1]);
23+
}
24+
// Test getEventListeners on EventTarget
25+
{
26+
const fn1 = common.mustNotCall();
27+
const fn2 = common.mustNotCall();
28+
const target = new EventTarget();
29+
target.addEventListener('foo', fn1);
30+
target.addEventListener('foo', fn2);
31+
target.addEventListener('baz', fn1);
32+
target.addEventListener('baz', fn1);
33+
deepStrictEqual(getEventListeners(target, 'foo'), [fn1, fn2]);
34+
deepStrictEqual(getEventListeners(target, 'bar'), []);
35+
deepStrictEqual(getEventListeners(target, 'baz'), [fn1]);
36+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.