From 1fa75f75c90b744d63e451519311f27ba55c21d7 Mon Sep 17 00:00:00 2001 From: Colin Ihrig Date: Mon, 16 May 2022 10:46:39 -0400 Subject: [PATCH] fix(ext/web): throw if listener and signal are null (#14601) This commit fixes a failing WPT test by making EventTarget's addEventListener() method throw if both the listener and the signal option are null. Fixes: https://github.com/denoland/deno/issues/14593 --- ext/web/02_event.js | 66 +++++++++++++++++++++++++++----------- tools/wpt/expectation.json | 26 ++++----------- 2 files changed, 55 insertions(+), 37 deletions(-) diff --git a/ext/web/02_event.js b/ext/web/02_event.js index 06df6429cf..9d5169b9e0 100644 --- a/ext/web/02_event.js +++ b/ext/web/02_event.js @@ -797,20 +797,6 @@ } } - function normalizeAddEventHandlerOptions( - options, - ) { - if (typeof options === "boolean" || typeof options === "undefined") { - return { - capture: Boolean(options), - once: false, - passive: false, - }; - } else { - return options; - } - } - function normalizeEventHandlerOptions( options, ) { @@ -889,6 +875,45 @@ }; } + // This is lazy loaded because there is a circular dependency with AbortSignal. + let addEventListenerOptionsConverter; + + function lazyAddEventListenerOptionsConverter() { + addEventListenerOptionsConverter ??= webidl.createDictionaryConverter( + "AddEventListenerOptions", + [ + { + key: "capture", + defaultValue: false, + converter: webidl.converters.boolean, + }, + { + key: "passive", + defaultValue: false, + converter: webidl.converters.boolean, + }, + { + key: "once", + defaultValue: false, + converter: webidl.converters.boolean, + }, + { + key: "signal", + converter: webidl.converters.AbortSignal, + }, + ], + ); + } + + webidl.converters.AddEventListenerOptions = (V, opts) => { + if (webidl.type(V) !== "Object" || V === null) { + V = { capture: Boolean(V) }; + } + + lazyAddEventListenerOptionsConverter(); + return addEventListenerOptionsConverter(V, opts); + }; + class EventTarget { constructor() { this[eventTargetData] = getDefaultTargetData(); @@ -899,14 +924,21 @@ callback, options, ) { + const prefix = "Failed to execute 'addEventListener' on 'EventTarget'"; + webidl.requiredArguments(arguments.length, 2, { - prefix: "Failed to execute 'addEventListener' on 'EventTarget'", + prefix, }); + + options = webidl.converters.AddEventListenerOptions(options, { + prefix, + context: "Argument 3", + }); + if (callback === null) { return; } - options = normalizeAddEventHandlerOptions(options); const { listeners } = (this ?? globalThis)[eventTargetData]; if (!(ReflectHas(listeners, type))) { @@ -936,8 +968,6 @@ this.removeEventListener(type, callback, options); }); } - } else if (options?.signal === null) { - throw new TypeError("signal must be non-null"); } ArrayPrototypePush(listeners[type], { callback, options }); diff --git a/tools/wpt/expectation.json b/tools/wpt/expectation.json index 2fa5f6e68e..018b3ebd33 100644 --- a/tools/wpt/expectation.json +++ b/tools/wpt/expectation.json @@ -902,28 +902,16 @@ "event.any.worker.html": true }, "events": { - "AddEventListenerOptions-once.any.html": [ - "Once listener should be added / removed like normal listeners" - ], - "AddEventListenerOptions-once.any.worker.html": [ - "Once listener should be added / removed like normal listeners" - ], + "AddEventListenerOptions-once.any.html": true, + "AddEventListenerOptions-once.any.worker.html": true, "AddEventListenerOptions-passive.any.html": [ - "Supports passive option on addEventListener only", - "returnValue should be ignored if-and-only-if the passive option is true", - "Equivalence of option values" + "returnValue should be ignored if-and-only-if the passive option is true" ], "AddEventListenerOptions-passive.any.worker.html": [ - "Supports passive option on addEventListener only", - "returnValue should be ignored if-and-only-if the passive option is true", - "Equivalence of option values" - ], - "AddEventListenerOptions-signal.any.html": [ - "Passing null as the signal should throw (listener is also null)" - ], - "AddEventListenerOptions-signal.any.worker.html": [ - "Passing null as the signal should throw (listener is also null)" + "returnValue should be ignored if-and-only-if the passive option is true" ], + "AddEventListenerOptions-signal.any.html": true, + "AddEventListenerOptions-signal.any.worker.html": true, "Event-isTrusted.any.html": true, "Event-isTrusted.any.worker.html": true, "EventTarget-add-remove-listener.any.html": true, @@ -4787,4 +4775,4 @@ "idlharness.https.any.worker.html": true, "idlharness-shadowrealm.window.html": false } -} \ No newline at end of file +}