From 55d1bc43d016891e241bf372cbde56cfbdcfc7c5 Mon Sep 17 00:00:00 2001 From: Deokjin Kim Date: Fri, 30 Dec 2022 13:44:18 +0900 Subject: [PATCH] events: validate options of `on` and `once` Check whether options is object or not to avoid passing invalid type as options to `on` and `once`. Refs: https://nodejs.org/dist/latest-v19.x/docs/api/events.html#eventsonceemitter-name-options --- lib/events.js | 3 +++ test/parallel/test-events-on-async-iterator.js | 9 +++++++++ test/parallel/test-events-once.js | 18 ++++++++---------- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/lib/events.js b/lib/events.js index f42a11ab3e701d..a1837cc1a9107e 100644 --- a/lib/events.js +++ b/lib/events.js @@ -81,6 +81,7 @@ const { validateBoolean, validateFunction, validateNumber, + validateObject, validateString, } = require('internal/validators'); @@ -960,6 +961,7 @@ function getMaxListeners(emitterOrTarget) { * @returns {Promise} */ async function once(emitter, name, options = kEmptyObject) { + validateObject(options, 'options'); const signal = options?.signal; validateAbortSignal(signal, 'options.signal'); if (signal?.aborted) @@ -1047,6 +1049,7 @@ function eventTargetAgnosticAddListener(emitter, name, listener, flags) { */ function on(emitter, event, options = kEmptyObject) { // Parameters validation + validateObject(options, 'options'); const signal = options.signal; validateAbortSignal(signal, 'options.signal'); if (signal?.aborted) diff --git a/test/parallel/test-events-on-async-iterator.js b/test/parallel/test-events-on-async-iterator.js index 94f66a81edb0c0..0083d1d7281a59 100644 --- a/test/parallel/test-events-on-async-iterator.js +++ b/test/parallel/test-events-on-async-iterator.js @@ -40,6 +40,15 @@ async function invalidArgType() { code: 'ERR_INVALID_ARG_TYPE', name: 'TypeError', })); + + const ee = new EventEmitter(); + + [1, 'hi', null, false].map((options) => { + return assert.throws(() => on(ee, 'foo', options), common.expectsError({ + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError', + })); + }); } async function error() { diff --git a/test/parallel/test-events-once.js b/test/parallel/test-events-once.js index be05028faaf0c2..7b7f1697ead120 100644 --- a/test/parallel/test-events-once.js +++ b/test/parallel/test-events-once.js @@ -4,10 +4,10 @@ const common = require('../common'); const { once, EventEmitter } = require('events'); const { - strictEqual, deepStrictEqual, fail, rejects, + strictEqual, } = require('assert'); const { kEvents } = require('internal/event_target'); @@ -24,18 +24,16 @@ async function onceAnEvent() { strictEqual(ee.listenerCount('myevent'), 0); } -async function onceAnEventWithNullOptions() { +async function onceAnEventWithInvalidOptions() { const ee = new EventEmitter(); - process.nextTick(() => { - ee.emit('myevent', 42); - }); - - const [value] = await once(ee, 'myevent', null); - strictEqual(value, 42); + await Promise.all([1, 'hi', null, false].map((options) => { + return rejects(once(ee, 'myevent', options), { + code: 'ERR_INVALID_ARG_TYPE', + }); + })); } - async function onceAnEventWithTwoArgs() { const ee = new EventEmitter(); @@ -267,7 +265,7 @@ async function eventTargetAbortSignalAfterEvent() { Promise.all([ onceAnEvent(), - onceAnEventWithNullOptions(), + onceAnEventWithInvalidOptions(), onceAnEventWithTwoArgs(), catchesErrors(), catchesErrorsWithAbortSignal(),