Can `postMessage` messages get lost/dropped e.g. if recipient’s main thread is coincidentally blocked at the time it should have received it?

Context:

I’m tracking down a hard-to-replicate bug related to messages between frames. One thing I’m mildly suspicious of is that messages between the main frame and an iframe are sometimes not being sent successfully. I.e. messages are possibly being “dropped” in rare cases.

Question:

Is there any spec-level guarantee that a message sent with postMessage will be received by the target frames, assuming there’s no bugs in my code?

For example, if the recipient frame happens to be unresponsive (e.g. due to a long computation which freezes the main thread) at the time that it would have received the message event, could that cause the message event to be lost? Or would is it guaranteed to be “queued” and eventually received by the window once the main thread is freed up.

Example Code:

In my test code below, the messages are not dropped by the child, despite several several seconds of blocking code which runs while it is being sent messages. Once the child finishes the heavy computation, it processes the full backlog of messages.

Note that I was only able to test this in Chrome, because as of writing Firefox puts a sandboxed iframe on the same thread as the main thread.

let iframe = document.createElement("iframe");
iframe.sandbox = "allow-scripts";
iframe.srcdoc = `
    <script>
      window.addEventListener('message', (event) => {
        console.log('Child received:', event.data);
      });
      setInterval(() => {
        console.log('Child: Starting heavy processing');
        const startTime = Date.now();
        while (Date.now() - startTime < 5000) {
          // Heavy loop for 5 seconds
        }
        console.log('Child: Finished heavy processing');
      }, 10000);
    </script>
  `;
document.body.append(iframe);

// Send a message every second
let messageIndex = 0;
setInterval(() => {
  const message = `Message ${messageIndex}`;
  console.log('Parent sending:', message);
  iframe.contentWindow.postMessage(message, '*');
  messageIndex++;
}, 1000);

Notes:

  • I’d prefer answers which reference specifications, since this would allow me to file bug reports on browser engines if needed.
  • I’ve noticed that if I have the debugger paused in the recipient frame, then all messages are lost. After unpausing, the messages are never received.
  • If there are no spec-level guarantees in this area, I’m also interested in any info on browser-engine-specific behavior, if anyone has any info on that.