Skip to content

Commit 588ab30

Browse files
daeyeonguangwong
authored andcommitted
events: fix adding abort listener in events.once
Event listeners passed to un/subscribe the abort event are mismatched. This removes the wrapper function in `eventTargetAgnosticAddListener()` and directly passes the given listener to the `EventTarget`. IMO, removing the wrapper seems harmless, and the `AbortSignal` is seemingly the only `EventTarget` passed to this function for now. Fixes: nodejs/node#43337 Refs: nodejs/node#33659 Refs: nodejs/node#34997 Signed-off-by: Daeyeon Jeong [email protected] PR-URL: nodejs/node#43373 Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Benjamin Gruenbaum <[email protected]>
1 parent 279625c commit 588ab30

File tree

2 files changed

+36
-5
lines changed

2 files changed

+36
-5
lines changed

lib/events.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -965,6 +965,8 @@ async function once(emitter, name, options = kEmptyObject) {
965965
};
966966
eventTargetAgnosticAddListener(emitter, name, resolver, { once: true });
967967
if (name !== 'error' && typeof emitter.once === 'function') {
968+
// EventTarget does not have `error` event semantics like Node
969+
// EventEmitters, we listen to `error` events only on EventEmitters.
968970
emitter.once('error', errorListener);
969971
}
970972
function abortListener() {
@@ -1004,9 +1006,7 @@ function eventTargetAgnosticAddListener(emitter, name, listener, flags) {
10041006
emitter.on(name, listener);
10051007
}
10061008
} else if (typeof emitter.addEventListener === 'function') {
1007-
// EventTarget does not have `error` event semantics like Node
1008-
// EventEmitters, we do not listen to `error` events here.
1009-
emitter.addEventListener(name, (arg) => { listener(arg); }, flags);
1009+
emitter.addEventListener(name, listener, flags);
10101010
} else {
10111011
throw new ERR_INVALID_ARG_TYPE('emitter', 'EventEmitter', emitter);
10121012
}

test/parallel/test-events-once.js

+33-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
'use strict';
2-
// Flags: --no-warnings
2+
// Flags: --expose-internals --no-warnings
33

44
const common = require('../common');
55
const { once, EventEmitter } = require('events');
@@ -9,6 +9,7 @@ const {
99
fail,
1010
rejects,
1111
} = require('assert');
12+
const { kEvents } = require('internal/event_target');
1213

1314
async function onceAnEvent() {
1415
const ee = new EventEmitter();
@@ -65,6 +66,32 @@ async function catchesErrors() {
6566
strictEqual(ee.listenerCount('myevent'), 0);
6667
}
6768

69+
async function catchesErrorsWithAbortSignal() {
70+
const ee = new EventEmitter();
71+
const ac = new AbortController();
72+
const signal = ac.signal;
73+
74+
const expected = new Error('boom');
75+
let err;
76+
process.nextTick(() => {
77+
ee.emit('error', expected);
78+
});
79+
80+
try {
81+
const promise = once(ee, 'myevent', { signal });
82+
strictEqual(ee.listenerCount('error'), 1);
83+
strictEqual(signal[kEvents].size, 1);
84+
85+
await promise;
86+
} catch (e) {
87+
err = e;
88+
}
89+
strictEqual(err, expected);
90+
strictEqual(ee.listenerCount('error'), 0);
91+
strictEqual(ee.listenerCount('myevent'), 0);
92+
strictEqual(signal[kEvents].size, 0);
93+
}
94+
6895
async function stopListeningAfterCatchingError() {
6996
const ee = new EventEmitter();
7097

@@ -165,7 +192,10 @@ async function abortSignalAfterEvent() {
165192
ee.emit('foo');
166193
ac.abort();
167194
});
168-
await once(ee, 'foo', { signal: ac.signal });
195+
const promise = once(ee, 'foo', { signal: ac.signal });
196+
strictEqual(ac.signal[kEvents].size, 1);
197+
await promise;
198+
strictEqual(ac.signal[kEvents].size, 0);
169199
}
170200

171201
async function abortSignalRemoveListener() {
@@ -221,6 +251,7 @@ Promise.all([
221251
onceAnEventWithNullOptions(),
222252
onceAnEventWithTwoArgs(),
223253
catchesErrors(),
254+
catchesErrorsWithAbortSignal(),
224255
stopListeningAfterCatchingError(),
225256
onceError(),
226257
onceWithEventTarget(),

0 commit comments

Comments
 (0)