Bug 1605566 - MessagePort + wasm - part 3 - MessagePort serializes objects using MessageData union, r=smaug
☠☠ backed out by 0bb7d3150587 ☠ ☠
authorAndrea Marchesini <amarchesini@mozilla.com>
Wed, 15 Jan 2020 10:01:11 +0000
changeset 510330 36631ec96f1fa043d0c37fe982e75af223087645
parent 510329 554b2bdce66cdbde6d4305e963aea95fd81b70d9
child 510331 3427a92445c8a735f6f0f1781084ddf2372362b4
push id37020
push userccoroiu@mozilla.com
push dateWed, 15 Jan 2020 21:36:21 +0000
treeherdermozilla-central@c35bb210b8ae [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1605566
milestone74.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1605566 - MessagePort + wasm - part 3 - MessagePort serializes objects using MessageData union, r=smaug Differential Revision: https://phabricator.services.mozilla.com/D59614
dom/ipc/StructuredCloneData.cpp
dom/ipc/StructuredCloneData.h
dom/messagechannel/MessagePort.cpp
dom/messagechannel/MessagePort.h
dom/messagechannel/MessagePortChild.cpp
dom/messagechannel/MessagePortChild.h
dom/messagechannel/MessagePortParent.cpp
dom/messagechannel/MessagePortParent.h
dom/messagechannel/MessagePortService.cpp
dom/messagechannel/PMessagePort.ipdl
dom/messagechannel/SharedMessagePortMessage.cpp
dom/messagechannel/SharedMessagePortMessage.h
xpcom/ds/nsTArray.h
--- a/dom/ipc/StructuredCloneData.cpp
+++ b/dom/ipc/StructuredCloneData.cpp
@@ -42,16 +42,29 @@ StructuredCloneData::StructuredCloneData
 StructuredCloneData::StructuredCloneData(
     TransferringSupport aSupportsTransferring)
     : StructuredCloneHolder(
           StructuredCloneHolder::CloningSupported, aSupportsTransferring,
           StructuredCloneHolder::StructuredCloneScope::DifferentProcess),
       mExternalData(JS::StructuredCloneScope::DifferentProcess),
       mInitialized(false) {}
 
+StructuredCloneData::StructuredCloneData(
+    StructuredCloneHolder::StructuredCloneScope aScope)
+    : StructuredCloneHolder(StructuredCloneHolder::CloningSupported,
+                            StructuredCloneHolder::TransferringSupported,
+                            aScope),
+      mExternalData(JS::StructuredCloneScope::DifferentProcess),
+      mInitialized(false) {
+  MOZ_ASSERT(
+      aScope == StructuredCloneHolder::StructuredCloneScope::DifferentProcess ||
+      aScope ==
+          StructuredCloneHolder::StructuredCloneScope::UnknownDestination);
+}
+
 StructuredCloneData::~StructuredCloneData() {}
 
 StructuredCloneData& StructuredCloneData::operator=(
     StructuredCloneData&& aOther) {
   mBlobImplArray = std::move(aOther.mBlobImplArray);
   mExternalData = std::move(aOther.mExternalData);
   mSharedData = std::move(aOther.mSharedData);
   mIPCStreams = std::move(aOther.mIPCStreams);
--- a/dom/ipc/StructuredCloneData.h
+++ b/dom/ipc/StructuredCloneData.h
@@ -144,16 +144,19 @@ class SharedJSAllocatedData final {
 class StructuredCloneData : public StructuredCloneHolder {
  public:
   StructuredCloneData();
 
   StructuredCloneData(const StructuredCloneData&) = delete;
 
   StructuredCloneData(StructuredCloneData&& aOther);
 
+  // Only DifferentProcess and UnknownDestination scopes are supported.
+  explicit StructuredCloneData(StructuredCloneScope aScope);
+
   ~StructuredCloneData();
 
   StructuredCloneData& operator=(const StructuredCloneData& aOther) = delete;
 
   StructuredCloneData& operator=(StructuredCloneData&& aOther);
 
   const nsTArray<RefPtr<BlobImpl>>& BlobImpls() const { return mBlobImplArray; }
 
--- a/dom/messagechannel/MessagePort.cpp
+++ b/dom/messagechannel/MessagePort.cpp
@@ -382,17 +382,17 @@ void MessagePort::PostMessage(JSContext*
   }
 
   MOZ_ASSERT(mActor);
   MOZ_ASSERT(mMessagesForTheOtherPort.IsEmpty());
 
   AutoTArray<RefPtr<SharedMessagePortMessage>, 1> array;
   array.AppendElement(data);
 
-  AutoTArray<ClonedMessageData, 1> messages;
+  AutoTArray<MessageData, 1> messages;
   // note: `messages` will borrow the underlying buffer, but this is okay
   // because reverse destruction order means `messages` will be destroyed prior
   // to `array`/`data`.
   SharedMessagePortMessage::FromSharedToMessagesChild(mActor, array, messages);
   mActor->SendPostMessages(messages);
 }
 
 void MessagePort::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
@@ -548,28 +548,28 @@ void MessagePort::SetOnmessage(EventHand
   // When using onmessage, the call to start() is implied.
   Start();
 }
 
 // This method is called when the PMessagePortChild actor is entangled to
 // another actor. It receives a list of messages to be dispatch. It can be that
 // we were waiting for this entangling step in order to disentangle the port or
 // to close it.
-void MessagePort::Entangled(nsTArray<ClonedMessageData>& aMessages) {
+void MessagePort::Entangled(nsTArray<MessageData>& aMessages) {
   MOZ_ASSERT(mState == eStateEntangling ||
              mState == eStateEntanglingForDisentangle ||
              mState == eStateEntanglingForClose);
 
   State oldState = mState;
   mState = eStateEntangled;
 
   // If we have pending messages, these have to be sent.
   if (!mMessagesForTheOtherPort.IsEmpty()) {
     {
-      nsTArray<ClonedMessageData> messages;
+      nsTArray<MessageData> messages;
       SharedMessagePortMessage::FromSharedToMessagesChild(
           mActor, mMessagesForTheOtherPort, messages);
       mActor->SendPostMessages(messages);
     }
     // Because `messages` borrow the underlying JSStructuredCloneData buffers,
     // only clear after `messages` have gone out of scope.
     mMessagesForTheOtherPort.Clear();
   }
@@ -609,17 +609,17 @@ void MessagePort::StartDisentangling() {
 
   // Sending this message we communicate to the parent actor that we don't want
   // to receive any new messages. It is possible that a message has been
   // already sent but not received yet. So we have to collect all of them and
   // we send them in the SendDispatch() request.
   mActor->SendStopSendingData();
 }
 
-void MessagePort::MessagesReceived(nsTArray<ClonedMessageData>& aMessages) {
+void MessagePort::MessagesReceived(nsTArray<MessageData>& aMessages) {
   MOZ_ASSERT(mState == eStateEntangled || mState == eStateDisentangling ||
              // This last step can happen only if Close() has been called
              // manually. At this point SendClose() is sent but we can still
              // receive something until the Closing request is processed.
              mState == eStateDisentangledForClose);
   MOZ_ASSERT(mMessagesForTheOtherPort.IsEmpty());
 
   RemoveDocFromBFCache();
@@ -647,23 +647,23 @@ void MessagePort::StopSendingDataConfirm
 
 void MessagePort::Disentangle() {
   MOZ_ASSERT(mState == eStateDisentangling);
   MOZ_ASSERT(mActor);
 
   mState = eStateDisentangled;
 
   {
-    nsTArray<ClonedMessageData> messages;
+    nsTArray<MessageData> messages;
     SharedMessagePortMessage::FromSharedToMessagesChild(mActor, mMessages,
                                                         messages);
     mActor->SendDisentangle(messages);
   }
-  // Only clear mMessages after the ClonedMessageData instances have gone out of
-  // scope because they borrow mMessages' underlying JSStructuredCloneDatas.
+  // Only clear mMessages after the MessageData instances have gone out of scope
+  // because they borrow mMessages' underlying JSStructuredCloneDatas.
   mMessages.Clear();
 
   mActor->SetPort(nullptr);
   mActor = nullptr;
 
   UpdateMustKeepAlive();
 }
 
--- a/dom/messagechannel/MessagePort.h
+++ b/dom/messagechannel/MessagePort.h
@@ -17,16 +17,17 @@
 #  undef PostMessage
 #endif
 
 class nsIGlobalObject;
 
 namespace mozilla {
 namespace dom {
 
+class MessageData;
 class MessagePortChild;
 struct PostMessageOptions;
 class PostMessageRunnable;
 class SharedMessagePortMessage;
 class StrongWorkerRef;
 
 // A class to hold a MessagePortIdentifier from
 // MessagePort::CloneAndDistentangle() and close if neither passed to
@@ -113,18 +114,18 @@ class MessagePort final : public DOMEven
   bool CanBeCloned() const { return !mHasBeenTransferredOrClosed; }
 
   void CloneAndDisentangle(UniqueMessagePortId& aIdentifier);
 
   void CloseForced();
 
   // These methods are useful for MessagePortChild
 
-  void Entangled(nsTArray<ClonedMessageData>& aMessages);
-  void MessagesReceived(nsTArray<ClonedMessageData>& aMessages);
+  void Entangled(nsTArray<MessageData>& aMessages);
+  void MessagesReceived(nsTArray<MessageData>& aMessages);
   void StopSendingDataConfirmed();
   void Closed();
 
  private:
   enum State {
     // When a port is created by a MessageChannel it is entangled with the
     // other. They both run on the same thread, same event loop and the
     // messages are added to the queues without using PBackground actors.
--- a/dom/messagechannel/MessagePortChild.cpp
+++ b/dom/messagechannel/MessagePortChild.cpp
@@ -17,25 +17,25 @@ MessagePortChild::MessagePortChild() : m
 mozilla::ipc::IPCResult MessagePortChild::RecvStopSendingDataConfirmed() {
   MOZ_ASSERT(mPort);
   mPort->StopSendingDataConfirmed();
   MOZ_ASSERT(!mPort);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult MessagePortChild::RecvEntangled(
-    nsTArray<ClonedMessageData>&& aMessages) {
+    nsTArray<MessageData>&& aMessages) {
   if (mPort) {
     mPort->Entangled(aMessages);
   }
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult MessagePortChild::RecvReceiveData(
-    nsTArray<ClonedMessageData>&& aMessages) {
+    nsTArray<MessageData>&& aMessages) {
   if (mPort) {
     mPort->MessagesReceived(aMessages);
   }
   return IPC_OK();
 }
 
 void MessagePortChild::ActorDestroy(ActorDestroyReason aWhy) {
   if (mPort) {
--- a/dom/messagechannel/MessagePortChild.h
+++ b/dom/messagechannel/MessagePortChild.h
@@ -24,21 +24,19 @@ class MessagePortChild final : public PM
 
   MessagePortChild();
 
   void SetPort(MessagePort* aPort) { mPort = aPort; }
 
  private:
   ~MessagePortChild() { MOZ_ASSERT(!mPort); }
 
-  mozilla::ipc::IPCResult RecvEntangled(
-      nsTArray<ClonedMessageData>&& aMessages);
+  mozilla::ipc::IPCResult RecvEntangled(nsTArray<MessageData>&& aMessages);
 
-  mozilla::ipc::IPCResult RecvReceiveData(
-      nsTArray<ClonedMessageData>&& aMessages);
+  mozilla::ipc::IPCResult RecvReceiveData(nsTArray<MessageData>&& aMessages);
 
   mozilla::ipc::IPCResult RecvStopSendingDataConfirmed();
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
   // This is a raw pointer because this child is owned by this MessagePort.
   MessagePort* mPort;
 };
--- a/dom/messagechannel/MessagePortParent.cpp
+++ b/dom/messagechannel/MessagePortParent.cpp
@@ -33,17 +33,17 @@ bool MessagePortParent::Entangle(const n
   }
 
   MOZ_ASSERT(!mEntangled);
 
   return mService->RequestEntangling(this, aDestinationUUID, aSequenceID);
 }
 
 mozilla::ipc::IPCResult MessagePortParent::RecvPostMessages(
-    nsTArray<ClonedMessageData>&& aMessages) {
+    nsTArray<MessageData>&& aMessages) {
   // This converts the object in a data struct where we have BlobImpls.
   FallibleTArray<RefPtr<SharedMessagePortMessage>> messages;
   if (NS_WARN_IF(!SharedMessagePortMessage::FromMessagesToSharedParent(
           aMessages, messages))) {
     return IPC_FAIL_NO_REASON(this);
   }
 
   if (!mEntangled) {
@@ -61,17 +61,17 @@ mozilla::ipc::IPCResult MessagePortParen
 
   if (!mService->PostMessages(this, messages)) {
     return IPC_FAIL_NO_REASON(this);
   }
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult MessagePortParent::RecvDisentangle(
-    nsTArray<ClonedMessageData>&& aMessages) {
+    nsTArray<MessageData>&& aMessages) {
   // This converts the object in a data struct where we have BlobImpls.
   FallibleTArray<RefPtr<SharedMessagePortMessage>> messages;
   if (NS_WARN_IF(!SharedMessagePortMessage::FromMessagesToSharedParent(
           aMessages, messages))) {
     return IPC_FAIL_NO_REASON(this);
   }
 
   if (!mEntangled) {
@@ -122,18 +122,17 @@ void MessagePortParent::ActorDestroy(Act
   if (mService && mEntangled) {
     // When the last parent is deleted, this service is freed but this cannot
     // be done when the hashtables are written by CloseAll.
     RefPtr<MessagePortService> kungFuDeathGrip = mService;
     kungFuDeathGrip->ParentDestroy(this);
   }
 }
 
-bool MessagePortParent::Entangled(
-    const nsTArray<ClonedMessageData>& aMessages) {
+bool MessagePortParent::Entangled(const nsTArray<MessageData>& aMessages) {
   MOZ_ASSERT(!mEntangled);
   mEntangled = true;
   return SendEntangled(aMessages);
 }
 
 void MessagePortParent::CloseAndDelete() {
   Close();
   Unused << Send__delete__(this);
--- a/dom/messagechannel/MessagePortParent.h
+++ b/dom/messagechannel/MessagePortParent.h
@@ -21,34 +21,32 @@ class MessagePortParent final
   friend class PMessagePortParent;
 
  public:
   explicit MessagePortParent(const nsID& aUUID);
   ~MessagePortParent();
 
   bool Entangle(const nsID& aDestinationUUID, const uint32_t& aSequenceID);
 
-  bool Entangled(const nsTArray<ClonedMessageData>& aMessages);
+  bool Entangled(const nsTArray<MessageData>& aMessages);
 
   void Close();
   void CloseAndDelete();
 
   bool CanSendData() const { return mCanSendData; }
 
   const nsID& ID() const { return mUUID; }
 
   static bool ForceClose(const nsID& aUUID, const nsID& aDestinationUUID,
                          const uint32_t& aSequenceID);
 
  private:
-  mozilla::ipc::IPCResult RecvPostMessages(
-      nsTArray<ClonedMessageData>&& aMessages);
+  mozilla::ipc::IPCResult RecvPostMessages(nsTArray<MessageData>&& aMessages);
 
-  mozilla::ipc::IPCResult RecvDisentangle(
-      nsTArray<ClonedMessageData>&& aMessages);
+  mozilla::ipc::IPCResult RecvDisentangle(nsTArray<MessageData>&& aMessages);
 
   mozilla::ipc::IPCResult RecvStopSendingData();
 
   mozilla::ipc::IPCResult RecvClose();
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
   RefPtr<MessagePortService> mService;
--- a/dom/messagechannel/MessagePortService.cpp
+++ b/dom/messagechannel/MessagePortService.cpp
@@ -143,17 +143,17 @@ bool MessagePortService::RequestEntangli
 
     // We want to ensure we clear data->mMessages even if we early return, while
     // also ensuring that its contents remain alive until after array's contents
     // are destroyed because of JSStructuredCloneData borrowing.  So we use
     // Move to initialize things swapped and do it before we declare `array` so
     // that reverse destruction order works for us.
     FallibleTArray<RefPtr<SharedMessagePortMessage>> messages(
         std::move(data->mMessages));
-    FallibleTArray<ClonedMessageData> array;
+    FallibleTArray<MessageData> array;
     if (!SharedMessagePortMessage::FromSharedToMessagesParent(aParent, messages,
                                                               array)) {
       CloseAll(aParent->ID());
       return false;
     }
 
     // We can entangle the port.
     if (!aParent->Entangled(array)) {
@@ -226,17 +226,17 @@ bool MessagePortService::DisentanglePort
     data->mWaitingForNewParent = true;
     data->mParent = nullptr;
     return true;
   }
 
   data->mParent = nextParent;
   data->mNextParents.RemoveElementAt(index);
 
-  FallibleTArray<ClonedMessageData> array;
+  FallibleTArray<MessageData> array;
   if (!SharedMessagePortMessage::FromSharedToMessagesParent(data->mParent,
                                                             aMessages, array)) {
     return false;
   }
 
   Unused << data->mParent->Entangled(array);
   return true;
 }
@@ -343,17 +343,17 @@ bool MessagePortService::PostMessages(
 
   if (!data->mMessages.AppendElements(aMessages, mozilla::fallible)) {
     return false;
   }
 
   // If the parent can send data to the child, let's proceed.
   if (data->mParent && data->mParent->CanSendData()) {
     {
-      FallibleTArray<ClonedMessageData> messages;
+      FallibleTArray<MessageData> messages;
       if (!SharedMessagePortMessage::FromSharedToMessagesParent(
               data->mParent, data->mMessages, messages)) {
         return false;
       }
 
       Unused << data->mParent->SendReceiveData(messages);
     }
     // `messages` borrows the underlying JSStructuredCloneData so we need to
--- a/dom/messagechannel/PMessagePort.ipdl
+++ b/dom/messagechannel/PMessagePort.ipdl
@@ -4,23 +4,33 @@
 
 include protocol PBackground;
 include protocol PChildToParentStream; // FIXME: bug 792908
 include protocol PFileDescriptorSet; // FIXME: bug 792908
 include protocol PIPCBlobInputStream; // FIXME: bug 792908
 include protocol PParentToChildStream; // FIXME: bug 792908
 
 include DOMTypes;
+include ProtocolTypes;
 
 using struct mozilla::SerializedStructuredCloneBuffer
   from "ipc/IPCMessageUtils.h";
 
 namespace mozilla {
 namespace dom {
 
+struct RefMessageData {
+  nsID uuid;
+};
+
+union MessageData {
+  ClonedMessageData;
+  RefMessageData;
+};
+
 // This protocol is used for the MessageChannel/MessagePort API
 protocol PMessagePort
 {
   manager PBackground;
 
   /* Many of these methods are used just for the shutdown sequence. The
      correct sequence for the child actor is:
      1. SendStopSendingData();
@@ -30,23 +40,23 @@ protocol PMessagePort
 
   /* When the port is transferred the sequence is:
      1. SendStopSendingData();
      2. RecvStopSendingDataConfirmed();
      3. SendDisentangle();
      4. Recv__delete__(); */
 
 parent:
-  async PostMessages(ClonedMessageData[] messages);
-  async Disentangle(ClonedMessageData[] messages);
+  async PostMessages(MessageData[] messages);
+  async Disentangle(MessageData[] messages);
   async StopSendingData();
   async Close();
 
 child:
-  async Entangled(ClonedMessageData[] messages);
-  async ReceiveData(ClonedMessageData[] messages);
+  async Entangled(MessageData[] messages);
+  async ReceiveData(MessageData[] messages);
   async StopSendingDataConfirmed();
 
   async __delete__();
 };
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/messagechannel/SharedMessagePortMessage.cpp
+++ b/dom/messagechannel/SharedMessagePortMessage.cpp
@@ -18,88 +18,123 @@ namespace mozilla {
 using namespace ipc;
 
 namespace dom {
 
 /* static */
 void SharedMessagePortMessage::FromSharedToMessagesChild(
     MessagePortChild* aActor,
     const nsTArray<RefPtr<SharedMessagePortMessage>>& aData,
-    nsTArray<ClonedMessageData>& aArray) {
+    nsTArray<MessageData>& aArray) {
   MOZ_ASSERT(aActor);
   MOZ_ASSERT(aArray.IsEmpty());
   aArray.SetCapacity(aData.Length());
 
   PBackgroundChild* backgroundManager = aActor->Manager();
   MOZ_ASSERT(backgroundManager);
 
   for (auto& data : aData) {
-    ClonedMessageData* message = aArray.AppendElement();
-    data->BuildClonedMessageDataForBackgroundChild(backgroundManager, *message);
+    MessageData* message = aArray.AppendElement();
+
+    if (data->CloneScope() ==
+        StructuredCloneHolder::StructuredCloneScope::DifferentProcess) {
+      ClonedMessageData clonedData;
+      data->BuildClonedMessageDataForBackgroundChild(backgroundManager,
+                                                     clonedData);
+      *message = clonedData;
+      continue;
+    }
+
+    MOZ_ASSERT(data->CloneScope() ==
+               StructuredCloneHolder::StructuredCloneScope::SameProcess);
+    *message = RefMessageData();  // TODO
   }
 }
 
 /* static */
 bool SharedMessagePortMessage::FromMessagesToSharedChild(
-    nsTArray<ClonedMessageData>& aArray,
+    nsTArray<MessageData>& aArray,
     FallibleTArray<RefPtr<SharedMessagePortMessage>>& aData) {
   MOZ_ASSERT(aData.IsEmpty());
 
   if (NS_WARN_IF(!aData.SetCapacity(aArray.Length(), mozilla::fallible))) {
     return false;
   }
 
   for (auto& message : aArray) {
     RefPtr<SharedMessagePortMessage> data = new SharedMessagePortMessage();
-    data->StealFromClonedMessageDataForBackgroundChild(message);
+
+    if (message.type() == MessageData::TClonedMessageData) {
+      data->StealFromClonedMessageDataForBackgroundChild(message);
+    } else {
+      MOZ_ASSERT(message.type() == MessageData::TRefMessageData);
+      // TODO
+    }
 
     if (!aData.AppendElement(data, mozilla::fallible)) {
       return false;
     }
   }
 
   return true;
 }
 
 /* static */
 bool SharedMessagePortMessage::FromSharedToMessagesParent(
     MessagePortParent* aActor,
     const nsTArray<RefPtr<SharedMessagePortMessage>>& aData,
-    FallibleTArray<ClonedMessageData>& aArray) {
+    FallibleTArray<MessageData>& aArray) {
   MOZ_ASSERT(aArray.IsEmpty());
 
   if (NS_WARN_IF(!aArray.SetCapacity(aData.Length(), mozilla::fallible))) {
     return false;
   }
 
   PBackgroundParent* backgroundManager = aActor->Manager();
   MOZ_ASSERT(backgroundManager);
 
   for (auto& data : aData) {
-    ClonedMessageData* message = aArray.AppendElement(mozilla::fallible);
-    data->BuildClonedMessageDataForBackgroundParent(backgroundManager,
-                                                    *message);
+    MessageData* message = aArray.AppendElement(mozilla::fallible);
+
+    if (data->CloneScope() ==
+        StructuredCloneHolder::StructuredCloneScope::DifferentProcess) {
+      ClonedMessageData clonedData;
+      data->BuildClonedMessageDataForBackgroundParent(backgroundManager,
+                                                      clonedData);
+      *message = clonedData;
+      continue;
+    }
+
+    MOZ_ASSERT(data->CloneScope() ==
+               StructuredCloneHolder::StructuredCloneScope::SameProcess);
+    *message = RefMessageData();  // TODO
   }
 
   return true;
 }
 
 /* static */
 bool SharedMessagePortMessage::FromMessagesToSharedParent(
-    nsTArray<ClonedMessageData>& aArray,
+    nsTArray<MessageData>& aArray,
     FallibleTArray<RefPtr<SharedMessagePortMessage>>& aData) {
   MOZ_ASSERT(aData.IsEmpty());
 
   if (NS_WARN_IF(!aData.SetCapacity(aArray.Length(), mozilla::fallible))) {
     return false;
   }
 
   for (auto& message : aArray) {
     RefPtr<SharedMessagePortMessage> data = new SharedMessagePortMessage();
-    data->StealFromClonedMessageDataForBackgroundParent(message);
+
+    if (message.type() == MessageData::TClonedMessageData) {
+      data->StealFromClonedMessageDataForBackgroundParent(message);
+    } else {
+      MOZ_ASSERT(message.type() == MessageData::TRefMessageData);
+      // TODO
+    }
 
     if (!aData.AppendElement(data, mozilla::fallible)) {
       return false;
     }
   }
 
   return true;
 }
--- a/dom/messagechannel/SharedMessagePortMessage.h
+++ b/dom/messagechannel/SharedMessagePortMessage.h
@@ -15,44 +15,45 @@ namespace dom {
 class MessagePortChild;
 class MessagePortMessage;
 class MessagePortParent;
 
 class SharedMessagePortMessage final : public ipc::StructuredCloneData {
  public:
   NS_INLINE_DECL_REFCOUNTING(SharedMessagePortMessage)
 
-  SharedMessagePortMessage() : ipc::StructuredCloneData() {}
+  SharedMessagePortMessage()
+      : ipc::StructuredCloneData(StructuredCloneScope::UnknownDestination) {}
 
-  // Note that the populated ClonedMessageData borrows the underlying
+  // Note that the populated MessageData borrows the underlying
   // JSStructuredCloneData from the SharedMessagePortMessage, so the caller is
-  // required to ensure that the ClonedMessageData instances are destroyed prior
-  // to the SharedMessagePortMessage instances.
+  // required to ensure that the MessageData instances are destroyed prior to
+  // the SharedMessagePortMessage instances.
   static void FromSharedToMessagesChild(
       MessagePortChild* aActor,
       const nsTArray<RefPtr<SharedMessagePortMessage>>& aData,
-      nsTArray<ClonedMessageData>& aArray);
+      nsTArray<MessageData>& aArray);
 
   static bool FromMessagesToSharedChild(
-      nsTArray<ClonedMessageData>& aArray,
+      nsTArray<MessageData>& aArray,
       FallibleTArray<RefPtr<SharedMessagePortMessage>>& aData);
 
-  // Note that the populated ClonedMessageData borrows the underlying
+  // Note that the populated MessageData borrows the underlying
   // JSStructuredCloneData from the SharedMessagePortMessage, so the caller is
-  // required to ensure that the ClonedMessageData instances are destroyed prior
-  // to the SharedMessagePortMessage instances.
+  // required to ensure that the MessageData instances are destroyed prior to
+  // the SharedMessagePortMessage instances.
   static bool FromSharedToMessagesParent(
       MessagePortParent* aActor,
       const nsTArray<RefPtr<SharedMessagePortMessage>>& aData,
-      FallibleTArray<ClonedMessageData>& aArray);
+      FallibleTArray<MessageData>& aArray);
 
   static bool FromMessagesToSharedParent(
-      nsTArray<ClonedMessageData>& aArray,
+      nsTArray<MessageData>& aArray,
       FallibleTArray<RefPtr<SharedMessagePortMessage>>& aData);
 
  private:
-  ~SharedMessagePortMessage() {}
+  ~SharedMessagePortMessage() = default;
 };
 
 }  // namespace dom
 }  // namespace mozilla
 
 #endif  // mozilla_dom_SharedMessagePortMessage_h
--- a/xpcom/ds/nsTArray.h
+++ b/xpcom/ds/nsTArray.h
@@ -64,17 +64,18 @@ namespace ipc {
 class StructuredCloneData;
 }  // namespace ipc
 }  // namespace dom
 }  // namespace mozilla
 
 namespace mozilla {
 namespace dom {
 class ClonedMessageData;
-class MessagePortMessage;
+class MessageData;
+class RefMessageData;
 namespace indexedDB {
 struct StructuredCloneReadInfo;
 class SerializedStructuredCloneReadInfo;
 class ObjectStoreCursorResponse;
 class IndexCursorResponse;
 }  // namespace indexedDB
 }  // namespace dom
 }  // namespace mozilla
@@ -726,17 +727,18 @@ DECLARE_USE_COPY_CONSTRUCTORS(mozilla::d
 DECLARE_USE_COPY_CONSTRUCTORS(mozilla::dom::ClonedMessageData)
 DECLARE_USE_COPY_CONSTRUCTORS(mozilla::dom::indexedDB::StructuredCloneReadInfo);
 DECLARE_USE_COPY_CONSTRUCTORS(
     mozilla::dom::indexedDB::ObjectStoreCursorResponse)
 DECLARE_USE_COPY_CONSTRUCTORS(mozilla::dom::indexedDB::IndexCursorResponse)
 DECLARE_USE_COPY_CONSTRUCTORS(
     mozilla::dom::indexedDB::SerializedStructuredCloneReadInfo);
 DECLARE_USE_COPY_CONSTRUCTORS(JSStructuredCloneData)
-DECLARE_USE_COPY_CONSTRUCTORS(mozilla::dom::MessagePortMessage)
+DECLARE_USE_COPY_CONSTRUCTORS(mozilla::dom::MessageData)
+DECLARE_USE_COPY_CONSTRUCTORS(mozilla::dom::RefMessageData)
 DECLARE_USE_COPY_CONSTRUCTORS(mozilla::SourceBufferTask)
 
 //
 // Base class for nsTArray_Impl that is templated on element type and derived
 // nsTArray_Impl class, to allow extra conversions to be added for specific
 // types.
 //
 template <class E, class Derived>