Skip to content

Using MessageChannel pulls in undici inappropriatelyΒ #57581

Description

@webstrand

Version

v22.13.1

Platform

Linux localhost 6.13.1-1-default #1 SMP PREEMPT_DYNAMIC Mon Feb  3 05:33:25 UTC 2025 (1918d13) x86_64 x86_64 x86_64 GNU/Linux

Subsystem

worker_threads

What steps will reproduce the bug?

Run this command:

node --jitless -e 'const { port1, port2 } = new MessageChannel(); port1.addEventListener("message", () => {});  port2.postMessage(null);'

or run this script with --jitless

const { port1, port2 } = new MessageChannel();
port1.addEventListener("message", () => {});
port2.postMessage(null);

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

Every time

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

No exception should be thrown, undici should not be loaded when fetch is not needed.

What do you see instead?

> node --jitless -e 'const { port1, port2 } = new MessageChannel(); port1.addEventListener("message", () => {});  port2.postMessage(null);'
Warning: disabling flag --expose_wasm due to conflicting flags
node:internal/deps/undici/undici:5827
        mod = await WebAssembly.compile(llhttpWasmData || require_llhttp_wasm());
        ^

ReferenceError: WebAssembly is not defined
    at lazyllhttp (node:internal/deps/undici/undici:5827:9)
    at lib/dispatcher/client-h1.js (node:internal/deps/undici/undici:5873:25)
    at __require (node:internal/deps/undici/undici:6:50)
    at lib/dispatcher/client.js (node:internal/deps/undici/undici:7607:21)
    at __require (node:internal/deps/undici/undici:6:50)
    at lib/dispatcher/pool.js (node:internal/deps/undici/undici:8068:18)
    at __require (node:internal/deps/undici/undici:6:50)
    at lib/dispatcher/agent.js (node:internal/deps/undici/undici:8151:16)
    at __require (node:internal/deps/undici/undici:6:50)
    at lib/global.js (node:internal/deps/undici/undici:8251:17)

Node.js v22.13.1

Additional information

I believe this is due to constructing the MessageEvent, which appears to come from undici:

fastCreateMessageEvent ??= require('internal/deps/undici/undici').createFastMessageEvent;

Activity

  1. marco-ippolito commented on Mar 24, 2025

    @marco-ippolito
    Member

    cc @nodejs/undici I think also typescript has the same issue since amaro lazy loads a wasm

  2. mcollina commented on Mar 24, 2025

    @mcollina
    SponsorMember

    MessageEvent is part of the HTML standard and it's at basis of WebSocket.

    https://html.spec.whatwg.org/multipage/comms.html

    That's why the global comes from undici. What I'm a bit puzzled about is why for non-spec compliant objects we are using it in

    // createFastMessageEvent skips webidl argument validation when the arguments
    .

    This appears to come from #52370.

    Wdyt @KhafraDev?

  3. KhafraDev commented on Mar 24, 2025

    @KhafraDev
    Member

    What I'm a bit puzzled about is why for non-spec compliant objects we are using it in

    It was exposed globally where the real issue arose from, when <message event from websocket> instanceof MessageEvent would be false. It was not a good implementation, and since undici already had a fully spec-compliant, faster implementation, it was easier to replace node's with undici's.

  4. mcollina commented on Mar 25, 2025

    @mcollina
    SponsorMember

    The only place where MessageEvent is mentioned in our docs is https://nodejs.org/api/worker_threads.html#broadcastchannelonmessage.

    I'm a bit puzzled why we use it here to begin with. @jasnell @addaleax do you recall?

  5. jasnell commented on Mar 25, 2025

    @jasnell
    Member

    Puzzled about using it where exactly?

  6. mcollina commented on Mar 25, 2025

    @mcollina
    SponsorMember

    About why our MessagePort and MessageChannel are using the spec-compliant MessageEvent. Do you recall what the design motivation was?

    I think we can add a fallback if there is no fetch/undici for MessageEvent.

  7. jasnell commented on Mar 25, 2025

    @jasnell
    Member

    well, MessagePort would have had a separate MessageEvent originally since that predates the introduction of undici and WebSockets but I guess it got replaced at some point with the undici one. The code in worker/io.js was updated about 11 months ago was updated (#52370) to switch to using undici's MessageEvent rather than the original implementation that still exists in the runtime in lib/internal/per_context/messageport.js.

  8. github-actions commented on Sep 22, 2025

    @github-actions
    Contributor

    There has been no activity on this feature request for 5 months. To help maintain relevant open issues, please add the never-stale Issues and PRs exempt from automated stale handling. label or close this issue if it should be closed. If not, the issue will be automatically closed 6 months after the last non-automated comment.
    For more information on how the project manages feature requests, please consult the feature request management document.

  9. added
    staleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.
    on Sep 22, 2025
  10. webstrand commented on Sep 22, 2025

    @webstrand
    Author

    This is still an issue, not stale.

  11. Uzlopak commented on Sep 22, 2025

    @Uzlopak
    Contributor

    I cant reproduce it on node 24. On node22 I can.

  12. webstrand commented on Sep 22, 2025

    @webstrand
    Author

    Nevermind then, I guess it got silently fixed. v24 seems to have fixed the issue, I only tested against v22.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature requestIssues requesting new Node.js features.staleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions