Sitelet https://web.archive.org/web/20220507195951/https://github.com/denoland/deno/issues/14254
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EventTarget#addEventListener mishandles nullish "signal" option #14254

Open
Garcia101 opened this issue Apr 11, 2022 · 7 comments
Open

EventTarget#addEventListener mishandles nullish "signal" option #14254

Garcia101 opened this issue Apr 11, 2022 · 7 comments
Labels
bug ext/web good first issue

Comments

@Garcia101
Copy link

@Garcia101 Garcia101 commented Apr 11, 2022 •

Currently, Deno accepts this example snippet without error:

window.addEventListener("load", null, {
 signal: null
});

According to https://dom.spec.whatwg.org/#eventtarget, EventTarget#addEventListener is defined as

interface EventTarget {
 ...
 undefined addEventListener(..., ..., optional (AddEventListenerOptions or boolean) options = {});
 ...
}

dictionary EventListenerOptions {
  boolean capture = false;
};

dictionary AddEventListenerOptions : EventListenerOptions {
  boolean passive = false;
  boolean once = false;
  AbortSignal signal;
};

Note the AbortSignal signal, which doesn't allow the signal value to be null, if the object property is present.

From a quick skim, it seems to be that this branch isn't being reached, even though it's intended to be?

deno/ext/web/02_event.js

Lines 932 to 934 in 8ae1702

} else if (options?.signal === null) {
throw new TypeError("signal must be non-null");
}

@crowlKats
Copy link

@crowlKats crowlKats commented Apr 11, 2022 •

The code there is quite outdated, and should be using webidl converters. There are many examples of such across the codebase, including the same file:

deno/ext/web/02_event.js

Lines 114 to 126 in 8ae1702

const eventInitConverter = webidl.createDictionaryConverter("EventInit", [{
key: "bubbles",
defaultValue: false,
converter: webidl.converters.boolean,
}, {
key: "cancelable",
defaultValue: false,
converter: webidl.converters.boolean,
}, {
key: "composed",
defaultValue: false,
converter: webidl.converters.boolean,
}]);

which is then used later:

deno/ext/web/02_event.js

Lines 158 to 161 in 8ae1702

const eventInit = eventInitConverter(eventInitDict, {
prefix: "Failed to construct 'Event'",
context: "Argument 2",
});

@crowlKats crowlKats added bug good first issue ext/web labels Apr 11, 2022
@randomicon00
Copy link

@randomicon00 randomicon00 commented Apr 14, 2022 •

From the spec, it states that the signal property can be null.

signal (null or an [AbortSignal] object)

@F3n67u
Copy link
Sponsor

@F3n67u F3n67u commented Apr 14, 2022

From the spec, it states that the signal property can be null.

signal (null or an [AbortSignal] object)

@randomicon00 I think null is not the javascript null value, it's more like undefined on spec text.

there is a wpt test which states a TypeError should throw when signal is null.

https://github.com/web-platform-tests/wpt/blob/3532a4b4082fbbb32438ae8670252e664aaa2efe/dom/events/AddEventListenerOptions-signal.any.js#L135-L138

@Garcia101
Copy link
Author

@Garcia101 Garcia101 commented Apr 14, 2022 •

From the spec, it states that the signal property can be null.

signal (null or an [AbortSignal] object)

If anything, the code snippet that I provide yields different results than Deno when evaluated in a browser (do try it yourself).
I expect that the null is internal, and intended to mark handlers that aren't storing an AbortSignal reference, but it isn't intended to accept null in the exposed interface as an AbortSignal object.

@F3n67u
Copy link
Sponsor

@F3n67u F3n67u commented Apr 15, 2022 •

@Garcia101 what's your deno version? "AddEventListenerOptions.signal shouldn't be nullable" fix is landed at version v1.12.0, so if you using version lower than version 1.12.0, then the problem will exist.

fix pr: #11348
release note: https://github.com/denoland/deno/releases/tag/v1.12.0

I am using version 1.20.6, the problem is not exist

$ cat test.js                                          
const et = new EventTarget();
et.addEventListener("foo", () => {}, { signal: null });

$ deno run test.js
error: Uncaught TypeError: signal must be non-null
et.addEventListener("foo", () => {}, { signal: null });
   ^
    at EventTarget.addEventListener (deno:ext/web/02_event.js:939:15)
    at file:///Users/feng/dev/deno/test.js:2:4

Deno Version

$ deno --version   
deno 1.20.6 (release, x86_64-apple-darwin)
v8 10.0.139.6
typescript 4.6.2

@Garcia101
Copy link
Author

@Garcia101 Garcia101 commented Apr 15, 2022 •

@Garcia101 what's your deno version? "AddEventListenerOptions.signal shouldn't be nullable" fix is landed at version v1.12.0, so if you using version lower than version 1.12.0, then the problem will exist.

fix pr: #11348 release note: https://github.com/denoland/deno/releases/tag/v1.12.0

I am using version 1.20.6, the problem is not exist

$ cat test.js                                          
const et = new EventTarget();
et.addEventListener("foo", () => {}, { signal: null });

$ deno run test.js
error: Uncaught TypeError: signal must be non-null
et.addEventListener("foo", () => {}, { signal: null });
   ^
    at EventTarget.addEventListener (deno:ext/web/02_event.js:939:15)
    at file:///Users/feng/dev/deno/test.js:2:4

Deno Version

$ deno --version   
deno 1.20.6 (release, x86_64-apple-darwin)
v8 10.0.139.6
typescript 4.6.2

I just ran this, to be fully certain:

const event_target = new EventTarget();

event_target.addEventListener("abc", null, {
 signal: null
});

console.log(Deno.version);

output:

{ deno: "1.20.6+0e4574b", v8: "10.0.139.6", typescript: "4.6.2" }

I also tried on the non-canary release,

{ deno: "1.20.6", v8: "10.0.139.6", typescript: "4.6.2" }

Furthermore, note that I reference what happens to be the code intended to prevent this bug, in the issue message itself:

From a quick skim, it seems to be that this branch isn't being reached, even though it's intended to be?

deno/ext/web/02_event.js

Lines 932 to 934 in 8ae1702

} else if (options?.signal === null) {
throw new TypeError("signal must be non-null");
}

That very code coincidentally comes from the PR that was intended to fix this issue.

The current implementation is erroneous and misaligned with the appropriate specification, as WebIDL type conversions are up-front, whereas this code is evaluated conditionally, that is, if the handler callback function is not null. Please do evaluate my suggested script snippet in your current version of Deno, and you will see the same. CrowlCats agreed that this is the case. So hopefully it may be fixed in due time. (Unfortunately, I don't have a means of locally building and testing Deno at the time, so my apologies for not attempting this myself.)

@F3n67u
Copy link
Sponsor

@F3n67u F3n67u commented Apr 15, 2022

@Garcia101 my bad. I copy the snippet from the wpt test. I can reproduce this problem when I execute your snippet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug ext/web good first issue
Projects
None yet
Development

No branches or pull requests

4 participants