diff --git a/lib/events.js b/lib/events.js index 51259e6821bf23..300f9f1e6b687f 100644 --- a/lib/events.js +++ b/lib/events.js @@ -623,7 +623,10 @@ function unwrapListeners(arr) { function once(emitter, name) { return new Promise((resolve, reject) => { - if (typeof emitter.addEventListener === 'function') { + if ( + typeof emitter.addEventListener === 'function' && + typeof emitter.on !== 'function' + ) { // EventTarget does not have `error` event semantics like Node // EventEmitters, we do not listen to `error` events here. emitter.addEventListener( diff --git a/test/parallel/test-events-once.js b/test/parallel/test-events-once.js index fea143f5877cc7..d07492ea63fa8e 100644 --- a/test/parallel/test-events-once.js +++ b/test/parallel/test-events-once.js @@ -166,6 +166,27 @@ async function onceWithEventTargetError() { strictEqual(Reflect.has(et.events, 'error'), false); } +async function assumesEventEmitterIfOnIsAFunction() { + const ee = new EventEmitter(); + ee.addEventListener = () => {}; + + const expected = new Error('kaboom'); + let err; + process.nextTick(() => { + ee.emit('error', expected); + }); + + try { + await once(ee, 'myevent'); + } catch (_e) { + err = _e; + } + + strictEqual(err, expected); + strictEqual(ee.listenerCount('error'), 0); + strictEqual(ee.listenerCount('myevent'), 0); +} + Promise.all([ onceAnEvent(), onceAnEventWithTwoArgs(), @@ -175,4 +196,5 @@ Promise.all([ onceWithEventTarget(), onceWithEventTargetTwoArgs(), onceWithEventTargetError(), + assumesEventEmitterIfOnIsAFunction(), ]).then(common.mustCall());