Backed out changeset 1d67d747b3eb (bug 911972) for frequent linux64 debug e10s test_post_message_advanced.html timeouts.
authorRyan VanderMeulen <ryanvm@gmail.com>
Mon, 15 Jun 2015 13:06:23 -0400
changeset 268435 53a99d02925f98b41f0fc1b949254d513ceaed51
parent 268434 79e11098d70acb581785906fd7db9820f626a35c
child 268436 cd0d976e5f5c6389512cad8f2cae03526b0fb0f3
child 268496 336d4a1f0f3cba256e8bd89061f1ed3f55b68d88
push id8157
push userjlund@mozilla.com
push dateMon, 29 Jun 2015 20:36:23 +0000
treeherdermozilla-aurora@d480e05bd276 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs911972
milestone41.0a1
backs out1d67d747b3eba11d8a9ba766abb19eb2ebcd0676
Backed out changeset 1d67d747b3eb (bug 911972) for frequent linux64 debug e10s test_post_message_advanced.html timeouts. CLOSED TREE
dom/base/MessageChannel.cpp
dom/base/MessageChannel.h
dom/base/MessagePort.cpp
dom/base/MessagePort.h
dom/base/MessagePortList.cpp
dom/base/MessagePortList.h
dom/base/NodeInfo.cpp
dom/base/PostMessageEvent.cpp
dom/base/PostMessageEvent.h
dom/base/ProcessGlobal.cpp
dom/base/moz.build
dom/base/nsContentUtils.cpp
dom/base/nsContentUtils.h
dom/base/nsCopySupport.cpp
dom/base/nsFrameMessageManager.cpp
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
dom/base/test/chrome.ini
dom/base/test/iframe_messageChannel_chrome.html
dom/base/test/iframe_messageChannel_cloning.html
dom/base/test/iframe_messageChannel_pingpong.html
dom/base/test/iframe_messageChannel_post.html
dom/base/test/mochitest.ini
dom/base/test/test_messageChannel.html
dom/base/test/test_messageChannel.xul
dom/base/test/test_messageChannel_cloning.html
dom/base/test/test_messageChannel_pingpong.html
dom/base/test/test_messageChannel_post.html
dom/base/test/test_messageChannel_pref.html
dom/base/test/test_messageChannel_start.html
dom/base/test/test_messageChannel_transferable.html
dom/base/test/test_messageChannel_unshipped.html
dom/bindings/Bindings.conf
dom/broadcastchannel/BroadcastChannel.cpp
dom/broadcastchannel/BroadcastChannelChild.cpp
dom/ipc/StructuredCloneUtils.cpp
dom/ipc/StructuredCloneUtils.h
dom/messagechannel/MessageChannel.cpp
dom/messagechannel/MessageChannel.h
dom/messagechannel/MessagePort.cpp
dom/messagechannel/MessagePort.h
dom/messagechannel/MessagePortChild.cpp
dom/messagechannel/MessagePortChild.h
dom/messagechannel/MessagePortList.cpp
dom/messagechannel/MessagePortList.h
dom/messagechannel/MessagePortParent.cpp
dom/messagechannel/MessagePortParent.h
dom/messagechannel/MessagePortService.cpp
dom/messagechannel/MessagePortService.h
dom/messagechannel/MessagePortUtils.cpp
dom/messagechannel/MessagePortUtils.h
dom/messagechannel/PMessagePort.ipdl
dom/messagechannel/SharedMessagePortMessage.cpp
dom/messagechannel/SharedMessagePortMessage.h
dom/messagechannel/moz.build
dom/messagechannel/tests/chrome.ini
dom/messagechannel/tests/iframe_messageChannel_chrome.html
dom/messagechannel/tests/iframe_messageChannel_cloning.html
dom/messagechannel/tests/iframe_messageChannel_pingpong.html
dom/messagechannel/tests/iframe_messageChannel_post.html
dom/messagechannel/tests/iframe_messageChannel_sharedWorker2.html
dom/messagechannel/tests/iframe_messageChannel_transferable.html
dom/messagechannel/tests/mochitest.ini
dom/messagechannel/tests/moz.build
dom/messagechannel/tests/sharedWorker2_messageChannel.js
dom/messagechannel/tests/sharedWorker_messageChannel.js
dom/messagechannel/tests/test_messageChannel.html
dom/messagechannel/tests/test_messageChannel.xul
dom/messagechannel/tests/test_messageChannel_any.html
dom/messagechannel/tests/test_messageChannel_cloning.html
dom/messagechannel/tests/test_messageChannel_pingpong.html
dom/messagechannel/tests/test_messageChannel_post.html
dom/messagechannel/tests/test_messageChannel_pref.html
dom/messagechannel/tests/test_messageChannel_selfTransferring.html
dom/messagechannel/tests/test_messageChannel_sharedWorker.html
dom/messagechannel/tests/test_messageChannel_sharedWorker2.html
dom/messagechannel/tests/test_messageChannel_start.html
dom/messagechannel/tests/test_messageChannel_transferable.html
dom/messagechannel/tests/test_messageChannel_unshipped.html
dom/messagechannel/tests/test_messageChannel_worker.html
dom/messagechannel/tests/worker_messageChannel.js
dom/messagechannel/tests/worker_messageChannel_any.js
dom/moz.build
dom/webidl/MessageChannel.webidl
dom/workers/MessagePort.cpp
dom/workers/MessagePort.h
dom/workers/ServiceWorkerClient.cpp
dom/workers/WorkerPrivate.cpp
dom/workers/WorkerPrivate.h
dom/workers/WorkerStructuredClone.h
dom/workers/XMLHttpRequest.cpp
dom/workers/XMLHttpRequest.h
dom/workers/test/sharedWorker_sharedWorker.js
ipc/glue/BackgroundChild.h
ipc/glue/BackgroundChildImpl.cpp
ipc/glue/BackgroundChildImpl.h
ipc/glue/BackgroundImpl.cpp
ipc/glue/BackgroundParentImpl.cpp
ipc/glue/BackgroundParentImpl.h
ipc/glue/PBackground.ipdl
js/public/StructuredClone.h
js/src/vm/StructuredClone.cpp
testing/web-platform/meta/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/event-ports-dedicated.html.ini
rename from dom/messagechannel/MessageChannel.cpp
rename to dom/base/MessageChannel.cpp
--- a/dom/messagechannel/MessageChannel.cpp
+++ b/dom/base/MessageChannel.cpp
@@ -4,225 +4,101 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "MessageChannel.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/MessageChannelBinding.h"
 #include "mozilla/dom/MessagePort.h"
-#include "mozilla/dom/Navigator.h"
-#include "mozilla/dom/WorkerPrivate.h"
-#include "mozilla/dom/WorkerRunnable.h"
 #include "nsContentUtils.h"
-#include "nsIDocument.h"
-#include "nsIPrincipal.h"
 #include "nsPIDOMWindow.h"
-#include "nsServiceManagerUtils.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(MessageChannel, mWindow, mPort1, mPort2)
 NS_IMPL_CYCLE_COLLECTING_ADDREF(MessageChannel)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(MessageChannel)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MessageChannel)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 namespace {
-bool gPrefInitialized = false;
-bool gPrefEnabled = false;
+  bool gPrefInitialized = false;
+  bool gPrefEnabled = false;
 
-bool
-CheckPermission(nsIPrincipal* aPrincipal, bool aCallerChrome)
+}
+
+/* static */ bool
+MessageChannel::Enabled(JSContext* aCx, JSObject* aObj)
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
   if (!gPrefInitialized) {
     Preferences::AddBoolVarCache(&gPrefEnabled, "dom.messageChannel.enabled");
     gPrefInitialized = true;
   }
 
   // Enabled by pref
   if (gPrefEnabled) {
     return true;
   }
 
   // Chrome callers are allowed.
-  if (aCallerChrome) {
+  if (nsContentUtils::ThreadsafeIsCallerChrome()) {
     return true;
   }
 
+  nsCOMPtr<nsIPrincipal> principal = nsContentUtils::SubjectPrincipal();
+  MOZ_ASSERT(principal);
+
   nsCOMPtr<nsIURI> uri;
-  if (NS_FAILED(aPrincipal->GetURI(getter_AddRefs(uri))) || !uri) {
+  if (NS_FAILED(principal->GetURI(getter_AddRefs(uri))) || !uri) {
     return false;
   }
 
   bool isResource = false;
   if (NS_FAILED(uri->SchemeIs("resource", &isResource))) {
     return false;
   }
 
   return isResource;
 }
 
-nsIPrincipal*
-GetPrincipalFromWorkerPrivate(workers::WorkerPrivate* aWorkerPrivate)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  nsIPrincipal* principal = aWorkerPrivate->GetPrincipal();
-  if (principal) {
-    return principal;
-  }
-
-  // Walk up to our containing page
-  workers::WorkerPrivate* wp = aWorkerPrivate;
-  while (wp->GetParent()) {
-    wp = wp->GetParent();
-  }
-
-  nsPIDOMWindow* window = wp->GetWindow();
-  if (!window) {
-    return nullptr;
-  }
-
-  nsIDocument* doc = window->GetExtantDoc();
-  if (!doc) {
-    return nullptr;
-  }
-
-  return doc->NodePrincipal();
-}
-
-// A WorkerMainThreadRunnable to synchronously dispatch the call of
-// CheckPermission() from the worker thread to the main thread.
-class CheckPermissionRunnable final : public workers::WorkerMainThreadRunnable
-{
-public:
-  bool mResult;
-  bool mCallerChrome;
-
-  explicit CheckPermissionRunnable(workers::WorkerPrivate* aWorkerPrivate)
-    : workers::WorkerMainThreadRunnable(aWorkerPrivate)
-    , mResult(false)
-    , mCallerChrome(false)
-  {
-    MOZ_ASSERT(aWorkerPrivate);
-    aWorkerPrivate->AssertIsOnWorkerThread();
-    mCallerChrome = aWorkerPrivate->UsesSystemPrincipal();
-  }
-
-protected:
-  virtual bool
-  MainThreadRun() override
-  {
-    MOZ_ASSERT(NS_IsMainThread());
-
-    nsIPrincipal* principal = GetPrincipalFromWorkerPrivate(mWorkerPrivate);
-    if (!principal) {
-      return true;
-    }
-
-    bool isNullPrincipal;
-    nsresult rv = principal->GetIsNullPrincipal(&isNullPrincipal);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-       return true;
-    }
-
-    if (NS_WARN_IF(isNullPrincipal)) {
-      return true;
-    }
-
-    mResult = CheckPermission(principal, mCallerChrome);
-    return true;
-  }
-};
-
-} // anonymous namespace
-
-/* static */ bool
-MessageChannel::Enabled(JSContext* aCx, JSObject* aGlobal)
-{
-  if (NS_IsMainThread()) {
-    JS::Rooted<JSObject*> global(aCx, aGlobal);
-
-    nsCOMPtr<nsPIDOMWindow> win = Navigator::GetWindowFromGlobal(global);
-    if (!win) {
-      return false;
-    }
-
-    nsIDocument* doc = win->GetExtantDoc();
-    if (!doc) {
-      return false;
-    }
-
-    return CheckPermission(doc->NodePrincipal(),
-                           nsContentUtils::IsCallerChrome());
-  }
-
-  workers::WorkerPrivate* workerPrivate =
-    workers::GetWorkerPrivateFromContext(aCx);
-  workerPrivate->AssertIsOnWorkerThread();
-
-  nsRefPtr<CheckPermissionRunnable> runnable =
-    new CheckPermissionRunnable(workerPrivate);
-  runnable->Dispatch(aCx);
-
-  return runnable->mResult;
-}
-
 MessageChannel::MessageChannel(nsPIDOMWindow* aWindow)
   : mWindow(aWindow)
 {
+  MOZ_COUNT_CTOR(MessageChannel);
+
+  mPort1 = new MessagePort(mWindow);
+  mPort2 = new MessagePort(mWindow);
+
+  mPort1->Entangle(mPort2);
+  mPort2->Entangle(mPort1);
 }
 
 MessageChannel::~MessageChannel()
 {
+  MOZ_COUNT_DTOR(MessageChannel);
 }
 
 JSObject*
 MessageChannel::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return MessageChannelBinding::Wrap(aCx, this, aGivenProto);
 }
 
 /* static */ already_AddRefed<MessageChannel>
 MessageChannel::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
 {
-  // window can be null in workers.
   nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
-
-  nsID portUUID1;
-  aRv = nsContentUtils::GenerateUUIDInPlace(portUUID1);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-
-  nsID portUUID2;
-  aRv = nsContentUtils::GenerateUUIDInPlace(portUUID2);
-  if (aRv.Failed()) {
+  if (!window) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
   nsRefPtr<MessageChannel> channel = new MessageChannel(window);
-
-  channel->mPort1 = MessagePort::Create(window, portUUID1, portUUID2, aRv);
-  if (NS_WARN_IF(aRv.Failed())) {
-    return nullptr;
-  }
-
-  channel->mPort2 = MessagePort::Create(window, portUUID2, portUUID1, aRv);
-  if (NS_WARN_IF(aRv.Failed())) {
-    return nullptr;
-  }
-
-  channel->mPort1->UnshippedEntangle(channel->mPort2);
-  channel->mPort2->UnshippedEntangle(channel->mPort1);
-
   return channel.forget();
 }
 
 } // namespace dom
 } // namespace mozilla
rename from dom/messagechannel/MessageChannel.h
rename to dom/base/MessageChannel.h
--- a/dom/messagechannel/MessageChannel.h
+++ b/dom/base/MessageChannel.h
@@ -26,16 +26,18 @@ class MessageChannel final : public nsIS
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MessageChannel)
 
   static bool Enabled(JSContext* aCx, JSObject* aGlobal);
 
 public:
+  explicit MessageChannel(nsPIDOMWindow* aWindow);
+
   nsPIDOMWindow*
   GetParentObject() const
   {
     return mWindow;
   }
 
   virtual JSObject*
   WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
@@ -51,17 +53,16 @@ public:
 
   MessagePort*
   Port2() const
   {
     return mPort2;
   }
 
 private:
-  explicit MessageChannel(nsPIDOMWindow* aWindow);
   ~MessageChannel();
 
   nsCOMPtr<nsPIDOMWindow> mWindow;
 
   nsRefPtr<MessagePort> mPort1;
   nsRefPtr<MessagePort> mPort2;
 };
 
rename from dom/messagechannel/MessagePort.cpp
rename to dom/base/MessagePort.cpp
--- a/dom/messagechannel/MessagePort.cpp
+++ b/dom/base/MessagePort.cpp
@@ -1,531 +1,516 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "MessagePort.h"
-
 #include "MessageEvent.h"
-#include "MessagePortChild.h"
 #include "mozilla/dom/BlobBinding.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/MessageChannel.h"
 #include "mozilla/dom/MessagePortBinding.h"
-#include "mozilla/dom/MessagePortChild.h"
 #include "mozilla/dom/MessagePortList.h"
-#include "mozilla/dom/PMessagePort.h"
 #include "mozilla/dom/StructuredCloneTags.h"
-#include "mozilla/dom/WorkerPrivate.h"
-#include "mozilla/dom/WorkerScope.h"
-#include "mozilla/ipc/BackgroundChild.h"
-#include "mozilla/ipc/PBackgroundChild.h"
 #include "nsContentUtils.h"
 #include "nsGlobalWindow.h"
 #include "nsPresContext.h"
 #include "ScriptSettings.h"
-#include "SharedMessagePortMessage.h"
 
-#include "nsIBFCacheEntry.h"
 #include "nsIDocument.h"
 #include "nsIDOMFileList.h"
 #include "nsIPresShell.h"
-#include "nsISupportsPrimitives.h"
-#include "nsServiceManagerUtils.h"
-
-#ifdef XP_WIN
-#undef PostMessage
-#endif
-
-using namespace mozilla::dom::workers;
 
 namespace mozilla {
 namespace dom {
 
-class DispatchEventRunnable final : public nsICancelableRunnable
+class DispatchEventRunnable : public nsRunnable
+{
+  friend class MessagePort;
+
+  public:
+    explicit DispatchEventRunnable(MessagePort* aPort)
+      : mPort(aPort)
+    {
+    }
+
+    NS_IMETHOD
+    Run()
+    {
+      nsRefPtr<DispatchEventRunnable> mKungFuDeathGrip(this);
+
+      mPort->mDispatchRunnable = nullptr;
+      mPort->Dispatch();
+
+      return NS_OK;
+    }
+
+  private:
+    nsRefPtr<MessagePort> mPort;
+};
+
+class PostMessageRunnable : public nsRunnable
 {
   friend class MessagePort;
 
-public:
-  NS_DECL_ISUPPORTS
+  public:
+    NS_DECL_NSIRUNNABLE
 
-  explicit DispatchEventRunnable(MessagePort* aPort)
-    : mPort(aPort)
-  { }
+    PostMessageRunnable()
+    {
+    }
 
-  NS_IMETHOD
-  Run() override
-  {
-    MOZ_ASSERT(mPort);
-    MOZ_ASSERT(mPort->mDispatchRunnable == this);
-    mPort->mDispatchRunnable = nullptr;
-    mPort->Dispatch();
+    ~PostMessageRunnable()
+    {
+    }
+
+    JSAutoStructuredCloneBuffer& Buffer()
+    {
+      return mBuffer;
+    }
 
-    return NS_OK;
-  }
+    bool StoreISupports(nsISupports* aSupports)
+    {
+      mSupportsArray.AppendElement(aSupports);
+      return true;
+    }
+
+    void Dispatch(MessagePort* aPort)
+    {
+      mPort = aPort;
+      NS_DispatchToCurrentThread(this);
+    }
 
-  NS_IMETHOD
-  Cancel() override
-  {
-    mPort = nullptr;
-    return NS_OK;
-  }
+  private:
+    nsRefPtr<MessagePort> mPort;
+    JSAutoStructuredCloneBuffer mBuffer;
+
+    nsTArray<nsCOMPtr<nsISupports> > mSupportsArray;
+};
 
-private:
-  ~DispatchEventRunnable()
-  {}
+namespace {
 
-  nsRefPtr<MessagePort> mPort;
+struct StructuredCloneInfo
+{
+  PostMessageRunnable* mEvent;
+  MessagePort* mPort;
+  nsRefPtrHashtable<nsRefPtrHashKey<MessagePortBase>, MessagePortBase> mPorts;
 };
 
-NS_IMPL_ISUPPORTS(DispatchEventRunnable, nsICancelableRunnable, nsIRunnable)
+static JSObject*
+PostMessageReadStructuredClone(JSContext* cx,
+                               JSStructuredCloneReader* reader,
+                               uint32_t tag,
+                               uint32_t data,
+                               void* closure)
+{
+  StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(closure);
+  NS_ASSERTION(scInfo, "Must have scInfo!");
 
-class PostMessageRunnable final : public nsICancelableRunnable
-{
-public:
-  NS_DECL_ISUPPORTS
+  if (tag == SCTAG_DOM_BLOB) {
+    NS_ASSERTION(!data, "Data should be empty");
 
-  PostMessageRunnable(MessagePort* aPort, SharedMessagePortMessage* aData)
-    : mPort(aPort)
-    , mData(aData)
-  {
-    MOZ_ASSERT(aPort);
-    MOZ_ASSERT(aData);
+    // What we get back from the reader is a BlobImpl.
+    // From that we create a new File.
+    BlobImpl* blobImpl;
+    if (JS_ReadBytes(reader, &blobImpl, sizeof(blobImpl))) {
+      MOZ_ASSERT(blobImpl);
+
+      // nsRefPtr<File> needs to go out of scope before toObjectOrNull() is
+      // called because the static analysis thinks dereferencing XPCOM objects
+      // can GC (because in some cases it can!), and a return statement with a
+      // JSObject* type means that JSObject* is on the stack as a raw pointer
+      // while destructors are running.
+      JS::Rooted<JS::Value> val(cx);
+      {
+        nsRefPtr<Blob> blob = Blob::Create(scInfo->mPort->GetParentObject(),
+                                           blobImpl);
+        if (!ToJSValue(cx, blob, &val)) {
+          return nullptr;
+        }
+      }
+
+      return &val.toObject();
+    }
   }
 
-  NS_IMETHOD
-  Run() override
-  {
-    nsCOMPtr<nsIGlobalObject> globalObject;
+  if (tag == SCTAG_DOM_FILELIST) {
+    NS_ASSERTION(!data, "Data should be empty");
+
+    nsISupports* supports;
+    if (JS_ReadBytes(reader, &supports, sizeof(supports))) {
+      JS::Rooted<JS::Value> val(cx);
+      if (NS_SUCCEEDED(nsContentUtils::WrapNative(cx, supports, &val))) {
+        return val.toObjectOrNull();
+      }
+    }
+  }
+
+  const JSStructuredCloneCallbacks* runtimeCallbacks =
+    js::GetContextStructuredCloneCallbacks(cx);
+
+  if (runtimeCallbacks) {
+    return runtimeCallbacks->read(cx, reader, tag, data, nullptr);
+  }
+
+  return nullptr;
+}
 
-    if (NS_IsMainThread()) {
-      globalObject = do_QueryInterface(mPort->GetParentObject());
-    } else {
-      WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
-      MOZ_ASSERT(workerPrivate);
-      globalObject = workerPrivate->GlobalScope();
+static bool
+PostMessageWriteStructuredClone(JSContext* cx,
+                                JSStructuredCloneWriter* writer,
+                                JS::Handle<JSObject*> obj,
+                                void *closure)
+{
+  StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(closure);
+  NS_ASSERTION(scInfo, "Must have scInfo!");
+
+  // See if this is a File/Blob object.
+  {
+    Blob* blob = nullptr;
+    if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob, obj, blob))) {
+      BlobImpl* blobImpl = blob->Impl();
+      if (JS_WriteUint32Pair(writer, SCTAG_DOM_BLOB, 0) &&
+          JS_WriteBytes(writer, &blobImpl, sizeof(blobImpl))) {
+        scInfo->mEvent->StoreISupports(blobImpl);
+        return true;
+      }
     }
+  }
 
-    AutoJSAPI jsapi;
-    if (!globalObject || !jsapi.Init(globalObject)) {
-      NS_WARNING("Failed to initialize AutoJSAPI object.");
-      return NS_ERROR_FAILURE;
+  nsCOMPtr<nsIXPConnectWrappedNative> wrappedNative;
+  nsContentUtils::XPConnect()->
+    GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wrappedNative));
+  if (wrappedNative) {
+    uint32_t scTag = 0;
+    nsISupports* supports = wrappedNative->Native();
+
+    nsCOMPtr<nsIDOMFileList> list = do_QueryInterface(supports);
+    if (list) {
+      scTag = SCTAG_DOM_FILELIST;
     }
 
-    JSContext* cx = jsapi.cx();
+    if (scTag) {
+      return JS_WriteUint32Pair(writer, scTag, 0) &&
+             JS_WriteBytes(writer, &supports, sizeof(supports)) &&
+             scInfo->mEvent->StoreISupports(supports);
+    }
+  }
+
+  const JSStructuredCloneCallbacks* runtimeCallbacks =
+    js::GetContextStructuredCloneCallbacks(cx);
+
+  if (runtimeCallbacks) {
+    return runtimeCallbacks->write(cx, writer, obj, nullptr);
+  }
 
-    nsTArray<nsRefPtr<MessagePort>> ports;
-    nsCOMPtr<nsPIDOMWindow> window =
-      do_QueryInterface(mPort->GetParentObject());
+  return false;
+}
+
+static bool
+PostMessageReadTransferStructuredClone(JSContext* aCx,
+                                       JSStructuredCloneReader* reader,
+                                       uint32_t tag, void* data,
+                                       uint64_t unused,
+                                       void* aClosure,
+                                       JS::MutableHandle<JSObject*> returnObject)
+{
+  StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(aClosure);
+  NS_ASSERTION(scInfo, "Must have scInfo!");
+
+  if (tag == SCTAG_DOM_MAP_MESSAGEPORT) {
+    MessagePort* port = static_cast<MessagePort*>(data);
+    port->BindToOwner(scInfo->mPort->GetOwner());
+    scInfo->mPorts.Put(port, nullptr);
 
-    JS::Rooted<JS::Value> value(cx);
-    if (!mData->mData.IsEmpty()) {
-      bool ok = ReadStructuredCloneWithTransfer(cx, mData->mData,
-                                                mData->mClosure,
-                                                &value, window, ports);
-      FreeStructuredClone(mData->mData, mData->mClosure);
+    JS::Rooted<JSObject*> obj(aCx, port->WrapObject(aCx, nullptr));
+    if (!obj || !JS_WrapObject(aCx, &obj)) {
+      return false;
+    }
+
+    MOZ_ASSERT(port->GetOwner() == scInfo->mPort->GetOwner());
+    returnObject.set(obj);
+    return true;
+  }
+
+  return false;
+}
 
-      if (!ok) {
-        return NS_ERROR_FAILURE;
-      }
+static bool
+PostMessageTransferStructuredClone(JSContext* aCx,
+                                   JS::Handle<JSObject*> aObj,
+                                   void* aClosure,
+                                   uint32_t* aTag,
+                                   JS::TransferableOwnership* aOwnership,
+                                   void** aContent,
+                                   uint64_t *aExtraData)
+{
+  StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(aClosure);
+  NS_ASSERTION(scInfo, "Must have scInfo!");
+
+  MessagePortBase *port = nullptr;
+  nsresult rv = UNWRAP_OBJECT(MessagePort, aObj, port);
+  if (NS_SUCCEEDED(rv)) {
+    nsRefPtr<MessagePortBase> newPort;
+    if (scInfo->mPorts.Get(port, getter_AddRefs(newPort))) {
+      // No duplicate.
+      return false;
     }
 
-    // The data should be already be cleaned.
-    MOZ_ASSERT(!mData->mData.Length());
-
-    // Create the event
-    nsCOMPtr<mozilla::dom::EventTarget> eventTarget =
-      do_QueryInterface(mPort->GetOwner());
-    nsRefPtr<MessageEvent> event =
-      new MessageEvent(eventTarget, nullptr, nullptr);
+    newPort = port->Clone();
+    scInfo->mPorts.Put(port, newPort);
 
-    event->InitMessageEvent(NS_LITERAL_STRING("message"),
-                            false /* non-bubbling */,
-                            false /* cancelable */, value, EmptyString(),
-                            EmptyString(), nullptr);
-    event->SetTrusted(true);
-    event->SetSource(mPort);
+    *aTag = SCTAG_DOM_MAP_MESSAGEPORT;
+    *aOwnership = JS::SCTAG_TMO_CUSTOM;
+    *aContent = newPort;
+    *aExtraData = 0;
 
-    nsTArray<nsRefPtr<MessagePortBase>> array;
-    array.SetCapacity(ports.Length());
-    for (uint32_t i = 0; i < ports.Length(); ++i) {
-      array.AppendElement(ports[i]);
-    }
-
-    nsRefPtr<MessagePortList> portList =
-      new MessagePortList(static_cast<dom::Event*>(event.get()), array);
-    event->SetPorts(portList);
-
-    bool dummy;
-    mPort->DispatchEvent(static_cast<dom::Event*>(event.get()), &dummy);
-    return NS_OK;
+    return true;
   }
 
-  NS_IMETHOD
-  Cancel() override
-  {
-    mPort = nullptr;
-    mData = nullptr;
-    return NS_OK;
+  return false;
+}
+
+static void
+PostMessageFreeTransferStructuredClone(uint32_t aTag, JS::TransferableOwnership aOwnership,
+                                       void* aData,
+                                       uint64_t aExtraData,
+                                       void* aClosure)
+{
+  StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(aClosure);
+  NS_ASSERTION(scInfo, "Must have scInfo!");
+
+  if (aTag == SCTAG_DOM_MAP_MESSAGEPORT) {
+    MOZ_ASSERT(aOwnership == JS::SCTAG_TMO_CUSTOM);
+    nsRefPtr<MessagePort> port(static_cast<MessagePort*>(aData));
+    scInfo->mPorts.Remove(port);
+  }
+}
+
+const JSStructuredCloneCallbacks kPostMessageCallbacks = {
+  PostMessageReadStructuredClone,
+  PostMessageWriteStructuredClone,
+  nullptr,
+  PostMessageReadTransferStructuredClone,
+  PostMessageTransferStructuredClone,
+  PostMessageFreeTransferStructuredClone
+};
+
+} // anonymous namespace
+
+static PLDHashOperator
+PopulateMessagePortList(MessagePortBase* aKey, MessagePortBase* aValue, void* aClosure)
+{
+  nsTArray<nsRefPtr<MessagePortBase> > *array =
+    static_cast<nsTArray<nsRefPtr<MessagePortBase> > *>(aClosure);
+
+  array->AppendElement(aKey);
+  return PL_DHASH_NEXT;
+}
+
+NS_IMETHODIMP
+PostMessageRunnable::Run()
+{
+  MOZ_ASSERT(mPort);
+
+  AutoJSAPI jsapi;
+  if (NS_WARN_IF(!jsapi.Init(mPort->GetParentObject()))) {
+    return NS_ERROR_UNEXPECTED;
+  }
+  JSContext* cx = jsapi.cx();
+
+  // Deserialize the structured clone data
+  JS::Rooted<JS::Value> messageData(cx);
+  StructuredCloneInfo scInfo;
+  scInfo.mEvent = this;
+  scInfo.mPort = mPort;
+
+  if (!mBuffer.read(cx, &messageData, &kPostMessageCallbacks, &scInfo)) {
+    return NS_ERROR_DOM_DATA_CLONE_ERR;
   }
 
-private:
-  ~PostMessageRunnable()
-  {}
+  // Create the event
+  nsCOMPtr<mozilla::dom::EventTarget> eventTarget =
+    do_QueryInterface(mPort->GetOwner());
+  nsRefPtr<MessageEvent> event =
+    new MessageEvent(eventTarget, nullptr, nullptr);
 
-  nsRefPtr<MessagePort> mPort;
-  nsRefPtr<SharedMessagePortMessage> mData;
-};
+  event->InitMessageEvent(NS_LITERAL_STRING("message"), false /* non-bubbling */,
+                          false /* cancelable */, messageData, EmptyString(),
+                          EmptyString(), nullptr);
+  event->SetTrusted(true);
+  event->SetSource(mPort);
 
-NS_IMPL_ISUPPORTS(PostMessageRunnable, nsICancelableRunnable, nsIRunnable)
+  nsTArray<nsRefPtr<MessagePortBase> > ports;
+  scInfo.mPorts.EnumerateRead(PopulateMessagePortList, &ports);
+  event->SetPorts(new MessagePortList(static_cast<dom::Event*>(event.get()), ports));
+
+  bool status;
+  mPort->DispatchEvent(static_cast<dom::Event*>(event.get()), &status);
+  return status ? NS_OK : NS_ERROR_FAILURE;
+}
 
 MessagePortBase::MessagePortBase(nsPIDOMWindow* aWindow)
   : DOMEventTargetHelper(aWindow)
 {
 }
 
 MessagePortBase::MessagePortBase()
 {
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(MessagePort)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MessagePort,
-                                                MessagePortBase)
+                                                DOMEventTargetHelper)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mEntangledPort)
+
+  // Custom unlink loop because this array contains nsRunnable objects
+  // which are not cycle colleactable.
+  while (!tmp->mMessageQueue.IsEmpty()) {
+    NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageQueue[0]->mPort);
+    NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageQueue[0]->mSupportsArray);
+    tmp->mMessageQueue.RemoveElementAt(0);
+  }
+
   if (tmp->mDispatchRunnable) {
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mDispatchRunnable->mPort);
   }
 
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessages);
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessagesForTheOtherPort);
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mUnshippedEntangledPort);
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MessagePort,
-                                                  MessagePortBase)
+                                                  DOMEventTargetHelper)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEntangledPort)
+
+  // Custom unlink loop because this array contains nsRunnable objects
+  // which are not cycle colleactable.
+  for (uint32_t i = 0, len = tmp->mMessageQueue.Length(); i < len; ++i) {
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageQueue[i]->mPort);
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageQueue[i]->mSupportsArray);
+  }
+
   if (tmp->mDispatchRunnable) {
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDispatchRunnable->mPort);
   }
 
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mUnshippedEntangledPort);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MessagePort)
-  NS_INTERFACE_MAP_ENTRY(nsIIPCBackgroundChildCreateCallback)
-  NS_INTERFACE_MAP_ENTRY(nsIObserver)
-NS_INTERFACE_MAP_END_INHERITING(MessagePortBase)
-
-NS_IMPL_ADDREF_INHERITED(MessagePort, MessagePortBase)
-NS_IMPL_RELEASE_INHERITED(MessagePort, MessagePortBase)
-
-namespace {
-
-class MessagePortFeature final : public workers::WorkerFeature
-{
-  MessagePort* mPort;
+NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
 
-public:
-  explicit MessagePortFeature(MessagePort* aPort)
-    : mPort(aPort)
-  {
-    MOZ_ASSERT(aPort);
-    MOZ_COUNT_CTOR(MessagePortFeature);
-  }
-
-  virtual bool Notify(JSContext* aCx, workers::Status aStatus) override
-  {
-    if (mPort && aStatus > Running) {
-      mPort->Close();
-    }
-
-    return true;
-  }
-
-private:
-  ~MessagePortFeature()
-  {
-    MOZ_COUNT_DTOR(MessagePortFeature);
-  }
-};
-
-} // anonymous namespace
+NS_IMPL_ADDREF_INHERITED(MessagePort, DOMEventTargetHelper)
+NS_IMPL_RELEASE_INHERITED(MessagePort, DOMEventTargetHelper)
 
 MessagePort::MessagePort(nsPIDOMWindow* aWindow)
   : MessagePortBase(aWindow)
-  , mInnerID(0)
   , mMessageQueueEnabled(false)
-  , mIsKeptAlive(false)
 {
-  mIdentifier = new MessagePortIdentifier();
-  mIdentifier->neutered() = true;
-  mIdentifier->sequenceId() = 0;
 }
 
 MessagePort::~MessagePort()
 {
   Close();
-  MOZ_ASSERT(!mWorkerFeature);
-}
-
-/* static */ already_AddRefed<MessagePort>
-MessagePort::Create(nsPIDOMWindow* aWindow, const nsID& aUUID,
-                    const nsID& aDestinationUUID, ErrorResult& aRv)
-{
-  nsRefPtr<MessagePort> mp = new MessagePort(aWindow);
-  mp->Initialize(aUUID, aDestinationUUID, 1 /* 0 is an invalid sequence ID */,
-                 false /* Neutered */, eStateUnshippedEntangled, aRv);
-  return mp.forget();
-}
-
-/* static */ already_AddRefed<MessagePort>
-MessagePort::Create(nsPIDOMWindow* aWindow,
-                    const MessagePortIdentifier& aIdentifier,
-                    ErrorResult& aRv)
-{
-  nsRefPtr<MessagePort> mp = new MessagePort(aWindow);
-  mp->Initialize(aIdentifier.uuid(), aIdentifier.destinationUuid(),
-                 aIdentifier.sequenceId(), aIdentifier.neutered(),
-                 eStateEntangling, aRv);
-  return mp.forget();
-}
-
-void
-MessagePort::UnshippedEntangle(MessagePort* aEntangledPort)
-{
-  MOZ_ASSERT(aEntangledPort);
-  MOZ_ASSERT(!mUnshippedEntangledPort);
-
-  mUnshippedEntangledPort = aEntangledPort;
-}
-
-void
-MessagePort::Initialize(const nsID& aUUID,
-                        const nsID& aDestinationUUID,
-                        uint32_t aSequenceID, bool mNeutered,
-                        State aState, ErrorResult& aRv)
-{
-  MOZ_ASSERT(mIdentifier);
-  mIdentifier->uuid() = aUUID;
-  mIdentifier->destinationUuid() = aDestinationUUID;
-  mIdentifier->sequenceId() = aSequenceID;
-
-  mState = aState;
-  mNextStep = eNextStepNone;
-
-  if (mNeutered) {
-    mState = eStateDisentangled;
-  } else if (mState == eStateEntangling) {
-    ConnectToPBackground();
-  } else {
-    MOZ_ASSERT(mState == eStateUnshippedEntangled);
-  }
-
-  // The port has to keep itself alive until it's entangled.
-  UpdateMustKeepAlive();
-
-  if (NS_IsMainThread()) {
-    MOZ_ASSERT(GetOwner());
-    MOZ_ASSERT(GetOwner()->IsInnerWindow());
-    mInnerID = GetOwner()->WindowID();
-
-    nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
-    if (obs) {
-      obs->AddObserver(this, "inner-window-destroyed", false);
-    }
-  } else {
-    WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
-    MOZ_ASSERT(workerPrivate);
-    MOZ_ASSERT(!mWorkerFeature);
-
-    nsAutoPtr<WorkerFeature> feature(new MessagePortFeature(this));
-    JSContext* cx = workerPrivate->GetJSContext();
-    if (NS_WARN_IF(!workerPrivate->AddFeature(cx, feature))) {
-      aRv.Throw(NS_ERROR_FAILURE);
-      return;
-    }
-
-    mWorkerFeature = Move(feature);
-  }
 }
 
 JSObject*
 MessagePort::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return MessagePortBinding::Wrap(aCx, this, aGivenProto);
 }
 
 void
-MessagePort::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
-                         const Optional<Sequence<JS::Value>>& aTransferable,
-                         ErrorResult& aRv)
+MessagePort::PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
+                            const Optional<Sequence<JS::Value>>& aTransferable,
+                            ErrorResult& aRv)
 {
+  nsRefPtr<PostMessageRunnable> event = new PostMessageRunnable();
+
   // We *must* clone the data here, or the JS::Value could be modified
   // by script
+  StructuredCloneInfo scInfo;
+  scInfo.mEvent = event;
+  scInfo.mPort = this;
 
   JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
   if (aTransferable.WasPassed()) {
     const Sequence<JS::Value>& realTransferable = aTransferable.Value();
 
-    // Here we want to check if the transerable object list contains
-    // this port. No other checks are done.
-    for (const JS::Value& value : realTransferable) {
-      if (!value.isObject()) {
-        continue;
-      }
-
-      MessagePortBase* port = nullptr;
-      nsresult rv = UNWRAP_OBJECT(MessagePort, &value.toObject(), port);
-      if (NS_FAILED(rv)) {
-        continue;
-      }
-
-      if (port == this) {
-        aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
-        return;
-      }
-    }
-
     // The input sequence only comes from the generated bindings code, which
     // ensures it is rooted.
     JS::HandleValueArray elements =
       JS::HandleValueArray::fromMarkedLocation(realTransferable.Length(),
                                                realTransferable.Elements());
 
     JSObject* array =
       JS_NewArrayObject(aCx, elements);
     if (!array) {
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return;
     }
-
     transferable.setObject(*array);
   }
 
-  nsRefPtr<SharedMessagePortMessage> data = new SharedMessagePortMessage();
-
-  if (!WriteStructuredCloneWithTransfer(aCx, aMessage, transferable,
-                                        data->mData, data->mClosure)) {
+  if (!event->Buffer().write(aCx, aMessage, transferable,
+                             &kPostMessageCallbacks, &scInfo)) {
     aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
     return;
   }
 
-  // This message has to be ignored.
-  if (mState > eStateEntangled) {
-    return;
-  }
-
-  // If we are unshipped we are connected to the other port on the same thread.
-  if (mState == eStateUnshippedEntangled) {
-    MOZ_ASSERT(mUnshippedEntangledPort);
-    mUnshippedEntangledPort->mMessages.AppendElement(data);
-    mUnshippedEntangledPort->Dispatch();
-    return;
-  }
-
-  // Not entangled yet, but already closed.
-  if (mNextStep != eNextStepNone) {
+  if (!mEntangledPort) {
     return;
   }
 
-  RemoveDocFromBFCache();
-
-  // Not entangled yet.
-  if (mState == eStateEntangling) {
-    mMessagesForTheOtherPort.AppendElement(data);
-    return;
-  }
-
-  MOZ_ASSERT(mActor);
-  MOZ_ASSERT(mMessagesForTheOtherPort.IsEmpty());
-
-  nsAutoTArray<nsRefPtr<SharedMessagePortMessage>, 1> array;
-  array.AppendElement(data);
-
-  nsAutoTArray<MessagePortMessage, 1> messages;
-  SharedMessagePortMessage::FromSharedToMessagesChild(mActor, array, messages);
-  mActor->SendPostMessages(messages);
+  mEntangledPort->mMessageQueue.AppendElement(event);
+  mEntangledPort->Dispatch();
 }
 
 void
 MessagePort::Start()
 {
   if (mMessageQueueEnabled) {
     return;
   }
 
   mMessageQueueEnabled = true;
   Dispatch();
 }
 
 void
 MessagePort::Dispatch()
 {
-  if (!mMessageQueueEnabled || mMessages.IsEmpty() || mDispatchRunnable ||
-      mState > eStateEntangled || mNextStep != eNextStepNone) {
+  if (!mMessageQueueEnabled || mMessageQueue.IsEmpty() || mDispatchRunnable) {
     return;
   }
 
-  nsRefPtr<SharedMessagePortMessage> data = mMessages.ElementAt(0);
-  mMessages.RemoveElementAt(0);
+  nsRefPtr<PostMessageRunnable> event = mMessageQueue.ElementAt(0);
+  mMessageQueue.RemoveElementAt(0);
 
-  nsRefPtr<PostMessageRunnable> runnable = new PostMessageRunnable(this, data);
-
-  MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToCurrentThread(runnable)));
+  event->Dispatch(this);
 
   mDispatchRunnable = new DispatchEventRunnable(this);
-
-  MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToCurrentThread(mDispatchRunnable)));
+  NS_DispatchToCurrentThread(mDispatchRunnable);
 }
 
 void
 MessagePort::Close()
 {
-  // Not entangled yet, but already closed.
-  if (mNextStep != eNextStepNone) {
-    return;
-  }
-
-  if (mState == eStateUnshippedEntangled) {
-    MOZ_ASSERT(mUnshippedEntangledPort);
-
-    // This avoids loops.
-    nsRefPtr<MessagePort> port = Move(mUnshippedEntangledPort);
-    MOZ_ASSERT(mUnshippedEntangledPort == nullptr);
-
-    mState = eStateDisentangled;
-    port->Close();
-
-    UpdateMustKeepAlive();
+  if (!mEntangledPort) {
     return;
   }
 
-  // Not entangled yet, we have to wait.
-  if (mState < eStateEntangling) {
-    mNextStep = eNextStepClose;
-    return;
-  }
-
-  if (mState > eStateEntangled) {
-    return;
-  }
+  // This avoids loops.
+  nsRefPtr<MessagePort> port = mEntangledPort;
+  mEntangledPort = nullptr;
 
-  // We don't care about stopping the sending of messages because from now all
-  // the incoming messages will be ignored.
-  mState = eStateDisentangled;
-
-  MOZ_ASSERT(mActor);
-
-  mActor->SendClose();
-  mActor->SetPort(nullptr);
-  mActor = nullptr;
-
-  UpdateMustKeepAlive();
+  // Let's disentangle the 2 ports symmetrically.
+  port->Close();
 }
 
 EventHandlerNonNull*
 MessagePort::GetOnmessage()
 {
   if (NS_IsMainThread()) {
     return GetEventHandler(nsGkAtoms::onmessage, EmptyString());
   }
@@ -540,328 +525,40 @@ MessagePort::SetOnmessage(EventHandlerNo
   } else {
     SetEventHandler(nullptr, NS_LITERAL_STRING("message"), aCallback);
   }
 
   // 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<MessagePortMessage>& aMessages)
+MessagePort::Entangle(MessagePort* aMessagePort)
 {
-  MOZ_ASSERT(mState == eStateEntangling);
-
-  mState = eStateEntangled;
-
-  // If we have pending messages, these have to be sent.
-  if (!mMessagesForTheOtherPort.IsEmpty()) {
-    nsTArray<MessagePortMessage> messages;
-    SharedMessagePortMessage::FromSharedToMessagesChild(mActor,
-                                                        mMessagesForTheOtherPort,
-                                                        messages);
-    mMessagesForTheOtherPort.Clear();
-    mActor->SendPostMessages(messages);
-  }
-
-  // We must convert the messages into SharedMessagePortMessages to avoid leaks.
-  FallibleTArray<nsRefPtr<SharedMessagePortMessage>> data;
-  if (NS_WARN_IF(!SharedMessagePortMessage::FromMessagesToSharedChild(aMessages,
-                                                                      data))) {
-    // OOM, we cannot continue.
-    return;
-  }
+  MOZ_ASSERT(aMessagePort);
+  MOZ_ASSERT(aMessagePort != this);
 
-  if (mNextStep == eNextStepClose) {
-    Close();
-    return;
-  }
-
-  mMessages.AppendElements(data);
-
-  // We were waiting for the entangling callback in order to disentangle this
-  // port immediately after.
-  if (mNextStep == eNextStepDisentangle) {
-    StartDisentangling();
-    return;
-  }
+  Close();
 
-  MOZ_ASSERT(mNextStep == eNextStepNone);
-  Dispatch();
-}
-
-void
-MessagePort::StartDisentangling()
-{
-  MOZ_ASSERT(mActor);
-  MOZ_ASSERT(mState == eStateEntangled);
-
-  mState = eStateDisentangling;
-  mNextStep = eNextStepNone;
-
-  // 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();
+  mEntangledPort = aMessagePort;
 }
 
-void
-MessagePort::MessagesReceived(nsTArray<MessagePortMessage>& aMessages)
-{
-  MOZ_ASSERT(mState == eStateEntangled || mState == eStateDisentangling);
-  MOZ_ASSERT(mNextStep == eNextStepNone);
-  MOZ_ASSERT(mMessagesForTheOtherPort.IsEmpty());
-
-  RemoveDocFromBFCache();
-
-  FallibleTArray<nsRefPtr<SharedMessagePortMessage>> data;
-  if (!NS_WARN_IF(SharedMessagePortMessage::FromMessagesToSharedChild(aMessages,
-                                                                      data))) {
-    // OOM, We cannot continue.
-    return;
-  }
-
-  mMessages.AppendElements(data);
-
-  if (mState == eStateEntangled) {
-    Dispatch();
-  }
-}
-
-void
-MessagePort::StopSendingDataConfirmed()
-{
-  MOZ_ASSERT(mState == eStateDisentangling);
-  MOZ_ASSERT(mActor);
-
-  Disentangle();
-}
-
-void
-MessagePort::Disentangle()
+already_AddRefed<MessagePortBase>
+MessagePort::Clone()
 {
-  MOZ_ASSERT(mState == eStateDisentangling);
-  MOZ_ASSERT(mActor);
-
-  mState = eStateDisentangled;
+  nsRefPtr<MessagePort> newPort = new MessagePort(nullptr);
 
-  nsTArray<MessagePortMessage> messages;
-  SharedMessagePortMessage::FromSharedToMessagesChild(mActor, mMessages,
-                                                      messages);
-  mMessages.Clear();
-  mActor->SendDisentangle(messages);
-
-  mActor->SetPort(nullptr);
-  mActor = nullptr;
-
-  UpdateMustKeepAlive();
-}
+  // Move all the events in the port message queue of original port.
+  newPort->mMessageQueue.SwapElements(mMessageQueue);
 
-bool
-MessagePort::CloneAndDisentangle(MessagePortIdentifier& aIdentifier)
-{
-  MOZ_ASSERT(mIdentifier);
+  if (mEntangledPort) {
+    nsRefPtr<MessagePort> port = mEntangledPort;
+    mEntangledPort = nullptr;
 
-  // We can clone a port that has already been transfered. In this case, on the
-  // otherside will have a neutered port. Here we set neutered to true so that
-  // we are safe in case a early return.
-  aIdentifier.neutered() = true;
-
-  if (mState > eStateEntangled) {
-    return true;
-  }
-
-  // We already have a 'next step'. We have to consider this port as already
-  // cloned/closed/disentangled.
-  if (mNextStep != eNextStepNone) {
-    return true;
+    newPort->Entangle(port);
+    port->Entangle(newPort);
   }
 
-  aIdentifier.uuid() = mIdentifier->uuid();
-  aIdentifier.destinationUuid() = mIdentifier->destinationUuid();
-  aIdentifier.sequenceId() = mIdentifier->sequenceId() + 1;
-  aIdentifier.neutered() = false;
-
-  // We have to entangle first.
-  if (mState == eStateUnshippedEntangled) {
-    MOZ_ASSERT(mUnshippedEntangledPort);
-    MOZ_ASSERT(mMessagesForTheOtherPort.IsEmpty());
-
-    // Disconnect the entangled port and connect it to PBackground.
-    mUnshippedEntangledPort->ConnectToPBackground();
-    mUnshippedEntangledPort = nullptr;
-
-    // In this case, we don't need to be connected to the PBackground service.
-    if (mMessages.IsEmpty()) {
-      aIdentifier.sequenceId() = mIdentifier->sequenceId();
-
-      mState = eStateDisentangled;
-      UpdateMustKeepAlive();
-      return true;
-    }
-
-    // Register this component to PBackground.
-    ConnectToPBackground();
-
-    mNextStep = eNextStepDisentangle;
-    return true;
-  }
-
-  // Not entangled yet, we have to wait.
-  if (mState < eStateEntangled) {
-    mNextStep = eNextStepDisentangle;
-    return true;
-  }
-
-  StartDisentangling();
-  return true;
-}
-
-void
-MessagePort::Closed()
-{
-  if (mState == eStateDisentangled) {
-    return;
-  }
-
-  mState = eStateDisentangled;
-
-  if (mActor) {
-    mActor->SetPort(nullptr);
-    mActor = nullptr;
-  }
-
-  UpdateMustKeepAlive();
-}
-
-void
-MessagePort::ConnectToPBackground()
-{
-  mState = eStateEntangling;
-
-  PBackgroundChild* actor =
-    mozilla::ipc::BackgroundChild::GetForCurrentThread();
-  if (actor) {
-    ActorCreated(actor);
-  } else {
-    if (NS_WARN_IF(
-        !mozilla::ipc::BackgroundChild::GetOrCreateForCurrentThread(this))) {
-      MOZ_CRASH();
-    }
-  }
-}
-
-void
-MessagePort::ActorFailed()
-{
-  MOZ_CRASH("Failed to create a PBackgroundChild actor!");
-}
-
-void
-MessagePort::ActorCreated(mozilla::ipc::PBackgroundChild* aActor)
-{
-  MOZ_ASSERT(aActor);
-  MOZ_ASSERT(!mActor);
-  MOZ_ASSERT(mIdentifier);
-  MOZ_ASSERT(mState == eStateEntangling);
-
-  PMessagePortChild* actor =
-    aActor->SendPMessagePortConstructor(mIdentifier->uuid(),
-                                        mIdentifier->destinationUuid(),
-                                        mIdentifier->sequenceId());
-
-  mActor = static_cast<MessagePortChild*>(actor);
-  MOZ_ASSERT(mActor);
-
-  mActor->SetPort(this);
-}
-
-void
-MessagePort::UpdateMustKeepAlive()
-{
-  if (mState == eStateDisentangled && mIsKeptAlive) {
-    mIsKeptAlive = false;
-
-    if (mWorkerFeature) {
-      WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
-      MOZ_ASSERT(workerPrivate);
-
-      workerPrivate->RemoveFeature(workerPrivate->GetJSContext(),
-                                   mWorkerFeature);
-      mWorkerFeature = nullptr;
-    }
-
-    Release();
-    return;
-  }
-
-  if (mState < eStateDisentangled && !mIsKeptAlive) {
-    mIsKeptAlive = true;
-    AddRef();
-  }
-}
-
-NS_IMETHODIMP
-MessagePort::Observe(nsISupports* aSubject, const char* aTopic,
-                     const char16_t* aData)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  if (strcmp(aTopic, "inner-window-destroyed")) {
-    return NS_OK;
-  }
-
-  // If the window id destroyed we have to release the reference that we are
-  // keeping.
-  if (!mIsKeptAlive) {
-    return NS_OK;
-  }
-
-  nsCOMPtr<nsISupportsPRUint64> wrapper = do_QueryInterface(aSubject);
-  NS_ENSURE_TRUE(wrapper, NS_ERROR_FAILURE);
-
-  uint64_t innerID;
-  nsresult rv = wrapper->GetData(&innerID);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (innerID == mInnerID) {
-    nsCOMPtr<nsIObserverService> obs =
-      do_GetService("@mozilla.org/observer-service;1");
-    if (obs) {
-      obs->RemoveObserver(this, "inner-window-destroyed");
-    }
-
-    Close();
-  }
-
-  return NS_OK;
-}
-
-void
-MessagePort::RemoveDocFromBFCache()
-{
-  if (!NS_IsMainThread()) {
-    return;
-  }
-
-  nsPIDOMWindow* window = GetOwner();
-  MOZ_ASSERT(window);
-
-  nsIDocument* doc = window->GetExtantDoc();
-  if (!doc) {
-    return;
-  }
-
-  nsCOMPtr<nsIBFCacheEntry> bfCacheEntry = doc->GetBFCacheEntry();
-  if (!bfCacheEntry) {
-    return;
-  }
-
-  bfCacheEntry->RemoveFromBFCacheSync();
+  return newPort.forget();
 }
 
 } // namespace dom
 } // namespace mozilla
rename from dom/messagechannel/MessagePort.h
rename to dom/base/MessagePort.h
--- a/dom/messagechannel/MessagePort.h
+++ b/dom/base/MessagePort.h
@@ -4,207 +4,112 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_MessagePort_h
 #define mozilla_dom_MessagePort_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/DOMEventTargetHelper.h"
-#include "nsIIPCBackgroundChildCreateCallback.h"
-#include "nsTArray.h"
-
-#ifdef XP_WIN
-#undef PostMessage
-#endif
 
 class nsPIDOMWindow;
 
 namespace mozilla {
 namespace dom {
 
 class DispatchEventRunnable;
-class MessagePortChild;
-class MessagePortIdentifier;
-class MessagePortMessage;
-class SharedMessagePortMessage;
-
-namespace workers {
-class WorkerFeature;
-}
+class PostMessageRunnable;
 
 class MessagePortBase : public DOMEventTargetHelper
 {
 protected:
   explicit MessagePortBase(nsPIDOMWindow* aWindow);
   MessagePortBase();
 
 public:
 
   virtual void
-  PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
-              const Optional<Sequence<JS::Value>>& aTransferable,
-              ErrorResult& aRv) = 0;
+  PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
+                const Optional<Sequence<JS::Value>>& aTransferable,
+                ErrorResult& aRv) = 0;
 
   virtual void
   Start() = 0;
 
   virtual void
   Close() = 0;
 
   // The 'message' event handler has to call |Start()| method, so we
   // cannot use IMPL_EVENT_HANDLER macro here.
   virtual EventHandlerNonNull*
   GetOnmessage() = 0;
 
   virtual void
   SetOnmessage(EventHandlerNonNull* aCallback) = 0;
 
   // Duplicate this message port. This method is used by the Structured Clone
-  // Algorithm and populates a MessagePortIdentifier object with the information
-  // useful to create new MessagePort.
-  virtual bool
-  CloneAndDisentangle(MessagePortIdentifier& aIdentifier) = 0;
+  // Algorithm and makes the new MessagePort active with the entangled
+  // MessagePort of this object.
+  virtual already_AddRefed<MessagePortBase>
+  Clone() = 0;
 };
 
 class MessagePort final : public MessagePortBase
-                        , public nsIIPCBackgroundChildCreateCallback
-                        , public nsIObserver
 {
   friend class DispatchEventRunnable;
+  friend class PostMessageRunnable;
 
 public:
-  NS_DECL_NSIIPCBACKGROUNDCHILDCREATECALLBACK
-  NS_DECL_NSIOBSERVER
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MessagePort,
                                            DOMEventTargetHelper)
 
-  static already_AddRefed<MessagePort>
-  Create(nsPIDOMWindow* aWindow, const nsID& aUUID,
-         const nsID& aDestinationUUID, ErrorResult& aRv);
-
-  static already_AddRefed<MessagePort>
-  Create(nsPIDOMWindow* aWindow, const MessagePortIdentifier& aIdentifier,
-         ErrorResult& aRv);
+  explicit MessagePort(nsPIDOMWindow* aWindow);
 
   virtual JSObject*
   WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   virtual void
-  PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
-              const Optional<Sequence<JS::Value>>& aTransferable,
-              ErrorResult& aRv) override;
+  PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
+                 const Optional<Sequence<JS::Value>>& aTransferable,
+                 ErrorResult& aRv) override;
 
-  virtual void Start() override;
+  virtual void
+  Start() override;
 
-  virtual void Close() override;
+  virtual void
+  Close() override;
 
-  virtual EventHandlerNonNull* GetOnmessage() override;
+  virtual EventHandlerNonNull*
+  GetOnmessage() override;
 
-  virtual void SetOnmessage(EventHandlerNonNull* aCallback) override;
+  virtual void
+  SetOnmessage(EventHandlerNonNull* aCallback) override;
 
   // Non WebIDL methods
 
-  void UnshippedEntangle(MessagePort* aEntangledPort);
-
-  virtual bool CloneAndDisentangle(MessagePortIdentifier& aIdentifier) override;
+  // This method entangles this MessagePort with another one.
+  // If it is already entangled, it's disentangled first and enatangle to the
+  // new one.
+  void
+  Entangle(MessagePort* aMessagePort);
 
-  // These methods are useful for MessagePortChild
-
-  void Entangled(nsTArray<MessagePortMessage>& aMessages);
-  void MessagesReceived(nsTArray<MessagePortMessage>& aMessages);
-  void StopSendingDataConfirmed();
-  void Closed();
+  virtual already_AddRefed<MessagePortBase>
+  Clone() override;
 
 private:
-  explicit MessagePort(nsPIDOMWindow* aWindow);
   ~MessagePort();
 
-  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.
-    // When one of the port is shipped, the state is changed to
-    // StateEntangling.
-    eStateUnshippedEntangled,
-
-    // If the port is closed or cloned when we are in this state, we set the
-    // mNextStep. This 'next' operation will be done when entangled() message
-    // is received.
-    eStateEntangling,
-
-    // When entangled() is received we send all the messages in the
-    // mMessagesForTheOtherPort to the actor and we change the state to
-    // StateEntangled. At this point the port is entangled with the other. We
-    // send and receive messages.
-    // If the port queue is not enabled, the received messages are stored in
-    // the mMessages.
-    eStateEntangled,
-
-    // When the port is cloned or disentangled we want to stop receiving
-    // messages. We call 'SendStopSendingData' to the actor and we wait for an
-    // answer. All the messages received between now and the
-    // 'StopSendingDataComfirmed are queued in the mMessages but not
-    // dispatched.
-    eStateDisentangling,
-
-    // When 'StopSendingDataConfirmed' is received, we can disentangle the port
-    // calling SendDisentangle in the actor because we are 100% sure that we
-    // don't receive any other message, so nothing will be lost.
-    // Disentangling the port we send all the messages from the mMessages
-    // though the actor.
-    eStateDisentangled
-  };
-
-  void Initialize(const nsID& aUUID, const nsID& aDestinationUUID,
-                  uint32_t aSequenceID, bool mNeutered, State aState,
-                  ErrorResult& aRv);
-
-  void ConnectToPBackground();
-
   // Dispatch events from the Message Queue using a nsRunnable.
   void Dispatch();
 
-  void StartDisentangling();
-  void Disentangle();
-
-  void RemoveDocFromBFCache();
-
-  // This method is meant to keep alive the MessagePort when this object is
-  // creating the actor and until the actor is entangled.
-  // We release the object when the port is closed or disentangled.
-  void UpdateMustKeepAlive();
-
-  nsAutoPtr<workers::WorkerFeature> mWorkerFeature;
-
   nsRefPtr<DispatchEventRunnable> mDispatchRunnable;
 
-  nsRefPtr<MessagePortChild> mActor;
-
-  nsRefPtr<MessagePort> mUnshippedEntangledPort;
-
-  nsTArray<nsRefPtr<SharedMessagePortMessage>> mMessages;
-  nsTArray<nsRefPtr<SharedMessagePortMessage>> mMessagesForTheOtherPort;
-
-  nsAutoPtr<MessagePortIdentifier> mIdentifier;
-
-  uint64_t mInnerID;
+  nsRefPtr<MessagePort> mEntangledPort;
 
-  State mState;
-
-  // This 'nextStep' is used when we are waiting to be entangled but the
-  // content has called Clone() or Close().
-  enum {
-    eNextStepNone,
-    eNextStepDisentangle,
-    eNextStepClose
-  } mNextStep;
-
+  nsTArray<nsRefPtr<PostMessageRunnable> > mMessageQueue;
   bool mMessageQueueEnabled;
-
-  bool mIsKeptAlive;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_MessagePort_h
rename from dom/messagechannel/MessagePortList.cpp
rename to dom/base/MessagePortList.cpp
rename from dom/messagechannel/MessagePortList.h
rename to dom/base/MessagePortList.h
--- a/dom/base/NodeInfo.cpp
+++ b/dom/base/NodeInfo.cpp
@@ -106,17 +106,17 @@ NodeInfo::NodeInfo(nsIAtom *aName, nsIAt
 
 
 // nsISupports
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(NodeInfo)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_0(NodeInfo)
 
-static const char* kNodeInfoNSURIs[] = {
+static const char* kNSURIs[] = {
   " ([none])",
   " (xmlns)",
   " (xml)",
   " (xhtml)",
   " (XLink)",
   " (XSLT)",
   " (XBL)",
   " (MathML)",
@@ -124,18 +124,18 @@ static const char* kNodeInfoNSURIs[] = {
   " (XUL)"
 };
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(NodeInfo)
   if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
     char name[72];
     uint32_t nsid = tmp->NamespaceID();
     nsAtomCString localName(tmp->NameAtom());
-    if (nsid < ArrayLength(kNodeInfoNSURIs)) {
-      PR_snprintf(name, sizeof(name), "NodeInfo%s %s", kNodeInfoNSURIs[nsid],
+    if (nsid < ArrayLength(kNSURIs)) {
+      PR_snprintf(name, sizeof(name), "NodeInfo%s %s", kNSURIs[nsid],
                   localName.get());
     }
     else {
       PR_snprintf(name, sizeof(name), "NodeInfo %s", localName.get());
     }
 
     cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name);
   }
deleted file mode 100644
--- a/dom/base/PostMessageEvent.cpp
+++ /dev/null
@@ -1,389 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "PostMessageEvent.h"
-
-#include "MessageEvent.h"
-#include "mozilla/dom/BlobBinding.h"
-#include "mozilla/dom/MessagePort.h"
-#include "mozilla/dom/MessagePortBinding.h"
-#include "mozilla/dom/PMessagePort.h"
-#include "mozilla/dom/StructuredCloneTags.h"
-#include "mozilla/EventDispatcher.h"
-#include "nsGlobalWindow.h"
-#include "nsIPresShell.h"
-#include "nsIPrincipal.h"
-
-namespace mozilla {
-namespace dom {
-
-namespace {
-
-struct StructuredCloneInfo
-{
-  PostMessageEvent* event;
-  bool subsumes;
-  nsPIDOMWindow* window;
-
-  // This hashtable contains the transferred ports - used to avoid duplicates.
-  nsTArray<nsRefPtr<MessagePortBase>> transferredPorts;
-
-  // This array is populated when the ports are cloned.
-  nsTArray<nsRefPtr<MessagePortBase>> clonedPorts;
-};
-
-} // anonymous namespace
-
-const JSStructuredCloneCallbacks PostMessageEvent::sPostMessageCallbacks = {
-  PostMessageEvent::ReadStructuredClone,
-  PostMessageEvent::WriteStructuredClone,
-  nullptr,
-  PostMessageEvent::ReadTransferStructuredClone,
-  PostMessageEvent::TransferStructuredClone,
-  PostMessageEvent::FreeTransferStructuredClone
-};
-
-/* static */ JSObject*
-PostMessageEvent::ReadStructuredClone(JSContext* cx,
-                                      JSStructuredCloneReader* reader,
-                                      uint32_t tag,
-                                      uint32_t data,
-                                      void* closure)
-{
-  StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(closure);
-  NS_ASSERTION(scInfo, "Must have scInfo!");
-
-  if (tag == SCTAG_DOM_BLOB) {
-    NS_ASSERTION(!data, "Data should be empty");
-
-    // What we get back from the reader is a BlobImpl.
-    // From that we create a new File.
-    BlobImpl* blobImpl;
-    if (JS_ReadBytes(reader, &blobImpl, sizeof(blobImpl))) {
-      MOZ_ASSERT(blobImpl);
-
-      // nsRefPtr<File> needs to go out of scope before toObjectOrNull() is
-      // called because the static analysis thinks dereferencing XPCOM objects
-      // can GC (because in some cases it can!), and a return statement with a
-      // JSObject* type means that JSObject* is on the stack as a raw pointer
-      // while destructors are running.
-      JS::Rooted<JS::Value> val(cx);
-      {
-        nsRefPtr<Blob> blob = Blob::Create(scInfo->window, blobImpl);
-        if (!ToJSValue(cx, blob, &val)) {
-          return nullptr;
-        }
-      }
-
-      return &val.toObject();
-    }
-  }
-
-  if (tag == SCTAG_DOM_FILELIST) {
-    NS_ASSERTION(!data, "Data should be empty");
-
-    nsISupports* supports;
-    if (JS_ReadBytes(reader, &supports, sizeof(supports))) {
-      JS::Rooted<JS::Value> val(cx);
-      if (NS_SUCCEEDED(nsContentUtils::WrapNative(cx, supports, &val))) {
-        return val.toObjectOrNull();
-      }
-    }
-  }
-
-  const JSStructuredCloneCallbacks* runtimeCallbacks =
-    js::GetContextStructuredCloneCallbacks(cx);
-
-  if (runtimeCallbacks) {
-    return runtimeCallbacks->read(cx, reader, tag, data, nullptr);
-  }
-
-  return nullptr;
-}
-
-/* static */ bool
-PostMessageEvent::WriteStructuredClone(JSContext* cx,
-                                       JSStructuredCloneWriter* writer,
-                                       JS::Handle<JSObject*> obj,
-                                       void *closure)
-{
-  StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(closure);
-  NS_ASSERTION(scInfo, "Must have scInfo!");
-
-  // See if this is a File/Blob object.
-  {
-    Blob* blob = nullptr;
-    if (scInfo->subsumes && NS_SUCCEEDED(UNWRAP_OBJECT(Blob, obj, blob))) {
-      BlobImpl* blobImpl = blob->Impl();
-      if (JS_WriteUint32Pair(writer, SCTAG_DOM_BLOB, 0) &&
-          JS_WriteBytes(writer, &blobImpl, sizeof(blobImpl))) {
-        scInfo->event->StoreISupports(blobImpl);
-        return true;
-      }
-    }
-  }
-
-  nsCOMPtr<nsIXPConnectWrappedNative> wrappedNative;
-  nsContentUtils::XPConnect()->
-    GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wrappedNative));
-  if (wrappedNative) {
-    uint32_t scTag = 0;
-    nsISupports* supports = wrappedNative->Native();
-
-    nsCOMPtr<nsIDOMFileList> list = do_QueryInterface(supports);
-    if (list && scInfo->subsumes)
-      scTag = SCTAG_DOM_FILELIST;
-
-    if (scTag)
-      return JS_WriteUint32Pair(writer, scTag, 0) &&
-             JS_WriteBytes(writer, &supports, sizeof(supports)) &&
-             scInfo->event->StoreISupports(supports);
-  }
-
-  const JSStructuredCloneCallbacks* runtimeCallbacks =
-    js::GetContextStructuredCloneCallbacks(cx);
-
-  if (runtimeCallbacks) {
-    return runtimeCallbacks->write(cx, writer, obj, nullptr);
-  }
-
-  return false;
-}
-
-/* static */ bool
-PostMessageEvent::ReadTransferStructuredClone(JSContext* aCx,
-                                              JSStructuredCloneReader* reader,
-                                              uint32_t tag, void* aData,
-                                              uint64_t aExtraData,
-                                              void* aClosure,
-                                              JS::MutableHandle<JSObject*> returnObject)
-{
-  StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(aClosure);
-  NS_ASSERTION(scInfo, "Must have scInfo!");
-
-  if (tag == SCTAG_DOM_MAP_MESSAGEPORT) {
-    MOZ_ASSERT(!aData);
-    // aExtraData is the index of this port identifier.
-    ErrorResult rv;
-    nsRefPtr<MessagePort> port =
-      MessagePort::Create(scInfo->window,
-                          scInfo->event->GetPortIdentifier(aExtraData),
-                          rv);
-    if (NS_WARN_IF(rv.Failed())) {
-      return false;
-    }
-
-    scInfo->clonedPorts.AppendElement(port);
-
-    JS::Rooted<JS::Value> value(aCx);
-    if (!GetOrCreateDOMReflector(aCx, port, &value)) {
-      JS_ClearPendingException(aCx);
-      return false;
-    }
-
-    returnObject.set(&value.toObject());
-    return true;
-  }
-
-  return false;
-}
-
-/* static */ bool
-PostMessageEvent::TransferStructuredClone(JSContext* aCx,
-                                          JS::Handle<JSObject*> aObj,
-                                          void* aClosure,
-                                          uint32_t* aTag,
-                                          JS::TransferableOwnership* aOwnership,
-                                          void** aContent,
-                                          uint64_t* aExtraData)
-{
-  StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(aClosure);
-  NS_ASSERTION(scInfo, "Must have scInfo!");
-
-  MessagePortBase* port = nullptr;
-  nsresult rv = UNWRAP_OBJECT(MessagePort, aObj, port);
-  if (NS_SUCCEEDED(rv)) {
-    if (scInfo->transferredPorts.Contains(port)) {
-      // No duplicates.
-      return false;
-    }
-
-    // We use aExtraData to store the index of this new port identifier.
-    MessagePortIdentifier* identifier =
-      scInfo->event->NewPortIdentifier(aExtraData);
-
-    if (!port->CloneAndDisentangle(*identifier)) {
-      return false;
-    }
-
-    scInfo->transferredPorts.AppendElement(port);
-
-    *aTag = SCTAG_DOM_MAP_MESSAGEPORT;
-    *aOwnership = JS::SCTAG_TMO_CUSTOM;
-    *aContent = nullptr;
-
-    return true;
-  }
-
-  return false;
-}
-
-/* static */ void
-PostMessageEvent::FreeTransferStructuredClone(uint32_t aTag,
-                                              JS::TransferableOwnership aOwnership,
-                                              void *aContent,
-                                              uint64_t aExtraData,
-                                              void* aClosure)
-{
-  // Nothing to do.
-}
-
-PostMessageEvent::PostMessageEvent(nsGlobalWindow* aSource,
-                                   const nsAString& aCallerOrigin,
-                                   nsGlobalWindow* aTargetWindow,
-                                   nsIPrincipal* aProvidedPrincipal,
-                                   bool aTrustedCaller)
-: mSource(aSource),
-  mCallerOrigin(aCallerOrigin),
-  mTargetWindow(aTargetWindow),
-  mProvidedPrincipal(aProvidedPrincipal),
-  mTrustedCaller(aTrustedCaller)
-{
-  MOZ_COUNT_CTOR(PostMessageEvent);
-}
-
-PostMessageEvent::~PostMessageEvent()
-{
-  MOZ_COUNT_DTOR(PostMessageEvent);
-}
-
-const MessagePortIdentifier&
-PostMessageEvent::GetPortIdentifier(uint64_t aId)
-{
-  MOZ_ASSERT(aId < mPortIdentifiers.Length());
-  return mPortIdentifiers[aId];
-}
-
-MessagePortIdentifier*
-PostMessageEvent::NewPortIdentifier(uint64_t* aPosition)
-{
-  *aPosition = mPortIdentifiers.Length();
-  return mPortIdentifiers.AppendElement();
-}
-
-NS_IMETHODIMP
-PostMessageEvent::Run()
-{
-  MOZ_ASSERT(mTargetWindow->IsOuterWindow(),
-             "should have been passed an outer window!");
-  MOZ_ASSERT(!mSource || mSource->IsOuterWindow(),
-             "should have been passed an outer window!");
-
-  AutoJSAPI jsapi;
-  jsapi.Init();
-  JSContext* cx = jsapi.cx();
-
-  // If we bailed before this point we're going to leak mMessage, but
-  // that's probably better than crashing.
-
-  nsRefPtr<nsGlobalWindow> targetWindow;
-  if (mTargetWindow->IsClosedOrClosing() ||
-      !(targetWindow = mTargetWindow->GetCurrentInnerWindowInternal()) ||
-      targetWindow->IsClosedOrClosing())
-    return NS_OK;
-
-  MOZ_ASSERT(targetWindow->IsInnerWindow(),
-             "we ordered an inner window!");
-  JSAutoCompartment ac(cx, targetWindow->GetWrapperPreserveColor());
-
-  // Ensure that any origin which might have been provided is the origin of this
-  // window's document.  Note that we do this *now* instead of when postMessage
-  // is called because the target window might have been navigated to a
-  // different location between then and now.  If this check happened when
-  // postMessage was called, it would be fairly easy for a malicious webpage to
-  // intercept messages intended for another site by carefully timing navigation
-  // of the target window so it changed location after postMessage but before
-  // now.
-  if (mProvidedPrincipal) {
-    // Get the target's origin either from its principal or, in the case the
-    // principal doesn't carry a URI (e.g. the system principal), the target's
-    // document.
-    nsIPrincipal* targetPrin = targetWindow->GetPrincipal();
-    if (NS_WARN_IF(!targetPrin))
-      return NS_OK;
-
-    // Note: This is contrary to the spec with respect to file: URLs, which
-    //       the spec groups into a single origin, but given we intentionally
-    //       don't do that in other places it seems better to hold the line for
-    //       now.  Long-term, we want HTML5 to address this so that we can
-    //       be compliant while being safer.
-    if (!targetPrin->Equals(mProvidedPrincipal)) {
-      return NS_OK;
-    }
-  }
-
-  // Deserialize the structured clone data
-  JS::Rooted<JS::Value> messageData(cx);
-  StructuredCloneInfo scInfo;
-  scInfo.event = this;
-  scInfo.window = targetWindow;
-
-  if (!mBuffer.read(cx, &messageData, &sPostMessageCallbacks, &scInfo)) {
-    return NS_ERROR_DOM_DATA_CLONE_ERR;
-  }
-
-  // Create the event
-  nsCOMPtr<mozilla::dom::EventTarget> eventTarget =
-    do_QueryInterface(static_cast<nsPIDOMWindow*>(targetWindow.get()));
-  nsRefPtr<MessageEvent> event =
-    new MessageEvent(eventTarget, nullptr, nullptr);
-
-  event->InitMessageEvent(NS_LITERAL_STRING("message"), false /*non-bubbling */,
-                          false /*cancelable */, messageData, mCallerOrigin,
-                          EmptyString(), mSource);
-
-  event->SetPorts(new MessagePortList(static_cast<dom::Event*>(event.get()),
-                                      scInfo.clonedPorts));
-
-  // We can't simply call dispatchEvent on the window because doing so ends
-  // up flipping the trusted bit on the event, and we don't want that to
-  // happen because then untrusted content can call postMessage on a chrome
-  // window if it can get a reference to it.
-
-  nsIPresShell *shell = targetWindow->GetExtantDoc()->GetShell();
-  nsRefPtr<nsPresContext> presContext;
-  if (shell)
-    presContext = shell->GetPresContext();
-
-  event->SetTrusted(mTrustedCaller);
-  WidgetEvent* internalEvent = event->GetInternalNSEvent();
-
-  nsEventStatus status = nsEventStatus_eIgnore;
-  EventDispatcher::Dispatch(static_cast<nsPIDOMWindow*>(mTargetWindow),
-                            presContext,
-                            internalEvent,
-                            static_cast<dom::Event*>(event.get()),
-                            &status);
-  return NS_OK;
-}
-
-bool
-PostMessageEvent::Write(JSContext* aCx, JS::Handle<JS::Value> aMessage,
-                        JS::Handle<JS::Value> aTransfer, bool aSubsumes,
-                        nsPIDOMWindow* aWindow)
-{
-  // We *must* clone the data here, or the JS::Value could be modified
-  // by script
-  StructuredCloneInfo scInfo;
-  scInfo.event = this;
-  scInfo.window = aWindow;
-
-  return mBuffer.write(aCx, aMessage, aTransfer, &sPostMessageCallbacks,
-                       &scInfo);
-}
-
-} // dom namespace
-} // mozilla namespace
deleted file mode 100644
--- a/dom/base/PostMessageEvent.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_PostMessageEvent_h
-#define mozilla_dom_PostMessageEvent_h
-
-#include "js/StructuredClone.h"
-#include "nsCOMPtr.h"
-#include "nsRefPtr.h"
-#include "nsTArray.h"
-
-class nsGlobalWindow;
-class nsIPrincipal;
-
-namespace mozilla {
-namespace dom {
-
-class MessagePortBase;
-class MessagePortIdentifier;
-
-/**
- * Class used to represent events generated by calls to Window.postMessage,
- * which asynchronously creates and dispatches events.
- */
-class PostMessageEvent final : public nsRunnable
-{
-public:
-  NS_DECL_NSIRUNNABLE
-
-  PostMessageEvent(nsGlobalWindow* aSource,
-                   const nsAString& aCallerOrigin,
-                   nsGlobalWindow* aTargetWindow,
-                   nsIPrincipal* aProvidedPrincipal,
-                   bool aTrustedCaller);
-
-  bool Write(JSContext* aCx, JS::Handle<JS::Value> aMessage,
-             JS::Handle<JS::Value> aTransfer, bool aSubsumes,
-             nsPIDOMWindow* aWindow);
-
-private:
-  ~PostMessageEvent();
-
-  const MessagePortIdentifier& GetPortIdentifier(uint64_t aId);
-
-  MessagePortIdentifier* NewPortIdentifier(uint64_t* aPosition);
-
-  bool StoreISupports(nsISupports* aSupports)
-  {
-    mSupportsArray.AppendElement(aSupports);
-    return true;
-  }
-
-  static JSObject*
-  ReadStructuredClone(JSContext* cx,
-                      JSStructuredCloneReader* reader,
-                      uint32_t tag,
-                      uint32_t data,
-                      void* closure);
-
-  static bool
-  WriteStructuredClone(JSContext* cx,
-                       JSStructuredCloneWriter* writer,
-                       JS::Handle<JSObject*> obj,
-                       void *closure);
-
-  static bool
-  ReadTransferStructuredClone(JSContext* aCx,
-                              JSStructuredCloneReader* reader,
-                              uint32_t tag, void* aData,
-                              uint64_t aExtraData,
-                              void* aClosure,
-                              JS::MutableHandle<JSObject*> returnObject);
-
-  static bool
-  TransferStructuredClone(JSContext* aCx,
-                          JS::Handle<JSObject*> aObj,
-                          void* aClosure,
-                          uint32_t* aTag,
-                          JS::TransferableOwnership* aOwnership,
-                          void** aContent,
-                          uint64_t* aExtraData);
-
-  static void
-  FreeTransferStructuredClone(uint32_t aTag,
-                              JS::TransferableOwnership aOwnership,
-                              void *aContent,
-                              uint64_t aExtraData,
-                              void* aClosure);
-
-  static const JSStructuredCloneCallbacks sPostMessageCallbacks;
-
-  JSAutoStructuredCloneBuffer mBuffer;
-  nsRefPtr<nsGlobalWindow> mSource;
-  nsString mCallerOrigin;
-  nsRefPtr<nsGlobalWindow> mTargetWindow;
-  nsCOMPtr<nsIPrincipal> mProvidedPrincipal;
-  bool mTrustedCaller;
-  nsTArray<nsCOMPtr<nsISupports>> mSupportsArray;
-  nsTArray<MessagePortIdentifier> mPortIdentifiers;
-};
-
-} // dom namespace
-} // mozilla namespace
-
-#endif // mozilla_dom_PostMessageEvent_h
--- a/dom/base/ProcessGlobal.cpp
+++ b/dom/base/ProcessGlobal.cpp
@@ -2,17 +2,16 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ProcessGlobal.h"
 
 #include "nsContentCID.h"
-#include "nsDOMClassInfoID.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 ProcessGlobal::ProcessGlobal(nsFrameMessageManager* aMessageManager)
  : mInitialized(false),
    mMessageManager(aMessageManager)
 {
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -174,16 +174,19 @@ EXPORTS.mozilla.dom += [
     'ElementInlines.h',
     'EventSource.h',
     'File.h',
     'FragmentOrElement.h',
     'FromParser.h',
     'ImageEncoder.h',
     'ImportManager.h',
     'Link.h',
+    'MessageChannel.h',
+    'MessagePort.h',
+    'MessagePortList.h',
     'NameSpaceConstants.h',
     'Navigator.h',
     'NodeInfo.h',
     'NodeInfoInlines.h',
     'NodeIterator.h',
     'PerformanceEntry.h',
     'PerformanceMark.h',
     'PerformanceMeasure.h',
@@ -229,16 +232,18 @@ UNIFIED_SOURCES += [
     'Element.cpp',
     'EventSource.cpp',
     'File.cpp',
     'FileIOObject.cpp',
     'FragmentOrElement.cpp',
     'ImageEncoder.cpp',
     'ImportManager.cpp',
     'Link.cpp',
+    'MessageChannel.cpp',
+    'MessagePortList.cpp',
     'MultipartBlobImpl.cpp',
     'Navigator.cpp',
     'NodeInfo.cpp',
     'NodeIterator.cpp',
     'nsAtomListUtils.cpp',
     'nsAttrAndChildArray.cpp',
     'nsAttrValue.cpp',
     'nsAttrValueOrString.cpp',
@@ -319,17 +324,16 @@ UNIFIED_SOURCES += [
     'nsXHTMLContentSerializer.cpp',
     'nsXMLContentSerializer.cpp',
     'nsXMLHttpRequest.cpp',
     'nsXMLNameSpaceMap.cpp',
     'PerformanceEntry.cpp',
     'PerformanceMark.cpp',
     'PerformanceMeasure.cpp',
     'PerformanceResourceTiming.cpp',
-    'PostMessageEvent.cpp',
     'ProcessGlobal.cpp',
     'ResponsiveImageSelector.cpp',
     'SameProcessMessageQueue.cpp',
     'ScriptSettings.cpp',
     'ShadowRoot.cpp',
     'StyleSheetList.cpp',
     'SubtleCrypto.cpp',
     'Text.cpp',
@@ -344,16 +348,18 @@ UNIFIED_SOURCES += [
 
 if CONFIG['MOZ_WEBRTC']:
     UNIFIED_SOURCES += [
         'nsDOMDataChannel.cpp',
     ]
 
 # these files couldn't be in UNIFIED_SOURCES for now for reasons given below:
 SOURCES += [
+    # this file doesn't like windows.h
+    'MessagePort.cpp',
     # Because of OS X headers.
     'nsContentUtils.cpp',
     # this file doesn't like windows.h
     'nsDOMWindowUtils.cpp',
     # Conflicts with windows.h's definition of SendMessage.
     'nsFrameMessageManager.cpp',
     # This file has a #error "Never include windows.h in this file!"
     'nsGlobalWindow.cpp',
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -213,17 +213,16 @@ const char kLoadAsData[] = "loadAsData";
 
 nsIXPConnect *nsContentUtils::sXPConnect;
 nsIScriptSecurityManager *nsContentUtils::sSecurityManager;
 nsIPrincipal *nsContentUtils::sSystemPrincipal;
 nsIPrincipal *nsContentUtils::sNullSubjectPrincipal;
 nsIParserService *nsContentUtils::sParserService = nullptr;
 nsNameSpaceManager *nsContentUtils::sNameSpaceManager;
 nsIIOService *nsContentUtils::sIOService;
-nsIUUIDGenerator *nsContentUtils::sUUIDGenerator;
 nsIConsoleService *nsContentUtils::sConsoleService;
 nsDataHashtable<nsISupportsHashKey, EventNameMapping>* nsContentUtils::sAtomEventTable = nullptr;
 nsDataHashtable<nsStringHashKey, EventNameMapping>* nsContentUtils::sStringEventTable = nullptr;
 nsCOMArray<nsIAtom>* nsContentUtils::sUserDefinedEvents = nullptr;
 nsIStringBundleService *nsContentUtils::sStringBundleService;
 nsIStringBundle *nsContentUtils::sStringBundles[PropertiesFile_COUNT];
 nsIContentPolicy *nsContentUtils::sContentPolicyService;
 bool nsContentUtils::sTriedToGetContentPolicy = false;
@@ -547,23 +546,16 @@ nsContentUtils::Init()
 
 #if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
   Preferences::AddBoolVarCache(&sDOMWindowDumpEnabled,
                                "browser.dom.window.dump.enabled");
 #endif
 
   Element::InitCCCallbacks();
 
-  nsCOMPtr<nsIUUIDGenerator> uuidGenerator =
-    do_GetService("@mozilla.org/uuid-generator;1", &rv);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-  uuidGenerator.forget(&sUUIDGenerator);
-
   sInitialized = true;
 
   return NS_OK;
 }
 
 void
 nsContentUtils::GetShiftText(nsAString& text)
 {
@@ -1806,17 +1798,16 @@ nsContentUtils::Shutdown()
   NS_IF_RELEASE(sStringBundleService);
   NS_IF_RELEASE(sConsoleService);
   sXPConnect = nullptr;
   NS_IF_RELEASE(sSecurityManager);
   NS_IF_RELEASE(sSystemPrincipal);
   NS_IF_RELEASE(sNullSubjectPrincipal);
   NS_IF_RELEASE(sParserService);
   NS_IF_RELEASE(sIOService);
-  NS_IF_RELEASE(sUUIDGenerator);
   NS_IF_RELEASE(sLineBreaker);
   NS_IF_RELEASE(sWordBreaker);
   NS_IF_RELEASE(sBidiKeyboard);
 
   delete sAtomEventTable;
   sAtomEventTable = nullptr;
   delete sStringEventTable;
   sStringEventTable = nullptr;
@@ -7155,29 +7146,16 @@ nsContentUtils::IsJavascriptMIMEType(con
     if (aMIMEType.LowerCaseEqualsASCII(jsTypes[i])) {
       return true;
     }
   }
 
   return false;
 }
 
-nsresult
-nsContentUtils::GenerateUUIDInPlace(nsID& aUUID)
-{
-  MOZ_ASSERT(sUUIDGenerator);
-
-  nsresult rv = sUUIDGenerator->GenerateUUIDInPlace(&aUUID);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
-  return NS_OK;
-}
-
 uint64_t
 nsContentUtils::GetInnerWindowID(nsIRequest* aRequest)
 {
   // can't do anything if there's no nsIRequest!
   if (!aRequest) {
     return 0;
   }
 
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -80,17 +80,16 @@ class nsIRequest;
 class nsIRunnable;
 class nsIScriptContext;
 class nsIScriptSecurityManager;
 class nsIStringBundle;
 class nsIStringBundleService;
 class nsISupportsArray;
 class nsISupportsHashKey;
 class nsIURI;
-class nsIUUIDGenerator;
 class nsIWidget;
 class nsIWordBreaker;
 class nsIXPConnect;
 class nsNodeInfoManager;
 class nsPIDOMWindow;
 class nsPresContext;
 class nsStringBuffer;
 class nsStringHashKey;
@@ -849,21 +848,16 @@ public:
    * A helper function that parses a sandbox attribute (of an <iframe> or
    * a CSP directive) and converts it to the set of flags used internally.
    *
    * @param sandboxAttr   the sandbox attribute
    * @return              the set of flags (0 if sandboxAttr is null)
    */
   static uint32_t ParseSandboxAttributeToFlags(const nsAttrValue* sandboxAttr);
 
-  /**
-   * Helper function that generates a UUID.
-   */
-  static nsresult GenerateUUIDInPlace(nsID& aUUID);
-
 
   /**
    * Fill (with the parameters given) the localized string named |aKey| in
    * properties file |aFile|.
    */
 private:
   static nsresult FormatLocalizedString(PropertiesFile aFile,
                                         const char* aKey,
@@ -2439,17 +2433,16 @@ private:
   static nsIPrincipal *sSystemPrincipal;
   static nsIPrincipal *sNullSubjectPrincipal;
 
   static nsIParserService *sParserService;
 
   static nsNameSpaceManager *sNameSpaceManager;
 
   static nsIIOService *sIOService;
-  static nsIUUIDGenerator *sUUIDGenerator;
 
   static bool sImgLoaderInitialized;
   static void InitImgLoader();
 
   // The following four members are initialized lazily
   static imgLoader* sImgLoader;
   static imgLoader* sPrivateImgLoader;
   static imgICache* sImgCache;
--- a/dom/base/nsCopySupport.cpp
+++ b/dom/base/nsCopySupport.cpp
@@ -6,17 +6,16 @@
 
 #include "nsCopySupport.h"
 #include "nsIDocumentEncoder.h"
 #include "nsISupports.h"
 #include "nsIContent.h"
 #include "nsIComponentManager.h" 
 #include "nsIServiceManager.h"
 #include "nsIClipboard.h"
-#include "nsIFormControl.h"
 #include "nsISelection.h"
 #include "nsWidgetsCID.h"
 #include "nsXPCOM.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIDOMRange.h"
 #include "nsRange.h"
 #include "imgIContainer.h"
 #include "nsIPresShell.h"
--- a/dom/base/nsFrameMessageManager.cpp
+++ b/dom/base/nsFrameMessageManager.cpp
@@ -272,25 +272,25 @@ template<ActorFlavorEnum Flavor>
 static bool
 BuildClonedMessageData(typename BlobTraits<Flavor>::ConcreteContentManagerType* aManager,
                        const StructuredCloneData& aData,
                        ClonedMessageData& aClonedData)
 {
   SerializedStructuredCloneBuffer& buffer = aClonedData.data();
   buffer.data = aData.mData;
   buffer.dataLength = aData.mDataLength;
-  const nsTArray<nsRefPtr<BlobImpl>>& blobImpls = aData.mClosure.mBlobImpls;
-  if (!blobImpls.IsEmpty()) {
+  const nsTArray<nsRefPtr<Blob>>& blobs = aData.mClosure.mBlobs;
+  if (!blobs.IsEmpty()) {
     typedef typename BlobTraits<Flavor>::ProtocolType ProtocolType;
     InfallibleTArray<ProtocolType*>& blobList = DataBlobs<Flavor>::Blobs(aClonedData);
-    uint32_t length = blobImpls.Length();
+    uint32_t length = blobs.Length();
     blobList.SetCapacity(length);
     for (uint32_t i = 0; i < length; ++i) {
       typename BlobTraits<Flavor>::BlobType* protocolActor =
-        aManager->GetOrCreateActorForBlobImpl(blobImpls[i]);
+        aManager->GetOrCreateActorForBlob(blobs[i]);
       if (!protocolActor) {
         return false;
       }
       blobList.AppendElement(protocolActor);
     }
   }
   return true;
 }
@@ -318,26 +318,29 @@ UnpackClonedMessageData(const ClonedMess
   const SerializedStructuredCloneBuffer& buffer = aData.data();
   typedef typename BlobTraits<Flavor>::ProtocolType ProtocolType;
   const InfallibleTArray<ProtocolType*>& blobs = DataBlobs<Flavor>::Blobs(aData);
   StructuredCloneData cloneData;
   cloneData.mData = buffer.data;
   cloneData.mDataLength = buffer.dataLength;
   if (!blobs.IsEmpty()) {
     uint32_t length = blobs.Length();
-    cloneData.mClosure.mBlobImpls.SetCapacity(length);
+    cloneData.mClosure.mBlobs.SetCapacity(length);
     for (uint32_t i = 0; i < length; ++i) {
       auto* blob =
         static_cast<typename BlobTraits<Flavor>::BlobType*>(blobs[i]);
       MOZ_ASSERT(blob);
 
       nsRefPtr<BlobImpl> blobImpl = blob->GetBlobImpl();
       MOZ_ASSERT(blobImpl);
 
-      cloneData.mClosure.mBlobImpls.AppendElement(blobImpl);
+      // This object will be duplicated with a correct parent before being
+      // exposed to JS.
+      nsRefPtr<Blob> domBlob = Blob::Create(nullptr, blobImpl);
+      cloneData.mClosure.mBlobs.AppendElement(domBlob);
     }
   }
   return cloneData;
 }
 
 StructuredCloneData
 mozilla::dom::ipc::UnpackClonedMessageDataForParent(const ClonedMessageData& aData)
 {
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -54,28 +54,29 @@
 #include "mozilla/unused.h"
 
 // Other Classes
 #include "mozilla/dom/BarProps.h"
 #include "nsContentCID.h"
 #include "nsLayoutStatics.h"
 #include "nsCCUncollectableMarker.h"
 #include "mozilla/dom/workers/Workers.h"
+#include "mozilla/dom/MessagePortList.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "nsJSPrincipals.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Debug.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/ProcessHangMonitor.h"
 #include "AudioChannelService.h"
+#include "MessageEvent.h"
 #include "nsAboutProtocolUtils.h"
 #include "nsCharTraits.h" // NS_IS_HIGH/LOW_SURROGATE
-#include "PostMessageEvent.h"
 
 // Interfaces Needed
 #include "nsIFrame.h"
 #include "nsCanvasFrame.h"
 #include "nsIWidget.h"
 #include "nsIWidgetListener.h"
 #include "nsIBaseWindow.h"
 #include "nsIDeviceSensors.h"
@@ -173,19 +174,23 @@
 #include "nsFrameLoader.h"
 #include "nsISupportsPrimitives.h"
 #include "nsXPCOMCID.h"
 #include "mozilla/Logging.h"
 #include "prenv.h"
 #include "prprf.h"
 
 #include "mozilla/dom/MessageChannel.h"
+#include "mozilla/dom/MessagePort.h"
+#include "mozilla/dom/MessagePortBinding.h"
 #include "mozilla/dom/indexedDB/IDBFactory.h"
 #include "mozilla/dom/Promise.h"
 
+#include "mozilla/dom/StructuredCloneTags.h"
+
 #ifdef MOZ_GAMEPAD
 #include "mozilla/dom/Gamepad.h"
 #include "mozilla/dom/GamepadService.h"
 #endif
 
 #include "mozilla/dom/VRDevice.h"
 
 #include "nsRefreshDriver.h"
@@ -197,16 +202,17 @@
 #include "nsHTMLDocument.h"
 #include "nsWrapperCacheInlines.h"
 #include "mozilla/DOMEventTargetHelper.h"
 #include "prrng.h"
 #include "nsSandboxFlags.h"
 #include "TimeChangeObserver.h"
 #include "TouchCaret.h"
 #include "mozilla/dom/AudioContext.h"
+#include "mozilla/dom/BlobBinding.h"
 #include "mozilla/dom/BrowserElementDictionariesBinding.h"
 #include "mozilla/dom/cache/CacheStorage.h"
 #include "mozilla/dom/Console.h"
 #include "mozilla/dom/Fetch.h"
 #include "mozilla/dom/FunctionBinding.h"
 #include "mozilla/dom/HashChangeEvent.h"
 #include "mozilla/dom/MozSelfSupportBinding.h"
 #include "mozilla/dom/PopStateEvent.h"
@@ -8027,16 +8033,377 @@ nsGlobalWindow::CallerInnerWindow()
   }
 
   // The calling window must be holding a reference, so we can return a weak
   // pointer.
   nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(global);
   return static_cast<nsGlobalWindow*>(win.get());
 }
 
+/**
+ * Class used to represent events generated by calls to Window.postMessage,
+ * which asynchronously creates and dispatches events.
+ */
+class PostMessageEvent : public nsRunnable
+{
+  public:
+    NS_DECL_NSIRUNNABLE
+
+    PostMessageEvent(nsGlobalWindow* aSource,
+                     const nsAString& aCallerOrigin,
+                     nsGlobalWindow* aTargetWindow,
+                     nsIPrincipal* aProvidedPrincipal,
+                     bool aTrustedCaller)
+    : mSource(aSource),
+      mCallerOrigin(aCallerOrigin),
+      mTargetWindow(aTargetWindow),
+      mProvidedPrincipal(aProvidedPrincipal),
+      mTrustedCaller(aTrustedCaller)
+    {
+      MOZ_COUNT_CTOR(PostMessageEvent);
+    }
+
+protected:
+    ~PostMessageEvent()
+    {
+      MOZ_COUNT_DTOR(PostMessageEvent);
+    }
+
+public:
+    JSAutoStructuredCloneBuffer& Buffer()
+    {
+      return mBuffer;
+    }
+
+    bool StoreISupports(nsISupports* aSupports)
+    {
+      mSupportsArray.AppendElement(aSupports);
+      return true;
+    }
+
+  private:
+    JSAutoStructuredCloneBuffer mBuffer;
+    nsRefPtr<nsGlobalWindow> mSource;
+    nsString mCallerOrigin;
+    nsRefPtr<nsGlobalWindow> mTargetWindow;
+    nsCOMPtr<nsIPrincipal> mProvidedPrincipal;
+    bool mTrustedCaller;
+    nsTArray<nsCOMPtr<nsISupports> > mSupportsArray;
+};
+
+namespace {
+
+struct StructuredCloneInfo {
+  PostMessageEvent* event;
+  bool subsumes;
+  nsPIDOMWindow* window;
+  nsRefPtrHashtable<nsRefPtrHashKey<MessagePortBase>, MessagePortBase> ports;
+};
+
+static JSObject*
+PostMessageReadStructuredClone(JSContext* cx,
+                               JSStructuredCloneReader* reader,
+                               uint32_t tag,
+                               uint32_t data,
+                               void* closure)
+{
+  StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(closure);
+  NS_ASSERTION(scInfo, "Must have scInfo!");
+
+  if (tag == SCTAG_DOM_BLOB) {
+    NS_ASSERTION(!data, "Data should be empty");
+
+    // What we get back from the reader is a BlobImpl.
+    // From that we create a new File.
+    BlobImpl* blobImpl;
+    if (JS_ReadBytes(reader, &blobImpl, sizeof(blobImpl))) {
+      MOZ_ASSERT(blobImpl);
+
+      // nsRefPtr<File> needs to go out of scope before toObjectOrNull() is
+      // called because the static analysis thinks dereferencing XPCOM objects
+      // can GC (because in some cases it can!), and a return statement with a
+      // JSObject* type means that JSObject* is on the stack as a raw pointer
+      // while destructors are running.
+      JS::Rooted<JS::Value> val(cx);
+      {
+        nsRefPtr<Blob> blob = Blob::Create(scInfo->window, blobImpl);
+        if (!ToJSValue(cx, blob, &val)) {
+          return nullptr;
+        }
+      }
+
+      return &val.toObject();
+    }
+  }
+
+  if (tag == SCTAG_DOM_FILELIST) {
+    NS_ASSERTION(!data, "Data should be empty");
+
+    nsISupports* supports;
+    if (JS_ReadBytes(reader, &supports, sizeof(supports))) {
+      JS::Rooted<JS::Value> val(cx);
+      if (NS_SUCCEEDED(nsContentUtils::WrapNative(cx, supports, &val))) {
+        return val.toObjectOrNull();
+      }
+    }
+  }
+
+  const JSStructuredCloneCallbacks* runtimeCallbacks =
+    js::GetContextStructuredCloneCallbacks(cx);
+
+  if (runtimeCallbacks) {
+    return runtimeCallbacks->read(cx, reader, tag, data, nullptr);
+  }
+
+  return nullptr;
+}
+
+static bool
+PostMessageWriteStructuredClone(JSContext* cx,
+                                JSStructuredCloneWriter* writer,
+                                JS::Handle<JSObject*> obj,
+                                void *closure)
+{
+  StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(closure);
+  NS_ASSERTION(scInfo, "Must have scInfo!");
+
+  // See if this is a File/Blob object.
+  {
+    Blob* blob = nullptr;
+    if (scInfo->subsumes && NS_SUCCEEDED(UNWRAP_OBJECT(Blob, obj, blob))) {
+      BlobImpl* blobImpl = blob->Impl();
+      if (JS_WriteUint32Pair(writer, SCTAG_DOM_BLOB, 0) &&
+          JS_WriteBytes(writer, &blobImpl, sizeof(blobImpl))) {
+        scInfo->event->StoreISupports(blobImpl);
+        return true;
+      }
+    }
+  }
+
+  nsCOMPtr<nsIXPConnectWrappedNative> wrappedNative;
+  nsContentUtils::XPConnect()->
+    GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wrappedNative));
+  if (wrappedNative) {
+    uint32_t scTag = 0;
+    nsISupports* supports = wrappedNative->Native();
+
+    nsCOMPtr<nsIDOMFileList> list = do_QueryInterface(supports);
+    if (list && scInfo->subsumes)
+      scTag = SCTAG_DOM_FILELIST;
+
+    if (scTag)
+      return JS_WriteUint32Pair(writer, scTag, 0) &&
+             JS_WriteBytes(writer, &supports, sizeof(supports)) &&
+             scInfo->event->StoreISupports(supports);
+  }
+
+  const JSStructuredCloneCallbacks* runtimeCallbacks =
+    js::GetContextStructuredCloneCallbacks(cx);
+
+  if (runtimeCallbacks) {
+    return runtimeCallbacks->write(cx, writer, obj, nullptr);
+  }
+
+  return false;
+}
+
+static bool
+PostMessageReadTransferStructuredClone(JSContext* aCx,
+                                       JSStructuredCloneReader* reader,
+                                       uint32_t tag, void* aData,
+                                       uint64_t aExtraData,
+                                       void* aClosure,
+                                       JS::MutableHandle<JSObject*> returnObject)
+{
+  StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(aClosure);
+  NS_ASSERTION(scInfo, "Must have scInfo!");
+
+  if (tag == SCTAG_DOM_MAP_MESSAGEPORT) {
+    MessagePort* port = static_cast<MessagePort*>(aData);
+    port->BindToOwner(scInfo->window);
+    scInfo->ports.Put(port, nullptr);
+
+    JS::Rooted<JSObject*> obj(aCx, port->WrapObject(aCx, nullptr));
+    if (JS_WrapObject(aCx, &obj)) {
+      MOZ_ASSERT(port->GetOwner() == scInfo->window);
+      returnObject.set(obj);
+    }
+
+    return true;
+  }
+
+  return false;
+}
+
+static bool
+PostMessageTransferStructuredClone(JSContext* aCx,
+                                   JS::Handle<JSObject*> aObj,
+                                   void* aClosure,
+                                   uint32_t* aTag,
+                                   JS::TransferableOwnership* aOwnership,
+                                   void** aContent,
+                                   uint64_t* aExtraData)
+{
+  StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(aClosure);
+  NS_ASSERTION(scInfo, "Must have scInfo!");
+
+  MessagePortBase* port = nullptr;
+  nsresult rv = UNWRAP_OBJECT(MessagePort, aObj, port);
+  if (NS_SUCCEEDED(rv)) {
+    nsRefPtr<MessagePortBase> newPort;
+    if (scInfo->ports.Get(port, getter_AddRefs(newPort))) {
+      // No duplicate.
+      return false;
+    }
+
+    newPort = port->Clone();
+    scInfo->ports.Put(port, newPort);
+
+    *aTag = SCTAG_DOM_MAP_MESSAGEPORT;
+    *aOwnership = JS::SCTAG_TMO_CUSTOM;
+    *aContent = newPort;
+    *aExtraData = 0;
+
+    return true;
+  }
+
+  return false;
+}
+
+void
+PostMessageFreeTransferStructuredClone(uint32_t aTag, JS::TransferableOwnership aOwnership,
+                                       void *aContent, uint64_t aExtraData, void* aClosure)
+{
+  StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(aClosure);
+  NS_ASSERTION(scInfo, "Must have scInfo!");
+
+  if (aTag == SCTAG_DOM_MAP_MESSAGEPORT) {
+    nsRefPtr<MessagePortBase> port(static_cast<MessagePort*>(aContent));
+    scInfo->ports.Remove(port);
+  }
+}
+
+const JSStructuredCloneCallbacks kPostMessageCallbacks = {
+  PostMessageReadStructuredClone,
+  PostMessageWriteStructuredClone,
+  nullptr,
+  PostMessageReadTransferStructuredClone,
+  PostMessageTransferStructuredClone,
+  PostMessageFreeTransferStructuredClone
+};
+
+} // anonymous namespace
+
+static PLDHashOperator
+PopulateMessagePortList(MessagePortBase* aKey, MessagePortBase* aValue, void* aClosure)
+{
+  nsTArray<nsRefPtr<MessagePortBase> > *array =
+    static_cast<nsTArray<nsRefPtr<MessagePortBase> > *>(aClosure);
+
+  array->AppendElement(aKey);
+  return PL_DHASH_NEXT;
+}
+
+NS_IMETHODIMP
+PostMessageEvent::Run()
+{
+  MOZ_ASSERT(mTargetWindow->IsOuterWindow(),
+             "should have been passed an outer window!");
+  MOZ_ASSERT(!mSource || mSource->IsOuterWindow(),
+             "should have been passed an outer window!");
+
+  AutoJSAPI jsapi;
+  jsapi.Init();
+  JSContext* cx = jsapi.cx();
+
+  // If we bailed before this point we're going to leak mMessage, but
+  // that's probably better than crashing.
+
+  nsRefPtr<nsGlobalWindow> targetWindow;
+  if (mTargetWindow->IsClosedOrClosing() ||
+      !(targetWindow = mTargetWindow->GetCurrentInnerWindowInternal()) ||
+      targetWindow->IsClosedOrClosing())
+    return NS_OK;
+
+  MOZ_ASSERT(targetWindow->IsInnerWindow(),
+             "we ordered an inner window!");
+  JSAutoCompartment ac(cx, targetWindow->GetWrapperPreserveColor());
+
+  // Ensure that any origin which might have been provided is the origin of this
+  // window's document.  Note that we do this *now* instead of when postMessage
+  // is called because the target window might have been navigated to a
+  // different location between then and now.  If this check happened when
+  // postMessage was called, it would be fairly easy for a malicious webpage to
+  // intercept messages intended for another site by carefully timing navigation
+  // of the target window so it changed location after postMessage but before
+  // now.
+  if (mProvidedPrincipal) {
+    // Get the target's origin either from its principal or, in the case the
+    // principal doesn't carry a URI (e.g. the system principal), the target's
+    // document.
+    nsIPrincipal* targetPrin = targetWindow->GetPrincipal();
+    if (NS_WARN_IF(!targetPrin))
+      return NS_OK;
+
+    // Note: This is contrary to the spec with respect to file: URLs, which
+    //       the spec groups into a single origin, but given we intentionally
+    //       don't do that in other places it seems better to hold the line for
+    //       now.  Long-term, we want HTML5 to address this so that we can
+    //       be compliant while being safer.
+    if (!targetPrin->Equals(mProvidedPrincipal)) {
+      return NS_OK;
+    }
+  }
+
+  // Deserialize the structured clone data
+  JS::Rooted<JS::Value> messageData(cx);
+  StructuredCloneInfo scInfo;
+  scInfo.event = this;
+  scInfo.window = targetWindow;
+
+  if (!mBuffer.read(cx, &messageData, &kPostMessageCallbacks, &scInfo)) {
+    return NS_ERROR_DOM_DATA_CLONE_ERR;
+  }
+
+  // Create the event
+  nsCOMPtr<mozilla::dom::EventTarget> eventTarget =
+    do_QueryInterface(static_cast<nsPIDOMWindow*>(targetWindow.get()));
+  nsRefPtr<MessageEvent> event =
+    new MessageEvent(eventTarget, nullptr, nullptr);
+
+  event->InitMessageEvent(NS_LITERAL_STRING("message"), false /*non-bubbling */,
+                          false /*cancelable */, messageData, mCallerOrigin,
+                          EmptyString(), mSource);
+
+  nsTArray<nsRefPtr<MessagePortBase> > ports;
+  scInfo.ports.EnumerateRead(PopulateMessagePortList, &ports);
+  event->SetPorts(new MessagePortList(static_cast<dom::Event*>(event.get()), ports));
+
+  // We can't simply call dispatchEvent on the window because doing so ends
+  // up flipping the trusted bit on the event, and we don't want that to
+  // happen because then untrusted content can call postMessage on a chrome
+  // window if it can get a reference to it.
+
+  nsIPresShell *shell = targetWindow->mDoc->GetShell();
+  nsRefPtr<nsPresContext> presContext;
+  if (shell)
+    presContext = shell->GetPresContext();
+
+  event->SetTrusted(mTrustedCaller);
+  WidgetEvent* internalEvent = event->GetInternalNSEvent();
+
+  nsEventStatus status = nsEventStatus_eIgnore;
+  EventDispatcher::Dispatch(static_cast<nsPIDOMWindow*>(mTargetWindow),
+                            presContext,
+                            internalEvent,
+                            static_cast<dom::Event*>(event.get()),
+                            &status);
+  return NS_OK;
+}
+
 void
 nsGlobalWindow::PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
                                const nsAString& aTargetOrigin,
                                JS::Handle<JS::Value> aTransfer,
                                ErrorResult& aError)
 {
   FORWARD_TO_OUTER_OR_THROW(PostMessageMoz,
                             (aCx, aMessage, aTargetOrigin, aTransfer, aError),
@@ -8150,23 +8517,28 @@ nsGlobalWindow::PostMessageMoz(JSContext
     new PostMessageEvent(nsContentUtils::IsCallerChrome() || !callerInnerWin
                          ? nullptr
                          : callerInnerWin->GetOuterWindowInternal(),
                          origin,
                          this,
                          providedPrincipal,
                          nsContentUtils::IsCallerChrome());
 
+  // We *must* clone the data here, or the JS::Value could be modified
+  // by script
+  StructuredCloneInfo scInfo;
+  scInfo.event = event;
+  scInfo.window = this;
+
   nsIPrincipal* principal = GetPrincipal();
   JS::Rooted<JS::Value> message(aCx, aMessage);
   JS::Rooted<JS::Value> transfer(aCx, aTransfer);
-  bool subsumes;
-
-  if (NS_FAILED(callerPrin->Subsumes(principal, &subsumes)) ||
-      !event->Write(aCx, message, transfer, subsumes, this)) {
+  if (NS_FAILED(callerPrin->Subsumes(principal, &scInfo.subsumes)) ||
+      !event->Buffer().write(aCx, message, transfer, &kPostMessageCallbacks,
+                             &scInfo)) {
     aError.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
     return;
   }
 
   aError = NS_DispatchToCurrentThread(event);
 }
 
 void
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -106,17 +106,16 @@ class External;
 class Function;
 class Gamepad;
 class VRDevice;
 class MediaQueryList;
 class MozSelfSupport;
 class Navigator;
 class OwningExternalOrWindowProxy;
 class Promise;
-class PostMessageEvent;
 struct RequestInit;
 class RequestOrUSVString;
 class Selection;
 class SpeechSynthesis;
 class WakeLock;
 namespace cache {
 class CacheStorage;
 } // namespace cache
@@ -1748,17 +1747,17 @@ protected:
   bool                                       mVRDevicesInitialized;
   // The VRDevies for this window
   nsTArray<nsRefPtr<mozilla::dom::VRDevice>> mVRDevices;
   // Any attached HMD when fullscreen
   nsRefPtr<mozilla::gfx::VRHMDInfo>          mVRHMDInfo;
 
   friend class nsDOMScriptableHelper;
   friend class nsDOMWindowUtils;
-  friend class mozilla::dom::PostMessageEvent;
+  friend class PostMessageEvent;
   friend class DesktopNotification;
 
   static WindowByIdTable* sWindowsById;
   static bool sWarnedAboutWindowInternal;
 };
 
 inline nsISupports*
 ToSupports(nsGlobalWindow *p)
--- a/dom/base/test/chrome.ini
+++ b/dom/base/test/chrome.ini
@@ -8,16 +8,17 @@ support-files =
   file_bug1008126_worker.js
 
 [test_anonymousContent_xul_window.xul]
 [test_bug715041.xul]
 [test_bug715041_removal.xul]
 [test_domrequesthelper.xul]
 [test_url.xul]
 [test_console.xul]
+[test_messageChannel.xul]
 [test_navigator_resolve_identity_xrays.xul]
 [test_sendQueryContentAndSelectionSetEvent.html]
 [test_bug1016960.html]
 [test_bug357450.js]
 [test_copypaste.xul]
 [test_messagemanager_principal.html]
 [test_messagemanager_send_principal.html]
 skip-if = buildapp == 'mulet'
rename from dom/messagechannel/tests/iframe_messageChannel_chrome.html
rename to dom/base/test/iframe_messageChannel_chrome.html
rename from dom/messagechannel/tests/iframe_messageChannel_cloning.html
rename to dom/base/test/iframe_messageChannel_cloning.html
rename from dom/messagechannel/tests/iframe_messageChannel_pingpong.html
rename to dom/base/test/iframe_messageChannel_pingpong.html
rename from dom/messagechannel/tests/iframe_messageChannel_post.html
rename to dom/base/test/iframe_messageChannel_post.html
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -1,14 +1,18 @@
 [DEFAULT]
 support-files =
   audio.ogg
   iframe_bug976673.html
   iframe_main_bug1022229.html
   iframe_sandbox_bug1022229.html
+  iframe_messageChannel_cloning.html
+  iframe_messageChannel_chrome.html
+  iframe_messageChannel_pingpong.html
+  iframe_messageChannel_post.html
   file_empty.html
   iframe_postMessage_solidus.html
   file_setname.html
   345339_iframe.html
   Ahem.ttf
   accesscontrol.resource
   accesscontrol.resource^headers^
   badContentType.eventsource
@@ -277,17 +281,25 @@ skip-if = buildapp == 'mulet' || buildap
 [test_gsp-standards.html]
 [test_getFeature_with_perm.html]
 [test_getFeature_without_perm.html]
 [test_hasFeature.html]
 [test_history_document_open.html]
 [test_history_state_null.html]
 [test_Image_constructor.html]
 [test_innersize_scrollport.html]
+[test_messageChannel.html]
+[test_messageChannel_cloning.html]
+[test_messageChannel_pingpong.html]
+[test_messageChannel_post.html]
+[test_messageChannel_pref.html]
+[test_messageChannel_start.html]
 [test_messagemanager_targetchain.html]
+[test_messageChannel_transferable.html]
+[test_messageChannel_unshipped.html]
 [test_named_frames.html]
 [test_navigator_resolve_identity.html]
 [test_navigator_language.html]
 [test_openDialogChromeOnly.html]
 [test_open_null_features.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Fails on b2g-desktop, tracked in bug 1011874
 [test_postMessage_solidus.html]
 [test_screen_orientation.html]
rename from dom/messagechannel/tests/test_messageChannel.html
rename to dom/base/test/test_messageChannel.html
rename from dom/messagechannel/tests/test_messageChannel.xul
rename to dom/base/test/test_messageChannel.xul
--- a/dom/messagechannel/tests/test_messageChannel.xul
+++ b/dom/base/test/test_messageChannel.xul
@@ -18,17 +18,17 @@
   ok(channel, "MessageChannel is created");
 
   channel.port1.onmessage = function(evt) {
     ok(true, "message received!");
     SimpleTest.finish();
   }
 
   var ifr = document.createElement('browser');
-  ifr.setAttribute("src", "iframe_messageChannel_chrome.html");
+  ifr.setAttribute("src", "http://mochi.test:8888/tests/dom/base/test/iframe_messageChannel_chrome.html");
   ifr.setAttribute("flex", "1");
   ifr.addEventListener('load', function() {
     ifr.contentWindow.postMessage(channel.port2, '*', [channel.port2]);
   });
 
   var body = document.getElementById("body");
   body.appendChild(ifr);
 
rename from dom/messagechannel/tests/test_messageChannel_cloning.html
rename to dom/base/test/test_messageChannel_cloning.html
rename from dom/messagechannel/tests/test_messageChannel_pingpong.html
rename to dom/base/test/test_messageChannel_pingpong.html
rename from dom/messagechannel/tests/test_messageChannel_post.html
rename to dom/base/test/test_messageChannel_post.html
rename from dom/messagechannel/tests/test_messageChannel_pref.html
rename to dom/base/test/test_messageChannel_pref.html
rename from dom/messagechannel/tests/test_messageChannel_start.html
rename to dom/base/test/test_messageChannel_start.html
rename from dom/messagechannel/tests/test_messageChannel_transferable.html
rename to dom/base/test/test_messageChannel_transferable.html
--- a/dom/messagechannel/tests/test_messageChannel_transferable.html
+++ b/dom/base/test/test_messageChannel_transferable.html
@@ -11,25 +11,24 @@ https://bugzilla.mozilla.org/show_bug.cg
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=677638">Mozilla Bug 677638</a>
 <div id="content"></div>
 <pre id="test">
 </pre>
   <script type="application/javascript">
 
-  function basic_test() {
+  function start() {
     var a = new MessageChannel();
     ok(a, "MessageChannel created");
 
     window.addEventListener('message', receiveMessage, false);
     function receiveMessage(evt) {
       if (evt.data.status == 'READY') {
-        a.port1.postMessage({ab: ab, cb: ab}, [ab]);
-        ok(ab.byteLength == 0, "PostMessage - The size is: 0 == " + ab.byteLength)
+        runTest();
       } else {
         ok(false, "Unknown message");
       }
     }
 
     var div = document.getElementById("content");
     ok(div, "Parent exists");
 
@@ -40,72 +39,29 @@ https://bugzilla.mozilla.org/show_bug.cg
 
     function iframeLoaded() {
       ifr.contentWindow.postMessage({ port: a.port2 }, '*', [a.port2]);
     }
 
     a.port1.addEventListener('message', receivePortMessage, false);
     function receivePortMessage(evt) {
       is(evt.data.ab.byteLength, size, "The size is: " + size + " == " + ab.byteLength);
-      window.removeEventListener('message', receiveMessage);
-      runTests();
+      SimpleTest.finish();
     }
 
     // Start() is not implicity invoked when addEventListener is used.
     a.port1.start();
 
     var size = 1024 * 1024 * 32;
     var ab = new ArrayBuffer(size);
     is(ab.byteLength, size, "The size is: " + size + " == " + ab.byteLength);
-  }
 
-  function port_test() {
-    window.addEventListener('message', receiveMessage, false);
-    function receiveMessage(evt) {
-      ok(evt.data.type == 'OK', evt.data.msg);
-    }
-
-    var a = new MessageChannel();
-    ok(a, "MessageChannel created");
-
-    var div = document.getElementById("content");
-    ok(div, "Parent exists");
-
-    var ifr = document.createElement("iframe");
-    ifr.addEventListener("load", iframeLoaded, false);
-    ifr.setAttribute('src', "iframe_messageChannel_transferable.html");
-    div.appendChild(ifr);
-
-    function iframeLoaded() {
-      ifr.contentWindow.postMessage('foobar!', '*', [a.port2]);
-    }
-
-    a.port1.onmessage = function(evt) {
-      ok(evt.ports.length == 1, "Iframe sent a new port!");
-      evt.ports[0].onmessage = function(evt) {
-        is(evt.data, "hello world!", "Message sent and received!");
-        runTests();
-      }
-
-      evt.ports[0].postMessage("hello world!");
+    function runTest() {
+      a.port1.postMessage({ab: ab, cb: ab}, [ab]);
+      ok(ab.byteLength == 0, "PostMessage - The size is: 0 == " + ab.byteLength)
     }
   }
 
-  var tests = [
-    basic_test,
-    port_test
-  ];
-
-  function runTests() {
-    if (!tests.length) {
-      SimpleTest.finish();
-      return;
-    }
-
-    var t = tests.shift();
-    t();
-  }
-
   SimpleTest.waitForExplicitFinish();
-  SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTests);
+  SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, start);
   </script>
 </body>
 </html>
rename from dom/messagechannel/tests/test_messageChannel_unshipped.html
rename to dom/base/test/test_messageChannel_unshipped.html
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -724,16 +724,19 @@ DOMInterfaces = {
 
 'MediaRecorder': {
     'headerFile': 'MediaRecorder.h',
 },
 
 'MessagePort': {
     'nativeType': 'mozilla::dom::MessagePortBase',
     'headerFile': 'mozilla/dom/MessagePort.h',
+    'binaryNames': {
+        'postMessage': 'postMessageMoz',
+    },
 },
 
 'MimeType': {
     'headerFile' : 'nsMimeTypeArray.h',
     'nativeType': 'nsMimeType',
 },
 
 'MimeTypeArray': {
--- a/dom/broadcastchannel/BroadcastChannel.cpp
+++ b/dom/broadcastchannel/BroadcastChannel.cpp
@@ -207,25 +207,24 @@ public:
 
     SerializedStructuredCloneBuffer& buffer = message.data();
     buffer.data = mData->mBuffer.data();
     buffer.dataLength = mData->mBuffer.nbytes();
 
     PBackgroundChild* backgroundManager = mActor->Manager();
     MOZ_ASSERT(backgroundManager);
 
-    const nsTArray<nsRefPtr<BlobImpl>>& blobImpls = mData->mClosure.mBlobImpls;
-
-    if (!blobImpls.IsEmpty()) {
-      message.blobsChild().SetCapacity(blobImpls.Length());
+    const nsTArray<nsRefPtr<Blob>>& blobs = mData->mClosure.mBlobs;
 
-      for (uint32_t i = 0, len = blobImpls.Length(); i < len; ++i) {
+    if (!blobs.IsEmpty()) {
+      message.blobsChild().SetCapacity(blobs.Length());
+
+      for (uint32_t i = 0, len = blobs.Length(); i < len; ++i) {
         PBlobChild* blobChild =
-          BackgroundChild::GetOrCreateActorForBlobImpl(backgroundManager,
-                                                       blobImpls[i]);
+          BackgroundChild::GetOrCreateActorForBlob(backgroundManager, blobs[i]);
         MOZ_ASSERT(blobChild);
 
         message.blobsChild().AppendElement(blobChild);
       }
     }
 
     mActor->SendPostMessage(message);
     return NS_OK;
@@ -537,19 +536,19 @@ BroadcastChannel::PostMessageInternal(JS
 {
   nsRefPtr<BroadcastChannelMessage> data = new BroadcastChannelMessage();
 
   if (!WriteStructuredClone(aCx, aMessage, data->mBuffer, data->mClosure)) {
     aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
     return;
   }
 
-  const nsTArray<nsRefPtr<BlobImpl>>& blobImpls = data->mClosure.mBlobImpls;
-  for (uint32_t i = 0, len = blobImpls.Length(); i < len; ++i) {
-    if (!blobImpls[i]->MayBeClonedToOtherThreads()) {
+  const nsTArray<nsRefPtr<Blob>>& blobs = data->mClosure.mBlobs;
+  for (uint32_t i = 0, len = blobs.Length(); i < len; ++i) {
+    if (!blobs[i]->Impl()->MayBeClonedToOtherThreads()) {
       aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
       return;
     }
   }
 
   PostMessageData(data);
 }
 
--- a/dom/broadcastchannel/BroadcastChannelChild.cpp
+++ b/dom/broadcastchannel/BroadcastChannelChild.cpp
@@ -37,25 +37,26 @@ BroadcastChannelChild::~BroadcastChannel
   MOZ_ASSERT(!mBC);
 }
 
 bool
 BroadcastChannelChild::RecvNotify(const ClonedMessageData& aData)
 {
   // Make sure to retrieve all blobs from the message before returning to avoid
   // leaking their actors.
-  nsTArray<nsRefPtr<BlobImpl>> blobs;
+  nsTArray<nsRefPtr<Blob>> blobs;
   if (!aData.blobsChild().IsEmpty()) {
     blobs.SetCapacity(aData.blobsChild().Length());
 
     for (uint32_t i = 0, len = aData.blobsChild().Length(); i < len; ++i) {
       nsRefPtr<BlobImpl> impl =
         static_cast<BlobChild*>(aData.blobsChild()[i])->GetBlobImpl();
 
-      blobs.AppendElement(impl);
+      nsRefPtr<Blob> blob = Blob::Create(mBC ? mBC->GetOwner() : nullptr, impl);
+      blobs.AppendElement(blob);
     }
   }
 
   nsCOMPtr<DOMEventTargetHelper> helper = mBC;
   nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(helper);
 
   // This object has been already closed by content or is going to be deleted
   // soon. No notify is required.
@@ -86,17 +87,17 @@ BroadcastChannelChild::RecvNotify(const 
   }
 
   JSContext* cx = jsapi.cx();
 
   const SerializedStructuredCloneBuffer& buffer = aData.data();
   StructuredCloneData cloneData;
   cloneData.mData = buffer.data;
   cloneData.mDataLength = buffer.dataLength;
-  cloneData.mClosure.mBlobImpls.SwapElements(blobs);
+  cloneData.mClosure.mBlobs.SwapElements(blobs);
 
   JS::Rooted<JS::Value> value(cx, JS::NullValue());
   if (cloneData.mDataLength && !ReadStructuredClone(cx, cloneData, &value)) {
     JS_ClearPendingException(cx);
     return false;
   }
 
   RootedDictionary<MessageEventInit> init(cx);
--- a/dom/ipc/StructuredCloneUtils.cpp
+++ b/dom/ipc/StructuredCloneUtils.cpp
@@ -45,33 +45,33 @@ Read(JSContext* aCx, JSStructuredCloneRe
   if (aTag == SCTAG_DOM_BLOB) {
     // nsRefPtr<File> needs to go out of scope before toObjectOrNull() is
     // called because the static analysis thinks dereferencing XPCOM objects
     // can GC (because in some cases it can!), and a return statement with a
     // JSObject* type means that JSObject* is on the stack as a raw pointer
     // while destructors are running.
     JS::Rooted<JS::Value> val(aCx);
     {
-      MOZ_ASSERT(aData < closure->mBlobImpls.Length());
-      nsRefPtr<BlobImpl> blobImpl = closure->mBlobImpls[aData];
+      MOZ_ASSERT(aData < closure->mBlobs.Length());
+      nsRefPtr<Blob> blob = closure->mBlobs[aData];
 
 #ifdef DEBUG
       {
         // Blob should not be mutable.
         bool isMutable;
-        MOZ_ASSERT(NS_SUCCEEDED(blobImpl->GetMutable(&isMutable)));
+        MOZ_ASSERT(NS_SUCCEEDED(blob->GetMutable(&isMutable)));
         MOZ_ASSERT(!isMutable);
       }
 #endif
 
       // Let's create a new blob with the correct parent.
       nsIGlobalObject *global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx));
       MOZ_ASSERT(global);
 
-      nsRefPtr<Blob> newBlob = Blob::Create(global, blobImpl);
+      nsRefPtr<Blob> newBlob = Blob::Create(global, blob->Impl());
       if (!ToJSValue(aCx, newBlob, &val)) {
         return nullptr;
       }
     }
 
     return &val.toObject();
   }
 
@@ -88,18 +88,18 @@ Write(JSContext* aCx, JSStructuredCloneW
     static_cast<StructuredCloneClosure*>(aClosure);
 
   // See if the wrapped native is a File/Blob.
   {
     Blob* blob = nullptr;
     if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob, aObj, blob)) &&
         NS_SUCCEEDED(blob->SetMutable(false)) &&
         JS_WriteUint32Pair(aWriter, SCTAG_DOM_BLOB,
-                           closure->mBlobImpls.Length())) {
-      closure->mBlobImpls.AppendElement(blob->Impl());
+                           closure->mBlobs.Length())) {
+      closure->mBlobs.AppendElement(blob);
       return true;
     }
   }
 
   return NS_DOMWriteStructuredClone(aCx, aWriter, aObj, nullptr);
 }
 
 const JSStructuredCloneCallbacks gCallbacks = {
--- a/dom/ipc/StructuredCloneUtils.h
+++ b/dom/ipc/StructuredCloneUtils.h
@@ -14,17 +14,17 @@
 #include "js/StructuredClone.h"
 
 namespace mozilla {
 namespace dom {
 
 struct
 StructuredCloneClosure
 {
-  nsTArray<nsRefPtr<BlobImpl>> mBlobImpls;
+  nsTArray<nsRefPtr<Blob>> mBlobs;
 };
 
 struct
 StructuredCloneData
 {
   StructuredCloneData() : mData(nullptr), mDataLength(0) {}
   uint64_t* mData;
   size_t mDataLength;
deleted file mode 100644
--- a/dom/messagechannel/MessagePortChild.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "MessagePortChild.h"
-#include "MessagePort.h"
-#include "mozilla/dom/MessageEvent.h"
-#include "mozilla/ipc/PBackgroundChild.h"
-
-namespace mozilla {
-namespace dom {
-
-bool
-MessagePortChild::RecvStopSendingDataConfirmed()
-{
-  MOZ_ASSERT(mPort);
-  mPort->StopSendingDataConfirmed();
-  MOZ_ASSERT(!mPort);
-  return true;
-}
-
-bool
-MessagePortChild::RecvEntangled(nsTArray<MessagePortMessage>&& aMessages)
-{
-  MOZ_ASSERT(mPort);
-  mPort->Entangled(aMessages);
-  return true;
-}
-
-bool
-MessagePortChild::RecvReceiveData(nsTArray<MessagePortMessage>&& aMessages)
-{
-  MOZ_ASSERT(mPort);
-  mPort->MessagesReceived(aMessages);
-  return true;
-}
-
-void
-MessagePortChild::ActorDestroy(ActorDestroyReason aWhy)
-{
-  if (mPort) {
-    mPort->Closed();
-    MOZ_ASSERT(!mPort);
-  }
-}
-
-} // dom namespace
-} // mozilla namespace
deleted file mode 100644
--- a/dom/messagechannel/MessagePortChild.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_MessagePortChild_h
-#define mozilla_dom_MessagePortChild_h
-
-#include "mozilla/Assertions.h"
-#include "mozilla/dom/PMessagePortChild.h"
-#include "nsISupportsImpl.h"
-
-namespace mozilla {
-namespace dom {
-
-class MessagePort;
-
-class MessagePortChild final : public PMessagePortChild
-{
-public:
-  NS_INLINE_DECL_REFCOUNTING(MessagePortChild)
-
-  MessagePortChild() {}
-
-  void SetPort(MessagePort* aPort)
-  {
-    mPort = aPort;
-  }
-
-private:
-  ~MessagePortChild()
-  {
-    MOZ_ASSERT(!mPort);
-  }
-
-  virtual bool
-  RecvEntangled(nsTArray<MessagePortMessage>&& aMessages) override;
-
-  virtual bool
-  RecvReceiveData(nsTArray<MessagePortMessage>&& aMessages) override;
-
-  virtual bool RecvStopSendingDataConfirmed() override;
-
-  virtual void ActorDestroy(ActorDestroyReason aWhy) override;
-
-  // This is a raw pointer because this child is owned by this MessagePort.
-  MessagePort* mPort;
-};
-
-} // dom namespace
-} // mozilla namespace
-
-#endif // mozilla_dom_MessagePortChild_h
deleted file mode 100644
--- a/dom/messagechannel/MessagePortParent.cpp
+++ /dev/null
@@ -1,163 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "MessagePortParent.h"
-#include "MessagePortService.h"
-#include "SharedMessagePortMessage.h"
-#include "mozilla/unused.h"
-
-namespace mozilla {
-namespace dom {
-
-MessagePortParent::MessagePortParent(const nsID& aUUID)
-  : mService(MessagePortService::GetOrCreate())
-  , mUUID(aUUID)
-  , mEntangled(false)
-  , mCanSendData(true)
-{
-  MOZ_ASSERT(mService);
-}
-
-MessagePortParent::~MessagePortParent()
-{
-  MOZ_ASSERT(!mService);
-  MOZ_ASSERT(!mEntangled);
-}
-
-bool
-MessagePortParent::Entangle(const nsID& aDestinationUUID,
-                            const uint32_t& aSequenceID)
-{
-  if (!mService) {
-    NS_WARNING("Entangle is called after a shutdown!");
-    return false;
-  }
-
-  MOZ_ASSERT(!mEntangled);
-
-  return mService->RequestEntangling(this, aDestinationUUID, aSequenceID);
-}
-
-bool
-MessagePortParent::RecvPostMessages(nsTArray<MessagePortMessage>&& aMessages)
-{
-  // This converts the object in a data struct where we have BlobImpls.
-  FallibleTArray<nsRefPtr<SharedMessagePortMessage>> messages;
-  if (NS_WARN_IF(
-      !SharedMessagePortMessage::FromMessagesToSharedParent(aMessages,
-                                                            messages))) {
-    return false;
-  }
-
-  if (!mEntangled) {
-    return false;
-  }
-
-  if (!mService) {
-    NS_WARNING("Entangle is called after a shutdown!");
-    return false;
-  }
-
-  if (messages.IsEmpty()) {
-    return false;
-  }
-
-  return mService->PostMessages(this, messages);
-}
-
-bool
-MessagePortParent::RecvDisentangle(nsTArray<MessagePortMessage>&& aMessages)
-{
-  // This converts the object in a data struct where we have BlobImpls.
-  FallibleTArray<nsRefPtr<SharedMessagePortMessage>> messages;
-  if (NS_WARN_IF(
-      !SharedMessagePortMessage::FromMessagesToSharedParent(aMessages,
-                                                            messages))) {
-    return false;
-  }
-
-  if (!mEntangled) {
-    return false;
-  }
-
-  if (!mService) {
-    NS_WARNING("Entangle is called after a shutdown!");
-    return false;
-  }
-
-  if (!mService->DisentanglePort(this, messages)) {
-    return false;
-  }
-
-  CloseAndDelete();
-  return true;
-}
-
-bool
-MessagePortParent::RecvStopSendingData()
-{
-  if (!mEntangled) {
-    return true;
-  }
-
-  mCanSendData = false;
-  unused << SendStopSendingDataConfirmed();
-  return true;
-}
-
-bool
-MessagePortParent::RecvClose()
-{
-  if (mService) {
-    MOZ_ASSERT(mEntangled);
-
-    if (!mService->ClosePort(this)) {
-      return false;
-    }
-
-    Close();
-  }
-
-  MOZ_ASSERT(!mEntangled);
-
-  unused << Send__delete__(this);
-  return true;
-}
-
-void
-MessagePortParent::ActorDestroy(ActorDestroyReason aWhy)
-{
-  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.
-    nsRefPtr<MessagePortService> kungFuDeathGrip = mService;
-    mService->ParentDestroy(this);
-  }
-}
-
-bool
-MessagePortParent::Entangled(const nsTArray<MessagePortMessage>& aMessages)
-{
-  MOZ_ASSERT(!mEntangled);
-  mEntangled = true;
-  return SendEntangled(aMessages);
-}
-
-void
-MessagePortParent::CloseAndDelete()
-{
-  Close();
-  unused << Send__delete__(this);
-}
-
-void
-MessagePortParent::Close()
-{
-  mService = nullptr;
-  mEntangled = false;
-}
-
-} // dom namespace
-} // mozilla namespace
deleted file mode 100644
--- a/dom/messagechannel/MessagePortParent.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_MessagePortParent_h
-#define mozilla_dom_MessagePortParent_h
-
-#include "mozilla/dom/PMessagePortParent.h"
-
-namespace mozilla {
-namespace dom {
-
-class MessagePortService;
-
-class MessagePortParent final : public PMessagePortParent
-{
-public:
-  explicit MessagePortParent(const nsID& aUUID);
-  ~MessagePortParent();
-
-  bool Entangle(const nsID& aDestinationUUID,
-                const uint32_t& aSequenceID);
-
-  bool Entangled(const nsTArray<MessagePortMessage>& aMessages);
-
-  void Close();
-  void CloseAndDelete();
-
-  bool CanSendData() const
-  {
-    return mCanSendData;
-  }
-
-  const nsID& ID() const
-  {
-    return mUUID;
-  }
-
-private:
-  virtual bool RecvPostMessages(nsTArray<MessagePortMessage>&& aMessages)
-                                                                       override;
-
-  virtual bool RecvDisentangle(nsTArray<MessagePortMessage>&& aMessages)
-                                                                       override;
-
-  virtual bool RecvStopSendingData() override;
-
-  virtual bool RecvClose() override;
-
-  virtual void ActorDestroy(ActorDestroyReason aWhy) override;
-
-  nsRefPtr<MessagePortService> mService;
-  const nsID mUUID;
-  bool mEntangled;
-  bool mCanSendData;
-};
-
-} // dom namespace
-} // mozilla namespace
-
-#endif // mozilla_dom_MessagePortParent_h
deleted file mode 100644
--- a/dom/messagechannel/MessagePortService.cpp
+++ /dev/null
@@ -1,328 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "MessagePortService.h"
-#include "MessagePortParent.h"
-#include "SharedMessagePortMessage.h"
-#include "mozilla/StaticPtr.h"
-#include "mozilla/unused.h"
-#include "nsDataHashtable.h"
-#include "nsTArray.h"
-
-namespace mozilla {
-namespace dom {
-
-namespace {
-StaticRefPtr<MessagePortService> gInstance;
-} // anonymous namespace
-
-class MessagePortService::MessagePortServiceData final
-{
-public:
-  explicit MessagePortServiceData(const nsID& aDestinationUUID)
-    : mDestinationUUID(aDestinationUUID)
-    , mSequenceID(1)
-    , mParent(nullptr)
-  {
-    MOZ_COUNT_CTOR(MessagePortServiceData);
-  }
-
-  MessagePortServiceData(const MessagePortServiceData& aOther) = delete;
-  MessagePortServiceData& operator=(const MessagePortServiceData&) = delete;
-
-  ~MessagePortServiceData()
-  {
-    MOZ_COUNT_DTOR(MessagePortServiceData);
-  }
-
-  nsID mDestinationUUID;
-
-  uint32_t mSequenceID;
-  MessagePortParent* mParent;
-
-  struct NextParent
-  {
-    uint32_t mSequenceID;
-    // MessagePortParent keeps the service alive, and we don't want a cycle.
-    MessagePortParent* mParent;
-  };
-
-  FallibleTArray<NextParent> mNextParents;
-  FallibleTArray<nsRefPtr<SharedMessagePortMessage>> mMessages;
-};
-
-/* static */ MessagePortService*
-MessagePortService::GetOrCreate()
-{
-  if (!gInstance) {
-    gInstance = new MessagePortService();
-  }
-
-  return gInstance;
-}
-
-bool
-MessagePortService::RequestEntangling(MessagePortParent* aParent,
-                                      const nsID& aDestinationUUID,
-                                      const uint32_t& aSequenceID)
-{
-  MOZ_ASSERT(aParent);
-  MessagePortServiceData* data;
-
-  // If we don't have a MessagePortServiceData, we must create 2 of them for
-  // both ports.
-  if (!mPorts.Get(aParent->ID(), &data)) {
-    // Create the MessagePortServiceData for the destination.
-    if (mPorts.Get(aDestinationUUID, nullptr)) {
-      MOZ_ASSERT(false, "The creation of the 2 ports should be in sync.");
-      return false;
-    }
-
-    data = new MessagePortServiceData(aParent->ID());
-    mPorts.Put(aDestinationUUID, data);
-
-    data = new MessagePortServiceData(aDestinationUUID);
-    mPorts.Put(aParent->ID(), data);
-  }
-
-  // This is a security check.
-  if (!data->mDestinationUUID.Equals(aDestinationUUID)) {
-    MOZ_ASSERT(false, "DestinationUUIDs do not match!");
-    return false;
-  }
-
-  if (aSequenceID < data->mSequenceID) {
-    MOZ_ASSERT(false, "Invalid sequence ID!");
-    return false;
-  }
-
-  if (aSequenceID == data->mSequenceID) {
-    if (data->mParent) {
-      MOZ_ASSERT(false, "Two ports cannot have the same sequenceID.");
-      return false;
-    }
-
-    // We activate this port, sending all the messages.
-    data->mParent = aParent;
-    FallibleTArray<MessagePortMessage> array;
-    if (!SharedMessagePortMessage::FromSharedToMessagesParent(aParent,
-                                                              data->mMessages,
-                                                              array)) {
-      return false;
-    }
-
-    data->mMessages.Clear();
-    return aParent->Entangled(array);
-  }
-
-  // This new parent will be the next one when a Disentangle request is
-  // received from the current parent.
-  MessagePortServiceData::NextParent* nextParent =
-    data->mNextParents.AppendElement(mozilla::fallible);
-  if (!nextParent) {
-    return false;
-  }
-
-  nextParent->mSequenceID = aSequenceID;
-  nextParent->mParent = aParent;
-
-  return true;
-}
-
-bool
-MessagePortService::DisentanglePort(
-                  MessagePortParent* aParent,
-                  FallibleTArray<nsRefPtr<SharedMessagePortMessage>>& aMessages)
-{
-  MessagePortServiceData* data;
-  if (!mPorts.Get(aParent->ID(), &data)) {
-    MOZ_ASSERT(false, "Unknown MessagePortParent should not happen.");
-    return false;
-  }
-
-  if (data->mParent != aParent) {
-    MOZ_ASSERT(false, "DisentanglePort() should be called just from the correct parent.");
-    return false;
-  }
-
-  // Let's put the messages in the correct order. |aMessages| contains the
-  // unsent messages so they have to go first.
-  if (!aMessages.AppendElements(data->mMessages, mozilla::fallible)) {
-    return false;
-  }
-
-  data->mMessages.Clear();
-
-  ++data->mSequenceID;
-
-  // If we don't have a parent, we have to store the pending messages and wait.
-  uint32_t index = 0;
-  MessagePortParent* nextParent = nullptr;
-  for (; index < data->mNextParents.Length(); ++index) {
-    if (data->mNextParents[index].mSequenceID == data->mSequenceID) {
-      nextParent = data->mNextParents[index].mParent;
-      break;
-    }
-  }
-
-  // We didn't find the parent.
-  if (!nextParent) {
-    data->mMessages.SwapElements(aMessages);
-    data->mParent = nullptr;
-    return true;
-  }
-
-  data->mParent = nextParent;
-  data->mNextParents.RemoveElementAt(index);
-
-  FallibleTArray<MessagePortMessage> array;
-  if (!SharedMessagePortMessage::FromSharedToMessagesParent(data->mParent,
-                                                            aMessages,
-                                                            array)) {
-    return false;
-  }
-
-  unused << data->mParent->Entangled(array);
-  return true;
-}
-
-bool
-MessagePortService::ClosePort(MessagePortParent* aParent)
-{
-  MessagePortServiceData* data;
-  if (!mPorts.Get(aParent->ID(), &data)) {
-    MOZ_ASSERT(false, "Unknown MessagePortParent should not happend.");
-    return false;
-  }
-
-  if (data->mParent != aParent) {
-    MOZ_ASSERT(false, "ClosePort() should be called just from the correct parent.");
-    return false;
-  }
-
-  if (!data->mNextParents.IsEmpty()) {
-    MOZ_ASSERT(false, "ClosePort() should be called when there are not next parents.");
-    return false;
-  }
-
-  // We don't want to send a message to this parent.
-  data->mParent = nullptr;
-
-  CloseAll(aParent->ID());
-  return true;
-}
-
-#ifdef DEBUG
-PLDHashOperator
-MessagePortService::CloseAllDebugCheck(const nsID& aID,
-                                       MessagePortServiceData* aData,
-                                       void* aPtr)
-{
-  nsID* id = static_cast<nsID*>(aPtr);
-  MOZ_ASSERT(!id->Equals(aID));
-  return PL_DHASH_NEXT;
-}
-#endif
-
-void
-MessagePortService::CloseAll(const nsID& aUUID)
-{
-  MessagePortServiceData* data;
-  if (!mPorts.Get(aUUID, &data)) {
-    MaybeShutdown();
-    return;
-  }
-
-  if (data->mParent) {
-    data->mParent->Close();
-  }
-
-  for (const MessagePortServiceData::NextParent& parent : data->mNextParents) {
-    parent.mParent->CloseAndDelete();
-  }
-
-  nsID destinationUUID = data->mDestinationUUID;
-  mPorts.Remove(aUUID);
-
-  CloseAll(destinationUUID);
-
-#ifdef DEBUG
-  mPorts.EnumerateRead(CloseAllDebugCheck, const_cast<nsID*>(&aUUID));
-#endif
-
-  MaybeShutdown();
-}
-
-// This service can be dismissed when there are not active ports.
-void
-MessagePortService::MaybeShutdown()
-{
-  if (mPorts.Count() == 0) {
-    gInstance = nullptr;
-  }
-}
-
-bool
-MessagePortService::PostMessages(
-                  MessagePortParent* aParent,
-                  FallibleTArray<nsRefPtr<SharedMessagePortMessage>>& aMessages)
-{
-  MessagePortServiceData* data;
-  if (!mPorts.Get(aParent->ID(), &data)) {
-    MOZ_ASSERT(false, "Unknown MessagePortParent should not happend.");
-    return false;
-  }
-
-  if (data->mParent != aParent) {
-    MOZ_ASSERT(false, "PostMessages() should be called just from the correct parent.");
-    return false;
-  }
-
-  MOZ_ALWAYS_TRUE(mPorts.Get(data->mDestinationUUID, &data));
-
-  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<MessagePortMessage> messages;
-    if (!SharedMessagePortMessage::FromSharedToMessagesParent(data->mParent,
-                                                              data->mMessages,
-                                                              messages)) {
-      return false;
-    }
-
-    data->mMessages.Clear();
-    unused << data->mParent->SendReceiveData(messages);
-  }
-
-  return true;
-}
-
-void
-MessagePortService::ParentDestroy(MessagePortParent* aParent)
-{
-  // This port has already been destroyed.
-  MessagePortServiceData* data;
-  if (!mPorts.Get(aParent->ID(), &data)) {
-    return;
-  }
-
-  if (data->mParent != aParent) {
-    // We don't want to send a message to this parent.
-    for (uint32_t i = 0; i < data->mNextParents.Length(); ++i) {
-      if (aParent == data->mNextParents[i].mParent) {
-       data->mNextParents.RemoveElementAt(i);
-       break;
-      }
-    }
-  }
-
-  CloseAll(aParent->ID());
-}
-
-} // dom namespace
-} // mozilla namespace
deleted file mode 100644
--- a/dom/messagechannel/MessagePortService.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_MessagePortService_h
-#define mozilla_dom_MessagePortService_h
-
-#include "nsClassHashtable.h"
-#include "nsHashKeys.h"
-#include "nsISupportsImpl.h"
-
-namespace mozilla {
-namespace dom {
-
-class MessagePortParent;
-class SharedMessagePortMessage;
-
-class MessagePortService final
-{
-public:
-  NS_INLINE_DECL_REFCOUNTING(MessagePortService)
-
-  static MessagePortService* GetOrCreate();
-
-  bool RequestEntangling(MessagePortParent* aParent,
-                         const nsID& aDestinationUUID,
-                         const uint32_t& aSequenceID);
-
-  bool DisentanglePort(
-                 MessagePortParent* aParent,
-                 FallibleTArray<nsRefPtr<SharedMessagePortMessage>>& aMessages);
-
-  bool ClosePort(MessagePortParent* aParent);
-
-  bool PostMessages(
-                 MessagePortParent* aParent,
-                 FallibleTArray<nsRefPtr<SharedMessagePortMessage>>& aMessages);
-
-  void ParentDestroy(MessagePortParent* aParent);
-
-private:
-  ~MessagePortService() {}
-
-  void CloseAll(const nsID& aUUID);
-  void MaybeShutdown();
-
-  class MessagePortServiceData;
-
-#ifdef DEBUG
-  static PLDHashOperator
-  CloseAllDebugCheck(const nsID& aID, MessagePortServiceData* aData,
-                     void* aPtr);
-#endif
-
-  nsClassHashtable<nsIDHashKey, MessagePortServiceData> mPorts;
-};
-
-} // dom namespace
-} // mozilla namespace
-
-#endif // mozilla_dom_MessagePortService_h
deleted file mode 100644
--- a/dom/messagechannel/MessagePortUtils.cpp
+++ /dev/null
@@ -1,277 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "MessagePortUtils.h"
-#include "MessagePort.h"
-#include "mozilla/dom/BlobBinding.h"
-#include "mozilla/dom/File.h"
-#include "mozilla/dom/MessagePortBinding.h"
-#include "mozilla/dom/StructuredCloneTags.h"
-
-namespace mozilla {
-namespace dom {
-namespace messageport {
-
-namespace {
-
-struct MOZ_STACK_CLASS StructuredCloneClosureInternal
-{
-  StructuredCloneClosureInternal(
-    StructuredCloneClosure& aClosure, nsPIDOMWindow* aWindow)
-    : mClosure(aClosure)
-    , mWindow(aWindow)
-  { }
-
-  StructuredCloneClosure& mClosure;
-  nsPIDOMWindow* mWindow;
-  nsTArray<nsRefPtr<MessagePort>> mMessagePorts;
-  nsTArray<nsRefPtr<MessagePortBase>> mTransferredPorts;
-};
-
-struct MOZ_STACK_CLASS StructuredCloneClosureInternalReadOnly
-{
-  StructuredCloneClosureInternalReadOnly(
-    const StructuredCloneClosure& aClosure, nsPIDOMWindow* aWindow)
-    : mClosure(aClosure)
-    , mWindow(aWindow)
-  { }
-
-  const StructuredCloneClosure& mClosure;
-  nsPIDOMWindow* mWindow;
-  nsTArray<nsRefPtr<MessagePort>> mMessagePorts;
-  nsTArray<nsRefPtr<MessagePortBase>> mTransferredPorts;
-};
-
-void
-Error(JSContext* aCx, uint32_t aErrorId)
-{
-  if (NS_IsMainThread()) {
-    NS_DOMStructuredCloneError(aCx, aErrorId);
-  } else {
-    Throw(aCx, NS_ERROR_DOM_DATA_CLONE_ERR);
-  }
-}
-
-JSObject*
-Read(JSContext* aCx, JSStructuredCloneReader* aReader, uint32_t aTag,
-     uint32_t aData, void* aClosure)
-{
-  MOZ_ASSERT(aClosure);
-
-  auto* closure = static_cast<StructuredCloneClosureInternalReadOnly*>(aClosure);
-
-  if (aTag == SCTAG_DOM_BLOB) {
-    // nsRefPtr<File> needs to go out of scope before toObjectOrNull() is
-    // called because the static analysis thinks dereferencing XPCOM objects
-    // can GC (because in some cases it can!), and a return statement with a
-    // JSObject* type means that JSObject* is on the stack as a raw pointer
-    // while destructors are running.
-    JS::Rooted<JS::Value> val(aCx);
-    {
-      MOZ_ASSERT(aData < closure->mClosure.mBlobImpls.Length());
-      nsRefPtr<BlobImpl> blobImpl = closure->mClosure.mBlobImpls[aData];
-
-#ifdef DEBUG
-      {
-        // Blob should not be mutable.
-        bool isMutable;
-        MOZ_ASSERT(NS_SUCCEEDED(blobImpl->GetMutable(&isMutable)));
-        MOZ_ASSERT(!isMutable);
-      }
-#endif
-
-      // Let's create a new blob with the correct parent.
-      nsIGlobalObject* global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx));
-      MOZ_ASSERT(global);
-
-      nsRefPtr<Blob> newBlob = Blob::Create(global, blobImpl);
-      if (!ToJSValue(aCx, newBlob, &val)) {
-        return nullptr;
-      }
-    }
-
-    return &val.toObject();
-  }
-
-  return NS_DOMReadStructuredClone(aCx, aReader, aTag, aData, nullptr);
-}
-
-bool
-Write(JSContext* aCx, JSStructuredCloneWriter* aWriter,
-      JS::Handle<JSObject*> aObj, void* aClosure)
-{
-  MOZ_ASSERT(aClosure);
-
-  auto* closure = static_cast<StructuredCloneClosureInternal*>(aClosure);
-
-  // See if the wrapped native is a File/Blob.
-  {
-    Blob* blob = nullptr;
-    if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob, aObj, blob)) &&
-        NS_SUCCEEDED(blob->SetMutable(false)) &&
-        JS_WriteUint32Pair(aWriter, SCTAG_DOM_BLOB,
-                           closure->mClosure.mBlobImpls.Length())) {
-      closure->mClosure.mBlobImpls.AppendElement(blob->Impl());
-      return true;
-    }
-  }
-
-  return NS_DOMWriteStructuredClone(aCx, aWriter, aObj, nullptr);
-}
-
-bool
-ReadTransfer(JSContext* aCx, JSStructuredCloneReader* aReader,
-             uint32_t aTag, void* aContent, uint64_t aExtraData,
-             void* aClosure, JS::MutableHandle<JSObject*> aReturnObject)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(aClosure);
-
-  auto* closure = static_cast<StructuredCloneClosureInternalReadOnly*>(aClosure);
-
-  if (aTag != SCTAG_DOM_MAP_MESSAGEPORT) {
-    return false;
-  }
-
-  MOZ_ASSERT(aContent == 0);
-  MOZ_ASSERT(aExtraData < closure->mClosure.mMessagePortIdentifiers.Length());
-
-  ErrorResult rv;
-  nsRefPtr<MessagePort> port =
-    MessagePort::Create(closure->mWindow,
-                        closure->mClosure.mMessagePortIdentifiers[(uint32_t)aExtraData],
-                        rv);
-  if (NS_WARN_IF(rv.Failed())) {
-    return false;
-  }
-
-  closure->mMessagePorts.AppendElement(port);
-
-  JS::Rooted<JS::Value> value(aCx);
-  if (!GetOrCreateDOMReflector(aCx, port, &value)) {
-    JS_ClearPendingException(aCx);
-    return false;
-  }
-
-  aReturnObject.set(&value.toObject());
-  return true;
-}
-
-bool
-WriteTransfer(JSContext* aCx, JS::Handle<JSObject*> aObj, void* aClosure,
-              uint32_t* aTag, JS::TransferableOwnership* aOwnership,
-              void** aContent, uint64_t* aExtraData)
-{
-  MOZ_ASSERT(aClosure);
-
-  auto* closure = static_cast<StructuredCloneClosureInternal*>(aClosure);
-
-  MessagePortBase* port = nullptr;
-  nsresult rv = UNWRAP_OBJECT(MessagePort, aObj, port);
-  if (NS_FAILED(rv)) {
-    return false;
-  }
-
-  if (closure->mTransferredPorts.Contains(port)) {
-    // No duplicates.
-    return false;
-  }
-
-  MessagePortIdentifier identifier;
-  if (!port->CloneAndDisentangle(identifier)) {
-    return false;
-  }
-
-  closure->mClosure.mMessagePortIdentifiers.AppendElement(identifier);
-  closure->mTransferredPorts.AppendElement(port);
-
-  *aTag = SCTAG_DOM_MAP_MESSAGEPORT;
-  *aOwnership = JS::SCTAG_TMO_CUSTOM;
-  *aContent = nullptr;
-  *aExtraData = closure->mClosure.mMessagePortIdentifiers.Length() - 1;
-
-  return true;
-}
-
-const JSStructuredCloneCallbacks gCallbacks = {
-  Read,
-  Write,
-  Error,
-  ReadTransfer,
-  WriteTransfer,
-  nullptr
-};
-
-} // anonymous namespace
-
-bool
-ReadStructuredCloneWithTransfer(JSContext* aCx, nsTArray<uint8_t>& aData,
-                                const StructuredCloneClosure& aClosure,
-                                JS::MutableHandle<JS::Value> aClone,
-                                nsPIDOMWindow* aParentWindow,
-                                nsTArray<nsRefPtr<MessagePort>>& aMessagePorts)
-{
-  auto* data = reinterpret_cast<uint64_t*>(aData.Elements());
-  size_t dataLen = aData.Length();
-  MOZ_ASSERT(!(dataLen % sizeof(*data)));
-
-  StructuredCloneClosureInternalReadOnly internalClosure(aClosure,
-                                                         aParentWindow);
-
-  bool rv = JS_ReadStructuredClone(aCx, data, dataLen,
-                                   JS_STRUCTURED_CLONE_VERSION, aClone,
-                                   &gCallbacks, &internalClosure);
-  if (rv) {
-    aMessagePorts.SwapElements(internalClosure.mMessagePorts);
-  }
-
-  return rv;
-}
-
-bool
-WriteStructuredCloneWithTransfer(JSContext* aCx, JS::Handle<JS::Value> aSource,
-                                 JS::Handle<JS::Value> aTransferable,
-                                 nsTArray<uint8_t>& aData,
-                                 StructuredCloneClosure& aClosure)
-{
-  StructuredCloneClosureInternal internalClosure(aClosure, nullptr);
-  JSAutoStructuredCloneBuffer buffer(&gCallbacks, &internalClosure);
-
-  if (!buffer.write(aCx, aSource, aTransferable, &gCallbacks,
-                    &internalClosure)) {
-    return false;
-  }
-
-  FallibleTArray<uint8_t> cloneData;
-  if (NS_WARN_IF(!cloneData.SetLength(buffer.nbytes(), mozilla::fallible))) {
-    return false;
-  }
-
-  uint64_t* data;
-  size_t size;
-  buffer.steal(&data, &size);
-
-  memcpy(cloneData.Elements(), data, size);
-  js_free(data);
-
-  MOZ_ASSERT(aData.IsEmpty());
-  aData.SwapElements(cloneData);
-  return true;
-}
-
-void
-FreeStructuredClone(nsTArray<uint8_t>& aData, StructuredCloneClosure& aClosure)
-{
-  auto* data = reinterpret_cast<uint64_t*>(aData.Elements());
-  size_t dataLen = aData.Length();
-  MOZ_ASSERT(!(dataLen % sizeof(*data)));
-
-  JS_ClearStructuredClone(data, dataLen, &gCallbacks, &aClosure, false);
-  aData.Clear();
-}
-
-} // messageport namespace
-} // dom namespace
-} // mozilla namespace
deleted file mode 100644
--- a/dom/messagechannel/MessagePortUtils.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_MessagePortUtils_h
-#define mozilla_dom_MessagePortUtils_h
-
-#include "MessagePort.h"
-#include "mozilla/dom/File.h"
-#include "mozilla/dom/PMessagePort.h"
-
-class nsPIDOMWindow;
-
-namespace mozilla {
-namespace dom {
-namespace messageport {
-
-struct
-StructuredCloneClosure
-{
-  nsTArray<nsRefPtr<BlobImpl>> mBlobImpls;
-  nsTArray<MessagePortIdentifier> mMessagePortIdentifiers;
-};
-
-struct
-StructuredCloneData
-{
-  StructuredCloneData() : mData(nullptr), mDataLength(0) {}
-  uint64_t* mData;
-  size_t mDataLength;
-  StructuredCloneClosure mClosure;
-};
-
-bool
-ReadStructuredCloneWithTransfer(JSContext* aCx, nsTArray<uint8_t>& aData,
-                                const StructuredCloneClosure& aClosure,
-                                JS::MutableHandle<JS::Value> aClone,
-                                nsPIDOMWindow* aParentWindow,
-                                nsTArray<nsRefPtr<MessagePort>>& aMessagePorts);
-
-bool
-WriteStructuredCloneWithTransfer(JSContext* aCx, JS::Handle<JS::Value> aSource,
-                                 JS::Handle<JS::Value> aTransferable,
-                                 nsTArray<uint8_t>& aData,
-                                 StructuredCloneClosure& aClosure);
-
-void
-FreeStructuredClone(nsTArray<uint8_t>& aData,
-                    StructuredCloneClosure& aClosure);
-
-} // messageport namespace
-} // dom namespace
-} // mozilla namespace
-
-#endif // mozilla_dom_MessagePortUtils_h
deleted file mode 100644
--- a/dom/messagechannel/PMessagePort.ipdl
+++ /dev/null
@@ -1,62 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-include protocol PBackground;
-include protocol PBlob;
-
-using struct nsID from "nsID.h";
-
-namespace mozilla {
-namespace dom {
-
-struct MessagePortIdentifier
-{
-  nsID uuid;
-  nsID destinationUuid;
-  uint32_t sequenceId;
-  bool neutered;
-};
-
-struct MessagePortMessage
-{
-  MessagePortIdentifier[] transferredPorts;
-  uint8_t[] data;
-  PBlob[] blobs;
-};
-
-// 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();
-     2. RecvStopSendingDataConfirmed();
-     3. SendClose();
-     4. Recv__delete__(); */
-
-  /* When the port is transferred the sequence is:
-     1. SendStopSendingData();
-     2. RecvStopSendingDataConfirmed();
-     3. SendDisentangle();
-     4. Recv__delete__(); */
-
-parent:
-  PostMessages(MessagePortMessage[] messages);
-  Disentangle(MessagePortMessage[] messages);
-  StopSendingData();
-  Close();
-
-child:
-  Entangled(MessagePortMessage[] messages);
-  ReceiveData(MessagePortMessage[] messages);
-  StopSendingDataConfirmed();
-
-  __delete__();
-};
-
-} // namespace dom
-} // namespace mozilla
-
deleted file mode 100644
--- a/dom/messagechannel/SharedMessagePortMessage.cpp
+++ /dev/null
@@ -1,180 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "SharedMessagePortMessage.h"
-#include "MessagePort.h"
-#include "MessagePortChild.h"
-#include "MessagePortParent.h"
-#include "mozilla/dom/ipc/BlobChild.h"
-#include "mozilla/dom/ipc/BlobParent.h"
-#include "mozilla/dom/File.h"
-#include "mozilla/dom/PMessagePort.h"
-#include "mozilla/ipc/BackgroundChild.h"
-#include "mozilla/ipc/BackgroundParent.h"
-
-namespace mozilla {
-
-using namespace ipc;
-
-namespace dom {
-
-SharedMessagePortMessage::~SharedMessagePortMessage()
-{
-  if (!mData.IsEmpty()) {
-    FreeStructuredClone(mData, mClosure);
-  }
-}
-
-/* static */ void
-SharedMessagePortMessage::FromSharedToMessagesChild(
-                      MessagePortChild* aActor,
-                      const nsTArray<nsRefPtr<SharedMessagePortMessage>>& aData,
-                      nsTArray<MessagePortMessage>& aArray)
-{
-  MOZ_ASSERT(aActor);
-  MOZ_ASSERT(aArray.IsEmpty());
-  aArray.SetCapacity(aData.Length());
-
-  PBackgroundChild* backgroundManager = aActor->Manager();
-  MOZ_ASSERT(backgroundManager);
-
-  for (auto& data : aData) {
-    MessagePortMessage* message = aArray.AppendElement();
-    message->data().SwapElements(data->mData);
-
-    const nsTArray<nsRefPtr<BlobImpl>>& blobImpls =
-      data->mClosure.mBlobImpls;
-    if (!blobImpls.IsEmpty()) {
-      message->blobsChild().SetCapacity(blobImpls.Length());
-
-      for (uint32_t i = 0, len = blobImpls.Length(); i < len; ++i) {
-        PBlobChild* blobChild =
-          BackgroundChild::GetOrCreateActorForBlobImpl(backgroundManager,
-                                                       blobImpls[i]);
-        message->blobsChild().AppendElement(blobChild);
-      }
-    }
-
-    message->transferredPorts().AppendElements(
-      data->mClosure.mMessagePortIdentifiers);
-  }
-}
-
-/* static */ bool
-SharedMessagePortMessage::FromMessagesToSharedChild(
-                      nsTArray<MessagePortMessage>& aArray,
-                      FallibleTArray<nsRefPtr<SharedMessagePortMessage>>& aData)
-{
-  MOZ_ASSERT(aData.IsEmpty());
-
-  if (NS_WARN_IF(!aData.SetCapacity(aArray.Length(), mozilla::fallible))) {
-    return false;
-  }
-
-  for (auto& message : aArray) {
-    nsRefPtr<SharedMessagePortMessage> data = new SharedMessagePortMessage();
-
-    data->mData.SwapElements(message.data());
-
-    const nsTArray<PBlobChild*>& blobs = message.blobsChild();
-    if (!blobs.IsEmpty()) {
-      data->mClosure.mBlobImpls.SetCapacity(blobs.Length());
-
-      for (uint32_t i = 0, len = blobs.Length(); i < len; ++i) {
-        nsRefPtr<BlobImpl> impl =
-          static_cast<BlobChild*>(blobs[i])->GetBlobImpl();
-        data->mClosure.mBlobImpls.AppendElement(impl);
-      }
-    }
-
-    data->mClosure.mMessagePortIdentifiers.AppendElements(
-      message.transferredPorts());
-
-    if (!aData.AppendElement(data, mozilla::fallible)) {
-      return false;
-    }
-  }
-
-  return true;
-}
-
-/* static */ bool
-SharedMessagePortMessage::FromSharedToMessagesParent(
-                      MessagePortParent* aActor,
-                      const nsTArray<nsRefPtr<SharedMessagePortMessage>>& aData,
-                      FallibleTArray<MessagePortMessage>& 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) {
-    MessagePortMessage* message = aArray.AppendElement(mozilla::fallible);
-    message->data().SwapElements(data->mData);
-
-    const nsTArray<nsRefPtr<BlobImpl>>& blobImpls = data->mClosure.mBlobImpls;
-    if (!blobImpls.IsEmpty()) {
-      message->blobsParent().SetCapacity(blobImpls.Length());
-
-      for (uint32_t i = 0, len = blobImpls.Length(); i < len; ++i) {
-        PBlobParent* blobParent =
-          BackgroundParent::GetOrCreateActorForBlobImpl(backgroundManager,
-                                                        blobImpls[i]);
-        message->blobsParent().AppendElement(blobParent);
-      }
-    }
-
-    message->transferredPorts().AppendElements(
-      data->mClosure.mMessagePortIdentifiers);
-  }
-
-  return true;
-}
-
-/* static */ bool
-SharedMessagePortMessage::FromMessagesToSharedParent(
-                      nsTArray<MessagePortMessage>& aArray,
-                      FallibleTArray<nsRefPtr<SharedMessagePortMessage>>& aData)
-{
-  MOZ_ASSERT(aData.IsEmpty());
-
-  if (NS_WARN_IF(!aData.SetCapacity(aArray.Length(), mozilla::fallible))) {
-    return false;
-  }
-
-  for (auto& message : aArray) {
-    nsRefPtr<SharedMessagePortMessage> data = new SharedMessagePortMessage();
-
-    data->mData.SwapElements(message.data());
-
-    const nsTArray<PBlobParent*>& blobs = message.blobsParent();
-    if (!blobs.IsEmpty()) {
-      data->mClosure.mBlobImpls.SetCapacity(blobs.Length());
-
-      for (uint32_t i = 0, len = blobs.Length(); i < len; ++i) {
-        nsRefPtr<BlobImpl> impl =
-          static_cast<BlobParent*>(blobs[i])->GetBlobImpl();
-        data->mClosure.mBlobImpls.AppendElement(impl);
-      }
-    }
-
-    data->mClosure.mMessagePortIdentifiers.AppendElements(
-      message.transferredPorts());
-
-    if (!aData.AppendElement(data, mozilla::fallible)) {
-      return false;
-    }
-  }
-
-  return true;
-}
-
-} // dom namespace
-} // mozilla namespace
deleted file mode 100644
--- a/dom/messagechannel/SharedMessagePortMessage.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_SharedMessagePortMessage_h
-#define mozilla_dom_SharedMessagePortMessage_h
-
-#include "MessagePortUtils.h"
-
-namespace mozilla {
-namespace dom {
-
-class MessagePortChild;
-class MessagePortMessage;
-class MessagePortParent;
-
-class SharedMessagePortMessage final
-{
-public:
-  NS_INLINE_DECL_REFCOUNTING(SharedMessagePortMessage)
-
-  nsTArray<uint8_t> mData;
-  messageport::StructuredCloneClosure mClosure;
-
-  SharedMessagePortMessage()
-  {}
-
-  static void
-  FromSharedToMessagesChild(
-                      MessagePortChild* aActor,
-                      const nsTArray<nsRefPtr<SharedMessagePortMessage>>& aData,
-                      nsTArray<MessagePortMessage>& aArray);
-
-  static bool
-  FromMessagesToSharedChild(
-                     nsTArray<MessagePortMessage>& aArray,
-                     FallibleTArray<nsRefPtr<SharedMessagePortMessage>>& aData);
-
-  static bool
-  FromSharedToMessagesParent(
-                      MessagePortParent* aActor,
-                      const nsTArray<nsRefPtr<SharedMessagePortMessage>>& aData,
-                      FallibleTArray<MessagePortMessage>& aArray);
-
-  static bool
-  FromMessagesToSharedParent(
-                     nsTArray<MessagePortMessage>& aArray,
-                     FallibleTArray<nsRefPtr<SharedMessagePortMessage>>& aData);
-
-private:
-  ~SharedMessagePortMessage();
-};
-
-} // dom namespace
-} // mozilla namespace
-
-#endif // mozilla_dom_SharedMessagePortMessage_h
deleted file mode 100644
--- a/dom/messagechannel/moz.build
+++ /dev/null
@@ -1,41 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-TEST_DIRS += ['tests']
-
-EXPORTS.mozilla.dom += [
-    'MessageChannel.h',
-    'MessagePort.h',
-    'MessagePortChild.h',
-    'MessagePortList.h',
-    'MessagePortParent.h',
-]
-
-UNIFIED_SOURCES += [
-    'MessageChannel.cpp',
-    'MessagePort.cpp',
-    'MessagePortChild.cpp',
-    'MessagePortList.cpp',
-    'MessagePortParent.cpp',
-    'MessagePortService.cpp',
-    'MessagePortUtils.cpp',
-    'SharedMessagePortMessage.cpp',
-]
-
-IPDL_SOURCES += [
-    'PMessagePort.ipdl',
-]
-
-LOCAL_INCLUDES += [
-    '../base',
-    '../events',
-    '../workers',
-]
-
-include('/ipc/chromium/chromium-config.mozbuild')
-
-FINAL_LIBRARY = 'xul'
-FAIL_ON_WARNINGS = True
deleted file mode 100644
--- a/dom/messagechannel/tests/chrome.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[DEFAULT]
-support-files =
-  iframe_messageChannel_chrome.html
-
-[test_messageChannel.xul]
deleted file mode 100644
--- a/dom/messagechannel/tests/iframe_messageChannel_sharedWorker2.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<body>
-  <script type="application/javascript">
-
-  var a = new SharedWorker('sharedWorker2_messageChannel.js');
-  a.port.onmessage = function(evt) {
-    evt.ports[0].postMessage("Hello from the iframe!");
-  }
-
-  </script>
-</body>
-</html>
-
deleted file mode 100644
--- a/dom/messagechannel/tests/iframe_messageChannel_transferable.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<body>
-  <script type="application/javascript">
-
-  function ok(what, msg) {
-    window.parent.postMessage({type: what ? 'OK' : 'KO', msg: msg }, '*');
-  }
-
-  window.addEventListener('message', receiveMessage, false);
-  function receiveMessage(evt) {
-    ok(evt.ports.length == 1, "Port transferred!");
-
-    var a = new MessageChannel();
-    ok(a, "MessageChannel created");
-    evt.ports[0].postMessage('hello world!', [a.port2]);
-    a.port1.onmessage = function(evt) {
-      evt.target.postMessage(evt.data);
-    }
-  }
-
-  </script>
-</body>
-</html>
-
-
deleted file mode 100644
--- a/dom/messagechannel/tests/mochitest.ini
+++ /dev/null
@@ -1,25 +0,0 @@
-[DEFAULT]
-support-files =
-  iframe_messageChannel_cloning.html
-  iframe_messageChannel_pingpong.html
-  iframe_messageChannel_post.html
-  iframe_messageChannel_transferable.html
-  worker_messageChannel.js
-  worker_messageChannel_any.js
-  sharedWorker_messageChannel.js
-  sharedWorker2_messageChannel.js
-  iframe_messageChannel_sharedWorker2.html
-
-[test_messageChannel.html]
-[test_messageChannel_cloning.html]
-[test_messageChannel_pingpong.html]
-[test_messageChannel_post.html]
-[test_messageChannel_pref.html]
-[test_messageChannel_start.html]
-[test_messageChannel_transferable.html]
-[test_messageChannel_unshipped.html]
-[test_messageChannel_worker.html]
-[test_messageChannel_selfTransferring.html]
-[test_messageChannel_sharedWorker.html]
-[test_messageChannel_sharedWorker2.html]
-[test_messageChannel_any.html]
deleted file mode 100644
--- a/dom/messagechannel/tests/moz.build
+++ /dev/null
@@ -1,8 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-MOCHITEST_MANIFESTS += ['mochitest.ini']
-MOCHITEST_CHROME_MANIFESTS += ['chrome.ini']
deleted file mode 100644
--- a/dom/messagechannel/tests/sharedWorker2_messageChannel.js
+++ /dev/null
@@ -1,7 +0,0 @@
-var mc = new MessageChannel();
-var i = 0;
-
-onconnect = function(evt) {
-  dump("CONNECTING: "+ i +"\n");
-  evt.ports[0].postMessage(42, [mc['port' + ++i]]);
-}
deleted file mode 100644
--- a/dom/messagechannel/tests/sharedWorker_messageChannel.js
+++ /dev/null
@@ -1,8 +0,0 @@
-onconnect = function(evt) {
-  var mc = new MessageChannel();
-
-  evt.ports[0].postMessage(42, [mc.port2]);
-  mc.port1.onmessage = function(e) {
-    mc.port1.postMessage(e.data);
-  }
-}
deleted file mode 100644
--- a/dom/messagechannel/tests/test_messageChannel_any.html
+++ /dev/null
@@ -1,115 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=677638
--->
-<head>
-  <meta charset="utf-8">
-  <title>MessagePort/Channel any content</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=677638">Mozilla Bug 677638</a>
-<div id="content"></div>
-<pre id="test">
-</pre>
-  <script type="application/javascript">
-
-var tests = [
- 'hello world',
- 123,
- null,
- true,
- new Date(),
- [ 1, 'test', true, new Date() ],
- { a: true, b:  null, c: new Date(), d: [ true, false, {} ] },
- new Blob([123], { type: 'plain/text' })
-];
-
-var currentTest = null;
-
-function getType(a) {
-  if (a === null || a === undefined)
-    return 'null';
-
-  if (Array.isArray(a))
-    return 'array';
-
-  if (typeof a == 'object')
-    return 'object';
-
-  return 'primitive';
-}
-
-function compare(a, b) {
-  is (getType(a), getType(b), 'Type matches');
-
-  var type = getType(a);
-  if (type == 'array') {
-    is (a.length, b.length, 'Array.length matches');
-    for (var i = 0; i < a.length; ++i) {
-      compare(a[i], b[i]);
-    }
-
-    return;
-  }
-
-  if (type == 'object') {
-    ok (a !== b, 'They should not match');
-
-    var aProps = [];
-    for (var p in a) aProps.push(p);
-
-    var bProps = [];
-    for (var p in b) bProps.push(p);
-
-    is (aProps.length, bProps.length, 'Props match');
-    is (aProps.sort().toSource(), bProps.sort().toSource(), 'Props match - using toSource()');
-
-    for (var p in a) {
-      compare(a[p], b[p]);
-    }
-
-    return;
-  }
-
-  if (type != 'null') {
-    is (a.toSource(), b.toSource(), 'Matching using toSource()');
-  }
-}
-
-function runTest() {
-  var mc = new MessageChannel('foobar');
-  ok(mc, "MessageChannel can be created");
-
-  mc.port1.onmessage = function(event) {
-    compare(event.data, currentTest);
-    next();
-  }
-
-  function next() {
-    if (!tests.length) {
-      SimpleTest.finish();
-      return;
-    }
-
-    currentTest = tests.shift();
-    mc.port1.postMessage(currentTest);
-  }
-
-  var worker = new Worker("worker_messageChannel_any.js");
-  worker.onmessage = function(event) {
-    if (event.data == "READY") {
-      next();
-    }
-  };
-
-  worker.postMessage(mc.port2, [mc.port2]);
-}
-
-SimpleTest.waitForExplicitFinish();
-SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
-  </script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/messagechannel/tests/test_messageChannel_selfTransferring.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=677638
--->
-<head>
-  <meta charset="utf-8">
-  <title>MessagePort/Channel no self tranferring</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=677638">Mozilla Bug 677638</a>
-<div id="content"></div>
-<pre id="test">
-</pre>
-  <script type="application/javascript">
-
-function runTest() {
-  var a = new MessageChannel();
-
-  var status = false;
-  try {
-    a.port1.postMessage('foobar', [a.port1]);
-  } catch(e) {
-    status =true;
-  }
-
-  ok(status, "Transfering the same port should throw");
-  SimpleTest.finish();
-}
-
-SimpleTest.waitForExplicitFinish();
-SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
-  </script>
-</body>
-</html>
-
deleted file mode 100644
--- a/dom/messagechannel/tests/test_messageChannel_sharedWorker.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=677638
--->
-<head>
-  <meta charset="utf-8">
-  <title>Test for Bug 677638 - sharedWorker</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=677638">Mozilla Bug 677638</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-  <iframe name="x" id="x"></iframe>
-  <iframe name="y" id="y"></iframe>
-</div>
-<pre id="test">
-</pre>
-  <script type="application/javascript">
-
-  function runTest() {
-    var a = new SharedWorker('sharedWorker_messageChannel.js');
-    a.port.onmessage = function(evt) {
-      is(evt.ports.length, 1, "We received a port.");
-      evt.ports[0].onmessage = function(e) {
-        is(e.data, 42, "Message reiceved back!");
-        SimpleTest.finish();
-      }
-      evt.ports[0].postMessage(42);
-    }
-  }
-
-  SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
-  SimpleTest.waitForExplicitFinish();
-  </script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/messagechannel/tests/test_messageChannel_sharedWorker2.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=677638
--->
-<head>
-  <meta charset="utf-8">
-  <title>Test for Bug 677638 - sharedWorker</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=677638">Mozilla Bug 677638</a>
-  <div id="content"></div>
-
-  <script type="application/javascript">
-
-  function runTest() {
-    var iframe = document.createElement('iframe');
-    iframe.setAttribute('src', "iframe_messageChannel_sharedWorker2.html");
-    document.getElementById('content').appendChild(iframe);
-
-    var a = new SharedWorker('sharedWorker2_messageChannel.js');
-    a.port.onmessage = function(evt) {
-      is(evt.ports.length, 1, "We received a port.");
-      evt.ports[0].onmessage = function(e) {
-        is(e.data, "Hello from the iframe!", "Message reiceved from the iframe!");
-        SimpleTest.finish();
-      }
-    }
-  }
-
-  SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
-  SimpleTest.waitForExplicitFinish();
-  </script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/messagechannel/tests/test_messageChannel_worker.html
+++ /dev/null
@@ -1,60 +0,0 @@
-
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=677638
--->
-<head>
-  <meta charset="utf-8">
-  <title>Test for Bug 677638 - basic support</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=677638">Mozilla Bug 677638</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-  <iframe name="x" id="x"></iframe>
-  <iframe name="y" id="y"></iframe>
-</div>
-<pre id="test">
-</pre>
-  <script type="application/javascript">
-
-  var tests = [ 0, 3 ];
-
-  function runTests() {
-    if (!tests.length) {
-      SimpleTest.finish();
-      return;
-    }
-
-    var a = new Worker('worker_messageChannel.js');
-    a.onmessage = function(evt) {
-      if (evt.data.type == 'finish') {
-        runTests();
-      } else if (evt.data.type == 'info') {
-        info(evt.data.message);
-      } else if (evt.data.type == 'check') {
-        ok(evt.data.check, evt.data.message);
-      } else if (evt.data.type == 'port') {
-        is(evt.ports.length, 1, "A port has been received!");
-        evt.ports[0].onmessage = function(e) {
-          e.target.postMessage(e.data);
-        }
-      } else if (evt.data.type == 'newport') {
-        var ch = new MessageChannel();
-        ok(ch, "MessageChannel created");
-        ch.port1.postMessage(42);
-        a.postMessage('a gift!', [ch.port2]);
-      }
-    }
-
-    a.postMessage(tests.shift());
-  }
-
-  SimpleTest.waitForExplicitFinish();
-  SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTests);
-  </script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/messagechannel/tests/worker_messageChannel.js
+++ /dev/null
@@ -1,119 +0,0 @@
-function ok(a, msg) {
-  postMessage({ type: 'check', check: !!a, message: msg });
-}
-
-function is(a, b, msg) {
-  ok (a === b, msg);
-}
-
-function info(msg) {
-  postMessage({ type: 'info', message: msg });
-}
-
-function finish() {
-  postMessage({ type: 'finish' });
-}
-
-function basic()
-{
-  var a = new MessageChannel();
-  ok(a, "MessageChannel created");
-
-  var port1 = a.port1;
-  ok(port1, "MessageChannel.port1 exists");
-  is(port1, a.port1, "MessageChannel.port1 is port1");
-
-  var port2 = a.port2;
-  ok(port2, "MessageChannel.port1 exists");
-  is(port2, a.port2, "MessageChannel.port2 is port2");
-
-  [ 'postMessage', 'start', 'close' ].forEach(function(e) {
-    ok(e in port1, "MessagePort1." + e + " exists");
-    ok(e in port2, "MessagePort2." + e + " exists");
-  });
-
-  runTests();
-}
-
-function sendMessages()
-{
-  var a = new MessageChannel();
-  ok(a, "MessageChannel created");
-
-  a.port1.postMessage("Hello world!");
-  a.port1.onmessage = function(e) {
-    is(e.data, "Hello world!", "The message is back!");
-    runTests();
-  }
-
-  a.port2.onmessage = function(e) {
-    a.port2.postMessage(e.data);
-  }
-}
-
-function transferPort()
-{
-  var a = new MessageChannel();
-  ok(a, "MessageChannel created");
-
-  a.port1.postMessage("Hello world!");
-  a.port1.onmessage = function(e) {
-    is(e.data, "Hello world!", "The message is back!");
-    runTests();
-  }
-
-  postMessage({ type: 'port' }, [a.port2]);
-}
-
-function transferPort2()
-{
-  onmessage = function(evt) {
-    is(evt.ports.length, 1, "A port has been received by the worker");
-    evt.ports[0].onmessage = function(e) {
-      is(e.data, 42, "Data is 42!");
-      runTests();
-    }
-  }
-
-  postMessage({ type: 'newport' });
-}
-
-var tests = [
-  basic,
-  sendMessages,
-  transferPort,
-  transferPort2,
-];
-
-function runTests() {
-  if (!tests.length) {
-    finish();
-    return;
-  }
-
-  var t = tests.shift();
-  t();
-}
-
-var subworker;
-onmessage = function(evt) {
-  if (evt.data == 0) {
-    runTests();
-    return;
-  }
-
-  if (!subworker) {
-    info("Create a subworkers. ID: " + evt.data);
-    subworker = new Worker('worker_messageChannel.js');
-    subworker.onmessage = function(e) {
-      info("Proxy a message to the parent.");
-      postMessage(e.data, e.ports);
-    }
-
-    subworker.postMessage(evt.data - 1);
-    return;
-  }
-
-  info("Dispatch a message to the subworker.");
-  subworker.postMessage(evt.data, evt.ports);
-}
deleted file mode 100644
--- a/dom/messagechannel/tests/worker_messageChannel_any.js
+++ /dev/null
@@ -1,7 +0,0 @@
-onmessage = function(evt) {
-  evt.data.onmessage = function(event) {
-    evt.data.postMessage(event.data);
-  }
-}
-
-postMessage("READY");
--- a/dom/moz.build
+++ b/dom/moz.build
@@ -91,17 +91,16 @@ DIRS += [
     'plugins/ipc',
     'indexedDB',
     'system',
     'ipc',
     'workers',
     'camera',
     'audiochannel',
     'broadcastchannel',
-    'messagechannel',
     'promise',
     'smil',
     'telephony',
     'tv',
     'voicemail',
     'inputmethod',
     'webidl',
     'xbl',
--- a/dom/webidl/MessageChannel.webidl
+++ b/dom/webidl/MessageChannel.webidl
@@ -2,14 +2,13 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  *
  * For more information on this interface, please see
  * http://www.whatwg.org/specs/web-apps/current-work/#channel-messaging
  */
 
-[Constructor, Func="MessageChannel::Enabled",
- Exposed=(Window,Worker)]
+[Constructor, Func="MessageChannel::Enabled"]
 interface MessageChannel {
   readonly attribute MessagePort port1;
   readonly attribute MessagePort port2;
 };
--- a/dom/workers/MessagePort.cpp
+++ b/dom/workers/MessagePort.cpp
@@ -12,17 +12,16 @@
 #include "nsIDOMEvent.h"
 
 #include "SharedWorker.h"
 #include "WorkerPrivate.h"
 #include "WorkerRunnable.h"
 
 using mozilla::dom::EventHandlerNonNull;
 using mozilla::dom::MessagePortBase;
-using mozilla::dom::MessagePortIdentifier;
 using mozilla::dom::Optional;
 using mozilla::dom::Sequence;
 using mozilla::dom::AutoNoJSAPI;
 using namespace mozilla;
 
 USING_WORKERS_NAMESPACE
 
 namespace {
@@ -92,19 +91,19 @@ MessagePort::MessagePort(WorkerPrivate* 
 }
 
 MessagePort::~MessagePort()
 {
   Close();
 }
 
 void
-MessagePort::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
-                         const Optional<Sequence<JS::Value>>& aTransferable,
-                         ErrorResult& aRv)
+MessagePort::PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
+                            const Optional<Sequence<JS::Value>>& aTransferable,
+                            ErrorResult& aRv)
 {
   AssertCorrectThread();
 
   if (IsClosed()) {
     aRv = NS_ERROR_DOM_INVALID_STATE_ERR;
     return;
   }
 
@@ -194,21 +193,21 @@ MessagePort::SetOnmessage(EventHandlerNo
   }
   else {
     SetEventHandler(nullptr, NS_LITERAL_STRING("message"), aCallback);
   }
 
   Start();
 }
 
-bool
-MessagePort::CloneAndDisentangle(MessagePortIdentifier& aIdentifier)
+already_AddRefed<MessagePortBase>
+MessagePort::Clone()
 {
   NS_WARNING("Haven't implemented structured clone for these ports yet!");
-  return false;
+  return nullptr;
 }
 
 void
 MessagePort::CloseInternal()
 {
   AssertCorrectThread();
   MOZ_ASSERT(!IsClosed());
   MOZ_ASSERT_IF(mStarted, mQueuedEvents.IsEmpty());
--- a/dom/workers/MessagePort.h
+++ b/dom/workers/MessagePort.h
@@ -38,19 +38,19 @@ class MessagePort final : public mozilla
   uint64_t mSerial;
   bool mStarted;
 
 public:
   static bool
   PrefEnabled();
 
   virtual void
-  PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
-              const Optional<Sequence<JS::Value>>& aTransferable,
-              ErrorResult& aRv) override;
+  PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
+                 const Optional<Sequence<JS::Value>>& aTransferable,
+                 ErrorResult& aRv) override;
 
   virtual void
   Start() override;
 
   virtual void
   Close() override;
 
   uint64_t
@@ -66,18 +66,18 @@ public:
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MessagePort, DOMEventTargetHelper)
 
   virtual EventHandlerNonNull*
   GetOnmessage() override;
 
   virtual void
   SetOnmessage(EventHandlerNonNull* aCallback) override;
 
-  virtual bool
-  CloneAndDisentangle(MessagePortIdentifier& aIdentifier) override;
+  virtual already_AddRefed<MessagePortBase>
+  Clone() override;
 
   bool
   IsClosed() const
   {
     return !mSharedWorker && !mWorkerPrivate;
   }
 
   virtual JSObject*
--- a/dom/workers/ServiceWorkerClient.cpp
+++ b/dom/workers/ServiceWorkerClient.cpp
@@ -7,17 +7,16 @@
 
 #include "ServiceWorkerClient.h"
 #include "ServiceWorkerContainer.h"
 
 #include "mozilla/dom/MessageEvent.h"
 #include "nsGlobalWindow.h"
 #include "nsIDocument.h"
 #include "WorkerPrivate.h"
-#include "WorkerStructuredClone.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::dom::workers;
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ServiceWorkerClient, mOwner)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(ServiceWorkerClient)
@@ -71,28 +70,26 @@ ServiceWorkerClient::WrapObject(JSContex
 }
 
 namespace {
 
 class ServiceWorkerClientPostMessageRunnable final : public nsRunnable
 {
   uint64_t mWindowId;
   JSAutoStructuredCloneBuffer mBuffer;
-  WorkerStructuredCloneClosure mClosure;
+  nsTArray<nsCOMPtr<nsISupports>> mClonedObjects;
 
 public:
   ServiceWorkerClientPostMessageRunnable(uint64_t aWindowId,
                                          JSAutoStructuredCloneBuffer&& aData,
-                                         WorkerStructuredCloneClosure& aClosure)
+                                         nsTArray<nsCOMPtr<nsISupports>>& aClonedObjects)
     : mWindowId(aWindowId),
       mBuffer(Move(aData))
   {
-    mClosure.mClonedObjects.SwapElements(aClosure.mClonedObjects);
-    MOZ_ASSERT(aClosure.mMessagePorts.IsEmpty());
-    mClosure.mMessagePortIdentifiers.SwapElements(aClosure.mMessagePortIdentifiers);
+    mClonedObjects.SwapElements(aClonedObjects);
   }
 
   NS_IMETHOD
   Run()
   {
     AssertIsOnMainThread();
     nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(mWindowId);
     if (!window) {
@@ -116,20 +113,18 @@ public:
 private:
   NS_IMETHOD
   DispatchDOMEvent(JSContext* aCx, ServiceWorkerContainer* aTargetContainer)
   {
     AssertIsOnMainThread();
 
     // Release reference to objects that were AddRef'd for
     // cloning into worker when array goes out of scope.
-    WorkerStructuredCloneClosure closure;
-    closure.mClonedObjects.SwapElements(mClosure.mClonedObjects);
-    MOZ_ASSERT(mClosure.mMessagePorts.IsEmpty());
-    closure.mMessagePortIdentifiers.SwapElements(mClosure.mMessagePortIdentifiers);
+    nsTArray<nsCOMPtr<nsISupports>> clonedObjects;
+    clonedObjects.SwapElements(mClonedObjects);
 
     JS::Rooted<JS::Value> messageData(aCx);
     if (!mBuffer.read(aCx, &messageData,
                       WorkerStructuredCloneCallbacks(true))) {
       xpc::Throw(aCx, NS_ERROR_DOM_DATA_CLONE_ERR);
       return NS_ERROR_FAILURE;
     }
 
@@ -185,25 +180,24 @@ ServiceWorkerClient::PostMessage(JSConte
       return;
     }
 
     transferable.setObject(*array);
   }
 
   const JSStructuredCloneCallbacks* callbacks = WorkerStructuredCloneCallbacks(false);
 
-  WorkerStructuredCloneClosure closure;
+  nsTArray<nsCOMPtr<nsISupports>> clonedObjects;
 
   JSAutoStructuredCloneBuffer buffer;
-  if (!buffer.write(aCx, aMessage, transferable, callbacks, &closure)) {
+  if (!buffer.write(aCx, aMessage, transferable, callbacks, &clonedObjects)) {
     aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
     return;
   }
 
   nsRefPtr<ServiceWorkerClientPostMessageRunnable> runnable =
-    new ServiceWorkerClientPostMessageRunnable(mWindowId, Move(buffer),
-                                               closure);
+    new ServiceWorkerClientPostMessageRunnable(mWindowId, Move(buffer), clonedObjects);
   nsresult rv = NS_DispatchToMainThread(runnable);
   if (NS_FAILED(rv)) {
     aRv.Throw(NS_ERROR_FAILURE);
   }
 }
 
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -47,18 +47,16 @@
 #include "mozilla/dom/ErrorEvent.h"
 #include "mozilla/dom/ErrorEventBinding.h"
 #include "mozilla/dom/Exceptions.h"
 #include "mozilla/dom/FunctionBinding.h"
 #include "mozilla/dom/ImageData.h"
 #include "mozilla/dom/ImageDataBinding.h"
 #include "mozilla/dom/MessageEvent.h"
 #include "mozilla/dom/MessageEventBinding.h"
-#include "mozilla/dom/MessagePort.h"
-#include "mozilla/dom/MessagePortBinding.h"
 #include "mozilla/dom/MessagePortList.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/PromiseDebugging.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/StructuredClone.h"
 #include "mozilla/dom/WebCryptoCommon.h"
 #include "mozilla/dom/WorkerBinding.h"
 #include "mozilla/dom/WorkerDebuggerGlobalScopeBinding.h"
@@ -102,17 +100,16 @@
 #include "RuntimeService.h"
 #include "ScriptLoader.h"
 #include "ServiceWorkerManager.h"
 #include "SharedWorker.h"
 #include "WorkerDebuggerManager.h"
 #include "WorkerFeature.h"
 #include "WorkerRunnable.h"
 #include "WorkerScope.h"
-#include "WorkerStructuredClone.h"
 #include "WorkerThread.h"
 
 #ifdef XP_WIN
 #undef PostMessage
 #endif
 
 // JS_MaybeGC will run once every second during normal execution.
 #define PERIODIC_GC_TIMER_DELAY_SEC 1
@@ -509,17 +506,17 @@ ReadFormData(JSContext* aCx,
 
   aFormData.set(formData->WrapObject(aCx, nullptr));
 }
 
 bool
 WriteBlobOrFile(JSContext* aCx,
                 JSStructuredCloneWriter* aWriter,
                 BlobImpl* aBlobOrBlobImpl,
-                WorkerStructuredCloneClosure& aClosure)
+                nsTArray<nsCOMPtr<nsISupports>>& aClonedObjects)
 {
   MOZ_ASSERT(aCx);
   MOZ_ASSERT(aWriter);
   MOZ_ASSERT(aBlobOrBlobImpl);
 
   nsRefPtr<BlobImpl> blobImpl = EnsureBlobForBackgroundManager(aBlobOrBlobImpl);
   MOZ_ASSERT(blobImpl);
 
@@ -527,17 +524,17 @@ WriteBlobOrFile(JSContext* aCx,
 
   if (NS_WARN_IF(!JS_WriteUint32Pair(aWriter, DOMWORKER_SCTAG_BLOB, 0)) ||
       NS_WARN_IF(!JS_WriteBytes(aWriter,
                                 &aBlobOrBlobImpl,
                                 sizeof(aBlobOrBlobImpl)))) {
     return false;
   }
 
-  aClosure.mClonedObjects.AppendElement(aBlobOrBlobImpl);
+  aClonedObjects.AppendElement(aBlobOrBlobImpl);
   return true;
 }
 
 // A FormData is serialized as:
 //  - A pair of ints (tag identifying it as a FormData, number of elements in
 //  the FormData)
 //  - for each (key, value) pair:
 //    - pair of ints (is value a file?, 0). If not a file, value is a string.
@@ -545,34 +542,34 @@ WriteBlobOrFile(JSContext* aCx,
 //    - if value is a file:
 //      - write the file/blob
 //    - else:
 //      - string value
 bool
 WriteFormData(JSContext* aCx,
               JSStructuredCloneWriter* aWriter,
               nsFormData* aFormData,
-              WorkerStructuredCloneClosure& aClosure)
+              nsTArray<nsCOMPtr<nsISupports>>& aClonedObjects)
 {
   MOZ_ASSERT(aCx);
   MOZ_ASSERT(aWriter);
   MOZ_ASSERT(aFormData);
 
   if (NS_WARN_IF(!JS_WriteUint32Pair(aWriter, DOMWORKER_SCTAG_FORMDATA, aFormData->Length()))) {
     return false;
   }
 
   class MOZ_STACK_CLASS Closure {
     JSContext* mCx;
     JSStructuredCloneWriter* mWriter;
-    WorkerStructuredCloneClosure& mClones;
+    nsTArray<nsCOMPtr<nsISupports>>& mClones;
 
   public:
     Closure(JSContext* aCx, JSStructuredCloneWriter* aWriter,
-            WorkerStructuredCloneClosure& aClones)
+            nsTArray<nsCOMPtr<nsISupports>>& aClones)
       : mCx(aCx), mWriter(aWriter), mClones(aClones)
     { }
 
     static bool
     Write(const nsString& aName, bool isFile, const nsString& aValue,
           File* aFile, void* aClosure)
     {
       Closure* closure = static_cast<Closure*>(aClosure);
@@ -593,17 +590,17 @@ WriteFormData(JSContext* aCx,
           return false;
         }
       }
 
       return true;
     }
   };
 
-  Closure closure(aCx, aWriter, aClosure);
+  Closure closure(aCx, aWriter, aClonedObjects);
   return aFormData->ForEach(Closure::Write, &closure);
 }
 
 struct WorkerStructuredCloneCallbacks
 {
   static JSObject*
   Read(JSContext* aCx, JSStructuredCloneReader* aReader, uint32_t aTag,
        uint32_t aData, void* aClosure)
@@ -637,26 +634,28 @@ struct WorkerStructuredCloneCallbacks
   }
 
   static bool
   Write(JSContext* aCx, JSStructuredCloneWriter* aWriter,
         JS::Handle<JSObject*> aObj, void* aClosure)
   {
     NS_ASSERTION(aClosure, "Null pointer!");
 
-    auto* closure = static_cast<WorkerStructuredCloneClosure*>(aClosure);
+    // We'll stash any nsISupports pointers that need to be AddRef'd here.
+    auto* clonedObjects =
+      static_cast<nsTArray<nsCOMPtr<nsISupports>>*>(aClosure);
 
     // See if this is a Blob/File object.
     {
       nsRefPtr<Blob> blob;
       if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob, aObj, blob))) {
         BlobImpl* blobImpl = blob->Impl();
         MOZ_ASSERT(blobImpl);
 
-        if (WriteBlobOrFile(aCx, aWriter, blobImpl, *closure)) {
+        if (WriteBlobOrFile(aCx, aWriter, blobImpl, *clonedObjects)) {
           return true;
         }
       }
     }
 
     // See if this is an ImageData object.
     {
       ImageData* imageData = nullptr;
@@ -664,121 +663,40 @@ struct WorkerStructuredCloneCallbacks
         return WriteStructuredCloneImageData(aCx, aWriter, imageData);
       }
     }
 
     // See if this is a FormData object.
     {
       nsFormData* formData = nullptr;
       if (NS_SUCCEEDED(UNWRAP_OBJECT(FormData, aObj, formData))) {
-        if (WriteFormData(aCx, aWriter, formData, *closure)) {
+        if (WriteFormData(aCx, aWriter, formData, *clonedObjects)) {
           return true;
         }
       }
     }
 
     Error(aCx, 0);
     return false;
   }
 
   static void
   Error(JSContext* aCx, uint32_t /* aErrorId */)
   {
     Throw(aCx, NS_ERROR_DOM_DATA_CLONE_ERR);
   }
