Skip to content

postMessage with MessagePort transfer fails in Firefox with DataCloneError #3077

@crisryantan

Description

@crisryantan

Description

When an application running under Hammerhead's proxy calls postMessage with MessagePort objects in the transfer list, Firefox throws:

DataCloneError: The object could not be cloned.

or:

MessagePort object could not be cloned.

This happens because MessageSandbox.postMessage wraps the original message in a Hammerhead envelope object before forwarding it via fastApply. The structured clone algorithm in Firefox cannot reconcile the wrapped envelope with the transferable MessagePort objects in the transfer list — the ports reference the original message, not the wrapped one.

Additionally, the postMessage(message, { targetOrigin, transfer }) overload (the modern options-based API) is not supported. When the second argument is an object, the call is silently dropped.

Steps to Reproduce

  1. Create a page with an iframe
  2. Set up a MessageChannel between the parent and iframe
  3. Use postMessage(message, targetOrigin, [channel.port1]) or the modern postMessage(message, { targetOrigin: '*', transfer: [channel.port1] }) to transfer a MessagePort to the iframe
  4. Run this under TestCafe using Firefox (not native automation)

Expected Behavior

The MessagePort is successfully transferred to the iframe, and both sides can communicate over the channel.

Actual Behavior

Firefox throws DataCloneError: MessagePort object could not be cloned. The message is never delivered and the communication channel is broken.

This works correctly in Chrome because TestCafe uses native automation (CDP) for Chrome, which bypasses Hammerhead's proxy entirely.

Environment

  • TestCafe version: 3.7.2
  • testcafe-hammerhead: 31.7.7
  • Browser: Firefox (ESR and stable)
  • OS: macOS, Linux (Docker)

Root Cause Analysis

In MessageSandbox.postMessage, the method wraps the user message in a { message, originUrl, targetUrl, type } envelope before calling fastApply. When the transfer list includes MessagePort objects, Firefox's structured clone fails because:

  1. The transferable ports are associated with the original message, not the envelope
  2. The envelope object cannot be structured-cloned alongside the original transferables

Additionally, when postMessage(message, options) is called with an object second argument, the code treats it as a non-string targetOrigin and returns null, silently dropping the call.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions