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
This commit is contained in:
Colin Ihrig 2022-05-16 10:46:39 -04:00 committed by GitHub
parent 8af81d98a6
commit 1fa75f75c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 55 additions and 37 deletions

View File

@ -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 });

View File

@ -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
}
}
}