-
-  static bool
-  ReadTransfer(JSContext* aCx, JSStructuredCloneReader* aReader,
-               uint32_t aTag, void* aContent, uint64_t aExtraData,
-               void* aClosure, JS::MutableHandle<JSObject*> aReturnObject)
-  {
-    MOZ_ASSERT(aClosure);
-
-    auto* closure = static_cast<WorkerStructuredCloneClosure*>(aClosure);
-
-    if (aTag == SCTAG_DOM_MAP_MESSAGEPORT) {
-      MOZ_ASSERT(!aContent);
-      MOZ_ASSERT(aExtraData < closure->mMessagePortIdentifiers.Length());
-
-      ErrorResult rv;
-      nsRefPtr<MessagePortBase> port =
-        dom::MessagePort::Create(closure->mParentWindow,
-                                 closure->mMessagePortIdentifiers[aExtraData],
-                                 rv);
-
-      if (NS_WARN_IF(rv.Failed())) {
-        return false;
-      }
-
-      closure->mMessagePorts.AppendElement(port);
-
-      JS::Rooted<JS::Value> value(aCx);
-      if (!GetOrCreateDOMReflector(aCx, port, &value)) {
-        JS_ClearPendingException(aCx);
-        return false;
-      }
-
-      aReturnObject.set(&value.toObject());
-      return true;
-    }
-
-    return false;
-  }
-
-  static bool
-  Transfer(JSContext* aCx, JS::Handle<JSObject*> aObj, void* aClosure,
-           uint32_t* aTag, JS::TransferableOwnership* aOwnership,
-           void** aContent, uint64_t *aExtraData)
-  {
-    MOZ_ASSERT(aClosure);
-
-    auto* closure = static_cast<WorkerStructuredCloneClosure*>(aClosure);
-
-    MessagePortBase* port;
-    nsresult rv = UNWRAP_OBJECT(MessagePort, aObj, port);
-    if (NS_SUCCEEDED(rv)) {
-      if (NS_WARN_IF(closure->mTransferredPorts.Contains(port))) {
-        // No duplicates.
-        return false;
-      }
-
-      MessagePortIdentifier identifier;
-      if (!port->CloneAndDisentangle(identifier)) {
-        return false;
-      }
-
-      closure->mMessagePortIdentifiers.AppendElement(identifier);
-      closure->mTransferredPorts.AppendElement(port);
-
-      *aTag = SCTAG_DOM_MAP_MESSAGEPORT;
-      *aOwnership = JS::SCTAG_TMO_CUSTOM;
-      *aContent = nullptr;
-      *aExtraData = closure->mMessagePortIdentifiers.Length() - 1;
-
-      return true;
-    }
-
-    return false;
-  }
-
-  static void
-  FreeTransfer(uint32_t aTag, JS::TransferableOwnership aOwnership,
-               void *aContent, uint64_t aExtraData, void* aClosure)
-  {
-    // Nothing to do.
-  }
 };
 
 const JSStructuredCloneCallbacks gWorkerStructuredCloneCallbacks = {
   WorkerStructuredCloneCallbacks::Read,
   WorkerStructuredCloneCallbacks::Write,
   WorkerStructuredCloneCallbacks::Error,
-  WorkerStructuredCloneCallbacks::ReadTransfer,
-  WorkerStructuredCloneCallbacks::Transfer,
-  WorkerStructuredCloneCallbacks::FreeTransfer
+  nullptr,
+  nullptr,
+  nullptr
 };
 
 struct MainThreadWorkerStructuredCloneCallbacks
 {
   static JSObject*
   Read(JSContext* aCx, JSStructuredCloneReader* aReader, uint32_t aTag,
        uint32_t aData, void* aClosure)
   {
@@ -808,28 +726,30 @@ struct MainThreadWorkerStructuredCloneCa
   static bool
   Write(JSContext* aCx, JSStructuredCloneWriter* aWriter,
         JS::Handle<JSObject*> aObj, void* aClosure)
   {
     AssertIsOnMainThread();
 
     NS_ASSERTION(aClosure, "Null pointer!");
 
-    auto* closure = static_cast<WorkerStructuredCloneClosure*>(aClosure);
+    // We'll stash any nsISupports pointers that need to be AddRef'd here.
+    auto* clonedObjects =
+      static_cast<nsTArray<nsCOMPtr<nsISupports>>*>(aClosure);
 
     // See if this is a Blob/File object.
     {
       nsRefPtr<Blob> blob;
       if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob, aObj, blob))) {
         BlobImpl* blobImpl = blob->Impl();
         MOZ_ASSERT(blobImpl);
 
         if (!blobImpl->MayBeClonedToOtherThreads()) {
           NS_WARNING("Not all the blob implementations can be sent between threads.");
-        } else if (WriteBlobOrFile(aCx, aWriter, blobImpl, *closure)) {
+        } else if (WriteBlobOrFile(aCx, aWriter, blobImpl, *clonedObjects)) {
           return true;
         }
       }
     }
 
     JS_ClearPendingException(aCx);
     return NS_DOMWriteStructuredClone(aCx, aWriter, aObj, nullptr);
   }
