cloudflare / cloudflare/workerd
EventTarget is broken and not aligned with spec
- Dominant language
- C++
- Stars
- 8.7k
- Forks
- 739
- Avg merge
- 2d 20h
- Merged PRs (30d)
- 174
Description
Spec: https://dom.spec.whatwg.org/#interface-eventtarget
Used e.g. in WebSocket
extra built-in wrappers around `on*` handling in `EventTarget` directly are not aligned with the spec and break usage of anything subclassing `EventTarget`, as adding `on*` handlers in subclasses causes double firing and out of order.
```js
const EventsTest1_AC = {
async test(ctrl, env, ctx) {
console.log('# Should print: a c')
const x = new EventTarget()
x.addEventListener('hit', () => console.log('a'))
x.onhit = () => console.log('[SHOULD NOT FIRE]')
x.addEventListener('hit', () => console.log('c'))
x.dispatchEvent(new Event('hit'))
await new Promise((accept) => setTimeout(accept, 100))
},
}
const EventsTest2_ABC = {
async test(ctrl, env, ctx) {
console.log('# Should print: a b c')
const x = new EventTarget()
for (const type of ['hit']) {
let current
Object.defineProperty(x, `on${type}`, {
get: () => current,
set(value) {
if (current) this.removeEventListener(type, current)
current = value
if (current) this.addEventListener(type, current)
},
})
}
x.addEventListener('hit', () => console.log('a'))
x.onhit = () => console.log('b')
x.addEventListener('hit', () => console.log('c'))
x.dispatchEvent(new Event('hit'))
await new Promise((accept) => setTimeout(accept, 100))
},
}
if (globalThis.process?.versions?.node || globalThis.window) {
await EventsTest1_AC.test()
console.log()
await EventsTest2_ABC.test()
}
export { EventsTest1_AC, EventsTest2_ABC }
```
on workerd, prints:
```
# Should print: a c
[SHOULD NOT FIRE]
a
c
# Should print: a b c
b
a
b
c
```
on Node.js, Chrome, Safari, Firefox, Deno and Bun prints:
```
# Should print: a c
a
c
# Should print: a b c
a
b
c
```
Contributor guide
Assessment
This issue has not been assessed yet.