MessagePort alignment with Nodejs - #19941
Conversation
…oop alive if MessagePort has been created
…r GC only after close
…a different worker
Jarred-Sumner
left a comment
There was a problem hiding this comment.
If the RefPtr causes it to be destructed, it would be really easy to lead to a use-after-free.
Instead, we should increment/decrement the reference count while messages are in-flight. Enqueuing a message should increment the reference count of the MessagePort and processing that message should decrement it. To do that, we can use a protectedThis = Ref{ *this } in the lambda capture. That is the typical pattern WebKit uses for this sort of thing.
|
@Jarred-Sumner that won't work because we need to keep MessagePort alive unitl we call MessagePort::close() for example : import { MessageChannel } from "node:worker_threads";
function main (){
const { port1, port2 } = new MessageChannel();
port1.on("message", (msg) =>
console.log("message received on port 1 via on:", msg),
);
port2.postMessage("hey");
}
main()this should never close or get GCed even if we got no messages left but it does in bun unless we keep Ref for MessagePort another solution could be to keep |
|
@Jarred-Sumner any update on this ? |
| if (auto port = JSMessagePort::toWrapped(vm, transferable.get())) { | ||
| if (port->isDetached()) | ||
| return Exception { DataCloneError, "MessagePort in transfer list is already detached"_s }; | ||
| port->dispatchCloseEvent(); |
There was a problem hiding this comment.
The dispatchCloseEvent() call during transfer appears to be inconsistent with the MessagePort specification. According to the standard, MessagePorts should only dispatch 'close' events when explicitly closed via the close() method, not when transferred between contexts. Transferring a port detaches it from its original context but doesn't conceptually "close" it - it continues to exist in the target context. This behavior difference could cause compatibility issues with Node.js and other standard implementations.
| port->dispatchCloseEvent(); | |
| port->detachWithoutClosing(); |
Spotted by Diamond
Is this helpful? React 👍 or 👎 to let us know.
| if (listener->isAttribute()) | ||
| start(); |
There was a problem hiding this comment.
Please see my comment on actual issue. #19863 (comment)
I will emphasis that we should make WebCore implementation to align withe the JS specs and have that NodeJS compatibility layer abstracted away.
And until then just having documentation for such points would be suffice.
|
Thanks for working on this. Both issues this PR targeted have since been fixed on main by other changes:
Verified on current main (f426a8e): the #19863 script prints the output of both handlers without an explicit The files this PR touches have also moved since ( |
What does this PR do?
fixed 19863 and 19862
How did you verify your code works?