@@ -842,19 +762,19 @@ struct MainThreadWorkerStructuredCloneCa
     NS_DOMStructuredCloneError(aCx, aErrorId);
   }
 };
 
 const JSStructuredCloneCallbacks gMainThreadWorkerStructuredCloneCallbacks = {
   MainThreadWorkerStructuredCloneCallbacks::Read,
   MainThreadWorkerStructuredCloneCallbacks::Write,
   MainThreadWorkerStructuredCloneCallbacks::Error,
-  WorkerStructuredCloneCallbacks::ReadTransfer,
-  WorkerStructuredCloneCallbacks::Transfer,
-  WorkerStructuredCloneCallbacks::FreeTransfer
+  nullptr,
+  nullptr,
+  nullptr
 };
 
 struct ChromeWorkerStructuredCloneCallbacks
 {
   static JSObject*
   Read(JSContext* aCx, JSStructuredCloneReader* aReader, uint32_t aTag,
        uint32_t aData, void* aClosure)
   {
@@ -875,19 +795,19 @@ struct ChromeWorkerStructuredCloneCallba
     return WorkerStructuredCloneCallbacks::Error(aCx, aErrorId);
   }
 };
 
 const JSStructuredCloneCallbacks gChromeWorkerStructuredCloneCallbacks = {
   ChromeWorkerStructuredCloneCallbacks::Read,
   ChromeWorkerStructuredCloneCallbacks::Write,
   ChromeWorkerStructuredCloneCallbacks::Error,
-  WorkerStructuredCloneCallbacks::ReadTransfer,
-  WorkerStructuredCloneCallbacks::Transfer,
-  WorkerStructuredCloneCallbacks::FreeTransfer
+  nullptr,
+  nullptr,
+  nullptr
 };
 
 struct MainThreadChromeWorkerStructuredCloneCallbacks
 {
   static JSObject*
   Read(JSContext* aCx, JSStructuredCloneReader* aReader, uint32_t aTag,
        uint32_t aData, void* aClosure)
   {
@@ -1228,71 +1148,55 @@ private:
 
     aWorkerPrivate->CloseHandlerFinished();
   }
 };
 
 class MessageEventRunnable final : public WorkerRunnable
 {
   JSAutoStructuredCloneBuffer mBuffer;
-  WorkerStructuredCloneClosure mClosure;
+  nsTArray<nsCOMPtr<nsISupports> > mClonedObjects;
   uint64_t mMessagePortSerial;
   bool mToMessagePort;
 
   // This is only used for messages dispatched to a service worker.
   nsAutoPtr<ServiceWorkerClientInfo> mEventSource;
 
 public:
   MessageEventRunnable(WorkerPrivate* aWorkerPrivate,
                        TargetAndBusyBehavior aBehavior,
+                       JSAutoStructuredCloneBuffer&& aData,
+                       nsTArray<nsCOMPtr<nsISupports> >& aClonedObjects,
                        bool aToMessagePort, uint64_t aMessagePortSerial)
   : WorkerRunnable(aWorkerPrivate, aBehavior)
+  , mBuffer(Move(aData))
   , mMessagePortSerial(aMessagePortSerial)
   , mToMessagePort(aToMessagePort)
   {
-  }
-
-  bool
-  Write(JSContext* aCx, JS::Handle<JS::Value> aValue,
-        JS::Handle<JS::Value> aTransferredValue,
-        const JSStructuredCloneCallbacks *aCallbacks)
-   {
-    bool ok = mBuffer.write(aCx, aValue, aTransferredValue, aCallbacks,
-                            &mClosure);
-    // This hashtable has to be empty because it could contain MessagePort
-    // objects that cannot be freed on a different thread.
-    mClosure.mTransferredPorts.Clear();
-    return ok;
+    mClonedObjects.SwapElements(aClonedObjects);
   }
 
   void
   SetMessageSource(ServiceWorkerClientInfo* aSource)
   {
     mEventSource = aSource;
   }
 
   bool
   DispatchDOMEvent(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
                    DOMEventTargetHelper* aTarget, bool aIsMainThread)
   {
     // Release reference to objects that were AddRef'd for
     // cloning into worker when array goes out of scope.
-    WorkerStructuredCloneClosure closure;
-    closure.mClonedObjects.SwapElements(mClosure.mClonedObjects);
-    MOZ_ASSERT(mClosure.mMessagePorts.IsEmpty());
-    closure.mMessagePortIdentifiers.SwapElements(mClosure.mMessagePortIdentifiers);
-
-    if (aIsMainThread) {
-      closure.mParentWindow = do_QueryInterface(aTarget->GetParentObject());
-    }
+    nsTArray<nsCOMPtr<nsISupports>> clonedObjects;
+    clonedObjects.SwapElements(mClonedObjects);
 
     JS::Rooted<JS::Value> messageData(aCx);
     if (!mBuffer.read(aCx, &messageData,
-                      workers::WorkerStructuredCloneCallbacks(aIsMainThread),
-                      &closure)) {
+                      workers::WorkerStructuredCloneCallbacks(aIsMainThread))) {
       xpc::Throw(aCx, NS_ERROR_DOM_DATA_CLONE_ERR);
       return false;
     }
 
     nsRefPtr<MessageEvent> event = new MessageEvent(aTarget, nullptr, nullptr);
     nsresult rv =
       event->InitMessageEvent(NS_LITERAL_STRING("message"),
                               false /* non-bubbling */,
@@ -1308,18 +1212,17 @@ public:
     }
 
     if (NS_FAILED(rv)) {
       xpc::Throw(aCx, rv);
       return false;
     }
 
     event->SetTrusted(true);
-    event->SetPorts(new MessagePortList(static_cast<dom::Event*>(event.get()),
-                                        closure.mMessagePorts));
+
     nsCOMPtr<nsIDOMEvent> domEvent = do_QueryObject(event);
 
     nsEventStatus dummy = nsEventStatus_eIgnore;
     aTarget->DispatchDOMEvent(nullptr, domEvent, nullptr, &dummy);
     return true;
   }
 
 private:
@@ -1335,17 +1238,17 @@ private:
         return true;
       }
 
       if (mToMessagePort) {
         return
           aWorkerPrivate->DispatchMessageEventToMessagePort(aCx,
                                                             mMessagePortSerial,
                                                             Move(mBuffer),
-                                                            mClosure);
+                                                            mClonedObjects);
       }
 
       if (aWorkerPrivate->IsFrozen()) {
         aWorkerPrivate->QueueRunnable(this);
         return true;
       }
 
       aWorkerPrivate->AssertInnerWindowIsCorrect();
@@ -3471,26 +3374,29 @@ WorkerPrivateParent<Derived>::PostMessag
       JS_NewArrayObject(aCx, elements);
     if (!array) {
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return;
     }
     transferable.setObject(*array);
   }
 
+  nsTArray<nsCOMPtr<nsISupports>> clonedObjects;
+
+  JSAutoStructuredCloneBuffer buffer;
+  if (!buffer.write(aCx, aMessage, transferable, callbacks, &clonedObjects)) {
+    aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
+    return;
+  }
+
   nsRefPtr<MessageEventRunnable> runnable =
     new MessageEventRunnable(ParentAsWorkerPrivate(),
                              WorkerRunnable::WorkerThreadModifyBusyCount,
-                             aToMessagePort, aMessagePortSerial);
-
-  if (!runnable->Write(aCx, aMessage, transferable, callbacks)) {
-    aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
-    return;
-  }
-
+                             Move(buffer), clonedObjects, aToMessagePort,
+                             aMessagePortSerial);
   runnable->SetMessageSource(aClientInfo);
 
   if (!runnable->Dispatch(aCx)) {
     aRv.Throw(NS_ERROR_FAILURE);
   }
 }
 
 template <class Derived>
