Open Bug 1756975 Opened 3 years ago Updated 9 months ago

MessagePort attempts to fire already-queued events on a shipped message port after the message port is shipped if the port message queue was already started prior to shipping

Categories

(Core :: DOM: postMessage, defect, P2)

Firefox 97
defect

Tracking

()

People

(Reporter: roberto.vidal, Unassigned)

References

Details

Steps to reproduce:

Working example: https://github.com/jrvidal/message-port-repro/tree/master/transfer

We have two workers, with a parent-child relation. The follower then:

  • Creates a new MessageChannel,
  • Listens to one end of the channel for messages,
  • Posts a message to other end of the channel, and
  • Transfers the first end of the channel to the parent worker, where it is listened for messages.

All this happens synchronously in follower thread.

Actual results:

The listener set up in the follower thread gets a message:

[follower] port got hello

Note that at this time, the receiving port has been transferred to the parent worker (!).

Expected results:

Not sure if this is what should happen, but in Chrome (98.0.4758.102), it's the leader who receives the message:

[leader] port got hello

There's an extra DESTROY flag in the example, that unsets onmessage on the follower right after setting it. In that case the message is lost in FF, but the result is the same in Chrome.

cc asutherland bholley

This is another MessagePort-related issue we've run into on Stackblitz.

Flags: needinfo?(bugmail)
Flags: needinfo?(bholley)

Blink/Chrome's behavior seems correct under the spec and Gecko/Firefox has a bug here. Thank you for your reporting the bug and continued dedication to creating minimized test cases!

The spec steps for transfer specifically transfer-receiving call for stealing all of the message events on receiving. This is very dubious from a spec language perspective, but as the second info box for entangle says:

While this specification describes this process as instantaneous, implementations are more likely to implement it via message passing. As with all algorithms, the key is "merely" that the end result be indistinguishable, in a black-box sense, from the specification.

Which is to say, the intent is quite clear that events that haven't yet been fired should be moved, so it's clear that our state machine has to handle this case. (There's some hand-waving around the port message queue and unshipped port message queue which makes things a little more awkward, but again, the intent is clear.)

In particular, what's going wrong here is:

Conceptually, the current implementation wants the PostMessageRunnable to request messages from the MessagePort at Run()-time, not at dispatch time.

Status: UNCONFIRMED → NEW
Component: Untriaged → DOM: postMessage
Ever confirmed: true
Flags: needinfo?(bugmail)
Flags: needinfo?(bholley)
Product: Firefox → Core
Summary: MessagePort loses messages if transferred immediately → MessagePort attempts to fire already-queued events on a shipped message port after the message port is shipped if the port message queue was already started prior to shipping
Severity: -- → S3
Priority: -- → P2
You need to log in before you can comment on or make changes to this bug.