node icon indicating copy to clipboard operation
node copied to clipboard

MessageEvent cannot be prevented even if cancelable is true

Open kettanaito opened this issue 1 year ago • 7 comments

Version

v18.14.2 (the same on LTS v20.11.0)

Platform

Darwin imac.home 22.6.0 Darwin Kernel Version 22.6.0: Wed Jul 5 22:21:56 PDT 2023; root:xnu-8796.141.3~6/RELEASE_X86_64 x86_64

Subsystem

No response

What steps will reproduce the bug?

// example.js
let t = new EventTarget()
t.addEventListener('message', (e) => console.log('cancelable?', e.cancelable))
t.dispatchEvent(new MessageEvent('message', { cancelable: true }))
node example.js

How often does it reproduce? Is there a required condition?

The issue can be reproduced every time.

What is the expected behavior? Why is that the expected behavior?

I expect the following:

  1. e.cancelable is true in the event listener for "message'.
  2. Calling e.preventDefault() will set e.defaultPrevented to true.

In other words, I expect the same behavior as with the regular Event instance:

let t = new EventTarget()
t.addEventListener('message', (e) => console.log('cancelable?', e.cancelable))

// Regular Event behaves correctly and can be canceled. 
t.dispatchEvent(new Event('message', { cancelable: true }))

What do you see instead?

The cancelable attribute on the MessageEvent instance is always false, no matter the cancelable value in the event init dictionary.

Calling e.preventDefault() has no effect on e.defaultPrevented (much likely because the cancelable attribute is false.

Additional information

I'm constructing a MessageEvent that I then dispatch on EventTarget and want to have the listeners being able to cancel that event (prevent its default).

kettanaito avatar Feb 15 '24 11:02 kettanaito

This is either an intentional behavior or a bug. In case this is intentional, can we please get some clarification as to why and have the docs updated to mention this behavior difference?

Note that both Event and MessageEvent scenarios run correctly in the browser (both events are cancelable and their defaults can be prevented).

kettanaito avatar Feb 15 '24 11:02 kettanaito

The only detail I can spot is that the event init dictionary for the MessageEvent is being transformed here:

https://github.com/nodejs/node/blob/10c6596f6d7abf7451112e767f8277fcd276d796/deps/undici/src/lib/websocket/events.js#L17

I don't know if this MessageEvent class is what we get as a global in Node.js though. I imagine it is since message events are WebSocket-specific events.

kettanaito avatar Feb 15 '24 11:02 kettanaito

https://github.com/nodejs/node/blob/fc801687eafe39f61880c7271e3b7529bdebb44a/lib/internal/worker/io.js#L131

undici's MessageEvent isn't exposed, I had no idea node implemented it honestly.

KhafraDev avatar Feb 15 '24 15:02 KhafraDev

@KhafraDev, it seems to be a global MessageEvent class, nothing from Undici. You can reproduce the issue using the code snippets I posted above even in a terminal (no dependencies).

kettanaito avatar Feb 15 '24 17:02 kettanaito