@@ -3521,68 +3427,67 @@ WorkerPrivateParent<Derived>::PostMessag
                       nullptr, aRv);
 }
 
 template <class Derived>
 bool
 WorkerPrivateParent<Derived>::DispatchMessageEventToMessagePort(
                                 JSContext* aCx, uint64_t aMessagePortSerial,
                                 JSAutoStructuredCloneBuffer&& aBuffer,
-                                WorkerStructuredCloneClosure& aClosure)
+                                nsTArray<nsCOMPtr<nsISupports>>& aClonedObjects)
 {
   AssertIsOnMainThread();
 
   JSAutoStructuredCloneBuffer buffer(Move(aBuffer));
 
-  WorkerStructuredCloneClosure closure;
-  closure.mClonedObjects.SwapElements(aClosure.mClonedObjects);
-  MOZ_ASSERT(aClosure.mMessagePorts.IsEmpty());
-  closure.mMessagePortIdentifiers.SwapElements(aClosure.mMessagePortIdentifiers);
+  nsTArray<nsCOMPtr<nsISupports>> clonedObjects;
+  clonedObjects.SwapElements(aClonedObjects);
 
   SharedWorker* sharedWorker;
   if (!mSharedWorkers.Get(aMessagePortSerial, &sharedWorker)) {
     // SharedWorker has already been unregistered?
     return true;
   }
 
   nsRefPtr<MessagePort> port = sharedWorker->Port();
   NS_ASSERTION(port, "SharedWorkers always have a port!");
 
   if (port->IsClosed()) {
     return true;
   }
 
-  closure.mParentWindow = do_QueryInterface(port->GetParentObject());
-
   AutoJSAPI jsapi;
   if (NS_WARN_IF(!jsapi.InitWithLegacyErrorReporting(port->GetParentObject()))) {
     return false;
   }
   JSContext* cx = jsapi.cx();
 
   JS::Rooted<JS::Value> data(cx);
-  if (!buffer.read(cx, &data, WorkerStructuredCloneCallbacks(true),
-                   &closure)) {
+  if (!buffer.read(cx, &data, WorkerStructuredCloneCallbacks(true))) {
     return false;
   }
 
   buffer.clear();
 
   nsRefPtr<MessageEvent> event = new MessageEvent(port, nullptr, nullptr);
   nsresult rv =
     event->InitMessageEvent(NS_LITERAL_STRING("message"), false, false, data,
                             EmptyString(), EmptyString(), nullptr);
   if (NS_FAILED(rv)) {
     xpc::Throw(cx, rv);
     return false;
   }
 
   event->SetTrusted(true);
 
-  event->SetPorts(new MessagePortList(port, closure.mMessagePorts));
+  nsTArray<nsRefPtr<MessagePortBase>> ports;
+  ports.AppendElement(port);
+
+  nsRefPtr<MessagePortList> portList = new MessagePortList(port, ports);
+  event->SetPorts(portList);
 
   nsCOMPtr<nsIDOMEvent> domEvent;
   CallQueryInterface(event.get(), getter_AddRefs(domEvent));
   NS_ASSERTION(domEvent, "This should never fail!");
 
   bool ignored;
   rv = port->DispatchEvent(domEvent, &ignored);
   if (NS_FAILED(rv)) {
@@ -6272,26 +6177,29 @@ WorkerPrivate::PostMessageToParentIntern
     transferable.setObject(*array);
   }
 
   const JSStructuredCloneCallbacks* callbacks =
     IsChromeWorker() ?
     &gChromeWorkerStructuredCloneCallbacks :
     &gWorkerStructuredCloneCallbacks;
 
+  nsTArray<nsCOMPtr<nsISupports>> clonedObjects;
+
+  JSAutoStructuredCloneBuffer buffer;
+  if (!buffer.write(aCx, aMessage, transferable, callbacks, &clonedObjects)) {
+    aRv = NS_ERROR_DOM_DATA_CLONE_ERR;
+    return;
+  }
+
   nsRefPtr<MessageEventRunnable> runnable =
     new MessageEventRunnable(this,
                              WorkerRunnable::ParentThreadUnchangedBusyCount,
-                             aToMessagePort, aMessagePortSerial);
-
-  if (!runnable->Write(aCx, aMessage, transferable, callbacks)) {
-    aRv = NS_ERROR_DOM_DATA_CLONE_ERR;
-    return;
-  }
-
+                             Move(buffer), clonedObjects, aToMessagePort,
+                             aMessagePortSerial);
   if (!runnable->Dispatch(aCx)) {
     aRv = NS_ERROR_FAILURE;
   }
 }
 
 void
 WorkerPrivate::PostMessageToParentMessagePort(
                              JSContext* aCx,
@@ -7435,25 +7343,9 @@ ChromeWorkerStructuredCloneCallbacks(boo
   return aMainRuntime ?
          &gMainThreadChromeWorkerStructuredCloneCallbacks :
          &gChromeWorkerStructuredCloneCallbacks;
 }
 
 // Force instantiation.
 template class WorkerPrivateParent<WorkerPrivate>;
 
-WorkerStructuredCloneClosure::WorkerStructuredCloneClosure()
-{}
-
-WorkerStructuredCloneClosure::~WorkerStructuredCloneClosure()
-{}
-
-void
-WorkerStructuredCloneClosure::Clear()
-{
-  mParentWindow = nullptr;
-  mClonedObjects.Clear();
-  mMessagePorts.Clear();
-  mMessagePortIdentifiers.Clear();
-  mTransferredPorts.Clear();
-}
-
 END_WORKERS_NAMESPACE
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -68,17 +68,16 @@ class MessagePort;
 class SharedWorker;
 class ServiceWorkerClientInfo;
 class WorkerControlRunnable;
 class WorkerDebugger;
 class WorkerDebuggerGlobalScope;
 class WorkerGlobalScope;
 class WorkerPrivate;
 class WorkerRunnable;
-class WorkerStructuredCloneClosure;
 class WorkerThread;
 
 // SharedMutex is a small wrapper around an (internal) reference-counted Mutex
 // object. It exists to avoid changing a lot of code to use Mutex* instead of
 // Mutex&.
 class SharedMutex
 {
   typedef mozilla::Mutex Mutex;
@@ -345,17 +344,17 @@ public:
                            const Optional<Sequence<JS::Value> >& aTransferable,
                            ErrorResult& aRv);
 
   bool
   DispatchMessageEventToMessagePort(
                                JSContext* aCx,
                                uint64_t aMessagePortSerial,
                                JSAutoStructuredCloneBuffer&& aBuffer,
-                               WorkerStructuredCloneClosure& aClosure);
+                               nsTArray<nsCOMPtr<nsISupports>>& aClonedObjects);
 
   void
   UpdateRuntimeOptions(JSContext* aCx,
                        const JS::RuntimeOptions& aRuntimeOptions);
 
   void
   UpdateLanguages(JSContext* aCx, const nsTArray<nsString>& aLanguages);
 
