From 520e62c4ea6226bdc4d91b4d8ba18dee150ca479 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 +++ .../parallel/test-events-on-async-iterator.js | 9 +++++++++ test/parallel/test-events-once.js | 19 +++++++++---------- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/lib/events.js b/lib/events.js index e05a3bc6b8b168..94f273a7cea59c 100644 --- a/lib/events.js +++ b/lib/events.js @@ -81,6 +81,7 @@ const { validateAbortSignal, validateBoolean, validateFunction, + validateObject, validateString, } = require('internal/validators'); @@ -931,6 +932,7 @@ function getEventListeners(emitterOrTarget, type) { * @returns {Promise} */ async function once(emitter, name, options = kEmptyObject) { + validateObject(options, 'options'); const signal = options?.signal; validateAbortSignal(signal, 'options.signal'); if (signal?.aborted) @@ -1015,6 +1017,7 @@ function eventTargetAgnosticAddListener(emitter, name, listener, flags) { */ function on(emitter, event, options = {}) { // 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..bf1c69f052db05 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) => { + 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 0b1d5677f60109..5dd8f147da7782 100644 --- a/test/parallel/test-events-once.js +++ b/test/parallel/test-events-once.js @@ -4,10 +4,11 @@ const common = require('../common'); const { once, EventEmitter } = require('events'); const { - strictEqual, deepStrictEqual, fail, rejects, + strictEqual, + throws, } = require('assert'); const { kEvents } = require('internal/event_target'); @@ -24,18 +25,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(); @@ -248,7 +247,7 @@ async function eventTargetAbortSignalAfterEvent() { Promise.all([ onceAnEvent(), - onceAnEventWithNullOptions(), + onceAnEventWithInvalidOptions(), onceAnEventWithTwoArgs(), catchesErrors(), catchesErrorsWithAbortSignal(),