deleted file mode 100644
--- a/dom/workers/WorkerStructuredClone.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_workers_WorkerStructuredClone_h
-#define mozilla_dom_workers_WorkerStructuredClone_h
-
-#include "Workers.h"
-#include "mozilla/dom/PMessagePort.h"
-
-class nsPIDOMWindow;
-
-namespace mozilla {
-namespace dom {
-
-class MessagePortBase;
-
-namespace workers {
-
-// This class is implemented in WorkerPrivate.cpp
-class WorkerStructuredCloneClosure final
-{
-private:
-  WorkerStructuredCloneClosure(const WorkerStructuredCloneClosure&) = delete;
-  WorkerStructuredCloneClosure & operator=(const WorkerStructuredCloneClosure&) = delete;
-
-public:
-  WorkerStructuredCloneClosure();
-  ~WorkerStructuredCloneClosure();
-
-  void Clear();
-
-  // This can be null if the MessagePort is created in a worker.
-  nsCOMPtr<nsPIDOMWindow> mParentWindow;
-
-  nsTArray<nsCOMPtr<nsISupports>> mClonedObjects;
-
-  // The transferred ports.
-  nsTArray<nsRefPtr<MessagePortBase>> mMessagePorts;
-
-  // Information for the transferring.
-  nsTArray<MessagePortIdentifier> mMessagePortIdentifiers;
-
-  // To avoid duplicates in the transferred ports.
-  nsTArray<nsRefPtr<MessagePortBase>> mTransferredPorts;
-};
-
-} // workers namespace
-} // dom namespace
-} // mozilla namespace
-
-#endif // mozilla_dom_workers_WorkerStructuredClone_h
--- a/dom/workers/XMLHttpRequest.cpp
+++ b/dom/workers/XMLHttpRequest.cpp
@@ -22,17 +22,16 @@
 #include "nsContentUtils.h"
 #include "nsFormData.h"
 #include "nsJSUtils.h"
 #include "nsThreadUtils.h"
 
 #include "RuntimeService.h"
 #include "WorkerPrivate.h"
 #include "WorkerRunnable.h"
-#include "WorkerStructuredClone.h"
 #include "XMLHttpRequestUpload.h"
 
 using namespace mozilla;
 
 using namespace mozilla::dom;
 USING_WORKERS_NAMESPACE
 
 /**
@@ -409,17 +408,17 @@ private:
     }
 };
 
 class EventRunnable final : public MainThreadProxyRunnable
 {
   nsString mType;
   nsString mResponseType;
   JSAutoStructuredCloneBuffer mResponseBuffer;
-  WorkerStructuredCloneClosure mResponseClosure;
+  nsTArray<nsCOMPtr<nsISupports> > mClonedObjects;
   JS::Heap<JS::Value> mResponse;
   nsString mResponseText;
   nsString mResponseURL;
   nsCString mStatusText;
   uint64_t mLoaded;
   uint64_t mTotal;
   uint32_t mEventStreamId;
   uint32_t mStatus;
@@ -790,34 +789,32 @@ private:
   nsresult
   MainThreadRunInternal();
 };
 
 class SendRunnable final : public WorkerThreadProxySyncRunnable
 {
   nsString mStringBody;
   JSAutoStructuredCloneBuffer mBody;
-  WorkerStructuredCloneClosure mClosure;
+  nsTArray<nsCOMPtr<nsISupports> > mClonedObjects;
   nsCOMPtr<nsIEventTarget> mSyncLoopTarget;
   bool mHasUploadListeners;
 
 public:
   SendRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy,
                const nsAString& aStringBody, JSAutoStructuredCloneBuffer&& aBody,
-               WorkerStructuredCloneClosure& aClosure,
+               nsTArray<nsCOMPtr<nsISupports>>& aClonedObjects,
                nsIEventTarget* aSyncLoopTarget, bool aHasUploadListeners)
   : WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy)
   , mStringBody(aStringBody)
   , mBody(Move(aBody))
   , mSyncLoopTarget(aSyncLoopTarget)
   , mHasUploadListeners(aHasUploadListeners)
   {
-    mClosure.mClonedObjects.SwapElements(aClosure.mClonedObjects);
-    MOZ_ASSERT(aClosure.mMessagePorts.IsEmpty());
-    MOZ_ASSERT(aClosure.mMessagePortIdentifiers.IsEmpty());
+    mClonedObjects.SwapElements(aClonedObjects);
   }
 
 private:
   ~SendRunnable()
   { }
 
   virtual nsresult
   MainThreadRun() override;
@@ -1227,23 +1224,21 @@ EventRunnable::PreDispatch(JSContext* aC
 
         if (doClone) {
           // Anything subject to GC must be cloned.
           const JSStructuredCloneCallbacks* callbacks =
             aWorkerPrivate->IsChromeWorker() ?
             workers::ChromeWorkerStructuredCloneCallbacks(true) :
             workers::WorkerStructuredCloneCallbacks(true);
 
-          WorkerStructuredCloneClosure closure;
+          nsTArray<nsCOMPtr<nsISupports> > clonedObjects;
 
           if (mResponseBuffer.write(aCx, response, transferable, callbacks,
-                                    &closure)) {
-            mResponseClosure.mClonedObjects.SwapElements(closure.mClonedObjects);
-            MOZ_ASSERT(mResponseClosure.mMessagePorts.IsEmpty());
-            MOZ_ASSERT(mResponseClosure.mMessagePortIdentifiers.IsEmpty());
+                                    &clonedObjects)) {
+            mClonedObjects.SwapElements(clonedObjects);
           } else {
             NS_WARNING("Failed to clone response!");
             mResponseResult = NS_ERROR_DOM_DATA_CLONE_ERR;
             mProxy->mArrayBufferResponseWasTransferred = false;
           }
         }
       }
     }
@@ -1341,23 +1336,21 @@ EventRunnable::WorkerRun(JSContext* aCx,
 
         JSAutoStructuredCloneBuffer responseBuffer(Move(mResponseBuffer));
 
         const JSStructuredCloneCallbacks* callbacks =
           aWorkerPrivate->IsChromeWorker() ?
           workers::ChromeWorkerStructuredCloneCallbacks(false) :
           workers::WorkerStructuredCloneCallbacks(false);
 
-        WorkerStructuredCloneClosure closure;
-        closure.mClonedObjects.SwapElements(mResponseClosure.mClonedObjects);
-        MOZ_ASSERT(mResponseClosure.mMessagePorts.IsEmpty());
-        MOZ_ASSERT(mResponseClosure.mMessagePortIdentifiers.IsEmpty());
+        nsTArray<nsCOMPtr<nsISupports> > clonedObjects;
+        clonedObjects.SwapElements(mClonedObjects);
 
         JS::Rooted<JS::Value> response(aCx);
-        if (!responseBuffer.read(aCx, &response, callbacks, &closure)) {
+        if (!responseBuffer.read(aCx, &response, callbacks, &clonedObjects)) {
           return false;
         }
 
         state->mResponse = response;
       }
       else {
         state->mResponse = mResponse;
       }
@@ -1528,27 +1521,27 @@ SendRunnable::MainThreadRun()
     nsresult rv = NS_OK;
 
     const JSStructuredCloneCallbacks* callbacks =
       mWorkerPrivate->IsChromeWorker() ?
       workers::ChromeWorkerStructuredCloneCallbacks(true) :
       workers::WorkerStructuredCloneCallbacks(true);
 
     JS::Rooted<JS::Value> body(cx);
-    if (mBody.read(cx, &body, callbacks, &mClosure)) {
+    if (mBody.read(cx, &body, callbacks, &mClonedObjects)) {
       if (NS_FAILED(xpc->JSValToVariant(cx, body, getter_AddRefs(variant)))) {
         rv = NS_ERROR_DOM_INVALID_STATE_ERR;
       }
     }
     else {
       rv = NS_ERROR_DOM_DATA_CLONE_ERR;
     }
 
     mBody.clear();
-    mClosure.Clear();
+    mClonedObjects.Clear();
 
     NS_ENSURE_SUCCESS(rv, rv);
   }
   else {
     nsCOMPtr<nsIWritableVariant> wvariant =
       do_CreateInstance(NS_VARIANT_CONTRACTID);
     NS_ENSURE_TRUE(wvariant, NS_ERROR_UNEXPECTED);
 
@@ -1848,17 +1841,17 @@ XMLHttpRequest::Unpin()
   mRooted = false;
 
   NS_RELEASE_THIS();
 }
 
 void
 XMLHttpRequest::SendInternal(const nsAString& aStringBody,
                              JSAutoStructuredCloneBuffer&& aBody,
-                             WorkerStructuredCloneClosure& aClosure,
+                             nsTArray<nsCOMPtr<nsISupports> >& aClonedObjects,
                              ErrorResult& aRv)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
 
   // No send() calls when open is running.
   if (mProxy->mOpening) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
@@ -1882,17 +1875,17 @@ XMLHttpRequest::SendInternal(const nsASt
   }
 
   mProxy->mOuterChannelId++;
 
   JSContext* cx = mWorkerPrivate->GetJSContext();
 
   nsRefPtr<SendRunnable> runnable =
     new SendRunnable(mWorkerPrivate, mProxy, aStringBody, Move(aBody),
-                     aClosure, syncLoopTarget, hasUploadListeners);
+                     aClonedObjects, syncLoopTarget, hasUploadListeners);
   if (!runnable->Dispatch(cx)) {
     // Dispatch() may have spun the event loop and we may have already unrooted.
     // If so we don't want autoUnpin to try again.
     if (!mRooted) {
       autoUnpin.Clear();
     }
     aRv.Throw(NS_ERROR_FAILURE);
     return;
@@ -2104,19 +2097,19 @@ XMLHttpRequest::Send(ErrorResult& aRv)
 
   if (!mProxy) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   // Nothing to clone.
   JSAutoStructuredCloneBuffer buffer;
-  WorkerStructuredCloneClosure closure;
-
-  SendInternal(NullString(), Move(buffer), closure, aRv);
+  nsTArray<nsCOMPtr<nsISupports> > clonedObjects;
+
+  SendInternal(NullString(), Move(buffer), clonedObjects, aRv);
 }
 
 void
 XMLHttpRequest::Send(const nsAString& aBody, ErrorResult& aRv)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
 
   if (mCanceled) {
@@ -2126,19 +2119,19 @@ XMLHttpRequest::Send(const nsAString& aB
 
   if (!mProxy) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   // Nothing to clone.
   JSAutoStructuredCloneBuffer buffer;
-  WorkerStructuredCloneClosure closure;
-
-  SendInternal(aBody, Move(buffer), closure, aRv);
+  nsTArray<nsCOMPtr<nsISupports> > clonedObjects;
+
+  SendInternal(aBody, Move(buffer), clonedObjects, aRv);
 }
 
 void
 XMLHttpRequest::Send(JS::Handle<JSObject*> aBody, ErrorResult& aRv)
 {
   JSContext* cx = mWorkerPrivate->GetJSContext();
 
   MOZ_ASSERT(aBody);
@@ -2169,25 +2162,25 @@ XMLHttpRequest::Send(JS::Handle<JSObject
     valToClone.setString(bodyStr);
   }
 
   const JSStructuredCloneCallbacks* callbacks =
     mWorkerPrivate->IsChromeWorker() ?
     ChromeWorkerStructuredCloneCallbacks(false) :
     WorkerStructuredCloneCallbacks(false);
 
-  WorkerStructuredCloneClosure closure;
+  nsTArray<nsCOMPtr<nsISupports> > clonedObjects;
 
   JSAutoStructuredCloneBuffer buffer;
-  if (!buffer.write(cx, valToClone, callbacks, &closure)) {
+  if (!buffer.write(cx, valToClone, callbacks, &clonedObjects)) {
     aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
     return;
   }
 
-  SendInternal(EmptyString(), Move(buffer), closure, aRv);
+  SendInternal(EmptyString(), Move(buffer), clonedObjects, aRv);
 }
 
 void
 XMLHttpRequest::Send(Blob& aBody, ErrorResult& aRv)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
   JSContext* cx = mWorkerPrivate->GetJSContext();
 
@@ -2215,25 +2208,25 @@ XMLHttpRequest::Send(Blob& aBody, ErrorR
     return;
   }
 
   const JSStructuredCloneCallbacks* callbacks =
     mWorkerPrivate->IsChromeWorker() ?
     ChromeWorkerStructuredCloneCallbacks(false) :
     WorkerStructuredCloneCallbacks(false);
 
-  WorkerStructuredCloneClosure closure;
+  nsTArray<nsCOMPtr<nsISupports> > clonedObjects;
 
   JSAutoStructuredCloneBuffer buffer;
-  if (!buffer.write(cx, value, callbacks, &closure)) {
+  if (!buffer.write(cx, value, callbacks, &clonedObjects)) {
     aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
     return;
   }
 
-  SendInternal(EmptyString(), Move(buffer), closure, aRv);
+  SendInternal(EmptyString(), Move(buffer), clonedObjects, aRv);
 }
 
 void
 XMLHttpRequest::Send(nsFormData& aBody, ErrorResult& aRv)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
   JSContext* cx = mWorkerPrivate->GetJSContext();
 
@@ -2253,24 +2246,25 @@ XMLHttpRequest::Send(nsFormData& aBody, 
     return;
   }
 
   const JSStructuredCloneCallbacks* callbacks =
     mWorkerPrivate->IsChromeWorker() ?
     ChromeWorkerStructuredCloneCallbacks(false) :
     WorkerStructuredCloneCallbacks(false);
 
+  nsTArray<nsCOMPtr<nsISupports>> clonedObjects;
+
   JSAutoStructuredCloneBuffer buffer;
-  WorkerStructuredCloneClosure closure;
-  if (!buffer.write(cx, value, callbacks, &closure)) {
+  if (!buffer.write(cx, value, callbacks, &clonedObjects)) {
     aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
     return;
   }
 
-  SendInternal(EmptyString(), Move(buffer), closure, aRv);
+  SendInternal(EmptyString(), Move(buffer), clonedObjects, aRv);
 }
 
 void
 XMLHttpRequest::Send(const ArrayBuffer& aBody, ErrorResult& aRv)
 {
   JS::Rooted<JSObject*> obj(mWorkerPrivate->GetJSContext(), aBody.Obj());
   return Send(obj, aRv);
 }
--- a/dom/workers/XMLHttpRequest.h
+++ b/dom/workers/XMLHttpRequest.h
@@ -23,17 +23,16 @@ class Blob;
 }
 }
 
 BEGIN_WORKERS_NAMESPACE
 
 class Proxy;
 class XMLHttpRequestUpload;
 class WorkerPrivate;
-class WorkerStructuredCloneClosure;
 
 class XMLHttpRequest final: public nsXHREventTarget,
                             public WorkerFeature
 {
 public:
   struct StateData
   {
     nsString mResponseText;
@@ -288,15 +287,15 @@ private:
   void
   DispatchPrematureAbortEvent(EventTarget* aTarget,
                               const nsAString& aEventType, bool aUploadTarget,
                               ErrorResult& aRv);
 
   void
   SendInternal(const nsAString& aStringBody,
                JSAutoStructuredCloneBuffer&& aBody,
-               WorkerStructuredCloneClosure& aClosure,
+               nsTArray<nsCOMPtr<nsISupports> >& aClonedObjects,
                ErrorResult& aRv);
 };
 
 END_WORKERS_NAMESPACE
 
 #endif // mozilla_dom_workers_xmlhttprequest_h__
--- a/dom/workers/test/sharedWorker_sharedWorker.js
+++ b/dom/workers/test/sharedWorker_sharedWorker.js
@@ -74,15 +74,15 @@ onconnect = function(event) {
 
   event.ports[0].onmessage = function(event) {
     if (!(event instanceof MessageEvent)) {
       throw new Error("'message' event is not a MessageEvent!");
     }
     if (!("ports" in event)) {
       throw new Error("'message' event doesn't have a 'ports' property!");
     }
-    if (event.ports === null) {
-      throw new Error("'message' event has a null 'ports' property!");
+    if (!(event.ports === null)) {
+      throw new Error("'message' event has a non-null 'ports' property!");
     }
     event.target.postMessage(event.data);
     throw new Error(event.data);
   };
 };
--- a/ipc/glue/BackgroundChild.h
+++ b/ipc/glue/BackgroundChild.h
@@ -10,17 +10,16 @@
 #include "mozilla/ipc/Transport.h"
 
 class nsIDOMBlob;
 class nsIIPCBackgroundChildCreateCallback;
 
 namespace mozilla {
 namespace dom {
 
-class BlobImpl;
 class ContentChild;
 class ContentParent;
 class PBlobChild;
 
 } // namespace dom
 
 namespace ipc {
 
@@ -63,20 +62,16 @@ public:
   // See above.
   static bool
   GetOrCreateForCurrentThread(nsIIPCBackgroundChildCreateCallback* aCallback);
 
   static mozilla::dom::PBlobChild*
   GetOrCreateActorForBlob(PBackgroundChild* aBackgroundActor,
                           nsIDOMBlob* aBlob);
 
-  static mozilla::dom::PBlobChild*
-  GetOrCreateActorForBlobImpl(PBackgroundChild* aBackgroundActor,
-                              mozilla::dom::BlobImpl* aBlobImpl);
-
   // See above.
   static void
   CloseForCurrentThread();
 
 private:
   // Only called by ContentChild or ContentParent.
   static void
   Startup();
--- a/ipc/glue/BackgroundChildImpl.cpp
+++ b/ipc/glue/BackgroundChildImpl.cpp
@@ -9,17 +9,16 @@
 #include "ServiceWorkerManagerChild.h"
 #include "FileDescriptorSetChild.h"
 #include "mozilla/media/MediaChild.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/dom/PBlobChild.h"
 #include "mozilla/dom/cache/ActorUtils.h"
 #include "mozilla/dom/indexedDB/PBackgroundIDBFactoryChild.h"
 #include "mozilla/dom/ipc/BlobChild.h"
-#include "mozilla/dom/MessagePortChild.h"
 #include "mozilla/ipc/PBackgroundTestChild.h"
 #include "mozilla/layout/VsyncChild.h"
 #include "mozilla/net/PUDPSocketChild.h"
 #include "mozilla/dom/network/UDPSocketChild.h"
 #include "nsID.h"
 #include "nsTraceRefcnt.h"
 
 namespace {
@@ -336,38 +335,16 @@ BackgroundChildImpl::AllocPMediaChild()
 }
 
 bool
 BackgroundChildImpl::DeallocPMediaChild(media::PMediaChild *aActor)
 {
   return media::DeallocPMediaChild(aActor);
 }
 
-// -----------------------------------------------------------------------------
-// MessageChannel/MessagePort API
-// -----------------------------------------------------------------------------
-
-dom::PMessagePortChild*
-BackgroundChildImpl::AllocPMessagePortChild(const nsID& aUUID,
-                                            const nsID& aDestinationUUID,
-                                            const uint32_t& aSequenceID)
-{
-  nsRefPtr<dom::MessagePortChild> agent = new dom::MessagePortChild();
-  return agent.forget().take();
-}
-
-bool
-BackgroundChildImpl::DeallocPMessagePortChild(PMessagePortChild* aActor)
-{
-  nsRefPtr<dom::MessagePortChild> child =
-    dont_AddRef(static_cast<dom::MessagePortChild*>(aActor));
-  MOZ_ASSERT(child);
-  return true;
-}
-
 } // namespace ipc
 } // namespace mozilla
 
 bool
 TestChild::Recv__delete__(const nsCString& aTestArg)
 {
   MOZ_RELEASE_ASSERT(aTestArg == mTestArg,
                      "BackgroundTest message was corrupted!");
--- a/ipc/glue/BackgroundChildImpl.h
+++ b/ipc/glue/BackgroundChildImpl.h
@@ -116,23 +116,16 @@ protected:
   virtual bool
   DeallocPCacheChild(dom::cache::PCacheChild* aActor) override;
 
   virtual dom::cache::PCacheStreamControlChild*
   AllocPCacheStreamControlChild() override;
 
   virtual bool
   DeallocPCacheStreamControlChild(dom::cache::PCacheStreamControlChild* aActor) override;
-
-  virtual PMessagePortChild*
-  AllocPMessagePortChild(const nsID& aUUID, const nsID& aDestinationUUID,
-                         const uint32_t& aSequenceID) override;
-
-  virtual bool
-  DeallocPMessagePortChild(PMessagePortChild* aActor) override;
 };
 
 class BackgroundChildImpl::ThreadLocal final
 {
   friend class nsAutoPtr<ThreadLocal>;
 
 public:
   nsAutoPtr<mozilla::dom::indexedDB::ThreadLocal> mIndexedDBThreadLocal;
--- a/ipc/glue/BackgroundImpl.cpp
+++ b/ipc/glue/BackgroundImpl.cpp
@@ -909,37 +909,27 @@ BackgroundChild::GetOrCreateForCurrentTh
   return ChildImpl::GetOrCreateForCurrentThread(aCallback);
 }
 
 // static
 PBlobChild*
 BackgroundChild::GetOrCreateActorForBlob(PBackgroundChild* aBackgroundActor,
                                          nsIDOMBlob* aBlob)
 {
+  MOZ_ASSERT(aBackgroundActor);
   MOZ_ASSERT(aBlob);
-
-  nsRefPtr<BlobImpl> blobImpl = static_cast<Blob*>(aBlob)->Impl();
-  MOZ_ASSERT(blobImpl);
-
-  return GetOrCreateActorForBlobImpl(aBackgroundActor, blobImpl);
-}
-
-// static
-PBlobChild*
-BackgroundChild::GetOrCreateActorForBlobImpl(PBackgroundChild* aBackgroundActor,
-                                             BlobImpl* aBlobImpl)
-{
-  MOZ_ASSERT(aBackgroundActor);
-  MOZ_ASSERT(aBlobImpl);
   MOZ_ASSERT(GetForCurrentThread(),
              "BackgroundChild not created on this thread yet!");
   MOZ_ASSERT(aBackgroundActor == GetForCurrentThread(),
              "BackgroundChild is bound to a different thread!");
 
-  BlobChild* actor = BlobChild::GetOrCreate(aBackgroundActor, aBlobImpl);
+  nsRefPtr<BlobImpl> blobImpl = static_cast<Blob*>(aBlob)->Impl();
+  MOZ_ASSERT(blobImpl);
+
+  BlobChild* actor = BlobChild::GetOrCreate(aBackgroundActor, blobImpl);
   if (NS_WARN_IF(!actor)) {
     return nullptr;
   }
 
   return actor;
 }
 
 // static
--- a/ipc/glue/BackgroundParentImpl.cpp
+++ b/ipc/glue/BackgroundParentImpl.cpp
@@ -6,17 +6,16 @@
 
 #include "BroadcastChannelParent.h"
 #include "FileDescriptorSetParent.h"
 #include "mozilla/media/MediaParent.h"
 #include "mozilla/AppProcessChecker.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/PBlobParent.h"
-#include "mozilla/dom/MessagePortParent.h"
 #include "mozilla/dom/ServiceWorkerRegistrar.h"
 #include "mozilla/dom/cache/ActorUtils.h"
 #include "mozilla/dom/indexedDB/ActorsParent.h"
 #include "mozilla/dom/ipc/BlobParent.h"
 #include "mozilla/ipc/BackgroundParent.h"
 #include "mozilla/ipc/BackgroundUtils.h"
 #include "mozilla/ipc/PBackgroundSharedTypes.h"
 #include "mozilla/ipc/PBackgroundTestParent.h"
@@ -35,18 +34,16 @@
 #else
 #define ASSERT_UNLESS_FUZZING(...) MOZ_ASSERT(false)
 #endif
 
 using mozilla::ipc::AssertIsOnBackgroundThread;
 using mozilla::dom::cache::PCacheParent;
 using mozilla::dom::cache::PCacheStorageParent;
 using mozilla::dom::cache::PCacheStreamControlParent;
-using mozilla::dom::MessagePortParent;
-using mozilla::dom::PMessagePortParent;
 using mozilla::dom::UDPSocketParent;
 
 namespace {
 
 void
 AssertIsInMainProcess()
 {
   MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
@@ -561,51 +558,16 @@ BackgroundParentImpl::AllocPCacheStreamC
 
 bool
 BackgroundParentImpl::DeallocPCacheStreamControlParent(PCacheStreamControlParent* aActor)
 {
   dom::cache::DeallocPCacheStreamControlParent(aActor);
   return true;
 }
 
-PMessagePortParent*
-BackgroundParentImpl::AllocPMessagePortParent(const nsID& aUUID,
-                                              const nsID& aDestinationUUID,
-                                              const uint32_t& aSequenceID)
-{
-  AssertIsInMainProcess();
-  AssertIsOnBackgroundThread();
-
-  return new MessagePortParent(aUUID);
-}
-
-bool
-BackgroundParentImpl::RecvPMessagePortConstructor(PMessagePortParent* aActor,
-                                                  const nsID& aUUID,
-                                                  const nsID& aDestinationUUID,
-                                                  const uint32_t& aSequenceID)
-{
-  AssertIsInMainProcess();
-  AssertIsOnBackgroundThread();
-
-  MessagePortParent* mp = static_cast<MessagePortParent*>(aActor);
-  return mp->Entangle(aDestinationUUID, aSequenceID);
-}
-
-bool
-BackgroundParentImpl::DeallocPMessagePortParent(PMessagePortParent* aActor)
-{
-  AssertIsInMainProcess();
-  AssertIsOnBackgroundThread();
-  MOZ_ASSERT(aActor);
-
-  delete static_cast<MessagePortParent*>(aActor);
-  return true;
-}
-
 } // namespace ipc
 } // namespace mozilla
 
 void
 TestParent::ActorDestroy(ActorDestroyReason aWhy)
 {
   AssertIsInMainProcess();
   AssertIsOnBackgroundThread();
--- a/ipc/glue/BackgroundParentImpl.h
+++ b/ipc/glue/BackgroundParentImpl.h
@@ -124,28 +124,14 @@ protected:
   AllocPUDPSocketParent(const OptionalPrincipalInfo& pInfo,
                         const nsCString& aFilter) override;
   virtual bool
   RecvPUDPSocketConstructor(PUDPSocketParent*,
                             const OptionalPrincipalInfo& aPrincipalInfo,
                             const nsCString& aFilter) override;
   virtual bool
   DeallocPUDPSocketParent(PUDPSocketParent*) override;
-
-  virtual PMessagePortParent*
-  AllocPMessagePortParent(const nsID& aUUID,
-                          const nsID& aDestinationUUID,
-                          const uint32_t& aSequenceID) override;
-
-  virtual bool
-  RecvPMessagePortConstructor(PMessagePortParent* aActor,
-                              const nsID& aUUID,
-                              const nsID& aDestinationUUID,
-                              const uint32_t& aSequenceID) override;
-
-  virtual bool
-  DeallocPMessagePortParent(PMessagePortParent* aActor) override;
 };
 
 } // namespace ipc
 } // namespace mozilla
 
 #endif // mozilla_ipc_backgroundparentimpl_h__
--- a/ipc/glue/PBackground.ipdl
+++ b/ipc/glue/PBackground.ipdl
@@ -5,17 +5,16 @@
 include protocol PBackgroundIDBFactory;
 include protocol PBackgroundTest;
 include protocol PBlob;
 include protocol PBroadcastChannel;
 include protocol PCache;
 include protocol PCacheStorage;
 include protocol PCacheStreamControl;
 include protocol PFileDescriptorSet;
-include protocol PMessagePort;
 include protocol PMedia;
 include protocol PServiceWorkerManager;
 include protocol PUDPSocket;
 include protocol PVsync;
 
 include DOMTypes;
 include PBackgroundSharedTypes;
 include PBackgroundIDBSharedTypes;
@@ -31,17 +30,16 @@ sync protocol PBackground
   manages PBackgroundIDBFactory;
   manages PBackgroundTest;
   manages PBlob;
   manages PBroadcastChannel;
   manages PCache;
   manages PCacheStorage;
   manages PCacheStreamControl;
   manages PFileDescriptorSet;
-  manages PMessagePort;
   manages PMedia;
   manages PServiceWorkerManager;
   manages PUDPSocket;
   manages PVsync;
 
 parent:
   // Only called at startup during mochitests to check the basic infrastructure.
   PBackgroundTest(nsCString testArg);
@@ -56,18 +54,16 @@ parent:
                     bool privateBrowsing);
 
   PServiceWorkerManager();
 
   ShutdownServiceWorkerRegistrar();
 
   PCacheStorage(Namespace aNamespace, PrincipalInfo aPrincipalInfo);
 
-  PMessagePort(nsID uuid, nsID destinationUuid, uint32_t sequenceId);
-
 child:
   PCache();
   PCacheStreamControl();
 
 both:
   PBlob(BlobConstructorParams params);
 
   PFileDescriptorSet(FileDescriptor fd);
--- a/js/public/StructuredClone.h
+++ b/js/public/StructuredClone.h
@@ -143,17 +143,17 @@ JS_ReadStructuredClone(JSContext* cx, ui
 JS_PUBLIC_API(bool)
 JS_WriteStructuredClone(JSContext* cx, JS::HandleValue v, uint64_t** datap, size_t* nbytesp,
                         const JSStructuredCloneCallbacks* optionalCallbacks,
                         void* closure, JS::HandleValue transferable);
 
 JS_PUBLIC_API(bool)
 JS_ClearStructuredClone(uint64_t* data, size_t nbytes,
                         const JSStructuredCloneCallbacks* optionalCallbacks,
-                        void *closure, bool freeData = true);
+                        void* closure);
 
 JS_PUBLIC_API(bool)
 JS_StructuredCloneHasTransferables(const uint64_t* data, size_t nbytes, bool* hasTransferable);
 
 JS_PUBLIC_API(bool)
 JS_StructuredClone(JSContext* cx, JS::HandleValue v, JS::MutableHandleValue vp,
                    const JSStructuredCloneCallbacks* optionalCallbacks, void* closure);
 
--- a/js/src/vm/StructuredClone.cpp
+++ b/js/src/vm/StructuredClone.cpp
@@ -1903,22 +1903,20 @@ JS_WriteStructuredClone(JSContext* cx, H
         optionalCallbacks :
         cx->runtime()->structuredCloneCallbacks;
     return WriteStructuredClone(cx, value, bufp, nbytesp, callbacks, closure, transferable);
 }
 
 JS_PUBLIC_API(bool)
 JS_ClearStructuredClone(uint64_t* data, size_t nbytes,
                         const JSStructuredCloneCallbacks* optionalCallbacks,
-                        void* closure, bool freeData)
+                        void* closure)
 {
     DiscardTransferables(data, nbytes, optionalCallbacks, closure);
-    if (freeData) {
-      js_free(data);
-    }
+    js_free(data);
     return true;
 }
 
 JS_PUBLIC_API(bool)
 JS_StructuredCloneHasTransferables(const uint64_t* data, size_t nbytes,
                                    bool* hasTransferable)
 {
     *hasTransferable = StructuredCloneHasTransferObjects(data, nbytes);
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/event-ports-dedicated.html.ini
@@ -0,0 +1,5 @@
+[event-ports-dedicated.html]
+  type: testharness
+  [e.ports in dedicated worker]
+    expected: FAIL
+