merge mozilla-inbound to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Tue, 13 Dec 2016 16:04:16 +0100
changeset 325719 cb369201f52f7f4c9cb35c3e7dca9262b13f006b
parent 325718 fee42adb860ed03be0de7dcb91cbfd2efcd8c01e (current diff)
parent 325685 2cc33db5d46c99957c1ba117692b54cf943db78b (diff)
child 325720 6ae74d693b83a0089f92bc118297620bd0fbfa73
child 325751 489f981e8c2beb050d7faee956dd940431bdafe6
child 325764 ca1d68c2fb549a1b9b41278bdeb34357faa8ad5c
push id84773
push usercbook@mozilla.com
push dateTue, 13 Dec 2016 15:52:51 +0000
treeherdermozilla-inbound@6ae74d693b83 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge mozilla-inbound to mozilla-central a=merge
js/src/wasm/WasmBaselineCompile.cpp
mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/SelectionHandlerTest.java
modules/libmar/tests/unit/data/0_sized_mar.mar
modules/libmar/tests/unit/data/1_byte_mar.mar
modules/libmar/tests/unit/data/binary_data_mar.mar
modules/libmar/tests/unit/data/manipulated_signed_mar.mar
modules/libmar/tests/unit/data/multiple_file_mar.mar
modules/libmar/tests/unit/data/multiple_signed_no_pib_mar.mar
modules/libmar/tests/unit/data/multiple_signed_pib_mar.mar
modules/libmar/tests/unit/data/multiple_signed_pib_mar_2.mar
modules/libmar/tests/unit/data/no_pib_mar.mar
modules/libmar/tests/unit/data/signed_no_pib_mar.mar
modules/libmar/tests/unit/data/signed_pib_mar.mar
modules/libmar/tests/unit/data/signed_pib_mar_with_mycert2.mar
modules/libmar/tests/unit/data/win_0_sized_mar.mar
modules/libmar/tests/unit/data/win_1_byte_mar.mar
modules/libmar/tests/unit/data/win_binary_data_mar.mar
modules/libmar/tests/unit/data/win_multiple_file_mar.mar
modules/libmar/tests/unit/data/win_multiple_signed_no_pib_mar.mar
modules/libmar/tests/unit/data/win_multiple_signed_pib_mar.mar
modules/libmar/tests/unit/data/win_signed_no_pib_mar.mar
modules/libmar/tests/unit/data/win_signed_pib_mar.mar
xpcom/build/nsXREAppData.h
xpcom/glue/AppData.cpp
xpcom/glue/AppData.h
--- a/browser/themes/osx/moz.build
+++ b/browser/themes/osx/moz.build
@@ -3,9 +3,11 @@
 # 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/.
 
 DIRS += ['communicator']
 
 JAR_MANIFESTS += ['jar.mn']
 
+DEFINES['CAN_DRAW_IN_TITLEBAR'] = 1
+
 include('../tab-svgs.mozbuild')
--- a/browser/themes/windows/moz.build
+++ b/browser/themes/windows/moz.build
@@ -3,9 +3,11 @@
 # 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/.
 
 DIRS += ['communicator']
 
 JAR_MANIFESTS += ['jar.mn']
 
+DEFINES['CAN_DRAW_IN_TITLEBAR'] = 1
+
 include('../tab-svgs.mozbuild')
--- a/devtools/client/inspector/markup/views/read-only-editor.js
+++ b/devtools/client/inspector/markup/views/read-only-editor.js
@@ -15,17 +15,17 @@ function ReadOnlyEditor(container, node)
   this.template = this.markup.template.bind(this.markup);
   this.elt = null;
   this.template("generic", this);
 
   if (node.isPseudoElement) {
     this.tag.classList.add("theme-fg-color5");
     this.tag.textContent = node.isBeforePseudoElement ? "::before" : "::after";
   } else if (node.nodeType == nodeConstants.DOCUMENT_TYPE_NODE) {
-    this.elt.classList.add("comment");
+    this.elt.classList.add("comment", "doctype");
     this.tag.textContent = node.doctypeString;
   } else {
     this.tag.textContent = node.nodeName;
   }
 }
 
 ReadOnlyEditor.prototype = {
   destroy: function () {
--- a/devtools/client/themes/common.css
+++ b/devtools/client/themes/common.css
@@ -27,17 +27,17 @@
   --proportional-font-family: Lucida Grande, Tahoma, sans-serif;
 }
 
 .devtools-monospace {
   font-family: var(--monospace-font-family);
 }
 
 :root[platform="linux"] .devtools-monospace {
-  font-size: 80%;
+  font-size: 11px;
 }
 
 /* Override wrong system font from forms.css */
 html|button, html|select {
   font: message-box;
 }
 
 /* Autocomplete Popup */
--- a/devtools/client/themes/markup.css
+++ b/devtools/client/themes/markup.css
@@ -294,16 +294,17 @@ ul.children + .tag-line::before {
   position: absolute;
   z-index: 1;
 }
 
 /* Firebug Theme */
 
 .theme-firebug .theme-fg-color3 {
   color: var(--theme-graphs-full-blue);
+  font-weight: normal;
 }
 
 .theme-firebug .open,
 .theme-firebug .close,
 .theme-firebug .attr-name.theme-fg-color2 {
   color: var(--theme-highlight-purple);
 }
 
@@ -330,20 +331,29 @@ ul.children + .tag-line::before {
 }
 
 /* Make sure even text nodes are white when selected in the Inspector panel. */
 .theme-firebug .theme-selected ~ .editor .open,
 .theme-firebug .theme-selected ~ .editor .close {
   color: var(--theme-selection-color);
 }
 
+/* Applicable to the DOCTYPE */
+.doctype {
+  font-style: italic;
+}
+
+.theme-firebug .doctype {
+  color: #787878;
+}
+
 /* In case a node isn't displayed in the page, we fade the syntax highlighting */
 .not-displayed .open,
 .not-displayed .close {
-  opacity: .7;
+  opacity: .5;
 }
 
 /* Events */
 .markupview-events {
   font-size: 8px;
   font-weight: bold;
   line-height: 10px;
   border-radius: 3px;
--- a/devtools/client/themes/rules.css
+++ b/devtools/client/themes/rules.css
@@ -14,21 +14,16 @@
 .theme-firebug {
   --rule-highlight-background-color: #ffee99;
   --rule-property-name: darkgreen;
   --rule-property-value: darkblue;
 }
 
 /* Rule View Tabpanel */
 
-.theme-firebug .ruleview {
-  font-family: monospace;
-  font-size: 11px;
-}
-
 #sidebar-panel-ruleview {
   margin: 0;
   display: flex;
   flex-direction: column;
   width: 100%;
   height: 100%;
   /* Override the min-width from .inspector-tabpanel, as the rule panel can support small
      widths */
--- a/devtools/client/themes/variables.css
+++ b/devtools/client/themes/variables.css
@@ -130,41 +130,41 @@
   --theme-tooltip-shadow: rgba(25, 25, 25, 0.76);
 
   /* Command line */
   --theme-command-line-image: url(chrome://devtools/skin/images/commandline-icon.svg#dark-theme);
   --theme-command-line-image-focus: url(chrome://devtools/skin/images/commandline-icon.svg#dark-theme-focus);
 }
 
 :root.theme-firebug {
-  --theme-body-background: #fcfcfc;
+  --theme-body-background: #fff;
   --theme-sidebar-background: #fcfcfc;
   --theme-contrast-background: #e6b064;
 
   --theme-tab-toolbar-background: #d8eaf9;
   --theme-toolbar-background: #f0f1f2;
   --theme-selection-background: #3399ff;
   --theme-selection-background-semitransparent: rgba(128,128,128,0.2);
   --theme-selection-color: white;
   --theme-splitter-color: #aabccf;
-  --theme-comment: green;
+  --theme-comment: darkgreen;
 
   --theme-body-color: #000000;
   --theme-body-color-alt: #585959;
   --theme-content-color1: #292e33;
   --theme-content-color2: #8fa1b2;
   --theme-content-color3: #667380;
 
   --theme-highlight-green: #2cbb0f;
   --theme-highlight-blue: #3455db;
   --theme-highlight-bluegrey: #0072ab;
-  --theme-highlight-purple: #887ce6;
+  --theme-highlight-purple: #000080;
   --theme-highlight-lightorange: #d97e00;
   --theme-highlight-orange: #f13c00;
-  --theme-highlight-red: #e22f6f;
+  --theme-highlight-red: #f00;
   --theme-highlight-pink: #b82ee5;
   --theme-highlight-gray: #dde1e4;
 
   /* Colors used in Graphs, like performance tools. Similar colors to Chrome's timeline. */
   --theme-graphs-green: #85d175;
   --theme-graphs-blue: #83b7f6;
   --theme-graphs-bluegrey: #0072ab;
   --theme-graphs-purple: #b693eb;
--- a/dom/archivereader/ArchiveEvent.cpp
+++ b/dom/archivereader/ArchiveEvent.cpp
@@ -10,22 +10,20 @@
 #include "nsProxyRelease.h"
 
 USING_ARCHIVEREADER_NAMESPACE
 
 NS_IMPL_ISUPPORTS0(ArchiveItem)
 
 ArchiveItem::ArchiveItem()
 {
-  MOZ_COUNT_CTOR(ArchiveItem);
 }
 
 ArchiveItem::~ArchiveItem()
 {
-  MOZ_COUNT_DTOR(ArchiveItem);
 }
 
 
 nsCString
 ArchiveItem::GetType()
 {
   if (mType.IsEmpty()) {
     return NS_LITERAL_CSTRING("binary/octet-stream");
@@ -38,26 +36,23 @@ void
 ArchiveItem::SetType(const nsCString& aType)
 {
   mType = aType;
 }
 
 ArchiveReaderEvent::ArchiveReaderEvent(ArchiveReader* aArchiveReader)
 : mArchiveReader(aArchiveReader)
 {
-  MOZ_COUNT_CTOR(ArchiveReaderEvent);
 }
 
 ArchiveReaderEvent::~ArchiveReaderEvent()
 {
   if (!NS_IsMainThread()) {
     NS_ReleaseOnMainThread(mMimeService.forget());
   }
-
-  MOZ_COUNT_DTOR(ArchiveReaderEvent);
 }
 
 // From the filename to the mimetype:
 nsresult
 ArchiveReaderEvent::GetType(nsCString& aExt,
                             nsCString& aMimeType)
 {
   MOZ_ASSERT(NS_IsMainThread());
--- a/dom/archivereader/ArchiveRequest.cpp
+++ b/dom/archivereader/ArchiveRequest.cpp
@@ -21,23 +21,21 @@ USING_ARCHIVEREADER_NAMESPACE
 class ArchiveRequestEvent : public Runnable
 {
 public:
   NS_DECL_NSIRUNNABLE
 
   explicit ArchiveRequestEvent(ArchiveRequest* aRequest)
   : mRequest(aRequest)
   {
-    MOZ_COUNT_CTOR(ArchiveRequestEvent);
   }
 
 protected:
   ~ArchiveRequestEvent()
   {
-    MOZ_COUNT_DTOR(ArchiveRequestEvent);
   }
 
 private: //data
   RefPtr<ArchiveRequest> mRequest;
 };
 
 NS_IMETHODIMP
 ArchiveRequestEvent::Run()
@@ -51,26 +49,23 @@ ArchiveRequestEvent::Run()
 
 ArchiveRequest::ArchiveRequest(nsPIDOMWindowInner* aWindow,
                                ArchiveReader* aReader)
 : DOMRequest(aWindow),
   mArchiveReader(aReader)
 {
   MOZ_ASSERT(aReader);
 
-  MOZ_COUNT_CTOR(ArchiveRequest);
-
   /* An event to make this request asynchronous: */
   RefPtr<ArchiveRequestEvent> event = new ArchiveRequestEvent(this);
   NS_DispatchToCurrentThread(event);
 }
 
 ArchiveRequest::~ArchiveRequest()
 {
-  MOZ_COUNT_DTOR(ArchiveRequest);
 }
 
 nsresult
 ArchiveRequest::GetEventTargetParent(EventChainPreVisitor& aVisitor)
 {
   aVisitor.mCanHandle = true;
   aVisitor.mParentTarget = nullptr;
   return NS_OK;
--- a/dom/archivereader/ArchiveZipEvent.cpp
+++ b/dom/archivereader/ArchiveZipEvent.cpp
@@ -23,22 +23,20 @@ USING_ARCHIVEREADER_NAMESPACE
 
 ArchiveZipItem::ArchiveZipItem(const char* aFilename,
                                const ZipCentral& aCentralStruct,
                                const nsACString& aEncoding)
 : mFilename(aFilename),
   mCentralStruct(aCentralStruct),
   mEncoding(aEncoding)
 {
-  MOZ_COUNT_CTOR(ArchiveZipItem);
 }
 
 ArchiveZipItem::~ArchiveZipItem()
 {
-  MOZ_COUNT_DTOR(ArchiveZipItem);
 }
 
 nsresult
 ArchiveZipItem::ConvertFilename()
 {
   if (mEncoding.IsEmpty()) {
     return NS_ERROR_FAILURE;
   }
--- a/dom/archivereader/ArchiveZipFile.cpp
+++ b/dom/archivereader/ArchiveZipFile.cpp
@@ -31,33 +31,30 @@ public:
                      uint32_t aLength,
                      ZipCentral& aCentral)
   : mCentral(aCentral),
     mFilename(aFilename),
     mStart(aStart),
     mLength(aLength),
     mStatus(NotStarted)
   {
-    MOZ_COUNT_CTOR(ArchiveInputStream);
-
     // Reset the data:
     memset(&mData, 0, sizeof(mData));
 
     mData.parentSize = aParentSize;
     mData.inputStream = aInputStream;
   }
 
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIINPUTSTREAM
   NS_DECL_NSISEEKABLESTREAM
 
 private:
   virtual ~ArchiveInputStream()
   {
-    MOZ_COUNT_DTOR(ArchiveInputStream);
     Close();
   }
 
   nsresult Init();
 
 private: // data
   ZipCentral mCentral;
   nsString mFilename;
--- a/dom/archivereader/ArchiveZipFile.h
+++ b/dom/archivereader/ArchiveZipFile.h
@@ -32,42 +32,39 @@ public:
                      ZipCentral& aCentral,
                      BlobImpl* aBlobImpl)
   : BlobImplBase(aName, aContentType, aLength),
     mCentral(aCentral),
     mBlobImpl(aBlobImpl),
     mFilename(aName)
   {
     MOZ_ASSERT(mBlobImpl);
-    MOZ_COUNT_CTOR(ArchiveZipBlobImpl);
   }
 
   ArchiveZipBlobImpl(const nsAString& aName,
                      const nsAString& aContentType,
                      uint64_t aStart,
                      uint64_t aLength,
                      ZipCentral& aCentral,
                      BlobImpl* aBlobImpl)
   : BlobImplBase(aContentType, aStart, aLength),
     mCentral(aCentral),
     mBlobImpl(aBlobImpl),
     mFilename(aName)
   {
     MOZ_ASSERT(mBlobImpl);
-    MOZ_COUNT_CTOR(ArchiveZipBlobImpl);
   }
 
   // Overrides:
   virtual void GetInternalStream(nsIInputStream** aInputStream,
                                  ErrorResult& aRv) override;
 
 protected:
   virtual ~ArchiveZipBlobImpl()
   {
-    MOZ_COUNT_DTOR(ArchiveZipBlobImpl);
   }
 
   virtual already_AddRefed<BlobImpl>
   CreateSlice(uint64_t aStart, uint64_t aLength, const nsAString& aContentType,
               mozilla::ErrorResult& aRv) override;
 
 private: // Data
   ZipCentral mCentral;
--- a/dom/asmjscache/AsmJSCache.cpp
+++ b/dom/asmjscache/AsmJSCache.cpp
@@ -355,26 +355,24 @@ public:
     mResult(JS::AsmJSCache_InternalError),
     mIsApp(false),
     mEnforcingQuota(true),
     mActorDestroyed(false),
     mOpened(false)
   {
     MOZ_ASSERT(XRE_IsParentProcess());
     AssertIsOnOwningThread();
-    MOZ_COUNT_CTOR(ParentRunnable);
   }
 
 private:
   ~ParentRunnable() override
   {
     MOZ_ASSERT(mState == eFinished);
     MOZ_ASSERT(!mDirectoryLock);
     MOZ_ASSERT(mActorDestroyed);
-    MOZ_COUNT_DTOR(ParentRunnable);
   }
 
   bool
   IsOnOwningThread() const
   {
     MOZ_ASSERT(mOwningThread);
 
     bool current;
@@ -1228,17 +1226,16 @@ public:
     mOpenMode(aOpenMode),
     mState(eInitial),
     mResult(JS::AsmJSCache_InternalError),
     mActorDestroyed(false),
     mWaiting(false),
     mOpened(false)
   {
     MOZ_ASSERT(!NS_IsMainThread());
-    MOZ_COUNT_CTOR(ChildRunnable);
   }
 
   JS::AsmJSCacheResult
   BlockUntilOpen(AutoClose* aCloser)
   {
     MOZ_ASSERT(!mWaiting, "Can only call BlockUntilOpen once");
     MOZ_ASSERT(!mOpened, "Can only call BlockUntilOpen once");
 
@@ -1277,17 +1274,16 @@ public:
 
 private:
   ~ChildRunnable() override
   {
     MOZ_ASSERT(!mWaiting, "Shouldn't be destroyed while thread is waiting");
     MOZ_ASSERT(!mOpened);
     MOZ_ASSERT(mState == eFinished);
     MOZ_ASSERT(mActorDestroyed);
-    MOZ_COUNT_DTOR(ChildRunnable);
   }
 
   // IPDL methods.
   mozilla::ipc::IPCResult
   RecvOnOpenMetadataForRead(const Metadata& aMetadata) override
   {
     MOZ_ASSERT(NS_IsMainThread());
     MOZ_ASSERT(mState == eOpening);
--- a/dom/base/Crypto.cpp
+++ b/dom/base/Crypto.cpp
@@ -27,22 +27,20 @@ NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(Crypto)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(Crypto)
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Crypto, mParent, mSubtle)
 
 Crypto::Crypto()
 {
-  MOZ_COUNT_CTOR(Crypto);
 }
 
 Crypto::~Crypto()
 {
-  MOZ_COUNT_DTOR(Crypto);
 }
 
 void
 Crypto::Init(nsIGlobalObject* aParent)
 {
   mParent = do_QueryInterface(aParent);
   MOZ_ASSERT(mParent);
 }
--- a/dom/base/PostMessageEvent.cpp
+++ b/dom/base/PostMessageEvent.cpp
@@ -39,22 +39,20 @@ PostMessageEvent::PostMessageEvent(nsGlo
                         StructuredCloneScope::SameProcessSameThread),
   mSource(aSource),
   mCallerOrigin(aCallerOrigin),
   mTargetWindow(aTargetWindow),
   mProvidedPrincipal(aProvidedPrincipal),
   mSourceDocument(aSourceDocument),
   mTrustedCaller(aTrustedCaller)
 {
-  MOZ_COUNT_CTOR(PostMessageEvent);
 }
 
 PostMessageEvent::~PostMessageEvent()
 {
-  MOZ_COUNT_DTOR(PostMessageEvent);
 }
 
 NS_IMETHODIMP
 PostMessageEvent::Run()
 {
   MOZ_ASSERT(mTargetWindow->IsOuterWindow(),
              "should have been passed an outer window!");
   MOZ_ASSERT(!mSource || mSource->IsOuterWindow(),
--- a/dom/base/ResponsiveImageSelector.cpp
+++ b/dom/base/ResponsiveImageSelector.cpp
@@ -237,17 +237,17 @@ ResponsiveImageSelector::SetSizesFromDes
 {
   ClearSelectedCandidate();
   mSizeQueries.Clear();
   mSizeValues.Clear();
 
   nsCSSParser cssParser;
 
   return cssParser.ParseSourceSizeList(aSizes, nullptr, 0,
-                                       mSizeQueries, mSizeValues, true);
+                                       mSizeQueries, mSizeValues);
 }
 
 void
 ResponsiveImageSelector::AppendCandidateIfUnique(const ResponsiveImageCandidate & aCandidate)
 {
   int numCandidates = mCandidates.Length();
 
   // With the exception of Default, which should not be added until we are done
--- a/dom/base/ShadowRoot.cpp
+++ b/dom/base/ShadowRoot.cpp
@@ -734,22 +734,20 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_
 NS_INTERFACE_MAP_END_INHERITING(StyleSheetList)
 
 NS_IMPL_ADDREF_INHERITED(ShadowRootStyleSheetList, StyleSheetList)
 NS_IMPL_RELEASE_INHERITED(ShadowRootStyleSheetList, StyleSheetList)
 
 ShadowRootStyleSheetList::ShadowRootStyleSheetList(ShadowRoot* aShadowRoot)
   : mShadowRoot(aShadowRoot)
 {
-  MOZ_COUNT_CTOR(ShadowRootStyleSheetList);
 }
 
 ShadowRootStyleSheetList::~ShadowRootStyleSheetList()
 {
-  MOZ_COUNT_DTOR(ShadowRootStyleSheetList);
 }
 
 StyleSheet*
 ShadowRootStyleSheetList::IndexedGetter(uint32_t aIndex, bool& aFound)
 {
   aFound = aIndex < mShadowRoot->mProtoBinding->SheetCount();
   if (!aFound) {
     return nullptr;
--- a/dom/base/nsContentPermissionHelper.cpp
+++ b/dom/base/nsContentPermissionHelper.cpp
@@ -569,22 +569,20 @@ nsContentPermissionRequestProxy::nsConte
 
   if (mOnChangeCallback) {
     mOnChangeCallback->NotifyVisibility(aIsVisible);
   }
 }
 
 nsContentPermissionRequestProxy::nsContentPermissionRequestProxy()
 {
-  MOZ_COUNT_CTOR(nsContentPermissionRequestProxy);
 }
 
 nsContentPermissionRequestProxy::~nsContentPermissionRequestProxy()
 {
-  MOZ_COUNT_DTOR(nsContentPermissionRequestProxy);
 }
 
 nsresult
 nsContentPermissionRequestProxy::Init(const nsTArray<PermissionRequest>& requests,
                                       ContentPermissionRequestParent* parent)
 {
   NS_ASSERTION(parent, "null parent");
   mParent = parent;
--- a/dom/base/nsCopySupport.cpp
+++ b/dom/base/nsCopySupport.cpp
@@ -584,16 +584,25 @@ static nsresult AppendDOMNode(nsITransfe
 #ifdef XP_WIN
 static nsresult AppendImagePromise(nsITransferable* aTransferable,
                                    imgIRequest* aImgRequest,
                                    nsIImageLoadingContent* aImageElement)
 {
   nsresult rv;
 
   NS_ENSURE_TRUE(aImgRequest, NS_OK);
+
+  uint32_t imageStatus;
+  rv = aImgRequest->GetImageStatus(&imageStatus);
+  NS_ENSURE_SUCCESS(rv, rv);
+  if (!(imageStatus & imgIRequest::STATUS_FRAME_COMPLETE) ||
+      (imageStatus & imgIRequest::STATUS_ERROR)) {
+    return NS_OK;
+  }
+
   nsCOMPtr<nsINode> node = do_QueryInterface(aImageElement, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Fix the file extension in the URL if necessary
   nsCOMPtr<nsIMIMEService> mimeService =
     do_GetService(NS_MIMESERVICE_CONTRACTID);
   NS_ENSURE_TRUE(mimeService, NS_OK);
 
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -787,26 +787,16 @@ NS_IMETHODIMP
 nsDOMClassInfo::PreCreate(nsISupports *nativeObj, JSContext *cx,
                           JSObject *globalObj, JSObject **parentObj)
 {
   *parentObj = globalObj;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDOMClassInfo::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                            JSObject *obj, jsid id, JS::Handle<JS::Value> val,
-                            bool *_retval)
-{
-  NS_WARNING("nsDOMClassInfo::AddProperty Don't call me!");
-
-  return NS_ERROR_UNEXPECTED;
-}
-
-NS_IMETHODIMP
 nsDOMClassInfo::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                             JSObject *obj, jsid id, JS::Value *vp,
                             bool *_retval)
 {
   NS_WARNING("nsDOMClassInfo::GetProperty Don't call me!");
 
   return NS_OK;
 }
@@ -1959,26 +1949,16 @@ nsEventTargetSH::PreCreate(nsISupports *
   nsCOMPtr<nsIScriptGlobalObject> native_parent;
   target->GetParentObject(getter_AddRefs(native_parent));
 
   *parentObj = native_parent ? native_parent->GetGlobalJSObject() : globalObj;
 
   return *parentObj ? NS_OK : NS_ERROR_FAILURE;
 }
 
-NS_IMETHODIMP
-nsEventTargetSH::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                             JSObject *obj, jsid id, JS::Handle<JS::Value> val,
-                             bool *_retval)
-{
-  nsEventTargetSH::PreserveWrapper(GetNative(wrapper, obj));
-
-  return NS_OK;
-}
-
 void
 nsEventTargetSH::PreserveWrapper(nsISupports *aNative)
 {
   DOMEventTargetHelper* target = DOMEventTargetHelper::FromSupports(aNative);
   target->PreserveWrapper(aNative);
 }
 
 // nsIDOMEventListener::HandleEvent() 'this' converter helper
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -170,26 +170,18 @@ protected:
   }
 
   virtual ~nsEventTargetSH()
   {
   }
 public:
   NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
                        JSObject *globalObj, JSObject **parentObj) override;
-  NS_IMETHOD AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                         JSObject *obj, jsid id, JS::Handle<JS::Value> val,
-                         bool *_retval) override;
 
   virtual void PreserveWrapper(nsISupports *aNative) override;
-
-  static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
-  {
-    return new nsEventTargetSH(aData);
-  }
 };
 
 // A place to hang some static methods that we should really consider
 // moving to be nsGlobalWindow member methods.  See bug 1062418.
 class nsWindowSH
 {
 protected:
   static nsresult GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -1213,23 +1213,21 @@ void nsIDocument::SelectorCache::CacheLi
 }
 
 class nsIDocument::SelectorCacheKeyDeleter final : public Runnable
 {
 public:
   explicit SelectorCacheKeyDeleter(SelectorCacheKey* aToDelete)
     : mSelector(aToDelete)
   {
-    MOZ_COUNT_CTOR(SelectorCacheKeyDeleter);
   }
 
 protected:
   ~SelectorCacheKeyDeleter()
   {
-    MOZ_COUNT_DTOR(SelectorCacheKeyDeleter);
   }
 
 public:
   NS_IMETHOD Run() override
   {
     return NS_OK;
   }
 
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -2818,18 +2818,17 @@ nsGlobalWindow::SetNewDocument(nsIDocume
         // Make a copy of the old window's performance object on document.open.
         // Note that we have to force eager creation of it here, because we need
         // to grab the current document channel and whatnot before that changes.
         currentInner->AsInner()->CreatePerformanceObjectIfNeeded();
         if (currentInner->mPerformance) {
           newInnerWindow->mPerformance =
             Performance::CreateForMainThread(newInnerWindow->AsInner(),
                                              currentInner->mPerformance->GetDOMTiming(),
-                                             currentInner->mPerformance->GetChannel(),
-                                             currentInner->mPerformance->GetParentPerformance());
+                                             currentInner->mPerformance->GetChannel());
         }
       }
 
       // Don't free objects on our current inner window if it's going to be
       // held in the bfcache.
       if (!currentInner->IsFrozen()) {
         currentInner->FreeInnerObjects();
       }
@@ -4028,32 +4027,17 @@ nsPIDOMWindowInner::CreatePerformanceObj
   nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(mDoc->GetChannel()));
   bool timingEnabled = false;
   if (!timedChannel ||
       !NS_SUCCEEDED(timedChannel->GetTimingEnabled(&timingEnabled)) ||
       !timingEnabled) {
     timedChannel = nullptr;
   }
   if (timing) {
-    // If we are dealing with an iframe, we will need the parent's performance
-    // object (so we can add the iframe as a resource of that page).
-    Performance* parentPerformance = nullptr;
-    nsCOMPtr<nsPIDOMWindowOuter> parentWindow = GetScriptableParentOrNull();
-    if (parentWindow) {
-      nsPIDOMWindowInner* parentInnerWindow = nullptr;
-      if (parentWindow) {
-        parentInnerWindow = parentWindow->GetCurrentInnerWindow();
-      }
-      if (parentInnerWindow) {
-        parentPerformance = parentInnerWindow->GetPerformance();
-      }
-    }
-    mPerformance =
-      Performance::CreateForMainThread(this, timing, timedChannel,
-                                       parentPerformance);
+    mPerformance = Performance::CreateForMainThread(this, timing, timedChannel);
   }
 }
 
 bool
 nsPIDOMWindowInner::IsSecureContext() const
 {
   return nsGlobalWindow::Cast(this)->IsSecureContext();
 }
@@ -6407,25 +6391,23 @@ public:
     : mWindow(aWindow)
     , mWidget(aWidget)
     , mScreen(aScreen)
     , mTransitionData(aTransitionData)
     , mDuration(aDuration)
     , mStage(eBeforeToggle)
     , mFullscreen(aFullscreen)
   {
-    MOZ_COUNT_CTOR(FullscreenTransitionTask);
   }
 
   NS_IMETHOD Run() override;
 
 private:
   ~FullscreenTransitionTask() override
   {
-    MOZ_COUNT_DTOR(FullscreenTransitionTask);
   }
 
   /**
    * The flow of fullscreen transition:
    *
    *         parent process         |         child process
    * ----------------------------------------------------------------
    *
@@ -10859,17 +10841,19 @@ nsGlobalWindow::GetLocalStorage(ErrorRes
     nsString documentURI;
     if (mDoc) {
       aError = mDoc->GetDocumentURI(documentURI);
       if (NS_WARN_IF(aError.Failed())) {
         return nullptr;
       }
     }
 
-    MOZ_DIAGNOSTIC_ASSERT((principal->GetPrivateBrowsingId() > 0) == IsPrivateBrowsing());
+    //XXX huseby -- was causing crashes see bug 1321969. Bug 1322760 covers
+    //investigating and fixing the following assert.
+    //MOZ_DIAGNOSTIC_ASSERT((principal->GetPrivateBrowsingId() > 0) == IsPrivateBrowsing());
 
     nsCOMPtr<nsIDOMStorage> storage;
     aError = storageManager->CreateStorage(AsInner(), principal, documentURI,
                                            getter_AddRefs(storage));
     if (aError.Failed()) {
       return nullptr;
     }
 
--- a/dom/base/nsScriptNameSpaceManager.cpp
+++ b/dom/base/nsScriptNameSpaceManager.cpp
@@ -97,23 +97,21 @@ static const PLDHashTableOps hash_table_
 };
 
 #define GLOBALNAME_HASHTABLE_INITIAL_LENGTH          32
 
 nsScriptNameSpaceManager::nsScriptNameSpaceManager()
   : mGlobalNames(&hash_table_ops, sizeof(GlobalNameMapEntry),
                  GLOBALNAME_HASHTABLE_INITIAL_LENGTH)
 {
-  MOZ_COUNT_CTOR(nsScriptNameSpaceManager);
 }
 
 nsScriptNameSpaceManager::~nsScriptNameSpaceManager()
 {
   UnregisterWeakMemoryReporter(this);
-  MOZ_COUNT_DTOR(nsScriptNameSpaceManager);
 }
 
 nsGlobalNameStruct *
 nsScriptNameSpaceManager::AddToHash(const char *aKey,
                                     const char16_t **aClassName)
 {
   NS_ConvertASCIItoUTF16 key(aKey);
   auto entry = static_cast<GlobalNameMapEntry*>(mGlobalNames.Add(&key, fallible));
--- a/dom/canvas/ImageData.h
+++ b/dom/canvas/ImageData.h
@@ -20,27 +20,25 @@
 
 namespace mozilla {
 namespace dom {
 
 class ImageData final : public nsISupports
 {
   ~ImageData()
   {
-    MOZ_COUNT_DTOR(ImageData);
     DropData();
   }
 
 public:
   ImageData(uint32_t aWidth, uint32_t aHeight, JSObject& aData)
     : mWidth(aWidth)
     , mHeight(aHeight)
     , mData(&aData)
   {
-    MOZ_COUNT_CTOR(ImageData);
     HoldData();
   }
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ImageData)
 
   static already_AddRefed<ImageData>
     Constructor(const GlobalObject& aGlobal,
--- a/dom/file/File.cpp
+++ b/dom/file/File.cpp
@@ -77,17 +77,17 @@ private:
   ~DataOwnerAdapter() {}
 
   DataOwnerAdapter(DataOwner* aDataOwner,
                    nsIInputStream* aStream)
     : mDataOwner(aDataOwner), mStream(aStream),
       mSeekableStream(do_QueryInterface(aStream)),
       mSerializableInputStream(do_QueryInterface(aStream))
   {
-    NS_ASSERTION(mSeekableStream, "Somebody gave us the wrong stream!");
+    MOZ_ASSERT(mSeekableStream, "Somebody gave us the wrong stream!");
   }
 
   RefPtr<DataOwner> mDataOwner;
   nsCOMPtr<nsIInputStream> mStream;
   nsCOMPtr<nsISeekableStream> mSeekableStream;
   nsCOMPtr<nsIIPCSerializableInputStream> mSerializableInputStream;
 };
 
@@ -103,17 +103,17 @@ NS_INTERFACE_MAP_BEGIN(DataOwnerAdapter)
 NS_INTERFACE_MAP_END
 
 nsresult DataOwnerAdapter::Create(DataOwner* aDataOwner,
                                   uint32_t aStart,
                                   uint32_t aLength,
                                   nsIInputStream** _retval)
 {
   nsresult rv;
-  NS_ASSERTION(aDataOwner, "Uh ...");
+  MOZ_ASSERT(aDataOwner, "Uh ...");
 
   nsCOMPtr<nsIInputStream> stream;
 
   rv = NS_NewByteInputStream(getter_AddRefs(stream),
                              static_cast<const char*>(aDataOwner->mData) +
                              aStart,
                              (int32_t)aLength,
                              NS_ASSIGNMENT_DEPEND);
@@ -667,38 +667,38 @@ NS_IMPL_ISUPPORTS(BlobImpl, BlobImpl)
 ////////////////////////////////////////////////////////////////////////////
 // BlobImplFile implementation
 
 NS_IMPL_ISUPPORTS_INHERITED0(BlobImplFile, BlobImpl)
 
 void
 BlobImplBase::GetName(nsAString& aName) const
 {
-  NS_ASSERTION(mIsFile, "Should only be called on files");
+  MOZ_ASSERT(mIsFile, "Should only be called on files");
   aName = mName;
 }
 
 void
 BlobImplBase::GetPath(nsAString& aPath) const
 {
-  NS_ASSERTION(mIsFile, "Should only be called on files");
+  MOZ_ASSERT(mIsFile, "Should only be called on files");
   aPath = mPath;
 }
 
 void
 BlobImplBase::SetPath(const nsAString& aPath)
 {
-  NS_ASSERTION(mIsFile, "Should only be called on files");
+  MOZ_ASSERT(mIsFile, "Should only be called on files");
   mPath = aPath;
 }
 
 void
 BlobImplBase::GetMozFullPath(nsAString& aFileName, ErrorResult& aRv) const
 {
-  NS_ASSERTION(mIsFile, "Should only be called on files");
+  MOZ_ASSERT(mIsFile, "Should only be called on files");
 
   aFileName.Truncate();
 
   if (NS_IsMainThread()) {
     if (nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
       GetMozFullPathInternal(aFileName, aRv);
     }
 
@@ -728,17 +728,17 @@ void
 BlobImplBase::GetType(nsAString& aType)
 {
   aType = mContentType;
 }
 
 int64_t
 BlobImplBase::GetLastModified(ErrorResult& aRv)
 {
-  NS_ASSERTION(mIsFile, "Should only be called on files");
+  MOZ_ASSERT(mIsFile, "Should only be called on files");
   if (IsDateUnknown()) {
     mLastModificationDate = PR_Now();
   }
 
   return mLastModificationDate / PR_USEC_PER_MSEC;
 }
 
 void
@@ -835,25 +835,25 @@ BlobImplFile::CreateSlice(uint64_t aStar
   RefPtr<BlobImpl> impl =
     new BlobImplFile(this, aStart, aLength, aContentType);
   return impl.forget();
 }
 
 void
 BlobImplFile::GetMozFullPathInternal(nsAString& aFilename, ErrorResult& aRv) const
 {
-  NS_ASSERTION(mIsFile, "Should only be called on files");
+  MOZ_ASSERT(mIsFile, "Should only be called on files");
   aRv = mFile->GetPath(aFilename);
 }
 
 uint64_t
 BlobImplFile::GetSize(ErrorResult& aRv)
 {
   if (BlobImplBase::IsSizeUnknown()) {
-    NS_ASSERTION(mWholeFile,
+    MOZ_ASSERT(mWholeFile,
                  "Should only use lazy size when using the whole file");
     int64_t fileSize;
     aRv = mFile->GetFileSize(&fileSize);
     if (NS_WARN_IF(aRv.Failed())) {
       return 0;
     }
 
     if (fileSize < 0) {
@@ -902,18 +902,18 @@ private:
 } // anonymous namespace
 
 void
 BlobImplFile::GetType(nsAString& aType)
 {
   aType.Truncate();
 
   if (mContentType.IsVoid()) {
-    NS_ASSERTION(mWholeFile,
-                 "Should only use lazy ContentType when using the whole file");
+    MOZ_ASSERT(mWholeFile,
+               "Should only use lazy ContentType when using the whole file");
 
     if (!NS_IsMainThread()) {
       WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
       if (!workerPrivate) {
         // I have no idea in which thread this method is called. We cannot
         // return any valid value.
         return;
       }
@@ -947,17 +947,17 @@ BlobImplFile::GetType(nsAString& aType)
   }
 
   aType = mContentType;
 }
 
 int64_t
 BlobImplFile::GetLastModified(ErrorResult& aRv)
 {
-  NS_ASSERTION(mIsFile, "Should only be called on files");
+  MOZ_ASSERT(mIsFile, "Should only be called on files");
   if (BlobImplBase::IsDateUnknown()) {
     PRTime msecs;
     aRv = mFile->GetLastModifiedTime(&msecs);
     if (NS_WARN_IF(aRv.Failed())) {
       return 0;
     }
 
     mLastModificationDate = msecs;
--- a/dom/file/File.h
+++ b/dom/file/File.h
@@ -389,18 +389,17 @@ public:
     : mIsFile(false)
     , mImmutable(false)
     , mContentType(aContentType)
     , mStart(aStart)
     , mLength(aLength)
     , mLastModificationDate(INT64_MAX)
     , mSerialNumber(NextSerialNumber())
   {
-    NS_ASSERTION(aLength != UINT64_MAX,
-                 "Must know length when creating slice");
+    MOZ_ASSERT(aLength != UINT64_MAX, "Must know length when creating slice");
     // Ensure non-null mContentType by default
     mContentType.SetIsVoid(false);
   }
 
   virtual void GetName(nsAString& aName) const override;
 
   virtual void GetPath(nsAString& aName) const override;
 
@@ -546,25 +545,25 @@ class BlobImplMemory final : public Blob
 public:
   NS_DECL_ISUPPORTS_INHERITED
 
   BlobImplMemory(void* aMemoryBuffer, uint64_t aLength, const nsAString& aName,
                  const nsAString& aContentType, int64_t aLastModifiedDate)
     : BlobImplBase(aName, aContentType, aLength, aLastModifiedDate)
     , mDataOwner(new DataOwner(aMemoryBuffer, aLength))
   {
-    NS_ASSERTION(mDataOwner && mDataOwner->mData, "must have data");
+    MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
   }
 
   BlobImplMemory(void* aMemoryBuffer, uint64_t aLength,
                  const nsAString& aContentType)
     : BlobImplBase(aContentType, aLength)
     , mDataOwner(new DataOwner(aMemoryBuffer, aLength))
   {
-    NS_ASSERTION(mDataOwner && mDataOwner->mData, "must have data");
+    MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
   }
 
   virtual void GetInternalStream(nsIInputStream** aStream,
                                  ErrorResult& aRv) override;
 
   virtual already_AddRefed<BlobImpl>
   CreateSlice(uint64_t aStart, uint64_t aLength,
               const nsAString& aContentType, ErrorResult& aRv) override;
@@ -621,17 +620,17 @@ public:
 
 private:
   // Create slice
   BlobImplMemory(const BlobImplMemory* aOther, uint64_t aStart,
                  uint64_t aLength, const nsAString& aContentType)
     : BlobImplBase(aContentType, aOther->mStart + aStart, aLength)
     , mDataOwner(aOther->mDataOwner)
   {
-    NS_ASSERTION(mDataOwner && mDataOwner->mData, "must have data");
+    MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
     mImmutable = aOther->mImmutable;
   }
 
   ~BlobImplMemory() {}
 
   // Used when backed by a memory store
   RefPtr<DataOwner> mDataOwner;
 };
@@ -678,53 +677,53 @@ public:
 
   // Create as a file
   explicit BlobImplFile(nsIFile* aFile, bool aTemporary = false)
     : BlobImplBase(EmptyString(), EmptyString(), UINT64_MAX, INT64_MAX)
     , mFile(aFile)
     , mWholeFile(true)
     , mIsTemporary(aTemporary)
   {
-    NS_ASSERTION(mFile, "must have file");
+    MOZ_ASSERT(mFile, "must have file");
     // Lazily get the content type and size
     mContentType.SetIsVoid(true);
     mFile->GetLeafName(mName);
   }
 
   // Create as a file
   BlobImplFile(const nsAString& aName, const nsAString& aContentType,
                uint64_t aLength, nsIFile* aFile)
     : BlobImplBase(aName, aContentType, aLength, UINT64_MAX)
     , mFile(aFile)
     , mWholeFile(true)
     , mIsTemporary(false)
   {
-    NS_ASSERTION(mFile, "must have file");
+    MOZ_ASSERT(mFile, "must have file");
   }
 
   BlobImplFile(const nsAString& aName, const nsAString& aContentType,
                uint64_t aLength, nsIFile* aFile,
                int64_t aLastModificationDate)
     : BlobImplBase(aName, aContentType, aLength, aLastModificationDate)
     , mFile(aFile)
     , mWholeFile(true)
     , mIsTemporary(false)
   {
-    NS_ASSERTION(mFile, "must have file");
+    MOZ_ASSERT(mFile, "must have file");
   }
 
   // Create as a file with custom name
   BlobImplFile(nsIFile* aFile, const nsAString& aName,
                const nsAString& aContentType)
     : BlobImplBase(aName, aContentType, UINT64_MAX, INT64_MAX)
     , mFile(aFile)
     , mWholeFile(true)
     , mIsTemporary(false)
   {
-    NS_ASSERTION(mFile, "must have file");
+    MOZ_ASSERT(mFile, "must have file");
     if (aContentType.IsEmpty()) {
       // Lazily get the content type and size
       mContentType.SetIsVoid(true);
     }
   }
 
   // Overrides
   virtual uint64_t GetSize(ErrorResult& aRv) override;
@@ -761,17 +760,17 @@ private:
   // Create slice
   BlobImplFile(const BlobImplFile* aOther, uint64_t aStart,
                uint64_t aLength, const nsAString& aContentType)
     : BlobImplBase(aContentType, aOther->mStart + aStart, aLength)
     , mFile(aOther->mFile)
     , mWholeFile(false)
     , mIsTemporary(false)
   {
-    NS_ASSERTION(mFile, "must have file");
+    MOZ_ASSERT(mFile, "must have file");
     mImmutable = aOther->mImmutable;
   }
 
   virtual already_AddRefed<BlobImpl>
   CreateSlice(uint64_t aStart, uint64_t aLength,
               const nsAString& aContentType, ErrorResult& aRv) override;
 
   nsCOMPtr<nsIFile> mFile;
--- a/dom/file/FileList.h
+++ b/dom/file/FileList.h
@@ -56,33 +56,16 @@ public:
     return false;
   }
 
   void Clear()
   {
     return mFiles.Clear();
   }
 
-  static FileList* FromSupports(nsISupports* aSupports)
-  {
-#ifdef DEBUG
-    {
-      nsCOMPtr<nsIDOMFileList> list_qi = do_QueryInterface(aSupports);
-
-      // If this assertion fires the QI implementation for the object in
-      // question doesn't use the nsIDOMFileList pointer as the nsISupports
-      // pointer. That must be fixed, or we'll crash...
-      NS_ASSERTION(list_qi == static_cast<nsIDOMFileList*>(aSupports),
-                   "Uh, fix QI!");
-    }
-#endif
-
-    return static_cast<FileList*>(aSupports);
-  }
-
   File* Item(uint32_t aIndex) const;
 
   File* IndexedGetter(uint32_t aIndex, bool& aFound) const;
 
   uint32_t Length() const
   {
     return mFiles.Length();
   }
--- a/dom/file/FileReader.cpp
+++ b/dom/file/FileReader.cpp
@@ -298,27 +298,27 @@ FileReader::DoAsyncWait()
 nsresult
 FileReader::DoReadData(uint64_t aCount)
 {
   MOZ_ASSERT(mAsyncStream);
 
   if (mDataFormat == FILE_AS_BINARY) {
     //Continuously update our binary string as data comes in
     uint32_t oldLen = mResult.Length();
-    NS_ASSERTION(mResult.Length() == mDataLen, "unexpected mResult length");
+    MOZ_ASSERT(mResult.Length() == mDataLen, "unexpected mResult length");
     if (uint64_t(oldLen) + aCount > UINT32_MAX)
       return NS_ERROR_OUT_OF_MEMORY;
     char16_t *buf = nullptr;
     mResult.GetMutableData(&buf, oldLen + aCount, fallible);
     NS_ENSURE_TRUE(buf, NS_ERROR_OUT_OF_MEMORY);
 
     uint32_t bytesRead = 0;
     mAsyncStream->ReadSegments(ReadFuncBinaryString, buf + oldLen, aCount,
                                &bytesRead);
-    NS_ASSERTION(bytesRead == aCount, "failed to read data");
+    MOZ_ASSERT(bytesRead == aCount, "failed to read data");
   }
   else {
     CheckedInt<uint64_t> size = mDataLen;
     size += aCount;
 
     //Update memory buffer to reflect the contents of the file
     if (!size.isValid() ||
         // PR_Realloc doesn't support over 4GB memory size even if 64-bit OS
@@ -329,17 +329,17 @@ FileReader::DoReadData(uint64_t aCount)
 
     if (mDataFormat != FILE_AS_ARRAYBUFFER) {
       mFileData = (char *) realloc(mFileData, mDataLen + aCount);
       NS_ENSURE_TRUE(mFileData, NS_ERROR_OUT_OF_MEMORY);
     }
 
     uint32_t bytesRead = 0;
     mAsyncStream->Read(mFileData + mDataLen, aCount, &bytesRead);
-    NS_ASSERTION(bytesRead == aCount, "failed to read data");
+    MOZ_ASSERT(bytesRead == aCount, "failed to read data");
   }
 
   mDataLen += aCount;
   return NS_OK;
 }
 
 // Helper methods
 
--- a/dom/file/MultipartBlobImpl.cpp
+++ b/dom/file/MultipartBlobImpl.cpp
@@ -323,17 +323,17 @@ MultipartBlobImpl::SetMutable(bool aMuta
   return NS_OK;
 }
 
 void
 MultipartBlobImpl::InitializeChromeFile(Blob& aBlob,
                                         const ChromeFilePropertyBag& aBag,
                                         ErrorResult& aRv)
 {
-  NS_ASSERTION(!mImmutable, "Something went wrong ...");
+  MOZ_ASSERT(!mImmutable, "Something went wrong ...");
 
   if (mImmutable) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return;
   }
 
   MOZ_ASSERT(nsContentUtils::ThreadsafeIsCallerChrome());
 
@@ -357,17 +357,17 @@ MultipartBlobImpl::InitializeChromeFile(
 
 void
 MultipartBlobImpl::InitializeChromeFile(nsPIDOMWindowInner* aWindow,
                                         nsIFile* aFile,
                                         const ChromeFilePropertyBag& aBag,
                                         bool aIsFromNsIFile,
                                         ErrorResult& aRv)
 {
-  NS_ASSERTION(!mImmutable, "Something went wrong ...");
+  MOZ_ASSERT(!mImmutable, "Something went wrong ...");
   if (mImmutable) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return;
   }
 
   MOZ_ASSERT(nsContentUtils::IsCallerChrome());
 
   mName = aBag.mName;
--- a/dom/file/nsHostObjectProtocolHandler.cpp
+++ b/dom/file/nsHostObjectProtocolHandler.cpp
@@ -804,17 +804,17 @@ nsHostObjectProtocolHandler::NewChannel2
 #ifdef DEBUG
   DataInfo* info = GetDataInfoFromURI(uri);
 
   // Info can be null, in case this blob URL has been revoked already.
   if (info) {
     nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(uri);
     nsCOMPtr<nsIPrincipal> principal;
     uriPrinc->GetPrincipal(getter_AddRefs(principal));
-    NS_ASSERTION(info->mPrincipal == principal, "Wrong principal!");
+    MOZ_ASSERT(info->mPrincipal == principal, "Wrong principal!");
   }
 #endif
 
   ErrorResult rv;
   nsCOMPtr<nsIInputStream> stream;
   blobImpl->GetInternalStream(getter_AddRefs(stream), rv);
   if (NS_WARN_IF(rv.Failed())) {
     return rv.StealNSResult();
@@ -881,18 +881,16 @@ nsFontTableProtocolHandler::GetScheme(ns
 {
   result.AssignLiteral(FONTTABLEURI_SCHEME);
   return NS_OK;
 }
 
 nsresult
 NS_GetBlobForBlobURI(nsIURI* aURI, BlobImpl** aBlob)
 {
-  NS_ASSERTION(IsBlobURI(aURI), "Only call this with blob URIs");
-
   *aBlob = nullptr;
 
   DataInfo* info = GetDataInfoFromURI(aURI);
   if (!info || info->mObjectType != DataInfo::eBlobImpl) {
     return NS_ERROR_DOM_BAD_URI;
   }
 
   RefPtr<BlobImpl> blob = info->mBlobImpl;
@@ -931,18 +929,16 @@ NS_GetStreamForBlobURI(nsIURI* aURI, nsI
   }
 
   return NS_OK;
 }
 
 nsresult
 NS_GetStreamForMediaStreamURI(nsIURI* aURI, mozilla::DOMMediaStream** aStream)
 {
-  NS_ASSERTION(IsMediaStreamURI(aURI), "Only call this with mediastream URIs");
-
   DataInfo* info = GetDataInfoFromURI(aURI);
   if (!info || info->mObjectType != DataInfo::eMediaStream) {
     return NS_ERROR_DOM_BAD_URI;
   }
 
   RefPtr<DOMMediaStream> mediaStream = info->mMediaStream;
   mediaStream.forget(aStream);
   return NS_OK;
@@ -980,18 +976,16 @@ nsFontTableProtocolHandler::NewURI(const
 
   uri.forget(aResult);
   return NS_OK;
 }
 
 nsresult
 NS_GetSourceForMediaSourceURI(nsIURI* aURI, mozilla::dom::MediaSource** aSource)
 {
-  NS_ASSERTION(IsMediaSourceURI(aURI), "Only call this with mediasource URIs");
-
   *aSource = nullptr;
 
   DataInfo* info = GetDataInfoFromURI(aURI);
   if (!info || info->mObjectType != DataInfo::eMediaSource) {
     return NS_ERROR_DOM_BAD_URI;
   }
 
   RefPtr<MediaSource> mediaSource = info->mMediaSource;
--- a/dom/html/HTMLContentElement.cpp
+++ b/dom/html/HTMLContentElement.cpp
@@ -328,18 +328,16 @@ NS_INTERFACE_TABLE_HEAD(DistributedConte
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(DistributedContentList)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(DistributedContentList)
 
 DistributedContentList::DistributedContentList(HTMLContentElement* aHostElement)
   : mParent(aHostElement)
 {
-  MOZ_COUNT_CTOR(DistributedContentList);
-
   if (aHostElement->IsInsertionPoint()) {
     if (aHostElement->MatchedNodes().IsEmpty()) {
       // Fallback content.
       nsINode* contentNode = aHostElement;
       for (nsIContent* content = contentNode->GetFirstChild();
            content;
            content = content->GetNextSibling()) {
         mDistributedNodes.AppendElement(content);
@@ -347,17 +345,16 @@ DistributedContentList::DistributedConte
     } else {
       mDistributedNodes.AppendElements(aHostElement->MatchedNodes());
     }
   }
 }
 
 DistributedContentList::~DistributedContentList()
 {
-  MOZ_COUNT_DTOR(DistributedContentList);
 }
 
 nsIContent*
 DistributedContentList::Item(uint32_t aIndex)
 {
   return mDistributedNodes.SafeElementAt(aIndex);
 }
 
--- a/dom/html/HTMLSourceElement.cpp
+++ b/dom/html/HTMLSourceElement.cpp
@@ -72,33 +72,33 @@ HTMLSourceElement::WouldMatchMediaForDoc
     return true;
   }
 
   nsIPresShell* presShell = aDocument->GetShell();
   nsPresContext* pctx = presShell ? presShell->GetPresContext() : nullptr;
 
   nsCSSParser cssParser;
   RefPtr<nsMediaList> mediaList = new nsMediaList();
-  cssParser.ParseMediaList(aMedia, nullptr, 0, mediaList, false);
+  cssParser.ParseMediaList(aMedia, nullptr, 0, mediaList);
 
   return pctx && mediaList->Matches(pctx, nullptr);
 }
 
 void
 HTMLSourceElement::UpdateMediaList(const nsAttrValue* aValue)
 {
   mMediaList = nullptr;
   nsString mediaStr;
   if (!aValue || (mediaStr = aValue->GetStringValue()).IsEmpty()) {
     return;
   }
 
   nsCSSParser cssParser;
   mMediaList = new nsMediaList();
-  cssParser.ParseMediaList(mediaStr, nullptr, 0, mMediaList, false);
+  cssParser.ParseMediaList(mediaStr, nullptr, 0, mMediaList);
 }
 
 nsresult
 HTMLSourceElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                                 const nsAttrValue* aValue, bool aNotify)
 {
   // If we are associated with a <picture> with a valid <img>, notify it of
   // responsive parameter changes
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -240,25 +240,23 @@ private:
 };
 
 NS_IMPL_ISUPPORTS(MemoryReportRequestChild, nsIRunnable)
 
 MemoryReportRequestChild::MemoryReportRequestChild(
   bool aAnonymize, const MaybeFileDesc& aDMDFile)
 : mAnonymize(aAnonymize)
 {
-  MOZ_COUNT_CTOR(MemoryReportRequestChild);
   if (aDMDFile.type() == MaybeFileDesc::TFileDescriptor) {
     mDMDFile = aDMDFile.get_FileDescriptor();
   }
 }
 
 MemoryReportRequestChild::~MemoryReportRequestChild()
 {
-  MOZ_COUNT_DTOR(MemoryReportRequestChild);
 }
 
 // IPC sender for remote GC/CC logging.
 class CycleCollectWithLogsChild final
   : public PCycleCollectWithLogsChild
   , public nsICycleCollectorLogSink
 {
 public:
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1786,16 +1786,17 @@ ContentParent::LaunchSubprocess(ProcessP
   SetReplyTimeoutMs(Preferences::GetInt("dom.ipc.cpow.timeout", 0));
 
   return true;
 }
 
 ContentParent::ContentParent(ContentParent* aOpener,
                              const nsAString& aRemoteType)
   : nsIContentParent()
+  , mLaunchTS(TimeStamp::Now())
   , mOpener(aOpener)
   , mRemoteType(aRemoteType)
   , mIsForBrowser(!mRemoteType.IsEmpty())
 {
   InitializeMembers();  // Perform common initialization.
 
   // Insert ourselves into the global linked list of ContentParent objects.
   if (!sContentParents) {
@@ -2500,16 +2501,20 @@ ContentParent::RecvGetXPCOMProcessAttrib
                                              InfallibleTArray<nsString>* dictionaries,
                                              ClipboardCapabilities* clipboardCaps,
                                              DomainPolicyClone* domainPolicy,
                                              StructuredCloneData* aInitialData,
                                              InfallibleTArray<FontFamilyListEntry>* fontFamilies,
                                              OptionalURIParams* aUserContentCSSURL,
                                              nsTArray<LookAndFeelInt>* aLookAndFeelIntCache)
 {
+  Telemetry::Accumulate(Telemetry::CONTENT_PROCESS_LAUNCH_TIME_MS,
+                        static_cast<uint32_t>((TimeStamp::Now() - mLaunchTS)
+                                              .ToMilliseconds()));
+
   nsCOMPtr<nsIIOService> io(do_GetIOService());
   MOZ_ASSERT(io, "No IO service?");
   DebugOnly<nsresult> rv = io->GetOffline(aIsOffline);
   MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed getting offline?");
 
   rv = io->GetConnectivity(aIsConnected);
   MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed getting connectivity?");
 
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -12,16 +12,17 @@
 #include "mozilla/gfx/gfxVarReceiver.h"
 #include "mozilla/gfx/GPUProcessListener.h"
 #include "mozilla/ipc/GeckoChildProcessHost.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/FileUtils.h"
 #include "mozilla/HalTypes.h"
 #include "mozilla/LinkedList.h"
 #include "mozilla/StaticPtr.h"
+#include "mozilla/TimeStamp.h"
 #include "mozilla/UniquePtr.h"
 
 #include "nsDataHashtable.h"
 #include "nsFrameMessageManager.h"
 #include "nsHashKeys.h"
 #include "nsIObserver.h"
 #include "nsIThreadInternal.h"
 #include "nsIDOMGeoPositionCallback.h"
@@ -1091,16 +1092,17 @@ public:
 
 private:
 
   // If you add strong pointers to cycle collected objects here, be sure to
   // release these objects in ShutDownProcess.  See the comment there for more
   // details.
 
   GeckoChildProcessHost* mSubprocess;
+  const TimeStamp mLaunchTS; // used to calculate time to start content process
   ContentParent* mOpener;
 
   nsString mRemoteType;
 
   ContentParentId mChildID;
   int32_t mGeolocationWatchID;
 
   nsCString mKillHardAnnotation;
--- a/dom/ipc/ProcessHangMonitor.cpp
+++ b/dom/ipc/ProcessHangMonitor.cpp
@@ -1074,36 +1074,32 @@ InterruptCallback(JSContext* cx)
 
 ProcessHangMonitor* ProcessHangMonitor::sInstance;
 
 ProcessHangMonitor::ProcessHangMonitor()
  : mCPOWTimeout(false)
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 
-  MOZ_COUNT_CTOR(ProcessHangMonitor);
-
   if (XRE_IsContentProcess()) {
     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     obs->AddObserver(this, "xpcom-shutdown", false);
   }
 
   mThread = new base::Thread("ProcessHangMonitor");
   if (!mThread->Start()) {
     delete mThread;
     mThread = nullptr;
   }
 }
 
 ProcessHangMonitor::~ProcessHangMonitor()
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 
-  MOZ_COUNT_DTOR(ProcessHangMonitor);
-
   MOZ_ASSERT(sInstance == this);
   sInstance = nullptr;
 
   delete mThread;
 }
 
 ProcessHangMonitor*
 ProcessHangMonitor::GetOrCreate()
--- a/dom/media/BufferMediaResource.h
+++ b/dom/media/BufferMediaResource.h
@@ -25,23 +25,21 @@ public:
                       nsIPrincipal* aPrincipal,
                       const nsACString& aContentType) :
     mBuffer(aBuffer),
     mLength(aLength),
     mOffset(0),
     mPrincipal(aPrincipal),
     mContentType(aContentType)
   {
-    MOZ_COUNT_CTOR(BufferMediaResource);
   }
 
 protected:
   virtual ~BufferMediaResource()
   {
-    MOZ_COUNT_DTOR(BufferMediaResource);
   }
 
 private:
   nsresult Close() override { return NS_OK; }
   void Suspend(bool aCloseImmediately) override {}
   void Resume() override {}
   // Get the current principal for the channel
   already_AddRefed<nsIPrincipal> GetCurrentPrincipal() override
--- a/dom/media/DOMMediaStream.h
+++ b/dom/media/DOMMediaStream.h
@@ -79,26 +79,24 @@ public:
 class MediaStreamTrackSourceGetter : public nsISupports
 {
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(MediaStreamTrackSourceGetter)
 
 public:
   MediaStreamTrackSourceGetter()
   {
-    MOZ_COUNT_CTOR(MediaStreamTrackSourceGetter);
   }
 
   virtual already_AddRefed<dom::MediaStreamTrackSource>
   GetMediaStreamTrackSource(TrackID aInputTrackID) = 0;
 
 protected:
   virtual ~MediaStreamTrackSourceGetter()
   {
-    MOZ_COUNT_DTOR(MediaStreamTrackSourceGetter);
   }
 };
 
 /**
  * DOM wrapper for MediaStreams.
  *
  * To account for track operations such as clone(), addTrack() and
  * removeTrack(), a DOMMediaStream wraps three internal (and chained)
--- a/dom/media/FileBlockCache.cpp
+++ b/dom/media/FileBlockCache.cpp
@@ -33,17 +33,16 @@ nsresult FileBlockCache::Open(PRFileDesc
 FileBlockCache::FileBlockCache()
   : mFileMonitor("MediaCache.Writer.IO.Monitor"),
     mFD(nullptr),
     mFDCurrentPos(0),
     mDataMonitor("MediaCache.Writer.Data.Monitor"),
     mIsWriteScheduled(false),
     mIsOpen(false)
 {
-  MOZ_COUNT_CTOR(FileBlockCache);
 }
 
 FileBlockCache::~FileBlockCache()
 {
   NS_ASSERTION(!mIsOpen, "Should Close() FileBlockCache before destroying");
   {
     // Note, mThread will be shutdown by the time this runs, so we won't
     // block while taking mFileMonitor.
@@ -52,17 +51,16 @@ FileBlockCache::~FileBlockCache()
       PRStatus prrc;
       prrc = PR_Close(mFD);
       if (prrc != PR_SUCCESS) {
         NS_WARNING("PR_Close() failed.");
       }
       mFD = nullptr;
     }
   }
-  MOZ_COUNT_DTOR(FileBlockCache);
 }
 
 
 void FileBlockCache::Close()
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
   MonitorAutoLock mon(mDataMonitor);
 
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -412,17 +412,16 @@ MediaDecoder::MediaDecoder(MediaDecoderO
   , INIT_CANONICAL(mSameOriginMedia, false)
   , INIT_CANONICAL(mMediaPrincipalHandle, PRINCIPAL_HANDLE_NONE)
   , INIT_CANONICAL(mPlaybackBytesPerSecond, 0.0)
   , INIT_CANONICAL(mPlaybackRateReliable, true)
   , INIT_CANONICAL(mDecoderPosition, 0)
   , INIT_CANONICAL(mIsVisible, !aOwner->IsHidden())
   , mTelemetryReported(false)
 {
-  MOZ_COUNT_CTOR(MediaDecoder);
   MOZ_ASSERT(NS_IsMainThread());
   MediaMemoryTracker::AddMediaDecoder(this);
 
   mAudioChannel = AudioChannelService::GetDefaultAudioChannel();
   mResourceCallback->Connect(this);
 
   //
   // Initialize watchers.
@@ -511,17 +510,16 @@ MediaDecoder::Shutdown()
 
 MediaDecoder::~MediaDecoder()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_DIAGNOSTIC_ASSERT(IsShutdown());
   mResourceCallback->Disconnect();
   MediaMemoryTracker::RemoveMediaDecoder(this);
   UnpinForSeek();
-  MOZ_COUNT_DTOR(MediaDecoder);
 }
 
 void
 MediaDecoder::OnPlaybackEvent(MediaEventType aEvent)
 {
   switch (aEvent) {
     case MediaEventType::PlaybackStarted:
       mPlaybackStatistics->Start();
--- a/dom/media/MediaRecorder.cpp
+++ b/dom/media/MediaRecorder.cpp
@@ -419,17 +419,16 @@ public:
     , mTimeSlice(aTimeSlice)
     , mStopIssued(false)
     , mIsStartEventFired(false)
     , mIsRegisterProfiler(false)
     , mNeedSessionEndTask(true)
     , mSelectedVideoTrackID(TRACK_NONE)
   {
     MOZ_ASSERT(NS_IsMainThread());
-    MOZ_COUNT_CTOR(MediaRecorder::Session);
 
     uint32_t maxMem = Preferences::GetUint("media.recorder.max_memory",
                                            MAX_ALLOW_MEMORY_BUFFER);
     mEncodedBufferCache = new EncodedBufferCache(maxMem);
     mLastBlobTimeStamp = TimeStamp::Now();
   }
 
   void PrincipalChanged(MediaStreamTrack* aTrack) override
@@ -584,17 +583,16 @@ public:
     return (mEncoder ?  mEncoder->SizeOfExcludingThis(aMallocSizeOf) : 0);
   }
 
 
 private:
   // Only DestroyRunnable is allowed to delete Session object.
   virtual ~Session()
   {
-    MOZ_COUNT_DTOR(MediaRecorder::Session);
     LOG(LogLevel::Debug, ("Session.~Session (%p)", this));
     CleanupStreams();
     if (mReadThread) {
       mReadThread->Shutdown();
       mReadThread = nullptr;
       // Inside the if() so that if we delete after xpcom-shutdown's Observe(), we
       // won't try to remove it after the observer service is shut down.
       nsContentUtils::UnregisterShutdownObserver(this);
--- a/dom/media/MediaResource.h
+++ b/dom/media/MediaResource.h
@@ -405,23 +405,21 @@ protected:
                     nsIURI* aURI,
                     const nsACString& aContentType) :
     mCallback(aCallback),
     mChannel(aChannel),
     mURI(aURI),
     mContentType(aContentType),
     mLoadInBackground(false)
   {
-    MOZ_COUNT_CTOR(BaseMediaResource);
     NS_ASSERTION(!mContentType.IsEmpty(), "Must know content type");
     mURI->GetSpec(mContentURL);
   }
   virtual ~BaseMediaResource()
   {
-    MOZ_COUNT_DTOR(BaseMediaResource);
   }
 
   const nsCString& GetContentType() const override
   {
     return mContentType;
   }
 
   // Set the request's load flags to aFlags.  If the request is part of a
--- a/dom/media/MediaShutdownManager.cpp
+++ b/dom/media/MediaShutdownManager.cpp
@@ -18,23 +18,21 @@ extern LazyLogModule gMediaDecoderLog;
 
 NS_IMPL_ISUPPORTS(MediaShutdownManager, nsIAsyncShutdownBlocker)
 
 MediaShutdownManager::MediaShutdownManager()
   : mIsObservingShutdown(false)
   , mIsDoingXPCOMShutDown(false)
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_COUNT_CTOR(MediaShutdownManager);
 }
 
 MediaShutdownManager::~MediaShutdownManager()
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_COUNT_DTOR(MediaShutdownManager);
 }
 
 // Note that we don't use ClearOnShutdown() on this StaticRefPtr, as that
 // may interfere with our shutdown listener.
 StaticRefPtr<MediaShutdownManager> MediaShutdownManager::sInstance;
 
 MediaShutdownManager&
 MediaShutdownManager::Instance()
--- a/dom/media/MediaStreamTrack.h
+++ b/dom/media/MediaStreamTrack.h
@@ -61,17 +61,16 @@ public:
   };
 
   MediaStreamTrackSource(nsIPrincipal* aPrincipal,
                          const nsString& aLabel)
     : mPrincipal(aPrincipal),
       mLabel(aLabel),
       mStopped(false)
   {
-    MOZ_COUNT_CTOR(MediaStreamTrackSource);
   }
 
   /**
    * Use to clean up any resources that have to be cleaned before the
    * destructor is called. It is often too late in the destructor because
    * of garbage collection having removed the members already.
    */
   virtual void Destroy() {}
@@ -161,17 +160,16 @@ public:
       Stop();
       mStopped = true;
     }
   }
 
 protected:
   virtual ~MediaStreamTrackSource()
   {
-    MOZ_COUNT_DTOR(MediaStreamTrackSource);
   }
 
   /**
    * Called by a sub class when the principal has changed.
    * Notifies all sinks.
    */
   void PrincipalChanged()
   {
--- a/dom/media/directshow/DirectShowDecoder.cpp
+++ b/dom/media/directshow/DirectShowDecoder.cpp
@@ -48,18 +48,14 @@ DirectShowDecoder::IsEnabled()
 {
   return CanDecodeMP3UsingDirectShow() &&
          Preferences::GetBool("media.directshow.enabled");
 }
 
 DirectShowDecoder::DirectShowDecoder(MediaDecoderOwner* aOwner)
   : MediaDecoder(aOwner)
 {
-  MOZ_COUNT_CTOR(DirectShowDecoder);
 }
 
-DirectShowDecoder::~DirectShowDecoder()
-{
-  MOZ_COUNT_DTOR(DirectShowDecoder);
-}
+DirectShowDecoder::~DirectShowDecoder() = default;
 
 } // namespace mozilla
 
--- a/dom/media/mediasource/SourceBufferResource.cpp
+++ b/dom/media/mediasource/SourceBufferResource.cpp
@@ -161,25 +161,23 @@ SourceBufferResource::Ended()
   ReentrantMonitorAutoEnter mon(mMonitor);
   mEnded = true;
   mon.NotifyAll();
 }
 
 SourceBufferResource::~SourceBufferResource()
 {
   SBR_DEBUG("");
-  MOZ_COUNT_DTOR(SourceBufferResource);
 }
 
 SourceBufferResource::SourceBufferResource(const nsACString& aType)
   : mType(aType)
   , mMonitor("mozilla::SourceBufferResource::mMonitor")
   , mOffset(0)
   , mClosed(false)
   , mEnded(false)
 {
   SBR_DEBUG("");
-  MOZ_COUNT_CTOR(SourceBufferResource);
 }
 
 #undef SBR_DEBUG
 #undef SBR_DEBUGV
 } // namespace mozilla
--- a/dom/media/systemservices/CamerasParent.cpp
+++ b/dom/media/systemservices/CamerasParent.cpp
@@ -1070,25 +1070,22 @@ CamerasParent::CamerasParent()
 #endif
       if (!self->mVideoCaptureThread->StartWithOptions(options)) {
         MOZ_CRASH();
       }
       self->mThreadMonitor.NotifyAll();
       return NS_OK;
     });
   NS_DispatchToMainThread(threadStart);
-
-  MOZ_COUNT_CTOR(CamerasParent);
 }
 
 CamerasParent::~CamerasParent()
 {
   LOG(("~CamerasParent: %p", this));
 
-  MOZ_COUNT_DTOR(CamerasParent);
 #ifdef DEBUG
   // Verify we have shut down the webrtc engines, this is
   // supposed to happen in ActorDestroy.
   // That runnable takes a ref to us, so it must have finished
   // by the time we get here.
   for (int i = 0; i < CaptureEngine::MaxEngine; i++) {
     MOZ_ASSERT(!mEngines[i].mEngine);
   }
--- a/dom/media/webaudio/BufferDecoder.cpp
+++ b/dom/media/webaudio/BufferDecoder.cpp
@@ -14,23 +14,21 @@ namespace mozilla {
 
 NS_IMPL_ISUPPORTS0(BufferDecoder)
 
 BufferDecoder::BufferDecoder(MediaResource* aResource, GMPCrashHelper* aCrashHelper)
   : mResource(aResource)
   , mCrashHelper(aCrashHelper)
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_COUNT_CTOR(BufferDecoder);
 }
 
 BufferDecoder::~BufferDecoder()
 {
   // The dtor may run on any thread, we cannot be sure.
-  MOZ_COUNT_DTOR(BufferDecoder);
 }
 
 void
 BufferDecoder::BeginDecoding(TaskQueue* aTaskQueueIdentity)
 {
   MOZ_ASSERT(!mTaskQueueIdentity && aTaskQueueIdentity);
   mTaskQueueIdentity = aTaskQueueIdentity;
 }
--- a/dom/media/webaudio/MediaBufferDecoder.cpp
+++ b/dom/media/webaudio/MediaBufferDecoder.cpp
@@ -2,16 +2,17 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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 "MediaBufferDecoder.h"
 #include "BufferDecoder.h"
 #include "mozilla/dom/AudioContextBinding.h"
+#include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include <speex/speex_resampler.h>
 #include "nsXPCOMCIDInternal.h"
 #include "nsComponentManagerUtils.h"
 #include "MediaDecoderReader.h"
 #include "BufferMediaResource.h"
 #include "DecoderTraits.h"
 #include "AudioContext.h"
@@ -606,17 +607,21 @@ WebAudioDecodeJob::OnFailure(ErrorCode a
                                   NS_LITERAL_CSTRING("Media"),
                                   doc,
                                   nsContentUtils::eDOM_PROPERTIES,
                                   errorMessage);
 
   // Ignore errors in calling the callback, since there is not much that we can
   // do about it here.
   if (mFailureCallback) {
-    mFailureCallback->Call();
+    nsAutoCString errorString(errorMessage);
+    RefPtr<DOMException> exception =
+      DOMException::Create(NS_ERROR_DOM_ENCODING_NOT_SUPPORTED_ERR,
+                           errorString);
+    mFailureCallback->Call(*exception);
   }
 
   mPromise->MaybeReject(NS_ERROR_DOM_ENCODING_NOT_SUPPORTED_ERR);
 
   mContext->RemoveFromDecodeQueue(this);
 }
 
 size_t
--- a/dom/media/webaudio/test/test_mediaDecoding.html
+++ b/dom/media/webaudio/test/test_mediaDecoding.html
@@ -321,17 +321,19 @@ function runTest(test, response, callbac
     ok(expectCallback, "Success callback should fire asynchronously");
     ok(test.valid, "Did expect success for test " + test.url);
 
     checkAudioBuffer(asyncResult, test);
 
     test.expectedBuffer = asyncResult;
     test.nativeContext = cx;
     runResampling(test, compressedAudio, callback);
-  }, function onFailure() {
+  }, function onFailure(e) {
+    ok(e instanceof DOMException, "We want to see an exception here");
+    is(e.name, "EncodingError", "Exception name matches");
     ok(expectCallback, "Failure callback should fire asynchronously");
     ok(!test.valid, "Did expect failure for test " + test.url);
     callback();
   });
   expectCallback = true;
 }
 
 function loadTest(test, callback) {
--- a/dom/media/webrtc/RTCIdentityProviderRegistrar.cpp
+++ b/dom/media/webrtc/RTCIdentityProviderRegistrar.cpp
@@ -24,22 +24,20 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(RT
                                       mValidateAssertionCallback)
 
 RTCIdentityProviderRegistrar::RTCIdentityProviderRegistrar(
     nsIGlobalObject* aGlobal)
     : mGlobal(aGlobal)
     , mGenerateAssertionCallback(nullptr)
     , mValidateAssertionCallback(nullptr)
 {
-  MOZ_COUNT_CTOR(RTCIdentityProviderRegistrar);
 }
 
 RTCIdentityProviderRegistrar::~RTCIdentityProviderRegistrar()
 {
-  MOZ_COUNT_DTOR(RTCIdentityProviderRegistrar);
 }
 
 nsIGlobalObject*
 RTCIdentityProviderRegistrar::GetParentObject() const
 {
   return mGlobal;
 }
 
--- a/dom/performance/Performance.cpp
+++ b/dom/performance/Performance.cpp
@@ -98,24 +98,22 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED(Perfo
                                    mResourceEntries);
 
 NS_IMPL_ADDREF_INHERITED(Performance, DOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(Performance, DOMEventTargetHelper)
 
 /* static */ already_AddRefed<Performance>
 Performance::CreateForMainThread(nsPIDOMWindowInner* aWindow,
                                  nsDOMNavigationTiming* aDOMTiming,
-                                 nsITimedChannel* aChannel,
-                                 Performance* aParentPerformance)
+                                 nsITimedChannel* aChannel)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   RefPtr<Performance> performance =
-    new PerformanceMainThread(aWindow, aDOMTiming, aChannel,
-                              aParentPerformance);
+    new PerformanceMainThread(aWindow, aDOMTiming, aChannel);
   return performance.forget();
 }
 
 /* static */ already_AddRefed<Performance>
 Performance::CreateForWorker(workers::WorkerPrivate* aWorkerPrivate)
 {
   MOZ_ASSERT(aWorkerPrivate);
   aWorkerPrivate->AssertIsOnWorkerThread();
--- a/dom/performance/Performance.h
+++ b/dom/performance/Performance.h
@@ -41,18 +41,17 @@ public:
 
   static bool IsEnabled(JSContext* aCx, JSObject* aGlobal);
 
   static bool IsObserverEnabled(JSContext* aCx, JSObject* aGlobal);
 
   static already_AddRefed<Performance>
   CreateForMainThread(nsPIDOMWindowInner* aWindow,
                       nsDOMNavigationTiming* aDOMTiming,
-                      nsITimedChannel* aChannel,
-                      Performance* aParentPerformance);
+                      nsITimedChannel* aChannel);
 
   static already_AddRefed<Performance>
   CreateForWorker(workers::WorkerPrivate* aWorkerPrivate);
 
   JSObject* WrapObject(JSContext *cx,
                        JS::Handle<JSObject*> aGivenProto) override;
 
   void GetEntries(nsTArray<RefPtr<PerformanceEntry>>& aRetval);
@@ -99,18 +98,16 @@ public:
 
   virtual void GetMozMemory(JSContext *aCx,
                             JS::MutableHandle<JSObject*> aObj) = 0;
 
   virtual nsDOMNavigationTiming* GetDOMTiming() const = 0;
 
   virtual nsITimedChannel* GetChannel() const = 0;
 
-  virtual Performance* GetParentPerformance() const = 0;
-
 protected:
   Performance();
   explicit Performance(nsPIDOMWindowInner* aWindow);
 
   virtual ~Performance();
 
   virtual void InsertUserEntry(PerformanceEntry* aEntry);
   void InsertResourceEntry(PerformanceEntry* aEntry);
--- a/dom/performance/PerformanceMainThread.cpp
+++ b/dom/performance/PerformanceMainThread.cpp
@@ -11,27 +11,25 @@
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(PerformanceMainThread)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PerformanceMainThread,
                                                 Performance)
 NS_IMPL_CYCLE_COLLECTION_UNLINK(mTiming,
-                                mNavigation,
-                                mParentPerformance)
+                                mNavigation)
   tmp->mMozMemory = nullptr;
   mozilla::DropJSObjects(this);
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PerformanceMainThread,
                                                   Performance)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTiming,
-                                    mNavigation,
-                                    mParentPerformance)
+                                    mNavigation)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(PerformanceMainThread,
                                                 Performance)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mMozMemory)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
@@ -41,22 +39,20 @@ NS_IMPL_RELEASE_INHERITED(PerformanceMai
 // QueryInterface implementation for PerformanceMainThread
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PerformanceMainThread)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END_INHERITING(Performance)
 
 PerformanceMainThread::PerformanceMainThread(nsPIDOMWindowInner* aWindow,
                                              nsDOMNavigationTiming* aDOMTiming,
-                                             nsITimedChannel* aChannel,
-                                             Performance* aParentPerformance)
+                                             nsITimedChannel* aChannel)
   : Performance(aWindow)
   , mDOMTiming(aDOMTiming)
   , mChannel(aChannel)
-  , mParentPerformance(aParentPerformance)
 {
   MOZ_ASSERT(aWindow, "Parent window object should be provided");
 }
 
 PerformanceMainThread::~PerformanceMainThread()
 {
   mozilla::DropJSObjects(this);
 }
--- a/dom/performance/PerformanceMainThread.h
+++ b/dom/performance/PerformanceMainThread.h
@@ -12,18 +12,17 @@
 namespace mozilla {
 namespace dom {
 
 class PerformanceMainThread final : public Performance
 {
 public:
   PerformanceMainThread(nsPIDOMWindowInner* aWindow,
                         nsDOMNavigationTiming* aDOMTiming,
-                        nsITimedChannel* aChannel,
-                        Performance* aParentPerformance);
+                        nsITimedChannel* aChannel);
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(PerformanceMainThread,
                                                          Performance)
 
   // Performance WebIDL methods
   DOMHighResTimeStamp Now() const override;
 
@@ -46,21 +45,16 @@ public:
     return mDOMTiming;
   }
 
   virtual nsITimedChannel* GetChannel() const override
   {
     return mChannel;
   }
 
-  virtual Performance* GetParentPerformance() const override
-  {
-    return mParentPerformance;
-  }
-
 protected:
   ~PerformanceMainThread();
 
   nsISupports* GetAsISupports() override
   {
     return this;
   }
 
@@ -72,16 +66,15 @@ protected:
   GetPerformanceTimingFromString(const nsAString& aTimingName) override;
 
   void DispatchBufferFullEvent() override;
 
   RefPtr<nsDOMNavigationTiming> mDOMTiming;
   nsCOMPtr<nsITimedChannel> mChannel;
   RefPtr<PerformanceTiming> mTiming;
   RefPtr<PerformanceNavigation> mNavigation;
-  RefPtr<Performance> mParentPerformance;
   JS::Heap<JSObject*> mMozMemory;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_PerformanceMainThread_h
--- a/dom/performance/PerformanceWorker.h
+++ b/dom/performance/PerformanceWorker.h
@@ -59,22 +59,16 @@ public:
   }
 
   virtual nsITimedChannel* GetChannel() const override
   {
     MOZ_CRASH("This should not be called on workers.");
     return nullptr;
   }
 
-  virtual Performance* GetParentPerformance() const override
-  {
-    MOZ_CRASH("This should not be called on workers.");
-    return nullptr;
-  }
-
 protected:
   ~PerformanceWorker();
 
   nsISupports* GetAsISupports() override
   {
     return nullptr;
   }
 
--- a/dom/presentation/ipc/PresentationBuilderParent.cpp
+++ b/dom/presentation/ipc/PresentationBuilderParent.cpp
@@ -105,23 +105,20 @@ PresentationSessionTransportIPC::Close(n
 
 NS_IMPL_ISUPPORTS(PresentationBuilderParent,
                   nsIPresentationSessionTransportBuilder,
                   nsIPresentationDataChannelSessionTransportBuilder)
 
 PresentationBuilderParent::PresentationBuilderParent(PresentationParent* aParent)
   : mParent(aParent)
 {
-  MOZ_COUNT_CTOR(PresentationBuilderParent);
 }
 
 PresentationBuilderParent::~PresentationBuilderParent()
 {
-  MOZ_COUNT_DTOR(PresentationBuilderParent);
-
   if (mNeedDestroyActor) {
     Unused << NS_WARN_IF(!Send__delete__(this));
   }
 }
 
 NS_IMETHODIMP
 PresentationBuilderParent::BuildDataChannelTransport(
                       uint8_t aRole,
--- a/dom/presentation/ipc/PresentationParent.cpp
+++ b/dom/presentation/ipc/PresentationParent.cpp
@@ -88,22 +88,20 @@ PresentationTransportBuilderConstructorI
 
 NS_IMPL_ISUPPORTS(PresentationParent,
                   nsIPresentationAvailabilityListener,
                   nsIPresentationSessionListener,
                   nsIPresentationRespondingListener)
 
 PresentationParent::PresentationParent()
 {
-  MOZ_COUNT_CTOR(PresentationParent);
 }
 
 /* virtual */ PresentationParent::~PresentationParent()
 {
-  MOZ_COUNT_DTOR(PresentationParent);
 }
 
 bool
 PresentationParent::Init(ContentParentId aContentParentId)
 {
   MOZ_ASSERT(!mService);
   mService = do_GetService(PRESENTATION_SERVICE_CONTRACTID);
   mChildId = aContentParentId;
@@ -383,22 +381,20 @@ PresentationParent::RecvNotifyTransportC
 
 NS_IMPL_ISUPPORTS(PresentationRequestParent, nsIPresentationServiceCallback)
 
 PresentationRequestParent::PresentationRequestParent(nsIPresentationService* aService,
                                                      ContentParentId aContentParentId)
   : mService(aService)
   , mChildId(aContentParentId)
 {
-  MOZ_COUNT_CTOR(PresentationRequestParent);
 }
 
 PresentationRequestParent::~PresentationRequestParent()
 {
-  MOZ_COUNT_DTOR(PresentationRequestParent);
 }
 
 void
 PresentationRequestParent::ActorDestroy(ActorDestroyReason aWhy)
 {
   mActorDestroyed = true;
   mService = nullptr;
 }
--- a/dom/webidl/AudioContext.webidl
+++ b/dom/webidl/AudioContext.webidl
@@ -6,17 +6,17 @@
  * The origin of this IDL file is
  * https://webaudio.github.io/web-audio-api/
  *
  * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
 callback DecodeSuccessCallback = void (AudioBuffer decodedData);
-callback DecodeErrorCallback = void ();
+callback DecodeErrorCallback = void (DOMException error);
 
 enum AudioContextState {
     "suspended",
     "running",
     "closed"
 };
 
 dictionary PeriodicWaveConstraints {
--- a/dom/xbl/XBLChildrenElement.h
+++ b/dom/xbl/XBLChildrenElement.h
@@ -156,17 +156,16 @@ private:
 } // namespace mozilla
 
 class nsAnonymousContentList : public nsINodeList
 {
 public:
   explicit nsAnonymousContentList(nsIContent* aParent)
     : mParent(aParent)
   {
-    MOZ_COUNT_CTOR(nsAnonymousContentList);
   }
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsAnonymousContentList)
   // nsIDOMNodeList interface
   NS_DECL_NSIDOMNODELIST
 
   // nsINodeList interface
@@ -178,15 +177,14 @@ public:
 
   bool IsListFor(nsIContent* aContent) {
     return mParent == aContent;
   }
 
 private:
   virtual ~nsAnonymousContentList()
   {
-    MOZ_COUNT_DTOR(nsAnonymousContentList);
   }
 
   nsCOMPtr<nsIContent> mParent;
 };
 
 #endif // nsXBLChildrenElement_h___
--- a/dom/xbl/nsXBLBinding.cpp
+++ b/dom/xbl/nsXBLBinding.cpp
@@ -421,17 +421,17 @@ nsXBLBinding::GenerateAnonymousContent()
       mContent->UnsetAttr(namespaceID, name, false);
   }
 
   // Now that we've finished shuffling the tree around, go ahead and restyle it
   // since frame construction is about to happen.
   nsIPresShell* presShell = mBoundElement->OwnerDoc()->GetShell();
   ServoStyleSet* servoSet = presShell->StyleSet()->GetAsServo();
   if (servoSet) {
-    servoSet->StyleNewChildren(mBoundElement);
+    servoSet->StyleNewChildren(mBoundElement->AsElement());
   }
 }
 
 nsIURI*
 nsXBLBinding::GetSourceDocURI()
 {
   nsIContent* targetContent =
     mPrototypeBinding->GetImmediateChild(nsGkAtoms::content);
--- a/dom/xul/templates/nsXULTemplateBuilder.cpp
+++ b/dom/xul/templates/nsXULTemplateBuilder.cpp
@@ -97,17 +97,16 @@ LazyLogModule gXULTemplateLog("nsXULTemp
 //
 
 nsXULTemplateBuilder::nsXULTemplateBuilder(void)
     : mQueriesCompiled(false),
       mFlags(0),
       mTop(nullptr),
       mObservedDocument(nullptr)
 {
-    MOZ_COUNT_CTOR(nsXULTemplateBuilder);
 }
 
 void
 nsXULTemplateBuilder::DestroyMatchMap()
 {
     for (auto iter = mMatchMap.Iter(); !iter.Done(); iter.Next()) {
         nsTemplateMatch*& match = iter.Data();
         // delete all the matches in the list
@@ -127,18 +126,16 @@ nsXULTemplateBuilder::~nsXULTemplateBuil
 
     if (--gRefCnt == 0) {
         NS_IF_RELEASE(gRDFService);
         NS_IF_RELEASE(gRDFContainerUtils);
         NS_IF_RELEASE(gSystemPrincipal);
         NS_IF_RELEASE(gScriptSecurityManager);
         NS_IF_RELEASE(gObserverService);
     }
-
-    MOZ_COUNT_DTOR(nsXULTemplateBuilder);
 }
 
 
 nsresult
 nsXULTemplateBuilder::InitGlobals()
 {
     nsresult rv;
 
--- a/embedding/browser/nsWebBrowserContentPolicy.cpp
+++ b/embedding/browser/nsWebBrowserContentPolicy.cpp
@@ -7,22 +7,20 @@
 #include "nsWebBrowserContentPolicy.h"
 #include "nsIDocShell.h"
 #include "nsCOMPtr.h"
 #include "nsContentPolicyUtils.h"
 #include "nsIContentViewer.h"
 
 nsWebBrowserContentPolicy::nsWebBrowserContentPolicy()
 {
-  MOZ_COUNT_CTOR(nsWebBrowserContentPolicy);
 }
 
 nsWebBrowserContentPolicy::~nsWebBrowserContentPolicy()
 {
-  MOZ_COUNT_DTOR(nsWebBrowserContentPolicy);
 }
 
 NS_IMPL_ISUPPORTS(nsWebBrowserContentPolicy, nsIContentPolicy)
 
 NS_IMETHODIMP
 nsWebBrowserContentPolicy::ShouldLoad(uint32_t aContentType,
                                       nsIURI* aContentLocation,
                                       nsIURI* aRequestingLocation,
--- a/embedding/components/printingui/ipc/PrintDataUtils.cpp
+++ b/embedding/components/printingui/ipc/PrintDataUtils.cpp
@@ -19,22 +19,20 @@ namespace embedding {
  * settings dialogs that need an nsIWebBrowserPrint to interrogate.
  */
 
 NS_IMPL_ISUPPORTS(MockWebBrowserPrint, nsIWebBrowserPrint);
 
 MockWebBrowserPrint::MockWebBrowserPrint(const PrintData &aData)
   : mData(aData)
 {
-  MOZ_COUNT_CTOR(MockWebBrowserPrint);
 }
 
 MockWebBrowserPrint::~MockWebBrowserPrint()
 {
-  MOZ_COUNT_DTOR(MockWebBrowserPrint);
 }
 
 NS_IMETHODIMP
 MockWebBrowserPrint::GetGlobalPrintSettings(nsIPrintSettings **aGlobalPrintSettings)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
--- a/embedding/components/printingui/ipc/PrintProgressDialogChild.cpp
+++ b/embedding/components/printingui/ipc/PrintProgressDialogChild.cpp
@@ -17,27 +17,25 @@ namespace embedding {
 NS_IMPL_ISUPPORTS(PrintProgressDialogChild,
                   nsIWebProgressListener,
                   nsIPrintProgressParams)
 
 PrintProgressDialogChild::PrintProgressDialogChild(
   nsIObserver* aOpenObserver) :
   mOpenObserver(aOpenObserver)
 {
-  MOZ_COUNT_CTOR(PrintProgressDialogChild);
 }
 
 PrintProgressDialogChild::~PrintProgressDialogChild()
 {
   // When the printing engine stops supplying information about printing
   // progress, it'll drop references to us and destroy us. We need to signal
   // the parent to decrement its refcount, as well as prevent it from attempting
   // to contact us further.
   Unused << Send__delete__(this);
-  MOZ_COUNT_DTOR(PrintProgressDialogChild);
 }
 
 mozilla::ipc::IPCResult
 PrintProgressDialogChild::RecvDialogOpened()
 {
   // nsPrintEngine's observer, which we're reporting to here, doesn't care
   // what gets passed as the subject, topic or data, so we'll just send
   // nullptrs.
--- a/embedding/components/printingui/ipc/PrintProgressDialogParent.cpp
+++ b/embedding/components/printingui/ipc/PrintProgressDialogParent.cpp
@@ -12,22 +12,20 @@ using mozilla::Unused;
 namespace mozilla {
 namespace embedding {
 
 NS_IMPL_ISUPPORTS(PrintProgressDialogParent, nsIObserver)
 
 PrintProgressDialogParent::PrintProgressDialogParent() :
   mActive(true)
 {
-  MOZ_COUNT_CTOR(PrintProgressDialogParent);
 }
 
 PrintProgressDialogParent::~PrintProgressDialogParent()
 {
-  MOZ_COUNT_DTOR(PrintProgressDialogParent);
 }
 
 void
 PrintProgressDialogParent::SetWebProgressListener(nsIWebProgressListener* aListener)
 {
   mWebProgressListener = aListener;
 }
 
--- a/embedding/components/printingui/ipc/PrintingParent.cpp
+++ b/embedding/components/printingui/ipc/PrintingParent.cpp
@@ -303,23 +303,20 @@ PrintingParent::SerializeAndEnsureRemote
     remotePrintJob->RegisterListener(aListener);
   }
 
   return NS_OK;
 }
 
 PrintingParent::PrintingParent()
 {
-  MOZ_COUNT_CTOR(PrintingParent);
-
   mPrintSettingsSvc =
     do_GetService("@mozilla.org/gfx/printsettings-service;1");
   MOZ_ASSERT(mPrintSettingsSvc);
 }
 
 PrintingParent::~PrintingParent()
 {
-  MOZ_COUNT_DTOR(PrintingParent);
 }
 
 } // namespace embedding
 } // namespace mozilla
 
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -209,22 +209,20 @@ Layer::Layer(LayerManager* aManager, voi
   mScrollbarDirection(ScrollDirection::NONE),
   mScrollbarThumbRatio(0.0f),
   mIsScrollbarContainer(false),
 #ifdef DEBUG
   mDebugColorIndex(0),
 #endif
   mAnimationGeneration(0)
 {
-  MOZ_COUNT_CTOR(Layer);
 }
 
 Layer::~Layer()
 {
-  MOZ_COUNT_DTOR(Layer);
 }
 
 Animation*
 Layer::AddAnimation()
 {
   MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) AddAnimation", this));
 
   MOZ_ASSERT(!mPendingAnimations, "should have called ClearAnimations first");
@@ -1117,23 +1115,21 @@ ContainerLayer::ContainerLayer(LayerMana
     mPresShellResolution(1.0f),
     mScaleToResolution(false),
     mUseIntermediateSurface(false),
     mSupportsComponentAlphaChildren(false),
     mMayHaveReadbackChild(false),
     mChildrenChanged(false),
     mEventRegionsOverride(EventRegionsOverride::NoOverride)
 {
-  MOZ_COUNT_CTOR(ContainerLayer);
   mContentFlags = 0; // Clear NO_TEXT, NO_TEXT_OVER_TRANSPARENT
 }
 
 ContainerLayer::~ContainerLayer()
 {
-  MOZ_COUNT_DTOR(ContainerLayer);
 }
 
 bool
 ContainerLayer::InsertAfter(Layer* aChild, Layer* aAfter)
 {
   if(aChild->Manager() != Manager()) {
     NS_ERROR("Child has wrong manager");
     return false;
--- a/gfx/layers/client/CompositableChild.cpp
+++ b/gfx/layers/client/CompositableChild.cpp
@@ -23,22 +23,20 @@ CompositableChild::DestroyActor(PComposi
   static_cast<CompositableChild*>(aChild)->Release();
 }
 
 CompositableChild::CompositableChild()
  : mCompositableClient(nullptr),
    mAsyncID(0),
    mCanSend(true)
 {
-  MOZ_COUNT_CTOR(CompositableChild);
 }
 
 CompositableChild::~CompositableChild()
 {
-  MOZ_COUNT_DTOR(CompositableChild);
 }
 
 bool
 CompositableChild::IsConnected() const
 {
   return mCompositableClient && mCanSend;
 }
 
--- a/gfx/layers/client/CompositableClient.cpp
+++ b/gfx/layers/client/CompositableClient.cpp
@@ -52,22 +52,20 @@ CompositableClient::FromIPDLActor(PCompo
   return client;
 }
 
 CompositableClient::CompositableClient(CompositableForwarder* aForwarder,
                                        TextureFlags aTextureFlags)
 : mForwarder(aForwarder)
 , mTextureFlags(aTextureFlags)
 {
-  MOZ_COUNT_CTOR(CompositableClient);
 }
 
 CompositableClient::~CompositableClient()
 {
-  MOZ_COUNT_DTOR(CompositableClient);
   Destroy();
 }
 
 LayersBackend
 CompositableClient::GetCompositorBackendType() const
 {
   return mForwarder->GetCompositorBackendType();
 }
--- a/gfx/layers/ipc/CompositorThread.cpp
+++ b/gfx/layers/ipc/CompositorThread.cpp
@@ -48,25 +48,22 @@ CompositorThreadHolder::GetSingleton()
 {
   return sCompositorThreadHolder;
 }
 
 CompositorThreadHolder::CompositorThreadHolder()
   : mCompositorThread(CreateCompositorThread())
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_COUNT_CTOR(CompositorThreadHolder);
 }
 
 CompositorThreadHolder::~CompositorThreadHolder()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  MOZ_COUNT_DTOR(CompositorThreadHolder);
-
   DestroyCompositorThread(mCompositorThread);
 }
 
 /* static */ void
 CompositorThreadHolder::DestroyCompositorThread(base::Thread* aCompositorThread)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
--- a/gfx/src/nsDeviceContext.cpp
+++ b/gfx/src/nsDeviceContext.cpp
@@ -41,33 +41,33 @@
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 using mozilla::services::GetObserverService;
 
 class nsFontCache final : public nsIObserver
 {
 public:
-    nsFontCache()   { MOZ_COUNT_CTOR(nsFontCache); }
+    nsFontCache() {}
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSIOBSERVER
 
     void Init(nsDeviceContext* aContext);
     void Destroy();
 
     already_AddRefed<nsFontMetrics> GetMetricsFor(
         const nsFont& aFont, const nsFontMetrics::Params& aParams);
 
     void FontMetricsDeleted(const nsFontMetrics* aFontMetrics);
     void Compact();
     void Flush();
 
 protected:
-    ~nsFontCache()  { MOZ_COUNT_DTOR(nsFontCache); }
+    ~nsFontCache() {}
 
     nsDeviceContext*          mContext; // owner
     nsCOMPtr<nsIAtom>         mLocaleLanguage;
     nsTArray<nsFontMetrics*>  mFontMetrics;
 };
 
 NS_IMPL_ISUPPORTS(nsFontCache, nsIObserver)
 
--- a/gfx/thebes/gfxContext.cpp
+++ b/gfx/thebes/gfxContext.cpp
@@ -71,18 +71,16 @@ gfxContext::gfxContext(DrawTarget *aTarg
   : mPathIsRect(false)
   , mTransformChanged(false)
   , mDT(aTarget)
 {
   if (!aTarget) {
     gfxCriticalError() << "Don't create a gfxContext without a DrawTarget";
   }
 
-  MOZ_COUNT_CTOR(gfxContext);
-
   mStateStack.SetLength(1);
   CurrentState().drawTarget = mDT;
   CurrentState().deviceOffset = aDeviceOffset;
   mDT->SetTransform(GetDTTransform());
 }
 
 /* static */ already_AddRefed<gfxContext>
 gfxContext::CreateOrNull(DrawTarget* aTarget,
@@ -114,17 +112,16 @@ gfxContext::CreatePreservingTransformOrN
 gfxContext::~gfxContext()
 {
   for (int i = mStateStack.Length() - 1; i >= 0; i--) {
     for (unsigned int c = 0; c < mStateStack[i].pushedClips.Length(); c++) {
       mStateStack[i].drawTarget->PopClip();
     }
   }
   mDT->Flush();
-  MOZ_COUNT_DTOR(gfxContext);
 }
 
 void
 gfxContext::Save()
 {
   CurrentState().transform = mTransform;
   mStateStack.AppendElement(AzureState(CurrentState()));
   CurrentState().pushedClips.Clear();
--- a/gfx/thebes/gfxTextRun.cpp
+++ b/gfx/thebes/gfxTextRun.cpp
@@ -149,17 +149,16 @@ gfxTextRun::gfxTextRun(const gfxTextRunF
                        uint32_t aLength, gfxFontGroup *aFontGroup, uint32_t aFlags)
     : gfxShapedText(aLength, aFlags, aParams->mAppUnitsPerDevUnit)
     , mUserData(aParams->mUserData)
     , mFontGroup(aFontGroup)
     , mReleasedFontGroup(false)
     , mShapingState(eShapingState_Normal)
 {
     NS_ASSERTION(mAppUnitsPerDevUnit > 0, "Invalid app unit scale");
-    MOZ_COUNT_CTOR(gfxTextRun);
     NS_ADDREF(mFontGroup);
 
 #ifndef RELEASE_OR_BETA
     gfxTextPerfMetrics *tp = aFontGroup->GetTextPerfMetrics();
     if (tp) {
         tp->current.textrunConst++;
     }
 #endif
@@ -194,18 +193,16 @@ gfxTextRun::~gfxTextRun()
 #ifndef RELEASE_OR_BETA
         gfxTextPerfMetrics *tp = mFontGroup->GetTextPerfMetrics();
         if (tp) {
             tp->current.textrunDestr++;
         }
 #endif
         NS_RELEASE(mFontGroup);
     }
-
-    MOZ_COUNT_DTOR(gfxTextRun);
 }
 
 void
 gfxTextRun::ReleaseFontGroup()
 {
     NS_ASSERTION(!mReleasedFontGroup, "doubly released!");
     NS_RELEASE(mFontGroup);
     mReleasedFontGroup = true;
--- a/gfx/vr/ipc/VRManagerChild.cpp
+++ b/gfx/vr/ipc/VRManagerChild.cpp
@@ -42,26 +42,24 @@ void ReleaseVRManagerParentSingleton() {
 VRManagerChild::VRManagerChild()
   : TextureForwarder()
   , mDisplaysInitialized(false)
   , mInputFrameID(-1)
   , mMessageLoop(MessageLoop::current())
   , mFrameRequestCallbackCounter(0)
   , mBackend(layers::LayersBackend::LAYERS_NONE)
 {
-  MOZ_COUNT_CTOR(VRManagerChild);
   MOZ_ASSERT(NS_IsMainThread());
 
   mStartTimeStamp = TimeStamp::Now();
 }
 
 VRManagerChild::~VRManagerChild()
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_COUNT_DTOR(VRManagerChild);
 }
 
 /*static*/ void
 VRManagerChild::IdentifyTextureHost(const TextureFactoryIdentifier& aIdentifier)
 {
   if (sVRManagerChildSingleton) {
     sVRManagerChildSingleton->mBackend = aIdentifier.mParentBackend;
     sVRManagerChildSingleton->mSyncObject = SyncObject::CreateSyncObject(aIdentifier.mSyncHandle);
--- a/image/decoders/nsIconDecoder.cpp
+++ b/image/decoders/nsIconDecoder.cpp
@@ -89,17 +89,18 @@ nsIconDecoder::ReadRowOfPixels(const cha
 {
   MOZ_ASSERT(aLength % 4 == 0, "Rows should contain a multiple of four bytes");
 
   auto result = mPipe.WritePixels<uint32_t>([&]() -> NextPixel<uint32_t> {
     if (aLength == 0) {
       return AsVariant(WriteState::NEED_MORE_DATA);  // Done with this row.
     }
 
-    uint32_t pixel = *reinterpret_cast<const uint32_t*>(aData);
+    uint32_t pixel;
+    memcpy(&pixel, aData, 4);
     aData += 4;
     aLength -= 4;
 
     return AsVariant(pixel);
   });
 
   MOZ_ASSERT(result != WriteState::FAILURE);
 
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -1693,31 +1693,46 @@ template <>
 Maybe<FunctionScope::Data*>
 Parser<FullParseHandler>::newFunctionScopeData(ParseContext::Scope& scope, bool hasParameterExprs)
 {
     Vector<BindingName> positionalFormals(context);
     Vector<BindingName> formals(context);
     Vector<BindingName> vars(context);
 
     bool allBindingsClosedOver = pc->sc()->allBindingsClosedOver();
+    bool hasDuplicateParams = pc->functionBox()->hasDuplicateParameters;
 
     // Positional parameter names must be added in order of appearance as they are
     // referenced using argument slots.
     for (size_t i = 0; i < pc->positionalFormalParameterNames().length(); i++) {
         JSAtom* name = pc->positionalFormalParameterNames()[i];
 
         BindingName bindName;
         if (name) {
             DeclaredNamePtr p = scope.lookupDeclaredName(name);
 
             // Do not consider any positional formal parameters closed over if
             // there are parameter defaults. It is the binding in the defaults
             // scope that is closed over instead.
-            bindName = BindingName(name, (allBindingsClosedOver ||
-                                          (p && p->value()->closedOver())));
+            bool closedOver = allBindingsClosedOver ||
+                              (p && p->value()->closedOver());
+
+            // If the parameter name has duplicates, only the final parameter
+            // name should be on the environment, as otherwise the environment
+            // object would have multiple, same-named properties.
+            if (hasDuplicateParams) {
+                for (size_t j = pc->positionalFormalParameterNames().length() - 1; j > i; j--) {
+                    if (pc->positionalFormalParameterNames()[j] == name) {
+                        closedOver = false;
+                        break;
+                    }
+                }
+            }
+
+            bindName = BindingName(name, closedOver);
         }
 
         if (!positionalFormals.append(bindName))
             return Nothing();
     }
 
     for (BindingIter bi = scope.bindings(pc); bi; bi++) {
         BindingName binding(bi.name(), allBindingsClosedOver || bi.closedOver());
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1316832.js
@@ -0,0 +1,10 @@
+
+(function(x, x) {
+    eval(`
+        var y = 1;
+        function f() {
+            return delete y;
+        }
+        f();
+    `);
+})()
--- a/js/src/jit-test/tests/wasm/integer.js
+++ b/js/src/jit-test/tests/wasm/integer.js
@@ -202,16 +202,18 @@ assertEq(testTrunc(13.37), 1);
     testBinary64('shr_s', "0xff00ff0000000", 28, 0xff00ff);
     testBinary64('shr_u', "0x8ffff00ff0000000", 56, 0x8f);
     testBinary64('rotl', 40, 2, 160);
     testBinary64('rotr', 40, 2, 10);
     testBinary64('rotr', "0x1234567812345678", 4, "0x8123456781234567");
     testBinary64('rotl', "0x1234567812345678", 4, "0x2345678123456781");
     testBinary64('rotl', "0x1234567812345678", 60, "0x8123456781234567");
     testBinary64('rotr', "0x1234567812345678", 60, "0x2345678123456781");
+    testBinary64('rotl', "0x0000000000001000", 127, "0x0000000000000800");
+    testBinary64('rotr', "0x0000000000001000", 127, "0x0000000000002000");
     testBinary64('rotr', 40, 0, 40);
     testBinary64('rotl', 40, 0, 40);
     testBinary64('and', 42, 0, 0);
     testBinary64('and', "0x0000000012345678", "0xffff0000ffff0000", "0x0000000012340000");
 
     testComparison64('eq', 40, 40, 1);
     testComparison64('ne', 40, 40, 0);
     testComparison64('lt_s', 40, 40, 0);
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -1672,24 +1672,19 @@ IonBuilder::visitBackEdge(CFGBackEdge* i
         return false;
     }
     if (r == AbortReason_Disable) {
         // If there are types for variables on the backedge that were not
         // present at the original loop header, then uses of the variables'
         // phis may have generated incorrect nodes. The new types have been
         // incorporated into the header phis, so remove all blocks for the
         // loop body and restart with the new types.
-        GraphSpewer& gs = graphSpewer();
-        gs.spewPass("beforeloop");
-
         *restarted = true;
         if (!restartLoop(ins->getSuccessor(0)))
             return false;
-
-        gs.spewPass("afterloop");
         return true;
     }
 
     loopHeaderStack_.popBack();
 #ifdef DEBUG
     cfgLoopHeaderStack_.popBack();
 #endif
     return true;
--- a/js/src/jit/IonControlFlow.cpp
+++ b/js/src/jit/IonControlFlow.cpp
@@ -1847,16 +1847,18 @@ ControlFlowGenerator::processTableSwitch
     CFGBlock* defaultcase = CFGBlock::New(alloc(), defaultpc);
 
     if (!tableswitch->addDefault(defaultcase))
         return ControlStatus::Error;
 
     // Create cases
     jsbytecode* casepc = nullptr;
     for (int i = 0; i < high-low+1; i++) {
+        if (!alloc().ensureBallast())
+            return ControlStatus::Error;
         casepc = pc + GET_JUMP_OFFSET(pc2);
 
         MOZ_ASSERT(casepc >= pc && casepc <= exitpc);
         CFGBlock* caseBlock;
 
         if (casepc == pc) {
             // If the casepc equals the current pc, it is not a written case,
             // but a filled gap. That way we can use a tableswitch instead of
--- a/js/src/jit/MacroAssembler.h
+++ b/js/src/jit/MacroAssembler.h
@@ -761,17 +761,17 @@ class MacroAssembler : public MacroAssem
     inline void addPtr(ImmWord imm, Register dest) PER_ARCH;
     inline void addPtr(ImmPtr imm, Register dest);
     inline void addPtr(Imm32 imm, const Address& dest) DEFINED_ON(mips_shared, arm, arm64, x86, x64);
     inline void addPtr(Imm32 imm, const AbsoluteAddress& dest) DEFINED_ON(x86, x64);
     inline void addPtr(const Address& src, Register dest) DEFINED_ON(mips_shared, arm, arm64, x86, x64);
 
     inline void add64(Register64 src, Register64 dest) PER_ARCH;
     inline void add64(Imm32 imm, Register64 dest) PER_ARCH;
-    inline void add64(Imm64 imm, Register64 dest) DEFINED_ON(x86, x64, arm, mips32, mips64);
+    inline void add64(Imm64 imm, Register64 dest) PER_ARCH;
     inline void add64(const Operand& src, Register64 dest) DEFINED_ON(x64, mips64);
 
     inline void addFloat32(FloatRegister src, FloatRegister dest) PER_SHARED_ARCH;
 
     inline void addDouble(FloatRegister src, FloatRegister dest) PER_SHARED_ARCH;
     inline void addConstantDouble(double d, FloatRegister dest) DEFINED_ON(x86);
 
     inline void sub32(const Address& src, Register dest) PER_SHARED_ARCH;
@@ -780,17 +780,17 @@ class MacroAssembler : public MacroAssem
 
     inline void subPtr(Register src, Register dest) PER_ARCH;
     inline void subPtr(Register src, const Address& dest) DEFINED_ON(mips_shared, arm, arm64, x86, x64);
     inline void subPtr(Imm32 imm, Register dest) PER_ARCH;
     inline void subPtr(ImmWord imm, Register dest) DEFINED_ON(x64);
     inline void subPtr(const Address& addr, Register dest) DEFINED_ON(mips_shared, arm, arm64, x86, x64);
 
     inline void sub64(Register64 src, Register64 dest) PER_ARCH;
-    inline void sub64(Imm64 imm, Register64 dest) DEFINED_ON(x86, x64, arm, mips32, mips64);
+    inline void sub64(Imm64 imm, Register64 dest) PER_ARCH;
     inline void sub64(const Operand& src, Register64 dest) DEFINED_ON(x64, mips64);
 
     inline void subFloat32(FloatRegister src, FloatRegister dest) PER_SHARED_ARCH;
 
     inline void subDouble(FloatRegister src, FloatRegister dest) PER_SHARED_ARCH;
 
     // On x86-shared, srcDest must be eax and edx will be clobbered.
     inline void mul32(Register rhs, Register srcDest) PER_SHARED_ARCH;
@@ -895,26 +895,26 @@ class MacroAssembler : public MacroAssem
     // Note: - on x86 and x64 the count register must be in CL.
     //       - on x64 the temp register should be InvalidReg.
 
     inline void rotateLeft(Imm32 count, Register input, Register dest) PER_SHARED_ARCH;
     inline void rotateLeft(Register count, Register input, Register dest) PER_SHARED_ARCH;
     inline void rotateLeft64(Imm32 count, Register64 input, Register64 dest) DEFINED_ON(x64);
     inline void rotateLeft64(Register count, Register64 input, Register64 dest) DEFINED_ON(x64);
     inline void rotateLeft64(Imm32 count, Register64 input, Register64 dest, Register temp)
-        DEFINED_ON(x86, x64, arm, mips32, mips64);
+        PER_ARCH;
     inline void rotateLeft64(Register count, Register64 input, Register64 dest, Register temp)
         PER_ARCH;
 
     inline void rotateRight(Imm32 count, Register input, Register dest) PER_SHARED_ARCH;
     inline void rotateRight(Register count, Register input, Register dest) PER_SHARED_ARCH;
     inline void rotateRight64(Imm32 count, Register64 input, Register64 dest) DEFINED_ON(x64);
     inline void rotateRight64(Register count, Register64 input, Register64 dest) DEFINED_ON(x64);
     inline void rotateRight64(Imm32 count, Register64 input, Register64 dest, Register temp)
-        DEFINED_ON(x86, x64, arm, mips32, mips64);
+        PER_ARCH;
     inline void rotateRight64(Register count, Register64 input, Register64 dest, Register temp)
         PER_ARCH;
 
     // ===============================================================
     // Bit counting functions
 
     // knownNotZero may be true only if the src is known not to be zero.
     inline void clz32(Register src, Register dest, bool knownNotZero) PER_SHARED_ARCH;
--- a/js/src/jit/arm64/MacroAssembler-arm64-inl.h
+++ b/js/src/jit/arm64/MacroAssembler-arm64-inl.h
@@ -302,16 +302,22 @@ MacroAssembler::add64(Register64 src, Re
 
 void
 MacroAssembler::add64(Imm32 imm, Register64 dest)
 {
     Add(ARMRegister(dest.reg, 64), ARMRegister(dest.reg, 64), Operand(imm.value));
 }
 
 void
+MacroAssembler::add64(Imm64 imm, Register64 dest)
+{
+    Add(ARMRegister(dest.reg, 64), ARMRegister(dest.reg, 64), Operand(imm.value));
+}
+
+void
 MacroAssembler::addDouble(FloatRegister src, FloatRegister dest)
 {
     fadd(ARMFPRegister(dest, 64), ARMFPRegister(dest, 64), ARMFPRegister(src, 64));
 }
 
 void
 MacroAssembler::addFloat32(FloatRegister src, FloatRegister dest)
 {
@@ -377,16 +383,22 @@ MacroAssembler::subPtr(const Address& ad
 
 void
 MacroAssembler::sub64(Register64 src, Register64 dest)
 {
     MOZ_CRASH("NYI: sub64");
 }
 
 void
+MacroAssembler::sub64(Imm64 imm, Register64 dest)
+{
+    MOZ_CRASH("NYI: sub64");
+}
+
+void
 MacroAssembler::subDouble(FloatRegister src, FloatRegister dest)
 {
     fsub(ARMFPRegister(dest, 64), ARMFPRegister(dest, 64), ARMFPRegister(src, 64));
 }
 
 void
 MacroAssembler::subFloat32(FloatRegister src, FloatRegister dest)
 {
@@ -721,21 +733,33 @@ MacroAssembler::rotateRight(Register cou
 
 void
 MacroAssembler::rotateLeft64(Register count, Register64 input, Register64 dest, Register temp)
 {
     MOZ_CRASH("NYI: rotateLeft64");
 }
 
 void
+MacroAssembler::rotateLeft64(Imm32 count, Register64 input, Register64 dest, Register temp)
+{
+    MOZ_CRASH("NYI: rotateLeft64");
+}
+
+void
 MacroAssembler::rotateRight64(Register count, Register64 input, Register64 dest, Register temp)
 {
     MOZ_CRASH("NYI: rotateRight64");
 }
 
+void
+MacroAssembler::rotateRight64(Imm32 count, Register64 input, Register64 dest, Register temp)
+{
+    MOZ_CRASH("NYI: rotateRight64");
+}
+
 // ===============================================================
 // Bit counting functions
 
 void
 MacroAssembler::clz32(Register src, Register dest, bool knownNotZero)
 {
     MOZ_CRASH("NYI: clz32");
 }
--- a/js/src/vm/Stopwatch.h
+++ b/js/src/vm/Stopwatch.h
@@ -296,19 +296,19 @@ struct PerformanceMonitoring {
      * The highest value of the timestamp counter encountered
      * during this iteration.
      */
     uint64_t highestTimestampCounter_;
 };
 
 #if WINVER >= 0x0600
 struct cpuid_t {
-    WORD group_;
-    BYTE number_;
-    cpuid_t(WORD group, BYTE number)
+    uint16_t group_;
+    uint8_t number_;
+    cpuid_t(uint16_t group, uint8_t number)
         : group_(group),
           number_(number)
     { }
     cpuid_t()
         : group_(0),
           number_(0)
     { }
 };
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -1687,16 +1687,25 @@ class BaseCompiler
         Stk& v = stk_.back();
         if (v.kind() != Stk::ConstI32)
             return false;
         c = v.i32val();
         stk_.popBack();
         return true;
     }
 
+    MOZ_MUST_USE bool popConstI64(int64_t& c) {
+        Stk& v = stk_.back();
+        if (v.kind() != Stk::ConstI64)
+            return false;
+        c = v.i64val();
+        stk_.popBack();
+        return true;
+    }
+
     // TODO / OPTIMIZE (Bug 1316818): At the moment we use ReturnReg
     // for JoinReg.  It is possible other choices would lead to better
     // register allocation, as ReturnReg is often first in the
     // register set and will be heavily wanted by the register
     // allocator that uses takeFirst().
     //
     // Obvious options:
     //  - pick a register at the back of the register set
@@ -2685,16 +2694,24 @@ class BaseCompiler
         *r1 = widenI32(specific_ecx);
         *r1 = popI64ToSpecific(*r1);
         *r0 = popI64();
 #else
         pop2xI64(r0, r1);
 #endif
     }
 
+    bool rotate64NeedsTemp() const {
+#if defined(JS_CODEGEN_X86)
+        return true;
+#else
+        return false;
+#endif
+    }
+
     void maskShiftCount32(RegI32 r) {
 #if defined(JS_CODEGEN_ARM)
         masm.and32(Imm32(31), r);
 #endif
     }
 
     bool popcnt32NeedsTemp() const {
 #if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
@@ -3982,64 +3999,82 @@ BaseCompiler::emitAddI32()
         freeI32(r1);
         pushI32(r0);
     }
 }
 
 void
 BaseCompiler::emitAddI64()
 {
-    // TODO / OPTIMIZE: Ditto check for constant here (Bug 1316803)
-    RegI64 r0, r1;
-    pop2xI64(&r0, &r1);
-    masm.add64(r1, r0);
-    freeI64(r1);
-    pushI64(r0);
+    int64_t c;
+    if (popConstI64(c)) {
+        RegI64 r = popI64();
+        masm.add64(Imm64(c), r);
+        pushI64(r);
+    } else {
+        RegI64 r0, r1;
+        pop2xI64(&r0, &r1);
+        masm.add64(r1, r0);
+        freeI64(r1);
+        pushI64(r0);
+    }
 }
 
 void
 BaseCompiler::emitAddF64()
 {
-    // TODO / OPTIMIZE: Ditto check for constant here (Bug 1316803)
     RegF64 r0, r1;
     pop2xF64(&r0, &r1);
     masm.addDouble(r1, r0);
     freeF64(r1);
     pushF64(r0);
 }
 
 void
 BaseCompiler::emitAddF32()
 {
-    // TODO / OPTIMIZE: Ditto check for constant here (Bug 1316803)
     RegF32 r0, r1;
     pop2xF32(&r0, &r1);
     masm.addFloat32(r1, r0);
     freeF32(r1);
     pushF32(r0);
 }
 
 void
 BaseCompiler::emitSubtractI32()
 {
-    RegI32 r0, r1;
-    pop2xI32(&r0, &r1);
-    masm.sub32(r1, r0);
-    freeI32(r1);
-    pushI32(r0);
+    int32_t c;
+    if (popConstI32(c)) {
+        RegI32 r = popI32();
+        masm.sub32(Imm32(c), r);
+        pushI32(r);
+    } else {
+        RegI32 r0, r1;
+        pop2xI32(&r0, &r1);
+        masm.sub32(r1, r0);
+        freeI32(r1);
+        pushI32(r0);
+    }
 }
 
 void
 BaseCompiler::emitSubtractI64()
 {
-    RegI64 r0, r1;
-    pop2xI64(&r0, &r1);
-    masm.sub64(r1, r0);
-    freeI64(r1);
-    pushI64(r0);
+    int64_t c;
+    if (popConstI64(c)) {
+        RegI64 r = popI64();
+        masm.sub64(Imm64(c), r);
+        pushI64(r);
+    } else {
+        RegI64 r0, r1;
+        pop2xI64(&r0, &r1);
+        masm.sub64(r1, r0);
+        freeI64(r1);
+        pushI64(r0);
+    }
 }
 
 void
 BaseCompiler::emitSubtractF32()
 {
     RegF32 r0, r1;
     pop2xF32(&r0, &r1);
     masm.subFloat32(r1, r0);
@@ -4399,71 +4434,113 @@ BaseCompiler::emitCopysignF64()
     freeI64(x1);
     freeF64(r1);
     pushF64(r0);
 }
 
 void
 BaseCompiler::emitOrI32()
 {
-    RegI32 r0, r1;
-    pop2xI32(&r0, &r1);
-    masm.or32(r1, r0);
-    freeI32(r1);
-    pushI32(r0);
+    int32_t c;
+    if (popConstI32(c)) {
+        RegI32 r = popI32();
+        masm.or32(Imm32(c), r);
+        pushI32(r);
+    } else {
+        RegI32 r0, r1;
+        pop2xI32(&r0, &r1);
+        masm.or32(r1, r0);
+        freeI32(r1);
+        pushI32(r0);
+    }
 }
 
 void
 BaseCompiler::emitOrI64()
 {
-    RegI64 r0, r1;
-    pop2xI64(&r0, &r1);
-    masm.or64(r1, r0);
-    freeI64(r1);
-    pushI64(r0);
+    int64_t c;
+    if (popConstI64(c)) {
+        RegI64 r = popI64();
+        masm.or64(Imm64(c), r);
+        pushI64(r);
+    } else {
+        RegI64 r0, r1;
+        pop2xI64(&r0, &r1);
+        masm.or64(r1, r0);
+        freeI64(r1);
+        pushI64(r0);
+    }
 }
 
 void
 BaseCompiler::emitAndI32()
 {
-    RegI32 r0, r1;
-    pop2xI32(&r0, &r1);
-    masm.and32(r1, r0);
-    freeI32(r1);
-    pushI32(r0);
+    int32_t c;
+    if (popConstI32(c)) {
+        RegI32 r = popI32();
+        masm.and32(Imm32(c), r);
+        pushI32(r);
+    } else {
+        RegI32 r0, r1;
+        pop2xI32(&r0, &r1);
+        masm.and32(r1, r0);
+        freeI32(r1);
+        pushI32(r0);
+    }
 }
 
 void
 BaseCompiler::emitAndI64()
 {
-    RegI64 r0, r1;
-    pop2xI64(&r0, &r1);
-    masm.and64(r1, r0);
-    freeI64(r1);
-    pushI64(r0);
+    int64_t c;
+    if (popConstI64(c)) {
+        RegI64 r = popI64();
+        masm.and64(Imm64(c), r);
+        pushI64(r);
+    } else {
+        RegI64 r0, r1;
+        pop2xI64(&r0, &r1);
+        masm.and64(r1, r0);
+        freeI64(r1);
+        pushI64(r0);
+    }
 }
 
 void
 BaseCompiler::emitXorI32()
 {
-    RegI32 r0, r1;
-    pop2xI32(&r0, &r1);
-    masm.xor32(r1, r0);
-    freeI32(r1);
-    pushI32(r0);
+    int32_t c;
+    if (popConstI32(c)) {
+        RegI32 r = popI32();
+        masm.xor32(Imm32(c), r);
+        pushI32(r);
+    } else {
+        RegI32 r0, r1;
+        pop2xI32(&r0, &r1);
+        masm.xor32(r1, r0);
+        freeI32(r1);
+        pushI32(r0);
+    }
 }
 
 void
 BaseCompiler::emitXorI64()
 {
-    RegI64 r0, r1;
-    pop2xI64(&r0, &r1);
-    masm.xor64(r1, r0);
-    freeI64(r1);
-    pushI64(r0);
+    int64_t c;
+    if (popConstI64(c)) {
+        RegI64 r = popI64();
+        masm.xor64(Imm64(c), r);
+        pushI64(r);
+    } else {
+        RegI64 r0, r1;
+        pop2xI64(&r0, &r1);
+        masm.xor64(r1, r0);
+        freeI64(r1);
+        pushI64(r0);
+    }
 }
 
 void
 BaseCompiler::emitShlI32()
 {
     int32_t c;
     if (popConstI32(c)) {
         RegI32 r = popI32();
@@ -4477,22 +4554,28 @@ BaseCompiler::emitShlI32()
         freeI32(r1);
         pushI32(r0);
     }
 }
 
 void
 BaseCompiler::emitShlI64()
 {
-    // TODO / OPTIMIZE: Constant rhs (Bug 1316803)
-    RegI64 r0, r1;
-    pop2xI64ForShiftOrRotate(&r0, &r1);
-    masm.lshift64(lowPart(r1), r0);
-    freeI64(r1);
-    pushI64(r0);
+    int64_t c;
+    if (popConstI64(c)) {
+        RegI64 r = popI64();
+        masm.lshift64(Imm32(c & 63), r);
+        pushI64(r);
+    } else {
+        RegI64 r0, r1;
+        pop2xI64ForShiftOrRotate(&r0, &r1);
+        masm.lshift64(lowPart(r1), r0);
+        freeI64(r1);
+        pushI64(r0);
+    }
 }
 
 void
 BaseCompiler::emitShrI32()
 {
     int32_t c;
     if (popConstI32(c)) {
         RegI32 r = popI32();
@@ -4506,22 +4589,28 @@ BaseCompiler::emitShrI32()
         freeI32(r1);
         pushI32(r0);
     }
 }
 
 void
 BaseCompiler::emitShrI64()
 {
-    // TODO / OPTIMIZE: Constant rhs (Bug 1316803)
-    RegI64 r0, r1;
-    pop2xI64ForShiftOrRotate(&r0, &r1);
-    masm.rshift64Arithmetic(lowPart(r1), r0);
-    freeI64(r1);
-    pushI64(r0);
+    int64_t c;
+    if (popConstI64(c)) {
+        RegI64 r = popI64();
+        masm.rshift64Arithmetic(Imm32(c & 63), r);
+        pushI64(r);
+    } else {
+        RegI64 r0, r1;
+        pop2xI64ForShiftOrRotate(&r0, &r1);
+        masm.rshift64Arithmetic(lowPart(r1), r0);
+        freeI64(r1);
+        pushI64(r0);
+    }
 }
 
 void
 BaseCompiler::emitShrU32()
 {
     int32_t c;
     if (popConstI32(c)) {
         RegI32 r = popI32();
@@ -4535,66 +4624,106 @@ BaseCompiler::emitShrU32()
         freeI32(r1);
         pushI32(r0);
     }
 }
 
 void
 BaseCompiler::emitShrU64()
 {
-    // TODO / OPTIMIZE: Constant rhs (Bug 1316803)
-    RegI64 r0, r1;
-    pop2xI64ForShiftOrRotate(&r0, &r1);
-    masm.rshift64(lowPart(r1), r0);
-    freeI64(r1);
-    pushI64(r0);
+    int64_t c;
+    if (popConstI64(c)) {
+        RegI64 r = popI64();
+        masm.rshift64(Imm32(c & 63), r);
+        pushI64(r);
+    } else {
+        RegI64 r0, r1;
+        pop2xI64ForShiftOrRotate(&r0, &r1);
+        masm.rshift64(lowPart(r1), r0);
+        freeI64(r1);
+        pushI64(r0);
+    }
 }
 
 void
 BaseCompiler::emitRotrI32()
 {
-    // TODO / OPTIMIZE: Constant rhs (Bug 1316803)
-    RegI32 r0, r1;
-    pop2xI32ForShiftOrRotate(&r0, &r1);
-    masm.rotateRight(r1, r0, r0);
-    freeI32(r1);
-    pushI32(r0);
+    int32_t c;
+    if (popConstI32(c)) {
+        RegI32 r = popI32();
+        masm.rotateRight(Imm32(c & 31), r, r);
+        pushI32(r);
+    } else {
+        RegI32 r0, r1;
+        pop2xI32ForShiftOrRotate(&r0, &r1);
+        masm.rotateRight(r1, r0, r0);
+        freeI32(r1);
+        pushI32(r0);
+    }
 }
 
 void
 BaseCompiler::emitRotrI64()
 {
-    // TODO / OPTIMIZE: Constant rhs (Bug 1316803)
-    RegI64 r0, r1;
-    pop2xI64ForShiftOrRotate(&r0, &r1);
-    masm.rotateRight64(lowPart(r1), r0, r0, maybeHighPart(r1));
-    freeI64(r1);
-    pushI64(r0);
+    int64_t c;
+    if (popConstI64(c)) {
+        RegI64 r = popI64();
+        RegI32 temp;
+        if (rotate64NeedsTemp())
+            temp = needI32();
+        masm.rotateRight64(Imm32(c & 63), r, r, temp);
+        if (temp != Register::Invalid())
+            freeI32(temp);
+        pushI64(r);
+    } else {
+        RegI64 r0, r1;
+        pop2xI64ForShiftOrRotate(&r0, &r1);
+        masm.rotateRight64(lowPart(r1), r0, r0, maybeHighPart(r1));
+        freeI64(r1);
+        pushI64(r0);
+    }
 }
 
 void
 BaseCompiler::emitRotlI32()
 {
-    // TODO / OPTIMIZE: Constant rhs (Bug 1316803)
-    RegI32 r0, r1;
-    pop2xI32ForShiftOrRotate(&r0, &r1);
-    masm.rotateLeft(r1, r0, r0);
-    freeI32(r1);
-    pushI32(r0);
+    int32_t c;
+    if (popConstI32(c)) {
+        RegI32 r = popI32();
+        masm.rotateLeft(Imm32(c & 31), r, r);
+        pushI32(r);
+    } else {
+        RegI32 r0, r1;
+        pop2xI32ForShiftOrRotate(&r0, &r1);
+        masm.rotateLeft(r1, r0, r0);
+        freeI32(r1);
+        pushI32(r0);
+    }
 }
 
 void
 BaseCompiler::emitRotlI64()
 {
-    // TODO / OPTIMIZE: Constant rhs (Bug 1316803)
-    RegI64 r0, r1;
-    pop2xI64ForShiftOrRotate(&r0, &r1);
-    masm.rotateLeft64(lowPart(r1), r0, r0, maybeHighPart(r1));
-    freeI64(r1);
-    pushI64(r0);
+    int64_t c;
+    if (popConstI64(c)) {
+        RegI64 r = popI64();
+        RegI32 temp;
+        if (rotate64NeedsTemp())
+            temp = needI32();
+        masm.rotateLeft64(Imm32(c & 63), r, r, temp);
+        if (temp != Register::Invalid())
+            freeI32(temp);
+        pushI64(r);
+    } else {
+        RegI64 r0, r1;
+        pop2xI64ForShiftOrRotate(&r0, &r1);
+        masm.rotateLeft64(lowPart(r1), r0, r0, maybeHighPart(r1));
+        freeI64(r1);
+        pushI64(r0);
+    }
 }
 
 void
 BaseCompiler::emitEqzI32()
 {
     if (sniffConditionalControlEqz(ValType::I32))
         return;
 
--- a/js/xpconnect/idl/nsIXPCScriptable.idl
+++ b/js/xpconnect/idl/nsIXPCScriptable.idl
@@ -35,17 +35,17 @@ interface nsIXPConnectWrappedNative;
 [uuid(19b70b26-7c3f-437f-a04a-2a8f9e28b617)]
 interface nsIXPCScriptable : nsISupports
 {
     /* bitflags used for 'flags' (only 32 bits available!) */
 
     const uint32_t WANT_PRECREATE                   = 1 <<  0;
     // unused bit here
     // unused bit here
-    const uint32_t WANT_ADDPROPERTY                 = 1 <<  3;
+    // unused bit here
     // unused bit here
     const uint32_t WANT_GETPROPERTY                 = 1 <<  5;
     const uint32_t WANT_SETPROPERTY                 = 1 <<  6;
     const uint32_t WANT_ENUMERATE                   = 1 <<  7;
     const uint32_t WANT_NEWENUMERATE                = 1 <<  8;
     const uint32_t WANT_RESOLVE                     = 1 <<  9;
     // unused bit here
     const uint32_t WANT_FINALIZE                    = 1 << 11;
@@ -72,20 +72,16 @@ interface nsIXPCScriptable : nsISupports
     const uint32_t RESERVED                         = 1 << 31;
 
     readonly attribute string   className;
     [notxpcom,nostdcall] uint32_t getScriptableFlags();
 
     void   preCreate(in nsISupports nativeObj, in JSContextPtr cx,
                      in JSObjectPtr globalObj, out JSObjectPtr parentObj);
 
-    boolean addProperty(in nsIXPConnectWrappedNative wrapper,
-                       in JSContextPtr cx, in JSObjectPtr obj, in jsid id,
-                       in jsval val);
-
     boolean getProperty(in nsIXPConnectWrappedNative wrapper,
                        in JSContextPtr cx, in JSObjectPtr obj, in jsid id,
                        in JSValPtr vp);
 
     boolean setProperty(in nsIXPConnectWrappedNative wrapper,
                        in JSContextPtr cx, in JSObjectPtr obj, in jsid id,
                        in JSValPtr vp);
 
--- a/js/xpconnect/public/xpc_map_end.h
+++ b/js/xpconnect/public/xpc_map_end.h
@@ -29,19 +29,16 @@ NS_IMETHODIMP XPC_MAP_CLASSNAME::GetClas
 // virtual
 uint32_t
 XPC_MAP_CLASSNAME::GetScriptableFlags()
 {
     return
 #ifdef XPC_MAP_WANT_PRECREATE
     nsIXPCScriptable::WANT_PRECREATE |
 #endif
-#ifdef XPC_MAP_WANT_ADDPROPERTY
-    nsIXPCScriptable::WANT_ADDPROPERTY |
-#endif
 #ifdef XPC_MAP_WANT_GETPROPERTY
     nsIXPCScriptable::WANT_GETPROPERTY |
 #endif
 #ifdef XPC_MAP_WANT_SETPROPERTY
     nsIXPCScriptable::WANT_SETPROPERTY |
 #endif
 #ifdef XPC_MAP_WANT_ENUMERATE
     nsIXPCScriptable::WANT_ENUMERATE |
@@ -72,21 +69,16 @@ XPC_MAP_CLASSNAME::GetScriptableFlags()
 
 /**************************************************************/
 
 #ifndef XPC_MAP_WANT_PRECREATE
 NS_IMETHODIMP XPC_MAP_CLASSNAME::PreCreate(nsISupports* nativeObj, JSContext * cx, JSObject * globalObj, JSObject * *parentObj)
     {NS_ERROR("never called"); return NS_ERROR_NOT_IMPLEMENTED;}
 #endif
 
-#ifndef XPC_MAP_WANT_ADDPROPERTY
-NS_IMETHODIMP XPC_MAP_CLASSNAME::AddProperty(nsIXPConnectWrappedNative* wrapper, JSContext * cx, JSObject * obj, jsid id, JS::HandleValue val, bool* _retval)
-    {NS_ERROR("never called"); return NS_ERROR_NOT_IMPLEMENTED;}
-#endif
-
 #ifndef XPC_MAP_WANT_GETPROPERTY
 NS_IMETHODIMP XPC_MAP_CLASSNAME::GetProperty(nsIXPConnectWrappedNative* wrapper, JSContext * cx, JSObject * obj, jsid id, JS::Value * vp, bool* _retval)
     {NS_WARNING("never called"); return NS_ERROR_NOT_IMPLEMENTED;}
 #endif
 
 #ifndef XPC_MAP_WANT_SETPROPERTY
 NS_IMETHODIMP XPC_MAP_CLASSNAME::SetProperty(nsIXPConnectWrappedNative* wrapper, JSContext * cx, JSObject * obj, jsid id, JS::Value * vp, bool* _retval)
     {NS_WARNING("never called"); return NS_ERROR_NOT_IMPLEMENTED;}
@@ -122,34 +114,28 @@ NS_IMETHODIMP XPC_MAP_CLASSNAME::Constru
     {NS_ERROR("never called"); return NS_ERROR_NOT_IMPLEMENTED;}
 #endif
 
 #ifndef XPC_MAP_WANT_HASINSTANCE
 NS_IMETHODIMP XPC_MAP_CLASSNAME::HasInstance(nsIXPConnectWrappedNative* wrapper, JSContext * cx, JSObject * obj, JS::HandleValue val, bool* bp, bool* _retval)
     {NS_ERROR("never called"); return NS_ERROR_NOT_IMPLEMENTED;}
 #endif
 
-#ifndef XPC_MAP_WANT_POST_CREATE_PROTOTYPE
 NS_IMETHODIMP XPC_MAP_CLASSNAME::PostCreatePrototype(JSContext* cx, JSObject* proto)
     {return NS_OK;}
-#endif
 
 /**************************************************************/
 
 #undef XPC_MAP_CLASSNAME
 #undef XPC_MAP_QUOTED_CLASSNAME
 
 #ifdef XPC_MAP_WANT_PRECREATE
 #undef XPC_MAP_WANT_PRECREATE
 #endif
 
-#ifdef XPC_MAP_WANT_ADDPROPERTY
-#undef XPC_MAP_WANT_ADDPROPERTY
-#endif
-
 #ifdef XPC_MAP_WANT_GETPROPERTY
 #undef XPC_MAP_WANT_GETPROPERTY
 #endif
 
 #ifdef XPC_MAP_WANT_SETPROPERTY
 #undef XPC_MAP_WANT_SETPROPERTY
 #endif
 
@@ -176,15 +162,11 @@ NS_IMETHODIMP XPC_MAP_CLASSNAME::PostCre
 #ifdef XPC_MAP_WANT_CONSTRUCT
 #undef XPC_MAP_WANT_CONSTRUCT
 #endif
 
 #ifdef XPC_MAP_WANT_HASINSTANCE
 #undef XPC_MAP_WANT_HASINSTANCE
 #endif
 
-#ifdef XPC_MAP_WANT_POST_CREATE_PROTOTYPE
-#undef XPC_MAP_WANT_POST_CREATE_PROTOTYPE
-#endif
-
 #ifdef XPC_MAP_FLAGS
 #undef XPC_MAP_FLAGS
 #endif
--- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
@@ -710,25 +710,16 @@ XPC_WN_MaybeResolvingDeletePropertyStub(
         return Throw(rv, cx);                                                 \
     return retval;
 
 #define POST_HELPER_STUB_WITH_OBJECTOPRESULT(failMethod)                      \
     if (NS_FAILED(rv))                                                        \
         return Throw(rv, cx);                                                 \
     return retval ? result.succeed() : result.failMethod();
 
-static bool
-XPC_WN_Helper_AddProperty(JSContext* cx, HandleObject obj, HandleId id,
-                          HandleValue v)
-{
-    PRE_HELPER_STUB
-    AddProperty(wrapper, cx, obj, id, v, &retval);
-    POST_HELPER_STUB
-}
-
 bool
 XPC_WN_Helper_GetProperty(JSContext* cx, HandleObject obj, HandleId id,
                           MutableHandleValue vp)
 {
     PRE_HELPER_STUB
     GetProperty(wrapper, cx, obj, id, vp.address(), &retval);
     POST_HELPER_STUB
 }
@@ -982,19 +973,17 @@ XPCNativeScriptableShared::XPCNativeScri
     // Initialize the js::ClassExtension.
 
     // This is an unusual js::ClassOps: it is heap-allocated and belongs to
     // |this|.
     js::ClassOps* cOps = new js::ClassOps;
     memset(cOps, 0, sizeof(js::ClassOps));
     mJSClass.cOps = cOps;
 
-    if (mFlags.WantAddProperty())
-        cOps->addProperty = XPC_WN_Helper_AddProperty;
-    else if (mFlags.UseJSStubForAddProperty())
+    if (mFlags.UseJSStubForAddProperty())
         cOps->addProperty = nullptr;
     else if (mFlags.AllowPropModsDuringResolve())
         cOps->addProperty = XPC_WN_MaybeResolvingPropertyStub;
     else
         cOps->addProperty = XPC_WN_CannotModifyPropertyStub;
 
     if (mFlags.UseJSStubForDelProperty())
         cOps->delProperty = nullptr;
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -1423,17 +1423,16 @@ public:
     }
 
 #ifdef GET_IT
 #undef GET_IT
 #endif
 #define GET_IT(f_) const { return 0 != (mFlags & nsIXPCScriptable:: f_ ); }
 
     bool WantPreCreate()                GET_IT(WANT_PRECREATE)
-    bool WantAddProperty()              GET_IT(WANT_ADDPROPERTY)
     bool WantGetProperty()              GET_IT(WANT_GETPROPERTY)
     bool WantSetProperty()              GET_IT(WANT_SETPROPERTY)
     bool WantEnumerate()                GET_IT(WANT_ENUMERATE)
     bool WantNewEnumerate()             GET_IT(WANT_NEWENUMERATE)
     bool WantResolve()                  GET_IT(WANT_RESOLVE)
     bool WantFinalize()                 GET_IT(WANT_FINALIZE)
     bool WantCall()                     GET_IT(WANT_CALL)
     bool WantConstruct()                GET_IT(WANT_CONSTRUCT)
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -4276,18 +4276,18 @@ nsCSSFrameConstructor::GetAnonymousConte
     }
   }
 
   if (ServoStyleSet* styleSet = mPresShell->StyleSet()->GetAsServo()) {
     // Eagerly compute styles for the anonymous content tree, but only do so
     // if the content doesn't have an explicit style context (if it does, we
     // don't need the normal computed values).
     for (auto& info : aContent) {
-      if (!info.mStyleContext) {
-        styleSet->StyleNewSubtree(info.mContent);
+      if (!info.mStyleContext && info.mContent->IsElement()) {
+        styleSet->StyleNewSubtree(info.mContent->AsElement());
       }
     }
   }
 
   return NS_OK;
 }
 
 static
@@ -7385,21 +7385,17 @@ nsCSSFrameConstructor::ContentAppended(n
   // We couldn't construct lazily. Make Servo eagerly traverse the subtree.
   if (ServoStyleSet* set = mPresShell->StyleSet()->GetAsServo()) {
     // We use the same codepaths to handle both of the following cases:
     //   (a) Newly-appended content for which lazy frame construction is disallowed.
     //   (b) Lazy frame construction driven by the restyle manager.
     // We need the styles for (a). In the case of (b), the Servo traversal has
     // already happened, so we don't need to do it again.
     if (!RestyleManager()->AsBase()->IsInStyleRefresh()) {
-      if (aFirstNewContent->GetNextSibling()) {
-        set->StyleNewChildren(aContainer);
-      } else {
-        set->StyleNewSubtree(aFirstNewContent);
-      }
+      set->StyleNewChildren(aContainer->AsElement());
     }
   }
 
   LAYOUT_PHASE_TEMP_EXIT();
   InsertionPoint insertion =
     GetRangeInsertionPoint(aContainer, aFirstNewContent, nullptr,
                            aAllowLazyConstruction);
   nsContainerFrame*& parentFrame = insertion.mParentFrame;
@@ -7850,17 +7846,17 @@ nsCSSFrameConstructor::ContentRangeInser
   // We couldn't construct lazily. Make Servo eagerly traverse the subtree.
   if (ServoStyleSet* set = mPresShell->StyleSet()->GetAsServo()) {
     // We use the same codepaths to handle both of the following cases:
     //   (a) Newly-appended content for which lazy frame construction is disallowed.
     //   (b) Lazy frame construction driven by the restyle manager.
     // We need the styles for (a). In the case of (b), the Servo traversal has
     // already happened, so we don't need to do it again.
     if (!RestyleManager()->AsBase()->IsInStyleRefresh()) {
-      set->StyleNewSubtree(aStartChild);
+      set->StyleNewChildren(aContainer->AsElement());
     }
   }
 
   InsertionPoint insertion;
   if (isSingleInsert) {
     // See if we have an XBL insertion point. If so, then that's our
     // real parent frame; if not, then the frame hasn't been built yet
     // and we just bail.
--- a/layout/forms/nsComboboxControlFrame.cpp
+++ b/layout/forms/nsComboboxControlFrame.cpp
@@ -378,23 +378,21 @@ nsComboboxControlFrame::ShowList(bool aS
 
 class nsResizeDropdownAtFinalPosition final
   : public nsIReflowCallback, public Runnable
 {
 public:
   explicit nsResizeDropdownAtFinalPosition(nsComboboxControlFrame* aFrame)
     : mFrame(aFrame)
   {
-    MOZ_COUNT_CTOR(nsResizeDropdownAtFinalPosition);
   }
 
 protected:
   ~nsResizeDropdownAtFinalPosition()
   {
-    MOZ_COUNT_DTOR(nsResizeDropdownAtFinalPosition);
   }
 
 public:
   virtual bool ReflowFinished() override
   {
     Run();
     NS_RELEASE_THIS();
     return false;
--- a/layout/mathml/nsMathMLChar.cpp
+++ b/layout/mathml/nsMathMLChar.cpp
@@ -601,34 +601,32 @@ public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
   nsPropertiesTable mUnicodeTable;
 
   nsGlyphTableList()
     : mUnicodeTable(NS_LITERAL_STRING("Unicode"))
   {
-    MOZ_COUNT_CTOR(nsGlyphTableList);
   }
 
   nsresult Initialize();
   nsresult Finalize();
 
   // Add a glyph table in the list, return the new table that was added
   nsGlyphTable*
   AddGlyphTable(const nsString& aPrimaryFontName);
 
   // Find the glyph table in the list corresponding to the given font family.
   nsGlyphTable*
   GetGlyphTableFor(const nsAString& aFamily);
 
 private:
   ~nsGlyphTableList()
   {
-    MOZ_COUNT_DTOR(nsGlyphTableList);
   }
 
   nsPropertiesTable* PropertiesTableAt(int32_t aIndex) {
     return &mPropertiesTableList.ElementAt(aIndex);
   }
   int32_t PropertiesTableCount() {
     return mPropertiesTableList.Length();
   }
--- a/layout/printing/ipc/RemotePrintJobChild.cpp
+++ b/layout/printing/ipc/RemotePrintJobChild.cpp
@@ -13,17 +13,16 @@
 namespace mozilla {
 namespace layout {
 
 NS_IMPL_ISUPPORTS(RemotePrintJobChild,
                   nsIWebProgressListener)
 
 RemotePrintJobChild::RemotePrintJobChild()
 {
-  MOZ_COUNT_CTOR(RemotePrintJobChild);
 }
 
 nsresult
 RemotePrintJobChild::InitializePrint(const nsString& aDocumentTitle,
                                      const nsString& aPrintToFile,
                                      const int32_t& aStartPage,
                                      const int32_t& aEndPage)
 {
@@ -136,17 +135,16 @@ RemotePrintJobChild::OnSecurityChange(ns
 {
   return NS_OK;
 }
 
 // End of nsIWebProgressListener
 
 RemotePrintJobChild::~RemotePrintJobChild()
 {
-  MOZ_COUNT_DTOR(RemotePrintJobChild);
 }
 
 void
 RemotePrintJobChild::ActorDestroy(ActorDestroyReason aWhy)
 {
   mPagePrintTimer = nullptr;
   mPrintEngine = nullptr;
 }
--- a/layout/style/CSSStyleSheet.cpp
+++ b/layout/style/CSSStyleSheet.cpp
@@ -641,20 +641,17 @@ nsMediaList::GetText(nsAString& aMediaTe
 }
 
 // XXXbz this is so ill-defined in the spec, it's not clear quite what
 // it should be doing....
 void
 nsMediaList::SetText(const nsAString& aMediaText)
 {
   nsCSSParser parser;
-
-  bool htmlMode = mStyleSheet && mStyleSheet->GetOwnerNode();
-
-  parser.ParseMediaList(aMediaText, nullptr, 0, this, htmlMode);
+  parser.ParseMediaList(aMediaText, nullptr, 0, this);
 }
 
 bool
 nsMediaList::Matches(nsPresContext* aPresContext,
                      nsMediaQueryResultCacheKey* aKey)
 {
   for (int32_t i = 0, i_end = mArray.Length(); i < i_end; ++i) {
     if (mArray[i]->Matches(aPresContext, aKey)) {
--- a/layout/style/FontFace.cpp
+++ b/layout/style/FontFace.cpp
@@ -104,23 +104,20 @@ FontFace::FontFace(nsISupports* aParent,
   , mLoadedRejection(NS_OK)
   , mStatus(FontFaceLoadStatus::Unloaded)
   , mSourceType(SourceType(0))
   , mSourceBuffer(nullptr)
   , mSourceBufferLength(0)
   , mFontFaceSet(aFontFaceSet)
   , mInFontFaceSet(false)
 {
-  MOZ_COUNT_CTOR(FontFace);
 }
 
 FontFace::~FontFace()
 {
-  MOZ_COUNT_DTOR(FontFace);
-
   SetUserFontEntry(nullptr);
 
   if (mSourceBuffer) {
     free(mSourceBuffer);
   }
 }
 
 JSObject*
--- a/layout/style/FontFaceSet.cpp
+++ b/layout/style/FontFaceSet.cpp
@@ -99,18 +99,16 @@ FontFaceSet::FontFaceSet(nsPIDOMWindowIn
   , mDocument(aDocument)
   , mResolveLazilyCreatedReadyPromise(false)
   , mStatus(FontFaceSetLoadStatus::Loaded)
   , mNonRuleFacesDirty(false)
   , mHasLoadingFontFaces(false)
   , mHasLoadingFontFacesIsDirty(false)
   , mDelayedLoadCheck(false)
 {
-  MOZ_COUNT_CTOR(FontFaceSet);
-
   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aWindow);
 
   // If the pref is not set, don't create the Promise (which the page wouldn't
   // be able to get to anyway) as it causes the window.FontFaceSet constructor
   // to be created.
   if (global && PrefEnabled()) {
     mResolveLazilyCreatedReadyPromise = true;
   }
@@ -122,18 +120,16 @@ FontFaceSet::FontFaceSet(nsPIDOMWindowIn
 
   mDocument->CSSLoader()->AddObserver(this);
 
   mUserFontSet = new UserFontSet(this);
 }
 
 FontFaceSet::~FontFaceSet()
 {
-  MOZ_COUNT_DTOR(FontFaceSet);
-
   Disconnect();
   for (auto it = mLoaders.Iter(); !it.Done(); it.Next()) {
     it.Get()->GetKey()->Cancel();
   }
 }
 
 JSObject*
 FontFaceSet::WrapObject(JSContext* aContext, JS::Handle<JSObject*> aGivenProto)
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -1295,17 +1295,17 @@ Loader::PrepareSheet(StyleSheet* aSheet,
     NS_ASSERTION(!aMediaList,
                  "must not provide both aMediaString and aMediaList");
     mediaList = new nsMediaList();
 
     nsCSSParser mediumParser(this);
 
     // We have aMediaString only when linked from link elements, style
     // elements, or PIs, so pass true.
-    mediumParser.ParseMediaList(aMediaString, nullptr, 0, mediaList, true);
+    mediumParser.ParseMediaList(aMediaString, nullptr, 0, mediaList);
   }
 
   sheet->SetMedia(mediaList);
 
   sheet->SetTitle(aTitle);
   sheet->SetEnabled(!isAlternate);
   sheet->SetScopeElement(aScopeElement);
 }
--- a/layout/style/MediaQueryList.cpp
+++ b/layout/style/MediaQueryList.cpp
@@ -19,17 +19,17 @@ MediaQueryList::MediaQueryList(nsIDocume
                                const nsAString &aMediaQueryList)
   : mDocument(aDocument),
     mMediaList(new nsMediaList),
     mMatchesValid(false)
 {
   PR_INIT_CLIST(this);
 
   nsCSSParser parser;
-  parser.ParseMediaList(aMediaQueryList, nullptr, 0, mMediaList, false);
+  parser.ParseMediaList(aMediaQueryList, nullptr, 0, mMediaList);
 }
 
 MediaQueryList::~MediaQueryList()
 {
   if (mDocument) {
     PR_REMOVE_LINK(this);
   }
 }
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -154,17 +154,17 @@ SERVO_BINDING_FUNC(Servo_NoteExplicitHin
 SERVO_BINDING_FUNC(Servo_CheckChangeHint, nsChangeHint, RawGeckoElementBorrowed element)
 SERVO_BINDING_FUNC(Servo_ResolveStyle, ServoComputedValuesStrong,
                    RawGeckoElementBorrowed element, RawServoStyleSetBorrowed set,
                    mozilla::ConsumeStyleBehavior consume, mozilla::LazyComputeBehavior compute)
 
 // Restyle the given subtree.
 SERVO_BINDING_FUNC(Servo_TraverseSubtree, void,
                    RawGeckoElementBorrowed root, RawServoStyleSetBorrowed set,
-                   mozilla::SkipRootBehavior skip_root)
+                   mozilla::TraversalRootBehavior root_behavior)
 
 // Assert that the tree has no pending or unconsumed restyles.
 SERVO_BINDING_FUNC(Servo_AssertTreeIsClean, void, RawGeckoElementBorrowed root)
 
 // Style-struct management.
 #define STYLE_STRUCT(name, checkdata_cb)                            \
   struct nsStyle##name;                                             \
   SERVO_BINDING_FUNC(Servo_GetStyle##name, const nsStyle##name*,  \
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -450,34 +450,33 @@ ServoStyleSet::HasStateDependentStyle(do
 void
 ServoStyleSet::StyleDocument()
 {
   // Restyle the document from the root element and each of the document level
   // NAC subtree roots.
   DocumentStyleRootIterator iter(mPresContext->Document());
   while (Element* root = iter.GetNextStyleRoot()) {
     if (root->ShouldTraverseForServo()) {
-      Servo_TraverseSubtree(root, mRawSet.get(), SkipRootBehavior::DontSkip);
+      Servo_TraverseSubtree(root, mRawSet.get(), TraversalRootBehavior::Normal);
     }
   }
 }
 
 void
-ServoStyleSet::StyleNewSubtree(nsIContent* aContent)
+ServoStyleSet::StyleNewSubtree(Element* aRoot)
 {
-  if (aContent->IsElement()) {
-    Servo_TraverseSubtree(aContent->AsElement(), mRawSet.get(), SkipRootBehavior::DontSkip);
-  }
+  MOZ_ASSERT(!aRoot->HasServoData());
+  Servo_TraverseSubtree(aRoot, mRawSet.get(), TraversalRootBehavior::Normal);
 }
 
 void
-ServoStyleSet::StyleNewChildren(nsIContent* aParent)
+ServoStyleSet::StyleNewChildren(Element* aParent)
 {
-  MOZ_ASSERT(aParent->IsElement());
-  Servo_TraverseSubtree(aParent->AsElement(), mRawSet.get(), SkipRootBehavior::Skip);
+  Servo_TraverseSubtree(aParent, mRawSet.get(),
+                        TraversalRootBehavior::UnstyledChildrenOnly);
 }
 
 #ifdef DEBUG
 void
 ServoStyleSet::AssertTreeIsClean()
 {
   if (Element* root = mPresContext->Document()->GetRootElement()) {
     Servo_AssertTreeIsClean(root);
--- a/layout/style/ServoStyleSet.h
+++ b/layout/style/ServoStyleSet.h
@@ -123,34 +123,29 @@ public:
 
   /**
    * Performs a Servo traversal to compute style for all dirty nodes in the
    * document. The root element must be non-null.
    */
   void StyleDocument();
 
   /**
-   * Eagerly styles a subtree of dirty nodes that were just appended to the
+   * Eagerly styles a subtree of unstyled nodes that was just appended to the
    * tree. This is used in situations where we need the style immediately and
    * cannot wait for a future batch restyle.
-   *
-   * The subtree must have the root dirty bit set, which currently gets
-   * propagated to all descendants. The dirty bits are cleared before
-   * returning.
    */
-  void StyleNewSubtree(nsIContent* aContent);
+  void StyleNewSubtree(Element* aRoot);
 
   /**
-   * Like the above, but does not assume that the root node is dirty. When
-   * appending multiple children to a potentially-non-dirty node, it's
-   * preferable to call StyleNewChildren on the node rather than making multiple
-   * calls to StyleNewSubtree on each child, since it allows for more
-   * parallelism.
+   * Like the above, but skips the root node, and only styles unstyled children.
+   * When potentially appending multiple children, it's preferable to call
+   * StyleNewChildren on the node rather than making multiple calls to
+   * StyleNewSubtree on each child, since it allows for more parallelism.
    */
-  void StyleNewChildren(nsIContent* aParent);
+  void StyleNewChildren(Element* aParent);
 
 #ifdef DEBUG
   void AssertTreeIsClean();
 #else
   void AssertTreeIsClean() {}
 #endif
 
 private:
--- a/layout/style/ServoTypes.h
+++ b/layout/style/ServoTypes.h
@@ -46,18 +46,19 @@ enum class ConsumeStyleBehavior {
 // Indicates whether the Servo style system should expect the style on an element
 // to have already been resolved (i.e. via a parallel traversal), or whether it
 // may be lazily computed.
 enum class LazyComputeBehavior {
   Allow,
   Assert,
 };
 
-// Indicates whether the Servo style system should skip processing on the root
-// element and start processing with its children.
-enum class SkipRootBehavior {
-  Skip,
-  DontSkip,
+// Indicates whether the Servo style system should perform normal processing or
+// whether it should only process unstyled children of the root and their
+// descendants.
+enum class TraversalRootBehavior {
+  Normal,
+  UnstyledChildrenOnly,
 };
 
 } // namespace mozilla
 
 #endif // mozilla_ServoTypes_h
--- a/layout/style/StyleRule.cpp
+++ b/layout/style/StyleRule.cpp
@@ -1125,24 +1125,21 @@ protected:
 };
 
 } // namespace css
 } // namespace mozilla
 
 DOMCSSDeclarationImpl::DOMCSSDeclarationImpl(css::StyleRule *aRule)
   : mRule(aRule)
 {
-  MOZ_COUNT_CTOR(DOMCSSDeclarationImpl);
 }
 
 DOMCSSDeclarationImpl::~DOMCSSDeclarationImpl(void)
 {
   NS_ASSERTION(!mRule, "DropReference not called.");
-
-  MOZ_COUNT_DTOR(DOMCSSDeclarationImpl);
 }
 
 inline css::DOMCSSStyleRule* DOMCSSDeclarationImpl::DomRule()
 {
   return reinterpret_cast<css::DOMCSSStyleRule*>
                          (reinterpret_cast<char*>(this) -
            offsetof(css::DOMCSSStyleRule, mDOMDeclaration));
 }
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -197,25 +197,23 @@ public:
 
   bool ParseTransformProperty(const nsAString& aPropValue,
                               bool aDisallowRelativeValues,
                               nsCSSValue& aResult);
 
   void ParseMediaList(const nsSubstring& aBuffer,
                       nsIURI* aURL, // for error reporting
                       uint32_t aLineNumber, // for error reporting
-                      nsMediaList* aMediaList,
-                      bool aHTMLMode);
+                      nsMediaList* aMediaList);
 
   bool ParseSourceSizeList(const nsAString& aBuffer,
                            nsIURI* aURI, // for error reporting
                            uint32_t aLineNumber, // for error reporting
                            InfallibleTArray< nsAutoPtr<nsMediaQuery> >& aQueries,
-                           InfallibleTArray<nsCSSValue>& aValues,
-                           bool aHTMLMode);
+                           InfallibleTArray<nsCSSValue>& aValues);
 
   void ParseVariable(const nsAString& aVariableName,
                      const nsAString& aPropValue,
                      nsIURI* aSheetURL,
                      nsIURI* aBaseURL,
                      nsIPrincipal* aSheetPrincipal,
                      css::Declaration* aDeclaration,
                      bool* aChanged,
@@ -1483,20 +1481,16 @@ protected:
   css::SheetParsingMode mParsingMode : 3;
 
   // True if we are in parsing rules for the chrome.
   bool mIsChrome : 1;
 
   // True if viewport units should be allowed.
   bool mViewportUnitsEnabled : 1;
 
-  // True for parsing media lists for HTML attributes, where we have to
-  // ignore CSS comments.
-  bool mHTMLMediaMode : 1;
-
   // This flag is set when parsing a non-box shorthand; it's used to not apply
   // some quirks during shorthand parsing
   bool          mParsingCompoundProperty : 1;
 
   // True if we are in the middle of parsing an @supports condition.
   // This is used to avoid recording the input stream when variable references
   // are encountered in a property declaration in the @supports condition.
   bool mInSupportsCondition : 1;
@@ -1608,17 +1602,16 @@ CSSParserImpl::CSSParserImpl()
     mNameSpaceMap(nullptr),
     mHavePushBack(false),
     mNavQuirkMode(false),
     mHashlessColorQuirk(false),
     mUnitlessLengthQuirk(false),
     mParsingMode(css::eAuthorSheetFeatures),
     mIsChrome(false),
     mViewportUnitsEnabled(true),
-    mHTMLMediaMode(false),
     mParsingCompoundProperty(false),
     mInSupportsCondition(false),
     mInFailingSupportsRule(false),
     mSuppressErrors(false),
     mSheetPrincipalRequired(true),
     mWebkitBoxUnprefixState(eNotParsingDecls),
     mNextFree(nullptr)
 {
@@ -1682,17 +1675,16 @@ CSSParserImpl::Reset()
 }
 
 void
 CSSParserImpl::InitScanner(nsCSSScanner& aScanner,
                            css::ErrorReporter& aReporter,
                            nsIURI* aSheetURI, nsIURI* aBaseURI,
                            nsIPrincipal* aSheetPrincipal)
 {
-  NS_PRECONDITION(!mHTMLMediaMode, "Bad initial state");
   NS_PRECONDITION(!mParsingCompoundProperty, "Bad initial state");
   NS_PRECONDITION(!mScanner, "already have scanner");
 
   mScanner = &aScanner;
   mReporter = &aReporter;
   mScanner->SetErrorReporter(mReporter);
 
   mBaseURI = aBaseURI;
@@ -2127,73 +2119,53 @@ CSSParserImpl::ParseVariable(const nsASt
 
   ReleaseScanner();
 }
 
 void
 CSSParserImpl::ParseMediaList(const nsSubstring& aBuffer,
                               nsIURI* aURI, // for error reporting
                               uint32_t aLineNumber, // for error reporting
-                              nsMediaList* aMediaList,
-                              bool aHTMLMode)
+                              nsMediaList* aMediaList)
 {
   // XXX Are there cases where the caller wants to keep what it already
   // has in case of parser error?  If GatherMedia ever changes to return
   // a value other than true, we probably should avoid modifying aMediaList.
   aMediaList->Clear();
 
   // fake base URI since media lists don't have URIs in them
   nsCSSScanner scanner(aBuffer, aLineNumber);
   css::ErrorReporter reporter(scanner, mSheet, mChildLoader, aURI);
   InitScanner(scanner, reporter, aURI, aURI, nullptr);
 
-  mHTMLMediaMode = aHTMLMode;
-
-    // XXXldb We need to make the scanner not skip CSS comments!  (Or
-    // should we?)
-
-  // For aHTMLMode, we used to follow the parsing rules in
-  // http://www.w3.org/TR/1999/REC-html401-19991224/types.html#type-media-descriptors
-  // which wouldn't work for media queries since they remove all but the
-  // first word.  However, they're changed in
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/section-document.html#media2
-  // (as of 2008-05-29) which says that the media attribute just points
-  // to a media query.  (The main substative difference is the relative
-  // precedence of commas and paretheses.)
-
   DebugOnly<bool> parsedOK = GatherMedia(aMediaList, false);
   NS_ASSERTION(parsedOK, "GatherMedia returned false; we probably want to avoid "
                          "trashing aMediaList");
 
   CLEAR_ERROR();
   ReleaseScanner();
-  mHTMLMediaMode = false;
 }
 
 //  <source-size-list> = <source-size>#?
 //  <source-size> = <media-condition>? <length>
 bool
 CSSParserImpl::ParseSourceSizeList(const nsAString& aBuffer,
                                    nsIURI* aURI, // for error reporting
                                    uint32_t aLineNumber, // for error reporting
                                    InfallibleTArray< nsAutoPtr<nsMediaQuery> >& aQueries,
-                                   InfallibleTArray<nsCSSValue>& aValues,
-                                   bool aHTMLMode)
+                                   InfallibleTArray<nsCSSValue>& aValues)
 {
   aQueries.Clear();
   aValues.Clear();
 
   // fake base URI since media value lists don't have URIs in them
   nsCSSScanner scanner(aBuffer, aLineNumber);
   css::ErrorReporter reporter(scanner, mSheet, mChildLoader, aURI);
   InitScanner(scanner, reporter, aURI, aURI, nullptr);
 
-  // See ParseMediaList comment about HTML mode
-  mHTMLMediaMode = aHTMLMode;
-
   // https://html.spec.whatwg.org/multipage/embedded-content.html#parse-a-sizes-attribute
   bool hitEnd = false;
   do {
     bool hitError = false;
     // Parse single <media-condition> <source-size-value>
     do {
       nsAutoPtr<nsMediaQuery> query;
       nsCSSValue value;
@@ -2252,17 +2224,16 @@ CSSParserImpl::ParseSourceSizeList(const
       if (!SkipUntil(',')) {
         hitEnd = true;
       }
     }
   } while (!hitEnd);
 
   CLEAR_ERROR();
   ReleaseScanner();
-  mHTMLMediaMode = false;
 
   return !aQueries.IsEmpty();
 }
 
 bool
 CSSParserImpl::ParseColorString(const nsSubstring& aBuffer,
                                 nsIURI* aURI, // for error reporting
                                 uint32_t aLineNumber, // for error reporting
@@ -18220,34 +18191,31 @@ nsCSSParser::ParseVariable(const nsAStri
     ParseVariable(aVariableName, aPropValue, aSheetURI, aBaseURI,
                   aSheetPrincipal, aDeclaration, aChanged, aIsImportant);
 }
 
 void
 nsCSSParser::ParseMediaList(const nsSubstring& aBuffer,
                             nsIURI*            aURI,
                             uint32_t           aLineNumber,
-                            nsMediaList*       aMediaList,
-                            bool               aHTMLMode)
+                            nsMediaList*       aMediaList)
 {
   static_cast<CSSParserImpl*>(mImpl)->
-    ParseMediaList(aBuffer, aURI, aLineNumber, aMediaList, aHTMLMode);
+    ParseMediaList(aBuffer, aURI, aLineNumber, aMediaList);
 }
 
 bool
 nsCSSParser::ParseSourceSizeList(const nsAString& aBuffer,
                                  nsIURI* aURI,
                                  uint32_t aLineNumber,
                                  InfallibleTArray< nsAutoPtr<nsMediaQuery> >& aQueries,
-                                 InfallibleTArray<nsCSSValue>& aValues,
-                                 bool aHTMLMode)
+                                 InfallibleTArray<nsCSSValue>& aValues)
 {
   return static_cast<CSSParserImpl*>(mImpl)->
-    ParseSourceSizeList(aBuffer, aURI, aLineNumber, aQueries, aValues,
-                        aHTMLMode);
+    ParseSourceSizeList(aBuffer, aURI, aLineNumber, aQueries, aValues);
 }
 
 bool
 nsCSSParser::ParseFontFamilyListString(const nsSubstring& aBuffer,
                                        nsIURI*            aURI,
                                        uint32_t           aLineNumber,
                                        nsCSSValue&        aValue)
 {
--- a/layout/style/nsCSSParser.h
+++ b/layout/style/nsCSSParser.h
@@ -147,28 +147,24 @@ public:
                      const nsAString&    aPropValue,
                      nsIURI*             aSheetURL,
                      nsIURI*             aBaseURL,
                      nsIPrincipal*       aSheetPrincipal,
                      mozilla::css::Declaration* aDeclaration,
                      bool*               aChanged,
                      bool                aIsImportant);
   /**
-   * Parse aBuffer into a media list |aMediaList|, which must be
-   * non-null, replacing its current contents.  If aHTMLMode is true,
-   * parse according to HTML rules, with commas as the most important
-   * delimiter.  Otherwise, parse according to CSS rules, with
-   * parentheses and strings more important than commas.  |aURL| and
-   * |aLineNumber| are used for error reporting.
+   * Parse aBuffer into a media list |aMediaList|, which must be non-null,
+   * replacing its current contents. |aURL| and |aLineNumber| are used for error
+   * reporting.
    */
   void ParseMediaList(const nsSubstring& aBuffer,
                       nsIURI*            aURL,
                       uint32_t           aLineNumber,
-                      nsMediaList*       aMediaList,
-                      bool               aHTMLMode);
+                      nsMediaList*       aMediaList);
 
   /*
    * Parse aBuffer into a list of media queries and their associated values,
    * according to grammar:
    *    <source-size-list> = <source-size>#?
    *    <source-size> = <media-condition>? <length>
    *
    * Note that this grammar is top-level: The function expects to consume the
@@ -176,18 +172,17 @@ public:
    *
    * Output arrays overwritten (not appended) and are cleared in case of parse
    * failure.
    */
   bool ParseSourceSizeList(const nsAString& aBuffer,
                            nsIURI* aURI, // for error reporting
                            uint32_t aLineNumber, // for error reporting
                            InfallibleTArray< nsAutoPtr<nsMediaQuery> >& aQueries,
-                           InfallibleTArray<nsCSSValue>& aValues,
-                           bool aHTMLMode);
+                           InfallibleTArray<nsCSSValue>& aValues);
 
   /**
    * Parse aBuffer into a nsCSSValue |aValue|. Will return false
    * if aBuffer is not a valid font family list.
    */
   bool ParseFontFamilyListString(const nsSubstring& aBuffer,
                                  nsIURI*            aURL,
                                  uint32_t           aLineNumber,
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -2400,17 +2400,16 @@ nsCSSValueList_heap::SizeOfIncludingThis
   }
   return n;
 }
 
 // --- nsCSSValueSharedList -----------------
 
 nsCSSValueSharedList::~nsCSSValueSharedList()
 {
-  MOZ_COUNT_DTOR(nsCSSValueSharedList);
   if (mHead) {
     NS_CSS_DELETE_LIST_MEMBER(nsCSSValueList, mHead, mNext);
     delete mHead;
   }
 }
 
 void
 nsCSSValueSharedList::AppendToString(nsCSSPropertyID aProperty, nsAString& aResult,
@@ -3056,24 +3055,20 @@ nsCSSValueGradient::SizeOfIncludingThis(
 }
 
 // --- nsCSSValueTokenStream ------------
 
 nsCSSValueTokenStream::nsCSSValueTokenStream()
   : mPropertyID(eCSSProperty_UNKNOWN)
   , mShorthandPropertyID(eCSSProperty_UNKNOWN)
   , mLevel(SheetType::Count)
-{
-  MOZ_COUNT_CTOR(nsCSSValueTokenStream);
-}
+{}
 
 nsCSSValueTokenStream::~nsCSSValueTokenStream()
-{
-  MOZ_COUNT_DTOR(nsCSSValueTokenStream);
-}
+{}
 
 size_t
 nsCSSValueTokenStream::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
 {
   // Only measure it if it's unshared, to avoid double-counting.
   size_t n = 0;
   if (mRefCnt <= 1) {
     n += aMallocSizeOf(this);
--- a/layout/style/nsCSSValue.h
+++ b/layout/style/nsCSSValue.h
@@ -294,45 +294,35 @@ private:
   GridTemplateAreasValue&
   operator=(const GridTemplateAreasValue& aOther) = delete;
 };
 
 class FontFamilyListRefCnt final : public FontFamilyList {
 public:
     FontFamilyListRefCnt()
         : FontFamilyList()
-    {
-        MOZ_COUNT_CTOR(FontFamilyListRefCnt);
-    }
+    {}
 
     explicit FontFamilyListRefCnt(FontFamilyType aGenericType)
         : FontFamilyList(aGenericType)
-    {
-        MOZ_COUNT_CTOR(FontFamilyListRefCnt);
-    }
+    {}
 
     FontFamilyListRefCnt(const nsAString& aFamilyName,
                          QuotedName aQuoted)
         : FontFamilyList(aFamilyName, aQuoted)
-    {
-        MOZ_COUNT_CTOR(FontFamilyListRefCnt);
-    }
+    {}
 
     FontFamilyListRefCnt(const FontFamilyListRefCnt& aOther)
         : FontFamilyList(aOther)
-    {
-        MOZ_COUNT_CTOR(FontFamilyListRefCnt);
-    }
+    {}
 
     NS_INLINE_DECL_REFCOUNTING(FontFamilyListRefCnt);
 
 private:
-    ~FontFamilyListRefCnt() {
-        MOZ_COUNT_DTOR(FontFamilyListRefCnt);
-    }
+    ~FontFamilyListRefCnt() {}
 };
 
 struct RGBAColorData
 {
   // 1.0 means 100% for all components, but the value may fall outside
   // the range of [0.0, 1.0], so it is necessary to clamp them when
   // converting to nscolor.
   float mR;
@@ -1115,25 +1105,23 @@ private:
 #define CSSVALUE_LIST_FOR_EXTRA_VALUES(var)                                   \
   for (nsCSSValue *var = First() + 1, *var##_end = First() + mCount;          \
        var != var##_end; ++var)
 
   explicit Array(size_t aItemCount)
     : mRefCnt(0)
     , mCount(aItemCount)
   {
-    MOZ_COUNT_CTOR(nsCSSValue::Array);
     CSSVALUE_LIST_FOR_EXTRA_VALUES(val) {
       new (val) nsCSSValue();
     }
   }
 
   ~Array()
   {
-    MOZ_COUNT_DTOR(nsCSSValue::Array);
     CSSVALUE_LIST_FOR_EXTRA_VALUES(val) {
       val->~nsCSSValue();
     }
   }
 
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
 #undef CSSVALUE_LIST_FOR_EXTRA_VALUES
@@ -1193,24 +1181,22 @@ private:
 // This is a reference counted list value.  Note that the object is
 // a wrapper for the reference count and a pointer to the head of the
 // list, whereas the other list types (such as nsCSSValueList) do
 // not have such a wrapper.
 struct nsCSSValueSharedList final {
   nsCSSValueSharedList()
     : mHead(nullptr)
   {
-    MOZ_COUNT_CTOR(nsCSSValueSharedList);
   }
 
   // Takes ownership of aList.
   explicit nsCSSValueSharedList(nsCSSValueList* aList)
     : mHead(aList)
   {
-    MOZ_COUNT_CTOR(nsCSSValueSharedList);
   }
 
 private:
   // Private destructor, to discourage deletion outside of Release():
   ~nsCSSValueSharedList();
 
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsCSSValueSharedList)
@@ -1837,26 +1823,22 @@ private:
 class nsCSSValueFloatColor final {
 public:
   nsCSSValueFloatColor(float aComponent1, float aComponent2, float aComponent3,
                        float aAlpha)
     : mComponent1(aComponent1)
     , mComponent2(aComponent2)
     , mComponent3(aComponent3)
     , mAlpha(aAlpha)
-  {
-    MOZ_COUNT_CTOR(nsCSSValueFloatColor);
-  }
+  {}
 
 private:
   // Private destructor, to discourage deletion outside of Release():
   ~nsCSSValueFloatColor()
-  {
-    MOZ_COUNT_DTOR(nsCSSValueFloatColor);
-  }
+  {}
 
 public:
   bool operator==(nsCSSValueFloatColor& aOther) const;
 
   nscolor GetColorValue(nsCSSUnit aUnit) const;
   float Comp1() const { return mComponent1; }
   float Comp2() const { return mComponent2; }
   float Comp3() const { return mComponent3; }
--- a/layout/style/nsDOMCSSAttrDeclaration.cpp
+++ b/layout/style/nsDOMCSSAttrDeclaration.cpp
@@ -23,24 +23,21 @@
 
 using namespace mozilla;
 
 nsDOMCSSAttributeDeclaration::nsDOMCSSAttributeDeclaration(dom::Element* aElement,
                                                            bool aIsSMILOverride)
   : mElement(aElement)
   , mIsSMILOverride(aIsSMILOverride)
 {
-  MOZ_COUNT_CTOR(nsDOMCSSAttributeDeclaration);
-
   NS_ASSERTION(aElement, "Inline style for a NULL element?");
 }
 
 nsDOMCSSAttributeDeclaration::~nsDOMCSSAttributeDeclaration()
 {
-  MOZ_COUNT_DTOR(nsDOMCSSAttributeDeclaration);
 }
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsDOMCSSAttributeDeclaration, mElement)
 
 // mElement holds a strong ref to us, so if it's going to be
 // skipped, the attribute declaration can't be part of a garbage
 // cycle.
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsDOMCSSAttributeDeclaration)
--- a/layout/style/nsStyleContext.cpp
+++ b/layout/style/nsStyleContext.cpp
@@ -93,19 +93,17 @@ nsStyleContext::nsStyleContext(nsStyleCo
 #endif
   , mCachedResetData(nullptr)
   , mBits(((uint64_t)aPseudoType) << NS_STYLE_CONTEXT_TYPE_SHIFT)
   , mRefCnt(0)
 #ifdef DEBUG
   , mFrameRefCnt(0)
   , mComputingStruct(nsStyleStructID_None)
 #endif
-{
-  MOZ_COUNT_CTOR(nsStyleContext);
-}
+{}
 
 nsStyleContext::nsStyleContext(nsStyleContext* aParent,
                                nsIAtom* aPseudoTag,
                                CSSPseudoElementType aPseudoType,
                                already_AddRefed<nsRuleNode> aRuleNode,
                                bool aSkipParentDisplayBasedStyleFixup)
   : nsStyleContext(aParent, OwningStyleContextSource(Move(aRuleNode)),
                    aPseudoTag, aPseudoType)
@@ -178,17 +176,16 @@ nsStyleContext::FinishConstruction(bool 
   #define eStyleStruct_LastItem (nsStyleStructID_Length - 1)
   NS_ASSERTION(NS_STYLE_INHERIT_MASK & NS_STYLE_INHERIT_BIT(LastItem),
                "NS_STYLE_INHERIT_MASK must be bigger, and other bits shifted");
   #undef eStyleStruct_LastItem
 }
 
 nsStyleContext::~nsStyleContext()
 {
-  MOZ_COUNT_DTOR(nsStyleContext);
   NS_ASSERTION((nullptr == mChild) && (nullptr == mEmptyChild), "destructing context with children");
 
 #ifdef DEBUG
   if (sExpensiveStyleStructAssertionsEnabled) {
     // Assert that the style structs we are about to destroy are not referenced
     // anywhere else in the style context tree.  These checks are expensive,
     // which is why they are not enabled by default.
     nsStyleContext* root = this;
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -1136,28 +1136,26 @@ public:
     // item, see the private declarations)
     return ::operator new(aBaseSize +
                           (aArrayLen - 1) * sizeof(nsCSSShadowItem));
   }
 
   explicit nsCSSShadowArray(uint32_t aArrayLen) :
     mLength(aArrayLen)
   {
-    MOZ_COUNT_CTOR(nsCSSShadowArray);
     for (uint32_t i = 1; i < mLength; ++i) {
       // Make sure we call the constructors of each nsCSSShadowItem
       // (the first one is called for us because we declared it under private)
       new (&mArray[i]) nsCSSShadowItem();
     }
   }
 
 private:
   // Private destructor, to discourage deletion outside of Release():
   ~nsCSSShadowArray() {
-    MOZ_COUNT_DTOR(nsCSSShadowArray);
     for (uint32_t i = 1; i < mLength; ++i) {
       mArray[i].~nsCSSShadowItem();
     }
   }
 
 public:
   uint32_t Length() const { return mLength; }
   nsCSSShadowItem* ShadowAt(uint32_t i) {
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -3871,18 +3871,18 @@ Tab.prototype = {
         // Attach a listener to watch for "click" events bubbling up from error
         // pages and other similar page. This lets us fix bugs like 401575 which
         // require error page UI to do privileged things, without letting error
         // pages have any privilege themselves.
         if (docURI.startsWith("about:neterror")) {
           NetErrorHelper.attachToBrowser(this.browser);
         }
 
-        Messaging.sendRequest({
-          type: "DOMContentLoaded",
+        GlobalEventDispatcher.sendRequest({
+          type: "Content:DOMContentLoaded",
           tabID: this.id,
           bgColor: backgroundColor,
           errorType: errorType,
           metadata: this.metatags,
         });
 
         // Reset isSearch so that the userRequested term will be erased on next page load
         this.metatags = null;
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoEditable.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoEditable.java
@@ -326,17 +326,17 @@ final class GeckoEditable extends JNIObj
             mShadowText.insert(start, mCurrentText, start, currentEnd);
 
             // SpannableStringBuilder has some internal logic to fix up selections, but we
             // don't want that, so we always fix up the selection a second time.
             final int selStart = Selection.getSelectionStart(mCurrentText);
             final int selEnd = Selection.getSelectionEnd(mCurrentText);
             Selection.setSelection(mShadowText, selStart, selEnd);
 
-            if (DEBUG && !mShadowText.equals(mCurrentText)) {
+            if (DEBUG && !checkEqualText(mShadowText, mCurrentText)) {
                 // Sanity check.
                 throw new IllegalStateException("Failed to sync: " +
                         mShadowStart + '-' + mShadowOldEnd + '-' + mShadowNewEnd + '/' +
                         mCurrentStart + '-' + mCurrentOldEnd + '-' + mCurrentNewEnd);
             }
 
             if (listener != null) {
                 // Call onTextChange after selection fix-up but before we call
@@ -352,16 +352,42 @@ final class GeckoEditable extends JNIObj
             // These values ensure the first change is properly added.
             mCurrentStart = mShadowStart = Integer.MAX_VALUE;
             mCurrentOldEnd = mShadowOldEnd = 0;
             mCurrentNewEnd = mShadowNewEnd = 0;
             mCurrentSelectionChanged = false;
         }
     }
 
+    private static boolean checkEqualText(final Spanned s1, final Spanned s2) {
+        if (!s1.toString().equals(s2.toString())) {
+            return false;
+        }
+
+        final Object[] o1s = s1.getSpans(0, s1.length(), Object.class);
+        final Object[] o2s = s2.getSpans(0, s2.length(), Object.class);
+
+        o1loop: for (final Object o1 : o1s) {
+            for (final Object o2 : o2s)  {
+                if (o1 != o2) {
+                    continue;
+                }
+                if (s1.getSpanStart(o1) != s2.getSpanStart(o2) ||
+                        s1.getSpanEnd(o1) != s2.getSpanEnd(o2) ||
+                        s1.getSpanFlags(o1) != s2.getSpanFlags(o2)) {
+                    return false;
+                }
+                continue o1loop;
+            }
+            // o1 not found in o2s.
+            return false;
+        }
+        return true;
+    }
+
     /* An action that alters the Editable
 
        Each action corresponds to a Gecko event. While the Gecko event is being sent to the Gecko
        thread, the action stays on top of mActions queue. After the Gecko event is processed and
        replied, the action is removed from the queue
     */
     private static final class Action {
         // For input events (keypress, etc.); use with onImeSynchronize
--- a/mobile/android/modules/Messaging.jsm
+++ b/mobile/android/modules/Messaging.jsm
@@ -169,17 +169,17 @@ DispatcherDelegate.prototype = {
           message: e.message || (e && e.toString()),
           stack: e.stack || Components.stack.formattedStack,
         });
       }
     }),
   },
 };
 
-const EventDispatcher = {
+var EventDispatcher = {
   instance: new DispatcherDelegate(Services.androidBridge),
 
   for: function (window) {
     let view = window && window.arguments && window.arguments[0] &&
         window.arguments[0].QueryInterface(Ci.nsIAndroidView);
     if (!view) {
       throw new Error("window is not a GeckoView-connected window");
     }
--- a/mobile/android/tests/browser/robocop/robocop_head.js
+++ b/mobile/android/tests/browser/robocop/robocop_head.js
@@ -763,43 +763,55 @@ function run_next_test()
 /**
  * JavaBridge facilitates communication between Java and JS. See
  * JavascriptBridge.java for the corresponding JavascriptBridge and docs.
  */
 
 function JavaBridge(obj) {
 
   this._EVENT_TYPE = "Robocop:JS";
+  this._JAVA_EVENT_TYPE = "Robocop:Java";
   this._target = obj;
   // The number of replies needed to answer all outstanding sync calls.
   this._repliesNeeded = 0;
-  this._Services.obs.addObserver(this, this._EVENT_TYPE, false);
+  this._EventDispatcher.registerListener(this, this._EVENT_TYPE);
 
   this._sendMessage("notify-loaded", []);
 };
 
 JavaBridge.prototype = {
 
   _Services: Components.utils.import(
     "resource://gre/modules/Services.jsm", {}).Services,
 
-  _sendMessageToJava: Components.utils.import(
-    "resource://gre/modules/Messaging.jsm", {}).Messaging.sendRequest,
+  _EventDispatcher: Components.utils.import(
+    "resource://gre/modules/Messaging.jsm", {}).EventDispatcher.instance,
+
+  _getArgs: function (args) {
+    let out = {
+      length: Math.max(0, args.length - 1),
+    };
+    for (let i = 1; i < args.length; i++) {
+      out[i - 1] = args[i];
+    }
+    return out;
+  },
 
   _sendMessage: function (innerType, args) {
-    this._sendMessageToJava({
-      type: this._EVENT_TYPE,
+    this._EventDispatcher.dispatch(this._JAVA_EVENT_TYPE, {
       innerType: innerType,
       method: args[0],
-      args: Array.prototype.slice.call(args, 1),
+      args: this._getArgs(args),
     });
   },
 
-  observe: function(subject, topic, data) {
-    let message = JSON.parse(data);
+  onEvent: function(event, message, callback) {
+    if (typeof SpecialPowers === 'object') {
+      message = SpecialPowers.wrap(message);
+    }
     if (message.innerType === "sync-reply") {
       // Reply to our Javascript-to-Java sync call
       this._repliesNeeded--;
       return;
     }
     // Call the corresponding method on the target
     try {
       this._target[message.method].apply(this._target, message.args);
@@ -838,11 +850,11 @@ JavaBridge.prototype = {
   asyncCall: function (methodName /*, ... */) {
     this._sendMessage("async-call", arguments);
   },
 
   /**
    * Disconnect with Java.
    */
   disconnect: function () {
-    this._Services.obs.removeObserver(this, this._EVENT_TYPE);
+    this._EventDispatcher.unregisterListener(this, this._EVENT_TYPE);
   },
 };
--- a/mobile/android/tests/browser/robocop/robocop_testharness.js
+++ b/mobile/android/tests/browser/robocop/robocop_testharness.js
@@ -1,15 +1,15 @@
 // -*- indent-tabs-mode: nil; js-indent-level: 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/. */
 
 function sendMessageToJava(message) {
-  SpecialPowers.Services.androidBridge.handleGeckoMessage(message);
+  SpecialPowers.Services.androidBridge.dispatch(message.type, message);
 }
 
 function _evalURI(uri, sandbox) {
   // We explicitly allow Cross-Origin requests, since it is useful for
   // testing, but we allow relative URLs by maintaining our baseURI.
   let req = SpecialPowers.Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
                          .createInstance();
 
@@ -31,17 +31,17 @@ function _evalURI(uri, sandbox) {
 /**
  * Execute the Javascript file at `uri` in a testing sandbox populated
  * with the Javascript test harness.
  *
  * `uri` should be a String, relative (to window.document.baseURI) or
  * absolute.
  *
  * The Javascript test harness sends all output to Java via
- * Robocop:JS messages.
+ * Robocop:Java messages.
  */
 function testOneFile(uri) {
   let HEAD_JS = "robocop_head.js";
 
   // System principal.  This is dangerous, but this is test code that
   // should only run on developer and build farm machines, and the
   // test harness needs access to a lot of the Components API,
   // including Components.stack.  Wrapping Components.stack in
@@ -54,17 +54,17 @@ function testOneFile(uri) {
 
   // Populate test environment with test harness prerequisites.
   testScope.Components = SpecialPowers.Components;
   testScope._TEST_FILE = uri;
 
   // Output from head.js is fed, line by line, to this function.  We
   // send any such output back to the Java Robocop harness.
   testScope.dump = function (str) {
-    let message = { type: "Robocop:JS",
+    let message = { type: "Robocop:Java",
                     innerType: "progress",
                     message: str,
                   };
     sendMessageToJava(message);
   };
 
   // Populate test environment with test harness.  The symbols defined
   // above must be present before executing the test harness.
--- a/mobile/android/tests/browser/robocop/roboextender/base/robocop_home_banner.html
+++ b/mobile/android/tests/browser/robocop/roboextender/base/robocop_home_banner.html
@@ -16,22 +16,22 @@ function start() {
 }
 
 var messageId;
 
 function addMessage() {
   messageId = Home.banner.add({
     text: TEXT,
     onshown: function() {
-      Messaging.sendRequest({ type: "TestHomeBanner:MessageShown" });
+      EventDispatcher.instance.sendRequest({ type: "TestHomeBanner:MessageShown" });
     },
     ondismiss: function() {
-      Messaging.sendRequest({ type: "TestHomeBanner:MessageDismissed" });
+      EventDispatcher.instance.sendRequest({ type: "TestHomeBanner:MessageDismissed" });
     }
   });
-  Messaging.sendRequest({ type: "TestHomeBanner:MessageAdded" });
+  EventDispatcher.instance.sendRequest({ type: "TestHomeBanner:MessageAdded" });
 }
 
     </script>
   </head>
   <body onload="start();">
   </body>
 </html>
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/AboutHomeTest.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/AboutHomeTest.java
@@ -79,17 +79,18 @@ abstract class AboutHomeTest extends Pix
 
         mAsserter.ok(isCorrect, "Checking that " + url + " displayed as a bookmark", url + " displayed");
     }
 
     // Loads a bookmark by tapping on the bookmark view in the Bookmarks tab
     protected void loadBookmark(String url) {
         View bookmark = getDisplayedBookmark(url);
         if (bookmark != null) {
-            Actions.EventExpecter contentEventExpecter = mActions.expectGeckoEvent("DOMContentLoaded");
+            Actions.EventExpecter contentEventExpecter =
+                    mActions.expectGlobalEvent(Actions.EventType.GECKO, "Content:DOMContentLoaded");
             mSolo.clickOnView(bookmark);
             contentEventExpecter.blockForEvent();
             contentEventExpecter.unregisterListener();
         } else {
             mAsserter.ok(false, url + " is not one of the displayed bookmarks", "Please make sure the url provided is bookmarked");
         }
     }
 
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/BaseTest.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/BaseTest.java
@@ -150,17 +150,18 @@ abstract class BaseTest extends BaseRobo
     }
 
     protected final Fragment getBrowserSearch() {
         final FragmentManager fm = ((FragmentActivity) getActivity()).getSupportFragmentManager();
         return fm.findFragmentByTag("browser_search");
     }
 
     protected final void hitEnterAndWait() {
-        Actions.EventExpecter contentEventExpecter = mActions.expectGeckoEvent("DOMContentLoaded");
+        Actions.EventExpecter contentEventExpecter =
+                mActions.expectGlobalEvent(Actions.EventType.GECKO, "Content:DOMContentLoaded");
         mActions.sendSpecialKey(Actions.SpecialKey.ENTER);
         // wait for screen to load
         contentEventExpecter.blockForEvent();
         contentEventExpecter.unregisterListener();
     }
 
     /**
      * Load <code>url</code> by sending key strokes to the URL bar UI.
@@ -193,17 +194,18 @@ abstract class BaseTest extends BaseRobo
         }
     }
 
     /**
      * Load <code>url</code> using the internal
      * <code>org.mozilla.gecko.Tabs</code> API and wait for DOMContentLoaded.
      */
     protected final void loadUrlAndWait(final String url) {
-        Actions.EventExpecter contentEventExpecter = mActions.expectGeckoEvent("DOMContentLoaded");
+        Actions.EventExpecter contentEventExpecter =
+                mActions.expectGlobalEvent(Actions.EventType.GECKO, "Content:DOMContentLoaded");
         loadUrl(url);
         contentEventExpecter.blockForEvent();
         contentEventExpecter.unregisterListener();
     }
 
     protected final void closeTab(int tabId) {
         Tabs tabs = Tabs.getInstance();
         Tab tab = tabs.getTab(tabId);
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/JavascriptTest.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/JavascriptTest.java
@@ -1,18 +1,18 @@
 /* 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/. */
 
 package org.mozilla.gecko.tests;
 
-import org.json.JSONObject;
 import org.mozilla.gecko.Actions;
 import org.mozilla.gecko.tests.helpers.JavascriptBridge;
 import org.mozilla.gecko.tests.helpers.JavascriptMessageParser;
+import org.mozilla.gecko.util.GeckoBundle;
 
 import android.util.Log;
 
 /**
  * Extended to test stand-alone Javascript in automation. If you're looking to test JS interactions
  * with Java, see {@link JavascriptBridgeTest}.
  *
  * There are also other tests that run stand-alone javascript but are more difficult for the mobile
@@ -39,36 +39,36 @@ public class JavascriptTest extends Base
 
         doTestJavascript();
     }
 
     protected void doTestJavascript() throws Exception {
         // We want to be waiting for Robocop messages before the page is loaded
         // because the test harness runs each test in the suite (and possibly
         // completes testing) before the page load event is fired.
-        final Actions.EventExpecter expecter = mActions.expectGeckoEvent(EVENT_TYPE);
+        final Actions.EventExpecter expecter =
+                mActions.expectGlobalEvent(Actions.EventType.GECKO, EVENT_TYPE);
         mAsserter.dumpLog("Registered listener for " + EVENT_TYPE);
 
         final String url = getAbsoluteUrl(mStringHelper.getHarnessUrlForJavascript(javascriptUrl));
         mAsserter.dumpLog("Loading JavaScript test from " + url);
         loadUrl(url);
 
         final JavascriptMessageParser testMessageParser =
                 new JavascriptMessageParser(mAsserter, false);
         try {
             while (!testMessageParser.isTestFinished()) {
                 if (logVerbose) {
                     Log.v(LOGTAG, "Waiting for " + EVENT_TYPE);
                 }
-                String data = expecter.blockForEventData();
+                final GeckoBundle o = expecter.blockForBundle();
                 if (logVerbose) {
-                    Log.v(LOGTAG, "Got event with data '" + data + "'");
+                    Log.v(LOGTAG, "Got event with data '" + o + "'");
                 }
 
-                JSONObject o = new JSONObject(data);
                 String innerType = o.getString("innerType");
                 if (!"progress".equals(innerType)) {
                     throw new Exception("Unexpected event innerType " + innerType);
                 }
 
                 String message = o.getString("message");
                 if (message == null) {
                     throw new Exception("Progress message must not be null");
deleted file mode 100644
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/SelectionHandlerTest.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package org.mozilla.gecko.tests;
-
-import org.mozilla.gecko.Actions;
-import org.mozilla.gecko.EventDispatcher;
-import org.mozilla.gecko.tests.helpers.GeckoHelper;
-import org.mozilla.gecko.tests.helpers.NavigationHelper;
-
-import android.util.Log;
-
-import org.json.JSONObject;
-
-/**
- * A base test class for selection handler tests.
- */
-abstract class SelectionHandlerTest extends UITest {
-    private static final String geckoEventString = "Robocop:testSelectionHandler";
-    private final String url;
-
-    public SelectionHandlerTest(String url) {
-        this.url = url;
-    }
-
-    public void testSelection() {
-        GeckoHelper.blockForReady();
-
-        Actions.EventExpecter robocopTestExpecter = getActions().expectGeckoEvent(geckoEventString);
-        NavigationHelper.enterAndLoadUrl(url);
-        mToolbar.assertTitle(url);
-
-        while (!test(robocopTestExpecter)) {
-            // do nothing
-        }
-
-        robocopTestExpecter.unregisterListener();
-    }
-
-    protected boolean test(Actions.EventExpecter expecter) {
-        final JSONObject eventData;
-        try {
-            eventData = new JSONObject(expecter.blockForEventData());
-        } catch(Exception ex) {
-            // Log and ignore
-            getAsserter().ok(false, "JS Test", "Error decoding data " + ex);
-            return false;
-        }
-
-        if (eventData.has("result")) {
-            getAsserter().ok(eventData.optBoolean("result"), "JS Test", eventData.optString("msg"));
-        } else if (eventData.has("todo")) {
-            getAsserter().todo(eventData.optBoolean("todo"), "JS TODO", eventData.optString("msg"));
-        }
-
-        EventDispatcher.sendResponse(eventData, new JSONObject());
-        return eventData.optBoolean("done", false);
-    }
-}
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/JavascriptBridge.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/JavascriptBridge.java
@@ -4,24 +4,21 @@
 
 package org.mozilla.gecko.tests.helpers;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 
 import junit.framework.AssertionFailedError;
 
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
 import org.mozilla.gecko.Actions;
 import org.mozilla.gecko.Actions.EventExpecter;
 import org.mozilla.gecko.Assert;
 import org.mozilla.gecko.tests.UITestContext;
+import org.mozilla.gecko.util.GeckoBundle;
 
 /**
  * Javascript bridge allows calls to and from JavaScript.
  *
  * To establish communication, create an instance of JavascriptBridge in Java and pass in
  * an object that will receive calls from JavaScript. For example:
  *
  *  {@code final JavascriptBridge js = new JavascriptBridge(javaObj);}
@@ -35,17 +32,17 @@ import org.mozilla.gecko.tests.UITestCon
  * syncCall waits for the call to finish before returning. For example:
  *
  *  {@code js.syncCall("abc", 1, 2, 3);} will synchronously call the JavaScript method
  *    jsObj.abc and pass in arguments 1, 2, and 3.
  *
  *  {@code java.asyncCall("def", 4, 5, 6);} will asynchronously call the Java method
  *    javaObj.def and pass in arguments 4, 5, and 6.
  *
- * Supported argument types include int, double, boolean, String, and JSONObject. Note
+ * Supported argument types include int, double, boolean, String, and GeckoBundle. Note
  * that only implicit conversion is done, meaning if a floating point argument is passed
  * from JavaScript to Java, the call will fail if the Java method has an int argument.
  *
  * Because JavascriptBridge and JavaBridge use one underlying communication channel,
  * creating multiple instances of them will not create independent links.
  *
  * Note also that because Robocop tests finish as soon as the Java test method returns,
  * the last call to JavaScript from Java must be a synchronous call. Otherwise, the test
@@ -77,56 +74,57 @@ public final class JavascriptBridge {
             super(msg, e);
         }
 
         public CallException(final Throwable e) {
             super(e);
         }
     }
 
-    public static final String EVENT_TYPE = "Robocop:JS";
+    public static final String EVENT_TYPE = "Robocop:Java";
+    public static final String JS_EVENT_TYPE = "Robocop:JS";
 
     private static Actions sActions;
     private static Assert sAsserter;
 
     // Target of JS-to-Java calls
     private final Object mTarget;
     // List of public methods in subclass
     private final Method[] mMethods;
     // Parser for handling xpcshell assertions
     private final JavascriptMessageParser mLogParser;
     // Expecter of our internal Robocop event
     private final EventExpecter mExpecter;
     // Saved async message; see processMessage() for its purpose.
-    private JSONObject mSavedAsyncMessage;
+    private GeckoBundle mSavedAsyncMessage;
     // Number of levels in the synchronous call stack
     private int mCallStackDepth;
     // If JavaBridge has been loaded
     private boolean mJavaBridgeLoaded;
 
     /* package */ static void init(final UITestContext context) {
         sActions = context.getActions();
         sAsserter = context.getAsserter();
     }
 
     public JavascriptBridge(final Object target) {
         mTarget = target;
         mMethods = target.getClass().getMethods();
-        mExpecter = sActions.expectGeckoEvent(EVENT_TYPE);
+        mExpecter = sActions.expectGlobalEvent(Actions.EventType.GECKO, EVENT_TYPE);
         // The JS here is unrelated to a test harness, so we
         // have our message parser end on assertion failure.
         mLogParser = new JavascriptMessageParser(sAsserter, true);
     }
 
     /**
      * Synchronously calls a method in Javascript.
      *
      * @param method Name of the method to call
      * @param args Arguments to pass to the Javascript method; must be a list of
-     *             values allowed by JSONObject.
+     *             values allowed by GeckoBundle.
      */
     public void syncCall(final String method, final Object... args) {
         mCallStackDepth++;
 
         sendMessage("sync-call", method, args);
         try {
             while (processPendingMessage() != MessageStatus.REPLIED) {
             }
@@ -146,17 +144,17 @@ public final class JavascriptBridge {
         mCallStackDepth--;
     }
 
     /**
      * Asynchronously calls a method in Javascript.
      *
      * @param method Name of the method to call
      * @param args Arguments to pass to the Javascript method; must be a list of
-     *             values allowed by JSONObject.
+     *             values allowed by GeckoBundle.
      */
     public void asyncCall(final String method, final Object... args) {
         sendMessage("async-call", method, args);
     }
 
     /**
      * Disconnect the bridge.
      */
@@ -169,38 +167,29 @@ public final class JavascriptBridge {
      *
      * @return MessageStatus value to indicate result of processing the message
      */
     private MessageStatus processPendingMessage() {
         // We're on the test thread.
         // We clear mSavedAsyncMessage in maybeProcessPendingMessage() but not here,
         // because we always have a new message for processing here, so we never
         // get a chance to clear mSavedAsyncMessage.
-        try {
-            final String message = mExpecter.blockForEventData();
-            return processMessage(new JSONObject(message));
-        } catch (final JSONException e) {
-            throw new IllegalStateException("Invalid message", e);
-        }
+        return processMessage(mExpecter.blockForBundle());
     }
 
     /**
      * Process a message if a new or saved message is available.
      *
      * @return MessageStatus value to indicate result of processing the message
      */
     private MessageStatus maybeProcessPendingMessage() {
         // We're on the test thread.
-        final String message = mExpecter.blockForEventDataWithTimeout(0);
+        final GeckoBundle message = mExpecter.blockForBundleWithTimeout(0);
         if (message != null) {
-            try {
-                return processMessage(new JSONObject(message));
-            } catch (final JSONException e) {
-                throw new IllegalStateException("Invalid message", e);
-            }
+            return processMessage(message);
         }
         if (mSavedAsyncMessage != null) {
             // processMessage clears mSavedAsyncMessage.
             return processMessage(mSavedAsyncMessage);
         }
         return MessageStatus.QUEUE_EMPTY;
     }
 
@@ -222,99 +211,92 @@ public final class JavascriptBridge {
             processPendingMessage();
         }
     }
 
     private void sendMessage(final String innerType, final String method, final Object[] args) {
         ensureJavaBridgeLoaded();
 
         // Call from Java to Javascript
-        final JSONObject message = new JSONObject();
-        final JSONArray jsonArgs = new JSONArray();
-        try {
-            if (args != null) {
-                for (final Object arg : args) {
-                    jsonArgs.put(convertToJSONValue(arg));
-                }
+        final GeckoBundle message = new GeckoBundle();
+        final GeckoBundle bundleArgs = new GeckoBundle();
+        if (args == null) {
+            bundleArgs.putInt("length", 0);
+        } else {
+            for (int i = 0; i < args.length; i++) {
+                putInBundle(bundleArgs, String.valueOf(i), args[i]);
             }
-            message.put("type", EVENT_TYPE)
-                   .put("innerType", innerType)
-                   .put("method", method)
-                   .put("args", jsonArgs);
-        } catch (final JSONException e) {
-            throw new IllegalStateException("Unable to create JSON message", e);
+            bundleArgs.putInt("length", args.length);
         }
-        sActions.sendGeckoEvent(EVENT_TYPE, message.toString());
+        message.putString("type", JS_EVENT_TYPE);
+        message.putString("innerType", innerType);
+        message.putString("method", method);
+        message.putBundle("args", bundleArgs);
+
+        sActions.sendGlobalEvent(JS_EVENT_TYPE, message);
     }
 
-    private MessageStatus processMessage(JSONObject message) {
+    private MessageStatus processMessage(GeckoBundle message) {
         final String type;
         final String methodName;
-        final JSONArray argsArray;
+        final GeckoBundle argsArray;
         final Object[] args;
-        try {
-            if (!EVENT_TYPE.equals(message.getString("type"))) {
-                throw new IllegalStateException("Message type is not " + EVENT_TYPE);
-            }
-            type = message.getString("innerType");
+
+        type = message.getString("innerType");
+
+        switch (type) {
+            case "progress":
+                // Javascript harness message
+                mLogParser.logMessage(message.getString("message"));
+                return MessageStatus.PROCESSED;
 
-            switch (type) {
-                case "progress":
-                    // Javascript harness message
-                    mLogParser.logMessage(message.getString("message"));
-                    return MessageStatus.PROCESSED;
+            case "notify-loaded":
+                mJavaBridgeLoaded = true;
+                return MessageStatus.PROCESSED;
 
-                case "notify-loaded":
-                    mJavaBridgeLoaded = true;
-                    return MessageStatus.PROCESSED;
+            case "sync-reply":
+                // Reply to Java-to-Javascript sync call
+                return MessageStatus.REPLIED;
 
-                case "sync-reply":
-                    // Reply to Java-to-Javascript sync call
-                    return MessageStatus.REPLIED;
-
-                case "sync-call":
-                case "async-call":
+            case "sync-call":
+            case "async-call":
 
-                    if ("async-call".equals(type)) {
-                        // Save this async message until another async message arrives, then we
-                        // process the saved message and save the new one. This is done as a
-                        // form of tail call optimization, by making sync-replies come before
-                        // async-calls. On the other hand, if (message == mSavedAsyncMessage),
-                        // it means we're currently processing the saved message and should clear
-                        // mSavedAsyncMessage.
-                        final JSONObject newSavedMessage =
-                                (message != mSavedAsyncMessage ? message : null);
-                        message = mSavedAsyncMessage;
-                        mSavedAsyncMessage = newSavedMessage;
-                        if (message == null) {
-                            // Saved current message and there wasn't an already saved one.
-                            return MessageStatus.SAVED;
-                        }
+                if ("async-call".equals(type)) {
+                    // Save this async message until another async message arrives, then we
+                    // process the saved message and save the new one. This is done as a
+                    // form of tail call optimization, by making sync-replies come before
+                    // async-calls. On the other hand, if (message == mSavedAsyncMessage),
+                    // it means we're currently processing the saved message and should clear
+                    // mSavedAsyncMessage.
+                    final GeckoBundle newSavedMessage =
+                            (message != mSavedAsyncMessage ? message : null);
+                    message = mSavedAsyncMessage;
+                    mSavedAsyncMessage = newSavedMessage;
+                    if (message == null) {
+                        // Saved current message and there wasn't an already saved one.
+                        return MessageStatus.SAVED;
                     }
+                }
 
-                    methodName = message.getString("method");
-                    argsArray = message.getJSONArray("args");
-                    args = new Object[argsArray.length()];
-                    for (int i = 0; i < args.length; i++) {
-                        args[i] = convertFromJSONValue(argsArray.get(i));
-                    }
-                    invokeMethod(methodName, args);
+                methodName = message.getString("method");
+                argsArray = message.getBundle("args");
+                args = new Object[argsArray.getInt("length")];
+                for (int i = 0; i < args.length; i++) {
+                    args[i] = argsArray.get(String.valueOf(i));
+                }
+                invokeMethod(methodName, args);
 
-                    if ("sync-call".equals(type)) {
-                        // Reply for sync messages
-                        sendMessage("sync-reply", methodName, null);
-                    }
-                    return MessageStatus.PROCESSED;
-            }
+                if ("sync-call".equals(type)) {
+                    // Reply for sync messages
+                    sendMessage("sync-reply", methodName, null);
+                }
+                return MessageStatus.PROCESSED;
+        }
 
-            throw new IllegalStateException("Message type is unexpected");
-
-        } catch (final JSONException e) {
-            throw new IllegalStateException("Unable to retrieve JSON message", e);
-        }
+        throw new IllegalStateException("Message type is unexpected");
     }
 
     /**
      * Given a method name and a list of arguments,
      * call the most suitable method in the subclass.
      */
     private Object invokeMethod(final String methodName, final Object[] args) {
         final Class<?>[] argTypes = new Class<?>[args.length];
@@ -373,22 +355,36 @@ public final class JavascriptBridge {
                 // Don't wrap CallExceptions; this can happen if a call is nested on top
                 // of existing sync calls, and the nested call throws a CallException
                 throw (CallException) cause;
             }
             throw new CallException("Failed to invoke " + method.getName(), cause);
         }
     }
 
-    private Object convertFromJSONValue(final Object value) {
-        if (value == JSONObject.NULL) {
-            return null;
+    private void putInBundle(final GeckoBundle bundle, final String key, final Object value) {
+        if (value == null) {
+            bundle.putBundle(key, null);
+        } else if (value instanceof Boolean) {
+            bundle.putBoolean(key, (Boolean) value);
+        } else if (value instanceof boolean[]) {
+            bundle.putBooleanArray(key, (boolean[]) value);
+        } else if (value instanceof Double) {
+            bundle.putDouble(key, (Double) value);
+        } else if (value instanceof double[]) {
+            bundle.putDoubleArray(key, (double[]) value);
+        } else if (value instanceof Integer) {
+            bundle.putInt(key, (Integer) value);
+        } else if (value instanceof int[]) {
+            bundle.putIntArray(key, (int[]) value);
+        } else if (value instanceof CharSequence) {
+            bundle.putString(key, value.toString());
+        } else if (value instanceof String[]) {
+            bundle.putStringArray(key, (String[]) value);
+        } else if (value instanceof GeckoBundle) {
+            bundle.putBundle(key, (GeckoBundle) value);
+        } else if (value instanceof GeckoBundle[]) {
+            bundle.putBundleArray(key, (GeckoBundle[]) value);
+        } else {
+            throw new UnsupportedOperationException();
         }
-        return value;
-    }
-
-    private Object convertToJSONValue(final Object value) {
-        if (value == null) {
-            return JSONObject.NULL;
-        }
-        return value;
     }
 }
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/JavascriptMessageParser.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/JavascriptMessageParser.java
@@ -14,19 +14,19 @@ import java.util.regex.Pattern;
 /**
  * Route messages from Javascript's head.js test framework into Java's
  * Mochitest framework.
  */
 public final class JavascriptMessageParser {
 
     /**
     * The Javascript test harness sends test events to Java.
-    * Each such test event is wrapped in a Robocop:JS event.
+    * Each such test event is wrapped in a Robocop:Java event.
     */
-    public static final String EVENT_TYPE = "Robocop:JS";
+    public static final String EVENT_TYPE = "Robocop:Java";
 
     // Messages matching this pattern are handled specially.  Messages not
     // matching this pattern are still printed. This pattern should be able
     // to handle having multiple lines in a message.
     private static final Pattern testMessagePattern =
         Pattern.compile("TEST-([A-Z\\-]+) \\| (.*?) \\| (.*)", Pattern.DOTALL);
 
     private final Assert asserter;
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/WaitHelper.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/WaitHelper.java
@@ -115,27 +115,27 @@ public final class WaitHelper {
         // state.
         final ChangeVerifier[] pageLoadVerifiers = PAGE_LOAD_VERIFIERS;
         for (final ChangeVerifier verifier : pageLoadVerifiers) {
             verifier.storeState();
         }
 
         // Wait for the page load and title changed event.
         final EventExpecter[] eventExpecters = new EventExpecter[] {
-            sActions.expectGeckoEvent("DOMContentLoaded"),
+            sActions.expectGlobalEvent(Actions.EventType.GECKO, "Content:DOMContentLoaded"),
             sActions.expectGeckoEvent("DOMTitleChanged")
         };
 
         initiatingAction.run();
 
         // PAGE_LOAD_WAIT_MS is the total time we wait for all events to finish.
         final long expecterStartMillis = SystemClock.uptimeMillis();
         for (final EventExpecter expecter : eventExpecters) {
             final int eventWaitTimeMillis = PAGE_LOAD_WAIT_MS - (int)(SystemClock.uptimeMillis() - expecterStartMillis);
-            expecter.blockForEventDataWithTimeout(eventWaitTimeMillis);
+            expecter.blockForEvent(eventWaitTimeMillis, /* failOnTimeout */ false);
             expecter.unregisterListener();
         }
 
         // The timeout wait time should be the aggregate time for all ChangeVerifiers.
         final long verifierStartMillis = SystemClock.uptimeMillis();
 
         // Verify remaining state has changed.
         for (final ChangeVerifier verifier : pageLoadVerifiers) {
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAboutPage.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAboutPage.java
@@ -25,17 +25,17 @@ public class testAboutPage extends Pixel
         url = getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_01_URL);
         loadUrlAndWait(url);
 
         // At this point the page title should have been set.
         verifyUrlInContentDescription(url);
 
         // Set up listeners to catch the page load we're about to do.
         Actions.EventExpecter tabEventExpecter = mActions.expectGlobalEvent(Actions.EventType.UI, "Tab:Added");
-        Actions.EventExpecter contentEventExpecter = mActions.expectGeckoEvent("DOMContentLoaded");
+        Actions.EventExpecter contentEventExpecter = mActions.expectGlobalEvent(Actions.EventType.GECKO, "Content:DOMContentLoaded");
 
         selectSettingsItem(mStringHelper.MOZILLA_SECTION_LABEL, mStringHelper.ABOUT_LABEL);
 
         // Wait for the new tab and page to load
         tabEventExpecter.blockForEvent();
         contentEventExpecter.blockForEvent();
 
         tabEventExpecter.unregisterListener();
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAddonManager.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAddonManager.java
@@ -25,17 +25,17 @@ public class testAddonManager extends Pi
 
         blockForGeckoReady();
 
         // Use the menu to open the Addon Manger
         selectMenuItem(mStringHelper.ADDONS_LABEL);
 
         // Set up listeners to catch the page load we're about to do
         tabEventExpecter = mActions.expectGlobalEvent(Actions.EventType.UI, "Tab:Added");
-        contentEventExpecter = mActions.expectGeckoEvent("DOMContentLoaded");
+        contentEventExpecter = mActions.expectGlobalEvent(Actions.EventType.GECKO, "Content:DOMContentLoaded");
 
         // Wait for the new tab and page to load
         tabEventExpecter.blockForEvent();
         contentEventExpecter.blockForEvent();
 
         tabEventExpecter.unregisterListener();
         contentEventExpecter.unregisterListener();
 
@@ -46,17 +46,17 @@ public class testAddonManager extends Pi
         mSolo.goBack();
 
         // Load the about:addons page and verify it was loaded
         loadAndPaint(aboutAddonsURL);
         verifyUrlBarTitle(aboutAddonsURL);
 
         // Setup wait for tab to spawn and load
         tabEventExpecter = mActions.expectGlobalEvent(Actions.EventType.UI, "Tab:Added");
-        contentEventExpecter = mActions.expectGeckoEvent("DOMContentLoaded");
+        contentEventExpecter = mActions.expectGlobalEvent(Actions.EventType.GECKO, "Content:DOMContentLoaded");
 
         // Open a new tab
         final String blankURL = getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_01_URL);
         addTab(blankURL);
 
         // Wait for the new tab and page to load
         tabEventExpecter.blockForEvent();
         contentEventExpecter.blockForEvent();
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testHomeBanner.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testHomeBanner.java
@@ -34,20 +34,22 @@ public class testHomeBanner extends UITe
     /**
      * Adds a banner message, verifies that it appears when it should, and verifies that
      * onshown/onclick handlers are called in JS.
      *
      * Note: This test does not remove the message after it is done.
      */
     private void addBannerTest() {
         // Load about:home and make sure the onshown handler is called.
-        Actions.EventExpecter eventExpecter = getActions().expectGeckoEvent("TestHomeBanner:MessageShown");
+        Actions.EventExpecter eventExpecter = getActions().expectGlobalEvent(
+                Actions.EventType.GECKO, "TestHomeBanner:MessageShown");
         addBannerMessage();
         NavigationHelper.enterAndLoadUrl(mStringHelper.ABOUT_HOME_URL);
         eventExpecter.blockForEvent();
+        eventExpecter.unregisterListener();
 
         // Verify that the banner is visible with the correct text.
         mAboutHome.assertBannerText(TEXT);
 
         // Verify that the banner isn't visible after navigating away from about:home.
         NavigationHelper.enterAndLoadUrl(mStringHelper.ABOUT_FIREFOX_URL);
         mAboutHome.assertBannerNotVisible();
     }
@@ -71,24 +73,28 @@ public class testHomeBanner extends UITe
      *
      * Note: This test does not remove the message after it is done.
      */
     private void dismissBannerTest() {
         NavigationHelper.enterAndLoadUrl(mStringHelper.ABOUT_HOME_URL);
         mAboutHome.assertVisible();
 
         // Test to make sure the ondismiss handler is called when the close button is clicked.
-        final Actions.EventExpecter eventExpecter = getActions().expectGeckoEvent("TestHomeBanner:MessageDismissed");
+        final Actions.EventExpecter eventExpecter = getActions().expectGlobalEvent(
+                Actions.EventType.GECKO, "TestHomeBanner:MessageDismissed");
         mAboutHome.dismissBanner();
         eventExpecter.blockForEvent();
+        eventExpecter.unregisterListener();
 
         mAboutHome.assertBannerNotVisible();
     }
 
     /**
      * Loads the roboextender page to add a message to the banner.
      */
     private void addBannerMessage() {
-        final Actions.EventExpecter eventExpecter = getActions().expectGeckoEvent("TestHomeBanner:MessageAdded");
+        final Actions.EventExpecter eventExpecter = getActions().expectGlobalEvent(
+                Actions.EventType.GECKO, "TestHomeBanner:MessageAdded");
         NavigationHelper.enterAndLoadUrl(TEST_URL + "#addMessage");
         eventExpecter.blockForEvent();
+        eventExpecter.unregisterListener();
     }
 }
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testJavascriptBridge.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testJavascriptBridge.java
@@ -1,18 +1,17 @@
 /* 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/. */
 
 package org.mozilla.gecko.tests;
 
 import static org.mozilla.gecko.tests.helpers.AssertionHelper.*;
 
-import org.json.JSONException;
-import org.json.JSONObject;
+import org.mozilla.gecko.util.GeckoBundle;
 
 /**
  * Tests the proper operation of JavascriptBridge and JavaBridge,
  * which are used by tests for communication between Java and JS.
  */
 public class testJavascriptBridge extends JavascriptBridgeTest {
 
     private static final String TEST_JS = "testJavascriptBridge.js";
@@ -37,25 +36,25 @@ public class testJavascriptBridge extend
     }
 
     public void checkJavaBooleanArg(final boolean booltrue) {
         // Async call from JS
         fAssertEquals("Boolean argument matches", true, booltrue);
         getJS().syncCall("check_js_string_arg", "foo");
     }
 
-    public void checkJavaStringArg(final String stringbar) throws JSONException {
+    public void checkJavaStringArg(final String stringbar) {
         // Async call from JS
         fAssertEquals("String argument matches", "bar", stringbar);
-        final JSONObject obj = new JSONObject();
-        obj.put("caller", "java");
-        getJS().syncCall("check_js_object_arg", (JSONObject) obj);
+        final GeckoBundle bundle = new GeckoBundle();
+        bundle.putString("caller", "java");
+        getJS().syncCall("check_js_object_arg", bundle);
     }
 
-    public void checkJavaObjectArg(final JSONObject obj) throws JSONException {
+    public void checkJavaObjectArg(final GeckoBundle obj) {
         // Async call from JS
         fAssertEquals("Object argument matches", "js", obj.getString("caller"));
         getJS().syncCall("check_js_sync_call");
     }
 
     public void doJSSyncCall() {
         // Sync call from JS
         syncCallReceived = true;
--- a/modules/libjar/nsZipArchive.cpp
+++ b/modules/libjar/nsZipArchive.cpp
@@ -165,17 +165,16 @@ nsresult gZlibInit(z_stream *zs)
 nsZipHandle::nsZipHandle()
   : mFileData(nullptr)
   , mLen(0)
   , mMap(nullptr)
   , mRefCnt(0)
   , mFileStart(nullptr)
   , mTotalLen(0)
 {
-  MOZ_COUNT_CTOR(nsZipHandle);
 }
 
 NS_IMPL_ADDREF(nsZipHandle)
 NS_IMPL_RELEASE(nsZipHandle)
 
 nsresult nsZipHandle::Init(nsIFile *file, nsZipHandle **ret,
                            PRFileDesc **aFd)
 {
@@ -339,17 +338,16 @@ nsZipHandle::~nsZipHandle()
   if (mMap) {
     PR_MemUnmap((void *)mFileStart, mTotalLen);
     PR_CloseFileMap(mMap);
   }
   mFileStart = nullptr;
   mFileData = nullptr;
   mMap = nullptr;
   mBuf = nullptr;
-  MOZ_COUNT_DTOR(nsZipHandle);
 }
 
 //***********************************************************
 //      nsZipArchive  --  public methods
 //***********************************************************
 
 //---------------------------------------------
 //  nsZipArchive::OpenArchive
@@ -951,31 +949,27 @@ int64_t nsZipArchive::SizeOfMapping()
 nsZipArchive::nsZipArchive()
   : mRefCnt(0)
   , mCommentPtr(nullptr)
   , mCommentLen(0)
   , mBuiltSynthetics(false)
 {
   zipLog.AddRef();
 
-  MOZ_COUNT_CTOR(nsZipArchive);
-
   // initialize the table to nullptr
   memset(mFiles, 0, sizeof(mFiles));
 }
 
 NS_IMPL_ADDREF(nsZipArchive)
 NS_IMPL_RELEASE(nsZipArchive)
 
 nsZipArchive::~nsZipArchive()
 {
   CloseArchive();
 
-  MOZ_COUNT_DTOR(nsZipArchive);
-
   zipLog.Release();
 }
 
 
 //------------------------------------------
 // nsZipFind constructor and destructor
 //------------------------------------------
 
rename from modules/libmar/tests/unit/data/win_0_sized_mar.mar
rename to modules/libmar/tests/unit/data/0_sized.mar
deleted file mode 100644
index a7d039e5328cc2c7431f51c11d25c2f7f8c4eef8..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
rename from modules/libmar/tests/unit/data/win_1_byte_mar.mar
rename to modules/libmar/tests/unit/data/1_byte.mar
deleted file mode 100644
index 4df020099c6be9fd4b1a465a983608130da84b67..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
rename from modules/libmar/tests/unit/data/win_binary_data_mar.mar
rename to modules/libmar/tests/unit/data/binary_data.mar
deleted file mode 100644
index 7632c22950d2608dfde783b251afe769a1b83194..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
rename from modules/libmar/tests/unit/data/manipulated_signed_mar.mar
rename to modules/libmar/tests/unit/data/manipulated_signed.mar
rename from modules/libmar/tests/unit/data/win_multiple_file_mar.mar
rename to modules/libmar/tests/unit/data/multiple_file.mar
deleted file mode 100644
index fa64edca41860336e18cd571e6e1304881ac0abe..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
rename from modules/libmar/tests/unit/data/win_multiple_signed_no_pib_mar.mar
rename to modules/libmar/tests/unit/data/multiple_signed_no_pib.mar
deleted file mode 100644
index 5832b526fd5d6d043f291cf2147909460bb168a2..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
rename from modules/libmar/tests/unit/data/win_multiple_signed_pib_mar.mar
rename to modules/libmar/tests/unit/data/multiple_signed_pib.mar
rename from modules/libmar/tests/unit/data/multiple_signed_pib_mar_2.mar
rename to modules/libmar/tests/unit/data/multiple_signed_pib_2.mar
index f31f1df20668365a67e3fc10c5159e3b30d6b59d..ee6a9975455b23725ff170f88f2d0ee166a807d8
GIT binary patch
literal 1465
zc%1E&YdjSO9EKl9irNU}QpwsRvynqmZQ~qKPB=v)ES-+9+$v4!I-0HyU36KLP%A7m
z87gW`)7;wRvaL{BNaZqCSrNweY2Wv8@9%&4{`}tebrrh{LFG7qOXc$LQ665Uk%?bl
z)@2(aj`yg)c{R_VEipd!nqpt5_0fVAv$O7s6DyTUeI@gf!^Boy!gfLGnc|>L-h#)^
zQU+QpMyG_#53mSUWUYFX;k8G8D5L;w&zb2y+1pobQ?}7<X*8Fu%&$`Ot*VGpwI4TL
zxp`uWezviWU3lFdGk>L<t%-stRqfzB6ZM+jIo;yG3U%rEo%YSMYHn>Dd?{>Oo2!-H
z-)Ca#AM3mN`a!?N)!V!@)17VgMi~n&2PCzcHVwXEwkBuQ78(pXB?*|(NV(y(BaME^
zrpo<In|r%-w>Vuibk~rk6?D{zx=&=rW_H^+o6fC_=yKcd&{CW>#co=g&cex(|2h1d
zLr$F1Dc4=~O*LkE!R-Qj<ER12$&lWR08gV=E~5MHeN7?$0jKWeK998Z%C&GyUoycX
z!*OV=wv|(5f;hW+$1+ie%g(I8q20IBqU&;VZtT^WQ=Aw+V78;VRNr&T!`Y=pGi%Hr
z^tZeBh+{M_-X2VHytKtN)g*e1oAsS~g~G}5z|$+C$s(Pw^5<(>Iy1_Xt0OxW_2eDT
zE)8!jDKWLqPY6vq7ZW((BU3C@xwCKi*0_5OsZkmma*T3nJrkyPMCi5}pY@RUXS`6A
zRyr=w4b&<xd|*?e?p?U`N%3X-Uh{QT%kmpfk12Y3OwBSSeR}?dPU+!V4eK(6q@iw7
zjMmhDIIw!;i(JL-viVM8snpR$CUFoUv@*Al3;FM)gkU&|qflWqV^Bqnv5ez2UPm1b
z#-oWA+Du>~I_RQ@K9iWt6bzV(A#X5^H+c&qren+uOn4hp-r-%$FlQzf2(iS9Sy(e0
z8|E;VdA!H_e1I)>h!A7Xd>n9O0Sj?L!Xlh;!4)ZsS%MqxEagKy@MIZYc;mxIEXS7>
z$XJOSKUU#S0D*iw3@wOYLI@>{HLPVF;jHHqBG|x2BH6@dwy>3LZ0A#=h-L?$5yMV)
zv70^YWgoF9h$Ei;9N-{_NZ>F>ILa|T=QxQZae|X1bBYvFN#itU_=2;XBb^K~`I7Tw
z@fF#8O%4~x<s0(Ir+|xG;xdI4afPdV%Qe2EnCpB`2{-tGQpzZ&f=X`kBR^5aEvl)Z
zmO6gs7k=e7cc`a<M(%QtChqea4``-^RvyyEBOddFb~@;!i{I&{hd+4AGoI7SpS<8D
pef0B+0R|ZwF@V8v6%Y5aV8jarenD&G>o?2%<q>jOU{GiPe*s3`1;_vZ
deleted file mode 100644
index 11c4cbedc674bdc10274658a4cc0cfdfc05e74bd..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
--- a/modules/libmar/tests/unit/data/multiple_signed_pib_mar.sig.0
+++ b/modules/libmar/tests/unit/data/multiple_signed_pib_mar.sig.0
@@ -1,6 +1,6 @@
-myuujl0MBwyLCrp8I84HrDbGLe+T5yfAR869QWvhcet/CglmuEsQEJczAoK8PtOR
-HcqczCRFtxNRKDPOUC0i+CS7RAQG4XJd9uprqHtB28s4SR/9nXKfWDnH2UYq9hkt
-X6qTab9M9ySrugOugomDb3ej/qYoNfJN9RnkLP4GP+cl96bWPU33rL0Uu7sUKizu
-QoYzxKeZ0r9hGMpOP2l/Jn+pydoEWGVB1mzvIFLPqD9cShUvV80xs8teV0G9IncC
-ZRuBwwNkfMTgJDCnxbrw3gIqNXMN1zjssztyJIpT2q8JGs+F6H0wz515xm32dCdQ
-b3Oo8a9Dx28NKKq83DJDQA==
\ No newline at end of file
+jXLI7j5rQY1V2sy9tB3nmY2Kv4uJbDWVtl42rN1BmcsBx11JOp1tQTPuMesCoKPB
+aXhZAun0n/3lygafa0NlMGqLrGPoqFiHYZFrtgATVi+nWq59Y3wDNxfk3C5fYLXP
+CV3Pyn8IQgsQA+MVnxmuJhY/cdSHLWQBzOWZAn8IE2q0KA7S9jjwQWbKDk6rhELj
+NNLQdv75MedvshKn+/ooKmSKXWjCkGJP0XxYEadLPhgEJjEy/UnTETfbXW0+KKUJ
+Rx3+SJoCACfcAMkfIZTcYp0qA/vfefbuF3pItx9SD06htuzUQPCbqYqp8DdLKjnL
+dO5RjkTkwaEcPyHnFkcbSQ==
\ No newline at end of file
--- a/modules/libmar/tests/unit/data/multiple_signed_pib_mar.sig.1
+++ b/modules/libmar/tests/unit/data/multiple_signed_pib_mar.sig.1
@@ -1,6 +1,6 @@
-xSnuhHyf8iEdPnRgNw9w0Tu6dJimNv+etdZagvbftkGuBlQArhPn7unCOEQ+jS0n
-ummJHp1yv64Q7Tte4te8OpRaR6eE333bHfFp++cKKJ2jWFeZ1SwRn59cWX0w4z9u
-I4VJmqzOKDUgZq24m6MfGr9iRKbrDjDgvfapzRkZNNU/I0jv20+G+vIUysQGLSN7
-fMAxxeurZNbinIiFQyudSpLU2n5PJDh/FIX2lt8H8nX5/yNyznbz0Gm+/hGMZj7+
-EfPxLxyOuSRVxI0ebAcRBQJLiyEh1iIluvjuBKohCxkWkEZG3weCz29JxdWOzobj
-3/6D+xJW5M1V8aE7EEjt4w==
\ No newline at end of file
+FtZexU7kCM3B90ksC6uYbbdHzwglHCxuZq1I8yIulFb73ncu6ivEbQZjZqd0XuKt
+0dnFVqZcpq/bGxyVc7SWZXbqSKpdiwten2hvpvolKafp3L148jpZo3D1G0mJ5pFZ
+fpb2tyNoJ2OC+qR0Za6Wy9w5L3krA0dNbGMMsidhM44TxEGwMGIP/m7rJ9p3TTXx
+wZ3Yu5XHuUzSYdUm2z9MvPb8NgdE2fo+oPsFmfZYZj0HY8qFzktg+ubNuZf4xiBN
+TbBgPEWYXh8bRZ0Hyz9qRIak+LEFFWmBU3r/kFUOv+eKzWnxgX/RQO3MObQdlBu8
+mNtLHXR3faLzIHxET9Vs7w==
\ No newline at end of file
--- a/modules/libmar/tests/unit/data/multiple_signed_pib_mar.sig.2
+++ b/modules/libmar/tests/unit/data/multiple_signed_pib_mar.sig.2
@@ -1,6 +1,6 @@
-VQmSlk8q2tmSd+C/d3ADde0lQoJw611sWboc7GOnFTRRsO0D61fIl3tlXLn/N4vN
-fCHQxwrszCizC1ddt9Bf5ujBqcAx+ZrN+iT2NlK2j6TN6K1W8LENJgCE7IXN5h1G
-VVryo5OkJzWd50DLX/qL9EAg3wx+P3b2BWXkhMuCDGvtAL3C4Ffnm7dw0hjErsEV
-X0cB5O5ozM0dOih+GNNX++wxT8E1NqNJOGaJR1KYeY17agz+QlSvFt/fL/a64Fsw
-DtOeGZ79nQZ6qkbmUxLXDQ630y3AQ8ceMJFIlI+T3Tk1DUuAWUpMXOICaqzDCdh+
-QC5nuQ7OK8Ycbm5fkIFfNQ==
\ No newline at end of file
+sIwBnk2F2t/SLRhq6wJCJn/9SZxr9qhlViT8TEDgUvrfa2Rlnt6y9Xc+WLIwUadQ
+FFWoRf8KEzNIy5JBrtGBV0DsTISsZv+G2KGA1LKwxYgWOMGZcf0tgePHGVYc5jbH
+uy/SLuL761LxQYMRt9j+mkW4ek2gKIAHUTXZ2ouLSDKP87xsnUAWbcn1buTtqMmd
+0XfsSvG0mK7HceXExCo1tZJsmqaDZv1aX4tTBdmJXHuM3tugfw91sCSw01aSJex0
+F+UmpVVh+6j4CE7LRUYXZhLJuuI3xA5ZunvqwblC9i5wz1e13KIHu/OWCTKfpyW1
+se1Ok9MPNciLSdvUGoMSHg==
\ No newline at end of file
rename from modules/libmar/tests/unit/data/no_pib_mar.mar
rename to modules/libmar/tests/unit/data/no_pib.mar
rename from modules/libmar/tests/unit/data/win_signed_no_pib_mar.mar
rename to modules/libmar/tests/unit/data/signed_no_pib.mar
deleted file mode 100644
index f6e449e3eaf14c8e5b6117eccaf0ebf9ff443d89..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
rename from modules/libmar/tests/unit/data/win_signed_pib_mar.mar
rename to modules/libmar/tests/unit/data/signed_pib.mar
deleted file mode 100644
index 72f4c25ec2fc58473edb325fc21d8160a0898f85..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
--- a/modules/libmar/tests/unit/data/signed_pib_mar.signature.mycert2
+++ b/modules/libmar/tests/unit/data/signed_pib_mar.signature.mycert2
@@ -1,6 +1,6 @@
-wYPEMA2nfrMfkL5+//r9Of8JicdmG5KxAzYUhSR3d/vr075LhGkc6nQc5orDIRnz
-vuMBRIqoAsK3IdtCEbZ6rRKN9d+N7HfvmLdDXGpK3lr9NKKTnk1n/0o7ziRi3Fm8
-hOkJpdit7OHV0RH5GBSM8tQziXGN+qe51W2otMA4d8+oa4tp2D7W4SSUxxJwBPiu
-5CJAA68qaxzhWd5iVtU8mcjbYOKZAciIPgqBxhgmukqNrShQpnwcop/WHggL7lxI
-QWZYpuU6MMxVmLSiAAEAwLMwL2UqHxcGQjIuepu9ikbJ251SwxYiH3xRMkYpQNNv
-YFEb9pm2HJq9oNgZUGakDQ==
\ No newline at end of file
+Ywj/i+4teNQ9jhAOQsibt4sJTGRHC+8l9T96pCxX+zq4qQio9ysPS+N7g+ODaArA
+pYGD7SsXEKC69PwhS8XeJtPTZ744YwLx0+YApwJg7ZxWji9bqrqS4qfp5o9j8A9q
+g3GLBH4S+xefbOrhgHptWs6ZwBAO6nhxlhviZA7Bp9m6ViUBNmGgTYnMsfhzU4Ol
+7Cmkbah3Hyt2EYUnZ8KJm46eebRvDnJNKX7s6tq/h0o/V8As1v805tgBlsyDwn6R
+6h0S7HqNx8JkIvVsIV2boXmkYYobVb8ssottyHc893ywQMPso1gdBMJYAgRW26wR
+ZEEL62q8zGzt+UB+V8pfNA==
\ No newline at end of file
rename from modules/libmar/tests/unit/data/signed_pib_mar_with_mycert2.mar
rename to modules/libmar/tests/unit/data/signed_pib_with_mycert2.mar
index 41ad2b3f99226434d0d545de655c7a5d45313de7..5263496e168d0072991be3733eaf663239c313de
GIT binary patch
literal 937
zc$}@1_g@SE0L8y|g@|hyAt8j65!s_Vl~G*?m3dA_$`xfaaN?{wvLhLxRQ4Vj<*bmI
zRhdONmz@w&_!GR(=e_s)`+T2N;^hDaOZX#$w2Bb?wE#b(a?RVe;dgq+nu_{nB^=XK
z_fYgVerHqS6q#i2Q`X~nno(-0or!zlEOnuJQjN^ydFo<23)95(&p)i)FFbCUljDD;
zo1gGQP7x`>am5?GW806~nZBwZ<#o|=zxO7A>JW{g%Dl{Ci&FP2Dl%x~_4rIvkuE$W
z&ayxuI-8Q4?rkIJB2Sb?XCL@FZKyg~Z<`d98rH;arrE+){@Un-*v%1#r-(wOwko|Y
zFJrNrlTW7oy>iE*2ZFe4wN|xKXJxLBTy{yTXjY=M9+R*&B1s-&IXuJupe86QtXJvm
z{o-@_?Y>rqT3?}|cm8fOg~a$x;Hhk7@i(!`=Zehn-xiZ9TP&4$$(#pBJUv}KWCLBq
zICN^)LGHl+lK>$G7*d6*RKtks)WDdU)Ix*_rkG()ZR${$dRS1O1~kNyMp)69CN#yG
zW;CY-HngM_t+AyIcG%OFcC@Dh4s@gwj&!CAUFk-5deD<z^rjC^h>_42XIyZlAN?7?
zK-_T011X*iVlYGSVkpBHjyFE|GJ=teVl-nIi;Qu|8IK<dCNL5IiqQfHWHL&E2xbaX
z2_ckeOlJl&2_u{cBALZ(=AdFOQOsjLY8J4NMJ#3s(Zrx(Da(juIV)JnDps?GwZyTG
z^~AG*1U9mX&1@l&t!!gENhGs_6jDiJC%f3q9`>@2{T$#Rhd9g;j&h9SoFJW(oZ>WR
z$RLxmXgSAuE^v`cWO11*TqT=pT;~Qixy5aAxWirUai0g|l1DxddBkI$@RVm1P{?y$
zP{d1K@fsa(&{ND?-tnFfeB=|KDd7vHeB~S8DdPt}`9*mp09F+YRQym_$->d`0m1Un
P2$@1YT`rp#pq#*O59AOm
--- a/modules/libmar/tests/unit/head_libmar.js
+++ b/modules/libmar/tests/unit/head_libmar.js
@@ -1,42 +1,40 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
-var Cc = Components.classes;
-var Ci = Components.interfaces;
+'use strict';
 
-const refMARPrefix = (mozinfo.os == "win" ? "win_" : "");
+const { classes: Cc, interfaces: Ci } = Components;
 const BIN_SUFFIX = mozinfo.bin_suffix;
-
-var tempDir = do_get_tempdir();
+const tempDir = do_get_tempdir();
 
 /**
  * Compares binary data of 2 arrays and throws if they aren't the same.
  * Throws on mismatch, does nothing on match.
  *
  * @param arr1 The first array to compare
  * @param arr2 The second array to compare
-*/
+ */
 function compareBinaryData(arr1, arr2) {
   do_check_eq(arr1.length, arr2.length);
   for (let i = 0; i < arr1.length; i++) {
     if (arr1[i] != arr2[i]) {
       throw "Data differs at index " + i + 
             ", arr1: " + arr1[i] + ", arr2: " + arr2[i];
     }
   }
 }
 
-/** 
+/**
  * Reads a file's data and returns it
  *
  * @param file The file to read the data from
  * @return a byte array for the data in the file.
-*/
+ */
 function getBinaryFileData(file) {
   let fileStream = Cc["@mozilla.org/network/file-input-stream;1"].
                    createInstance(Ci.nsIFileInputStream);
   // Open as RD_ONLY with default permissions.
   fileStream.init(file, -1, -1, null);
 
   // Check the returned size versus the expected size.
   let stream = Cc["@mozilla.org/binaryinputstream;1"].
@@ -49,49 +47,49 @@ function getBinaryFileData(file) {
 
 /**
  * Runs each method in the passed in object
  * Every method of the passed in object that starts with test_ will be ran
  * The cleanup_per_test method of the object will be run right away, it will be
  * registered to be the cleanup function, and it will be run between each test.
  *
  * @return The number of tests ran
-*/
+ */
 function run_tests(obj) {
   let cleanup_per_test = obj.cleanup_per_test;
   if (cleanup_per_test === undefined) {
-    cleanup_per_test = function() {};
+    cleanup_per_test = function __cleanup_per_test() {};
   }
 
   do_register_cleanup(cleanup_per_test);
 
   // Make sure there's nothing left over from a preious failed test
   cleanup_per_test();
 
   let ranCount = 0;
   // hasOwnProperty ensures we only see direct properties and not all
   for (let f in obj) {
-    if (typeof obj[f] === "function" && 
+    if (typeof obj[f] === "function" &&
         obj.hasOwnProperty(f) &&
         f.toString().indexOf("test_") === 0) {
       obj[f]();
       cleanup_per_test();
       ranCount++;
     }
   }
   return ranCount;
 }
 
 /**
  * Creates a MAR file with the content of files.
  *
  * @param outMAR  The file where the MAR should be created to
  * @param dataDir The directory where the relative file paths exist
  * @param files   The relative file paths of the files to include in the MAR
-*/
+ */
 function createMAR(outMAR, dataDir, files) {
   // You cannot create an empy MAR.
   do_check_true(files.length > 0);
 
   // Get an nsIProcess to the signmar binary.
   let process = Cc["@mozilla.org/process/util;1"].
                 createInstance(Ci.nsIProcess);
   let signmarBin = do_get_file("signmar" + BIN_SUFFIX);
@@ -100,24 +98,24 @@ function createMAR(outMAR, dataDir, file
   do_check_true(signmarBin.exists());
   do_check_true(signmarBin.isExecutable());
 
   // Ensure on non Windows platforms we encode the same permissions
   // as the refernence MARs contain.  On Windows this is also safe.
   // The reference MAR files have permissions of 0o664, so in case
   // someone is running these tests locally with another permission
   // (perhaps 0o777), make sure that we encode them as 0o664.
-  for (filePath of files) {
+  for (let filePath of files) {
     let f = dataDir.clone();
     f.append(filePath);
     f.permissions = 0o664;
   }
 
   // Setup the command line arguments to create the MAR.
-  let args = ["-C", dataDir.path, "-H", "\@MAR_CHANNEL_ID\@", 
+  let args = ["-C", dataDir.path, "-H", "\@MAR_CHANNEL_ID\@",
               "-V", "13.0a1", "-c", outMAR.path];
   args = args.concat(files);
 
   do_print('Running: ' + signmarBin.path);
   process.init(signmarBin);
   process.run(true, args, args.length);
 
   // Verify signmar returned 0 for success.
@@ -127,17 +125,17 @@ function createMAR(outMAR, dataDir, file
   do_check_true(outMAR.exists());
 }
 
 /**
  * Extracts a MAR file to the specified output directory.
  *
  * @param mar     The MAR file that should be matched
  * @param dataDir The directory to extract to
-*/
+ */
 function extractMAR(mar, dataDir) {
   // Get an nsIProcess to the signmar binary.
   let process = Cc["@mozilla.org/process/util;1"].
                 createInstance(Ci.nsIProcess);
   let signmarBin = do_get_file("signmar" + BIN_SUFFIX);
 
   // Make sure the signmar binary exists and is an executable.
   do_check_true(signmarBin.exists());
@@ -148,10 +146,8 @@ function extractMAR(mar, dataDir) {
 
   do_print('Running: ' + signmarBin.path);
   process.init(signmarBin);
   process.run(true, args, args.length);
 
   // Verify signmar returned 0 for success.
   do_check_eq(process.exitValue, 0);
 }
-
-
--- a/modules/libmar/tests/unit/test_create.js
+++ b/modules/libmar/tests/unit/test_create.js
@@ -4,17 +4,17 @@
 function run_test() {
 
   /**
    * Creates MAR from the passed files, compares it to the reference MAR.
    *
    * @param refMARFileName The name of the MAR file that should match
    * @param files          The files that should go in the created MAR
    * @param checkNoMAR     If true return an error if a file already exists
-  */
+   */
   function run_one_test(refMARFileName, files, checkNoMAR) {
     if (checkNoMAR === undefined) {
       checkNoMAR = true;
     }
 
     // Ensure the MAR we will create doesn't already exist.
     let outMAR = tempDir.clone();
     outMAR.append("out.mar");
@@ -26,50 +26,82 @@ function run_test() {
     createMAR(outMAR, do_get_file("data"), files);
 
     // Get the reference MAR data.
     let refMAR = do_get_file("data/" + refMARFileName);
     let refMARData = getBinaryFileData(refMAR);
 
     // Verify the data of the MAR is what it should be.
     let outMARData = getBinaryFileData(outMAR);
+    if (mozinfo.os != "win") {
+      // Modify the array index that contains the file permission in this mar so
+      // the comparison succeeds. This value is only changed when the value is
+      // the expected value on non-Windows platforms since the MAR files are
+      // created on Windows. This makes it possible to use the same MAR files for
+      // all platforms.
+      switch (refMARFileName) {
+        case "0_sized.mar":
+          if (outMARData[143] == 180) {
+            outMARData[143] = 182;
+          }
+          break;
+        case "1_byte.mar":
+          if (outMARData[144] == 180) {
+            outMARData[144] = 182;
+          }
+          break;
+        case "binary_data.mar":
+          if (outMARData[655] == 180) {
+            outMARData[655] = 182;
+          }
+          break;
+        case "multiple_file.mar":
+          if (outMARData[656] == 180) {
+            outMARData[656] = 182;
+          }
+          if (outMARData[681] == 180) {
+            outMARData[681] = 182;
+          }
+          if (outMARData[705] == 180) {
+            outMARData[705] = 182;
+          }
+      }
+    }
     compareBinaryData(outMARData, refMARData);
   }
 
   // Define the unit tests to run.
   let tests = {
     // Test creating a MAR file with a 0 byte file.
-    test_zero_sized: function() {
-      return run_one_test(refMARPrefix + "0_sized_mar.mar", ["0_sized_file"]);
+    test_zero_sized: function _test_zero_sized() {
+      return run_one_test("0_sized.mar", ["0_sized_file"]);
     },
     // Test creating a MAR file with a 1 byte file.
-    test_one_byte: function() {
-      return run_one_test(refMARPrefix + "1_byte_mar.mar", ["1_byte_file"]);
+    test_one_byte: function _test_one_byte() {
+      return run_one_test("1_byte.mar", ["1_byte_file"]);
     },
     // Test creating a MAR file with binary data.
-    test_binary_data: function() {
-      return run_one_test(refMARPrefix + "binary_data_mar.mar", 
-                          ["binary_data_file"]);
+    test_binary_data: function _test_binary_data() {
+      return run_one_test("binary_data.mar", ["binary_data_file"]);
     },
     // Test creating a MAR file with multiple files inside of it.
-    test_multiple_file: function() {
-      return run_one_test(refMARPrefix + "multiple_file_mar.mar", 
+    test_multiple_file: function _test_multiple_file() {
+      return run_one_test("multiple_file.mar",
                           ["0_sized_file", "1_byte_file", "binary_data_file"]);
     },
     // Test creating a MAR file on top of a different one that already exists
     // at the location the new one will be created at.
-    test_overwrite_already_exists: function() {
-      let differentFile = do_get_file("data/1_byte_mar.mar");
+    test_overwrite_already_exists: function _test_overwrite_already_exists() {
+      let differentFile = do_get_file("data/1_byte.mar");
       let outMARDir = tempDir.clone();
       differentFile.copyTo(outMARDir, "out.mar");
-      return run_one_test(refMARPrefix + "binary_data_mar.mar", 
-                          ["binary_data_file"], false);
+      return run_one_test("binary_data.mar", ["binary_data_file"], false);
     },
     // Between each test make sure the out MAR does not exist.
-    cleanup_per_test: function() {
+    cleanup_per_test: function _cleanup_per_test() {
       let outMAR = tempDir.clone();
       outMAR.append("out.mar");
       if (outMAR.exists()) {
         outMAR.remove(false);
       }
     }
   };
 
--- a/modules/libmar/tests/unit/test_extract.js
+++ b/modules/libmar/tests/unit/test_extract.js
@@ -3,18 +3,18 @@
 
 function run_test() {
 
   /**
    * Extracts a MAR and makes sure each file matches the reference files.
    *
    * @param marFileName The name of the MAR file to extract
    * @param files       The files that the extracted MAR should contain
-  */
-  function run_one_test(marFileName, files) { 
+   */
+  function run_one_test(marFileName, files) {
     // Get the MAR file that we will be extracting
     let mar = do_get_file("data/" + marFileName);
 
     // Get the path that we will extract to
     let outDir = tempDir.clone();
     outDir.append("out");
     do_check_false(outDir.exists());
     outDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o777);
@@ -41,50 +41,50 @@ function run_test() {
       let outFileData = getBinaryFileData(outFiles[i]);
       compareBinaryData(refFileData, outFileData);
     }
   }
 
   // Define the unit tests to run.
   let tests = {
     // Test extracting a MAR file with a 0 byte file.
-    test_zero_sized: function() {
-      return run_one_test("0_sized_mar.mar", ["0_sized_file"]);
-    }, 
+    test_zero_sized: function _test_zero_sized() {
+      return run_one_test("0_sized.mar", ["0_sized_file"]);
+    },
     // Test extracting a MAR file with a 1 byte file.
-    test_one_byte: function() {
-      return run_one_test("1_byte_mar.mar", ["1_byte_file"]);
+    test_one_byte: function _test_one_byte() {
+      return run_one_test("1_byte.mar", ["1_byte_file"]);
     },
     // Test extracting a MAR file with binary data.
-    test_binary_data: function() {
-      return run_one_test("binary_data_mar.mar", ["binary_data_file"]);
+    test_binary_data: function _test_binary_data() {
+      return run_one_test("binary_data.mar", ["binary_data_file"]);
     },
     // Test extracting a MAR without a product information block (PIB) which
     // contains binary data.
-    test_no_pib: function() {
-      return run_one_test("no_pib_mar.mar", ["binary_data_file"]);
+    test_no_pib: function _test_no_pib() {
+      return run_one_test("no_pib.mar", ["binary_data_file"]);
     },
     // Test extracting a MAR without a product information block (PIB) that is
     // signed and which contains binary data.
-    test_no_pib_signed: function() {
-      return run_one_test("signed_no_pib_mar.mar", ["binary_data_file"]);
+    test_no_pib_signed: function _test_no_pib_signed() {
+      return run_one_test("signed_no_pib.mar", ["binary_data_file"]);
     },
     // Test extracting a MAR with a product information block (PIB) that is
     // signed and which contains binary data.
-    test_pib_signed: function() {
-      return run_one_test("signed_pib_mar.mar", ["binary_data_file"]);
+    test_pib_signed: function _test_pib_signed() {
+      return run_one_test("signed_pib.mar", ["binary_data_file"]);
     },
     // Test extracting a MAR file with multiple files inside of it.
-    test_multiple_file: function() {
-      return run_one_test("multiple_file_mar.mar", 
+    test_multiple_file: function _test_multiple_file() {
+      return run_one_test("multiple_file.mar",
                           ["0_sized_file", "1_byte_file", "binary_data_file"]);
-    }, 
-    // Between each test make sure the out directory and its subfiles do 
+    },
+    // Between each test make sure the out directory and its subfiles do
     // not exist.
-    cleanup_per_test: function() {
+    cleanup_per_test: function _cleanup_per_test() {
       let outDir = tempDir.clone();
       outDir.append("out");
       if (outDir.exists()) {
         outDir.remove(true);
       }
     }
   };
 
--- a/modules/libmar/tests/unit/test_sign_verify.js
+++ b/modules/libmar/tests/unit/test_sign_verify.js
@@ -3,137 +3,142 @@
 
 function run_test() {
 
   /**
    * Signs a MAR file.
    *
    * @param inMAR The MAR file that should be signed
    * @param outMAR The MAR file to create
-  */
+   */
   function signMAR(inMAR, outMAR, certs, wantSuccess, useShortHandCmdLine) {
     // Get a process to the signmar binary from the dist/bin directory.
     let process = Cc["@mozilla.org/process/util;1"].
                   createInstance(Ci.nsIProcess);
     let signmarBin = do_get_file("signmar" + BIN_SUFFIX);
 
     // Make sure the signmar binary exists and is an executable.
     do_check_true(signmarBin.exists());
     do_check_true(signmarBin.isExecutable());
 
     // Setup the command line arguments to sign the MAR.
     let NSSConfigDir = do_get_file("data");
     let args = ["-d", NSSConfigDir.path];
     if (certs.length == 1 && useShortHandCmdLine) {
       args.push("-n", certs[0]);
     } else {
-      for (var i = 0; i < certs.length; i++) {
+      for (let i = 0; i < certs.length; i++) {
         args.push("-n" + i, certs[i]);
       }
     }
     args.push("-s", inMAR.path, outMAR.path);
 
+    let exitValue;
     process.init(signmarBin);
     try {
       process.run(true, args, args.length);
-    } catch(e) {
+      exitValue = process.exitValue;
+    } catch (e) {
       // On Windows negative return value throws an exception
-      process.exitValue = -1;
+      exitValue = -1;
     }
 
     // Verify signmar returned 0 for success.
     if (wantSuccess) {
-      do_check_eq(process.exitValue, 0);
+      do_check_eq(exitValue, 0);
     } else {
-      do_check_neq(process.exitValue, 0);
+      do_check_neq(exitValue, 0);
     }
   }
 
-
   /**
    * Extract a MAR signature.
    *
    * @param inMAR        The MAR file who's signature should be extracted
    * @param sigIndex     The index of the signature to extract
    * @param extractedSig The file where the extracted signature will be stored
    * @param wantSuccess  True if a successful signmar return code is desired
-  */
+   */
   function extractMARSignature(inMAR, sigIndex, extractedSig, wantSuccess) {
     // Get a process to the signmar binary from the dist/bin directory.
     let process = Cc["@mozilla.org/process/util;1"].
                   createInstance(Ci.nsIProcess);
     let signmarBin = do_get_file("signmar" + BIN_SUFFIX);
 
     // Make sure the signmar binary exists and is an executable.
     do_check_true(signmarBin.exists());
     do_check_true(signmarBin.isExecutable());
 
     // Setup the command line arguments to extract the signature in the MAR.
     let args = ["-n" + sigIndex, "-X", inMAR.path, extractedSig.path];
 
+    let exitValue;
     process.init(signmarBin);
     try {
       process.run(true, args, args.length);
-    } catch(e) {
+      exitValue = process.exitValue;
+    } catch (e) {
       // On Windows negative return value throws an exception
-      process.exitValue = -1;
+      exitValue = -1;
     }
 
     // Verify signmar returned 0 for success.
     if (wantSuccess) {
-      do_check_eq(process.exitValue, 0);
+      do_check_eq(exitValue, 0);
     } else {
-      do_check_neq(process.exitValue, 0);
+      do_check_neq(exitValue, 0);
     }
   }
 
   /**
    * Import a MAR signature.
    *
    * @param inMAR        The MAR file who's signature should be imported to
    * @param sigIndex     The index of the signature to import to
    * @param sigFile      The file where the base64 signature exists
    * @param outMAR       The same as inMAR but with the specified signature
    *                     swapped at the specified index.
    * @param wantSuccess  True if a successful signmar return code is desired
-  */
+   */
   function importMARSignature(inMAR, sigIndex, sigFile, outMAR, wantSuccess) {
     // Get a process to the signmar binary from the dist/bin directory.
     let process = Cc["@mozilla.org/process/util;1"].
                   createInstance(Ci.nsIProcess);
     let signmarBin = do_get_file("signmar" + BIN_SUFFIX);
 
     // Make sure the signmar binary exists and is an executable.
     do_check_true(signmarBin.exists());
     do_check_true(signmarBin.isExecutable());
 
     // Setup the command line arguments to import the signature in the MAR.
     let args = ["-n" + sigIndex, "-I", inMAR.path, sigFile.path, outMAR.path];
 
+    let exitValue;
     process.init(signmarBin);
     try {
       process.run(true, args, args.length);
-    } catch(e) {
+      exitValue = process.exitValue;
+    } catch (e) {
       // On Windows negative return value throws an exception
-      process.exitValue = -1;
+      exitValue = -1;
     }
 
     // Verify signmar returned 0 for success.
     if (wantSuccess) {
-      do_check_eq(process.exitValue, 0);
+      do_check_eq(exitValue, 0);
     } else {
-      do_check_neq(process.exitValue, 0);
+      do_check_neq(exitValue, 0);
     }
   }
 
   /**
    * Verifies a MAR file.
    *
    * @param signedMAR Verifies a MAR file
-  */
+   */
   function verifyMAR(signedMAR, wantSuccess, certs, useShortHandCmdLine) {
     // Get a process to the signmar binary from the dist/bin directory.
     let process = Cc["@mozilla.org/process/util;1"].
                   createInstance(Ci.nsIProcess);
     let signmarBin = do_get_file("signmar" + BIN_SUFFIX);
 
     // Make sure the signmar binary exists and is an executable.
     do_check_true(signmarBin.exists());
@@ -147,86 +152,89 @@ function run_test() {
     // since on Windows we verify with CryptoAPI, on Mac with Security
     // Transforms or CDSA/CSSM and on all other platforms we verify with NSS. So
     // on Windows and Mac we use an exported DER file and on other platforms we
     // use the NSS config db.
     if (mozinfo.os == "win" || mozinfo.os == "mac") {
       if (certs.length == 1 && useShortHandCmdLine) {
         args.push("-D", "data/" + certs[0] + ".der");
       } else {
-        for (var i = 0; i < certs.length; i++) {
+        for (let i = 0; i < certs.length; i++) {
           args.push("-D" + i, "data/" + certs[i] + ".der");
         }
       }
     } else {
       let NSSConfigDir = do_get_file("data");
       args = ["-d", NSSConfigDir.path];
       if (certs.length == 1 && useShortHandCmdLine) {
         args.push("-n", certs[0]);
       } else {
-        for (var i = 0; i < certs.length; i++) {
+        for (let i = 0; i < certs.length; i++) {
           args.push("-n" + i, certs[i]);
         }
       }
     }
     args.push("-v", signedMAR.path);
 
+    let exitValue;
     process.init(signmarBin);
     try {
       // We put this in a try block because nsIProcess doesn't like -1 returns
       process.run(true, args, args.length);
+      exitValue = process.exitValue;
     } catch (e) {
       // On Windows negative return value throws an exception
-      process.exitValue = -1;
+      exitValue = -1;
     }
 
     // Verify signmar returned 0 for success.
     if (wantSuccess) {
-      do_check_eq(process.exitValue, 0);
+      do_check_eq(exitValue, 0);
     } else {
-      do_check_neq(process.exitValue, 0);
+      do_check_neq(exitValue, 0);
     }
   }
 
   /**
    * Strips a MAR signature.
    *
    * @param signedMAR The MAR file that should be signed
    * @param outMAR The MAR file to write to with signature stripped
-  */
+   */
   function stripMARSignature(signedMAR, outMAR, wantSuccess) {
     // Get a process to the signmar binary from the dist/bin directory.
     let process = Cc["@mozilla.org/process/util;1"].
                   createInstance(Ci.nsIProcess);
     let signmarBin = do_get_file("signmar" + BIN_SUFFIX);
 
     // Make sure the signmar binary exists and is an executable.
     do_check_true(signmarBin.exists());
     do_check_true(signmarBin.isExecutable());
 
     // Setup the command line arguments to create the MAR.
     let args = ["-r", signedMAR.path, outMAR.path];
 
+    let exitValue;
     process.init(signmarBin);
     try {
       process.run(true, args, args.length);
+      exitValue = process.exitValue;
     } catch (e) {
       // On Windows negative return value throws an exception
-      process.exitValue = -1;
+      exitValue = -1;
     }
 
     // Verify signmar returned 0 for success.
     if (wantSuccess) {
-      do_check_eq(process.exitValue, 0);
+      do_check_eq(exitValue, 0);
     } else {
-      do_check_neq(process.exitValue, 0);
+      do_check_neq(exitValue, 0);
     }
   }
 
-
   function cleanup() {
     let outMAR = tempDir.clone();
     outMAR.append("signed_out.mar");
     if (outMAR.exists()) {
       outMAR.remove(false);
     }
     outMAR = tempDir.clone();
     outMAR.append("multiple_signed_out.mar");
@@ -246,328 +254,325 @@ function run_test() {
     }
   }
 
   const wantFailure = false;
   const wantSuccess = true;
   // Define the unit tests to run.
   let tests = {
     // Test signing a MAR file with a single signature
-    test_sign_single: function() {
-      let inMAR = do_get_file("data/" + refMARPrefix + "binary_data_mar.mar");
+    test_sign_single: function _test_sign_single() {
+      let inMAR = do_get_file("data/binary_data.mar");
       let outMAR = tempDir.clone();
       outMAR.append("signed_out.mar");
       if (outMAR.exists()) {
         outMAR.remove(false);
       }
       signMAR(inMAR, outMAR, ["mycert"], wantSuccess, true);
       do_check_true(outMAR.exists());
       let outMARData = getBinaryFileData(outMAR);
-      let refMAR = do_get_file("data/" + refMARPrefix + "signed_pib_mar.mar");
+      let refMAR = do_get_file("data/signed_pib.mar");
       let refMARData = getBinaryFileData(refMAR);
       compareBinaryData(outMARData, refMARData);
-    }, 
+    },
     // Test signing a MAR file with multiple signatures
-    test_sign_multiple: function() {
-      let inMAR = do_get_file("data/" + refMARPrefix + "binary_data_mar.mar");
+    test_sign_multiple: function _test_sign_multiple() {
+      let inMAR = do_get_file("data/binary_data.mar");
       let outMAR = tempDir.clone();
       outMAR.append("multiple_signed_out.mar");
       if (outMAR.exists()) {
         outMAR.remove(false);
       }
       do_check_false(outMAR.exists());
       signMAR(inMAR, outMAR, ["mycert", "mycert2", "mycert3"],
               wantSuccess, true);
       do_check_true(outMAR.exists());
       let outMARData = getBinaryFileData(outMAR);
-      let refMAR = do_get_file("data/" + refMARPrefix + "multiple_signed_pib_mar.mar");
+      let refMAR = do_get_file("data/multiple_signed_pib.mar");
       let refMARData = getBinaryFileData(refMAR);
       compareBinaryData(outMARData, refMARData);
     },
     // Test verifying a signed MAR file
-    test_verify_single: function() {
-      let signedMAR = do_get_file("data/signed_pib_mar.mar");
+    test_verify_single: function _test_verify_single() {
+      let signedMAR = do_get_file("data/signed_pib.mar");
       verifyMAR(signedMAR, wantSuccess, ["mycert"], true);
       verifyMAR(signedMAR, wantSuccess, ["mycert"], false);
-    }, 
+    },
     // Test verifying a signed MAR file with too many certs fails.
     // Or if you want to look at it another way, One mycert signature
     // is missing.
-    test_verify_single_too_many_certs: function() {
-      let signedMAR = do_get_file("data/signed_pib_mar.mar");
+    test_verify_single_too_many_certs: function _test_verify_single_too_many_certs() {
+      let signedMAR = do_get_file("data/signed_pib.mar");
       verifyMAR(signedMAR, wantFailure, ["mycert", "mycert"], true);
       verifyMAR(signedMAR, wantFailure, ["mycert", "mycert"], false);
     },
     // Test verifying a signed MAR file fails when using a wrong cert
-    test_verify_single_wrong_cert: function() {
-      let signedMAR = do_get_file("data/signed_pib_mar.mar");
+    test_verify_single_wrong_cert: function _test_verify_single_wrong_cert() {
+      let signedMAR = do_get_file("data/signed_pib.mar");
       verifyMAR(signedMAR, wantFailure, ["mycert2"], true);
       verifyMAR(signedMAR, wantFailure, ["mycert2"], false);
     },
     // Test verifying a signed MAR file with multiple signatures
-    test_verify_multiple: function() {
-      let signedMAR = do_get_file("data/multiple_signed_pib_mar.mar");
+    test_verify_multiple: function _test_verify_multiple() {
+      let signedMAR = do_get_file("data/multiple_signed_pib.mar");
       verifyMAR(signedMAR, wantSuccess, ["mycert", "mycert2", "mycert3"]);
     },
     // Test verifying an unsigned MAR file fails
-    test_verify_unsigned_mar_file_fails: function() {
-      let unsignedMAR = do_get_file("data/binary_data_mar.mar");
+    test_verify_unsigned_mar_file_fails: function _test_verify_unsigned_mar_file_fails() {
+      let unsignedMAR = do_get_file("data/binary_data.mar");
       verifyMAR(unsignedMAR, wantFailure, ["mycert", "mycert2", "mycert3"]);
     },
     // Test verifying a signed MAR file with the same signature multiple
     // times fails.  The input MAR has: mycert, mycert2, mycert3.
     // we're checking to make sure the number of verified signatures
     // is only 1 and not 3.  Each signature should be verified once.
-    test_verify_multiple_same_cert: function() {
-      let signedMAR = do_get_file("data/multiple_signed_pib_mar.mar");
+    test_verify_multiple_same_cert: function _test_verify_multiple_same_cert() {
+      let signedMAR = do_get_file("data/multiple_signed_pib.mar");
       verifyMAR(signedMAR, wantFailure, ["mycert", "mycert", "mycert"]);
     },
     // Test verifying a signed MAR file with the correct signatures but in
     // a different order fails
-    test_verify_multiple_wrong_order: function() {
-      let signedMAR = do_get_file("data/multiple_signed_pib_mar.mar");
+    test_verify_multiple_wrong_order: function _test_verify_multiple_wrong_order() {
+      let signedMAR = do_get_file("data/multiple_signed_pib.mar");
       verifyMAR(signedMAR, wantSuccess, ["mycert", "mycert2", "mycert3"]);
       verifyMAR(signedMAR, wantFailure, ["mycert", "mycert3", "mycert2"]);
       verifyMAR(signedMAR, wantFailure, ["mycert2", "mycert", "mycert3"]);
       verifyMAR(signedMAR, wantFailure, ["mycert2", "mycert3", "mycert"]);
       verifyMAR(signedMAR, wantFailure, ["mycert3", "mycert", "mycert2"]);
       verifyMAR(signedMAR, wantFailure, ["mycert3", "mycert2", "mycert"]);
     },
     // Test verifying a signed MAR file without a PIB
-    test_verify_no_pib: function() {
-      let signedMAR = do_get_file("data/signed_no_pib_mar.mar");
+    test_verify_no_pib: function _test_verify_no_pib() {
+      let signedMAR = do_get_file("data/signed_no_pib.mar");
       verifyMAR(signedMAR, wantSuccess, ["mycert"], true);
       verifyMAR(signedMAR, wantSuccess, ["mycert"], false);
-    }, 
+    },
     // Test verifying a signed MAR file with multiple signatures without a PIB
-    test_verify_no_pib_multiple: function() {
-      let signedMAR = do_get_file("data/multiple_signed_no_pib_mar.mar");
+    test_verify_no_pib_multiple: function _test_verify_no_pib_multiple() {
+      let signedMAR = do_get_file("data/multiple_signed_no_pib.mar");
       verifyMAR(signedMAR, wantSuccess, ["mycert", "mycert2", "mycert3"]);
     },
     // Test verifying a crafted MAR file where the attacker tried to adjust
     // the version number manually.
-    test_crafted_mar: function() {
-      let signedBadMAR = do_get_file("data/manipulated_signed_mar.mar");
+    test_crafted_mar: function _test_crafted_mar() {
+      let signedBadMAR = do_get_file("data/manipulated_signed.mar");
       verifyMAR(signedBadMAR, wantFailure, ["mycert"], true);
       verifyMAR(signedBadMAR, wantFailure, ["mycert"], false);
-    }, 
+    },
     // Test verifying a file that doesn't exist fails
-    test_bad_path_verify_fails: function() {
-      let noMAR = do_get_file("data/does_not_exist_.mar", true);
+    test_bad_path_verify_fails: function _test_bad_path_verify_fails() {
+      let noMAR = do_get_file("data/does_not_exist.mar", true);
       do_check_false(noMAR.exists());
       verifyMAR(noMAR, wantFailure, ["mycert"], true);
     },
     // Test to make sure a stripped MAR is the same as the original MAR
-    test_strip_signature: function() {
-      let originalMAR = do_get_file("data/" + 
-                                    refMARPrefix + 
-                                    "binary_data_mar.mar");
+    test_strip_signature: function _test_strip_signature() {
+      let originalMAR = do_get_file("data/binary_data.mar");
       let signedMAR = tempDir.clone();
       signedMAR.append("signed_out.mar");
       let outMAR = tempDir.clone();
       outMAR.append("out.mar", true);
       stripMARSignature(signedMAR, outMAR, wantSuccess);
 
       // Verify that the stripped MAR matches the original data MAR exactly
       let outMARData = getBinaryFileData(outMAR);
       let originalMARData = getBinaryFileData(originalMAR);
       compareBinaryData(outMARData, originalMARData);
     },
     // Test to make sure a stripped multi-signature-MAR is the same as the original MAR
-    test_strip_multiple_signatures: function() {
-      let originalMAR = do_get_file("data/" +
-                                    refMARPrefix +
-                                    "binary_data_mar.mar");
+    test_strip_multiple_signatures: function _test_strip_multiple_signatures() {
+      let originalMAR = do_get_file("data/binary_data.mar");
       let signedMAR = tempDir.clone();
       signedMAR.append("multiple_signed_out.mar");
       let outMAR = tempDir.clone();
       outMAR.append("out.mar");
       stripMARSignature(signedMAR, outMAR, wantSuccess);
 
       // Verify that the stripped MAR matches the original data MAR exactly
       let outMARData = getBinaryFileData(outMAR);
       let originalMARData = getBinaryFileData(originalMAR);
       compareBinaryData(outMARData, originalMARData);
     },
     // Test extracting the first signature in a MAR that has only a single signature
-    test_extract_sig_single: function() {
-      let inMAR = do_get_file("data/signed_pib_mar.mar");
+    test_extract_sig_single: function _test_extract_sig_single() {
+      let inMAR = do_get_file("data/signed_pib.mar");
       let extractedSig = do_get_file("extracted_signature", true);
       if (extractedSig.exists()) {
         extractedSig.remove(false);
       }
       extractMARSignature(inMAR, 0, extractedSig, wantSuccess);
       do_check_true(extractedSig.exists());
 
-      let referenceSig = do_get_file("data/signed_pib_mar.signature.0"); +
+      let referenceSig = do_get_file("data/signed_pib_mar.signature.0");
       compareBinaryData(extractedSig, referenceSig);
     },
     // Test extracting the all signatures in a multi signature MAR
     // The input MAR has 3 signatures.
-    test_extract_sig_multi: function() {
+    test_extract_sig_multi: function _test_extract_sig_multi() {
       for (let i = 0; i < 3; i++) {
-        let inMAR = do_get_file("data/multiple_signed_pib_mar.mar");
+        let inMAR = do_get_file("data/multiple_signed_pib.mar");
         let extractedSig = do_get_file("extracted_signature", true);
         if (extractedSig.exists()) {
           extractedSig.remove(false);
         }
         extractMARSignature(inMAR, i, extractedSig, wantSuccess);
         do_check_true(extractedSig.exists());
 
-        let referenceSig = do_get_file("data/multiple_signed_pib_mar.sig." + i); +
+        let referenceSig = do_get_file("data/multiple_signed_pib_mar.sig." + i);
         compareBinaryData(extractedSig, referenceSig);
       }
     },
     // Test extracting a signature that is out of range fails
-    test_extract_sig_out_of_range: function() {
-      let inMAR = do_get_file("data/signed_pib_mar.mar");
+    test_extract_sig_out_of_range: function _test_extract_sig_out_of_range() {
+      let inMAR = do_get_file("data/signed_pib.mar");
       let extractedSig = do_get_file("extracted_signature", true);
       if (extractedSig.exists()) {
         extractedSig.remove(false);
       }
       const outOfBoundsIndex = 5;
       extractMARSignature(inMAR, outOfBoundsIndex, extractedSig, wantFailure);
       do_check_false(extractedSig.exists());
     },
     // Test signing a file that doesn't exist fails
-    test_bad_path_sign_fails: function() {
-      let inMAR = do_get_file("data/does_not_exist_.mar", true);
+    test_bad_path_sign_fails: function _test_bad_path_sign_fails() {
+      let inMAR = do_get_file("data/does_not_exist.mar", true);
       let outMAR = tempDir.clone();
       outMAR.append("signed_out.mar");
       do_check_false(inMAR.exists());
       signMAR(inMAR, outMAR, ["mycert"], wantFailure, true);
       do_check_false(outMAR.exists());
     },
     // Test verifying only a subset of the signatures fails.
     // The input MAR has: mycert, mycert2, mycert3.
     // We're only verifying 2 of the 3 signatures and that should fail.
-    test_verify_multiple_subset: function() {
-      let signedMAR = do_get_file("data/multiple_signed_pib_mar.mar");
+    test_verify_multiple_subset: function _test_verify_multiple_subset() {
+      let signedMAR = do_get_file("data/multiple_signed_pib.mar");
       verifyMAR(signedMAR, wantFailure, ["mycert", "mycert2"]);
     },
     // Test importing the first signature in a MAR that has only
     // a single signature
-    test_import_sig_single: function() {
+    test_import_sig_single: function _test_import_sig_single() {
       // Make sure the input MAR was signed with mycert only
-      let inMAR = do_get_file("data/signed_pib_mar.mar");
+      let inMAR = do_get_file("data/signed_pib.mar");
       verifyMAR(inMAR, wantSuccess, ["mycert"], false);
       verifyMAR(inMAR, wantFailure, ["mycert2"], false);
       verifyMAR(inMAR, wantFailure, ["mycert3"], false);
 
       // Get the signature file for this MAR signed with the key from mycert2
       let sigFile = do_get_file("data/signed_pib_mar.signature.mycert2");
       do_check_true(sigFile.exists());
       let outMAR = tempDir.clone();
-      outMAR.append("sigchanged_signed_pib_mar.mar");
+      outMAR.append("sigchanged_signed_pib.mar");
       if (outMAR.exists()) {
         outMAR.remove(false);
       }
 
-      //Run the import operation
+      // Run the import operation
       importMARSignature(inMAR, 0, sigFile, outMAR, wantSuccess);
 
-      // Verify we have a new MAR file and that mycert no longer verifies
-      // and that mycert2 does verify
+      // Verify we have a new MAR file, that mycert no longer verifies and that,
+      // mycert2 does verify
       do_check_true(outMAR.exists());
       verifyMAR(outMAR, wantFailure, ["mycert"], false);
       verifyMAR(outMAR, wantSuccess, ["mycert2"], false);
       verifyMAR(outMAR, wantFailure, ["mycert3"], false);
 
       // Compare the binary data to something that was signed originally
       // with the private key from mycert2
-      let refMAR = do_get_file("data/signed_pib_mar_with_mycert2.mar");
+      let refMAR = do_get_file("data/signed_pib_with_mycert2.mar");
       do_check_true(refMAR.exists());
       let refMARData = getBinaryFileData(refMAR);
       let outMARData = getBinaryFileData(outMAR);
       compareBinaryData(outMARData, refMARData);
     },
     // Test importing a signature that doesn't belong to the file
     // fails to verify.
-    test_import_wrong_sig: function() {
+    test_import_wrong_sig: function _test_import_wrong_sig() {
       // Make sure the input MAR was signed with mycert only
-      let inMAR = do_get_file("data/signed_pib_mar.mar");
+      let inMAR = do_get_file("data/signed_pib.mar");
       verifyMAR(inMAR, wantSuccess, ["mycert"], false);
       verifyMAR(inMAR, wantFailure, ["mycert2"], false);
       verifyMAR(inMAR, wantFailure, ["mycert3"], false);
 
-      // Get the signature file for this MAR signed with the key from mycert2
+      // Get the signature file for multiple_signed_pib.mar signed with the
+      // key from mycert
       let sigFile = do_get_file("data/multiple_signed_pib_mar.sig.0");
       do_check_true(sigFile.exists());
       let outMAR = tempDir.clone();
-      outMAR.append("sigchanged_signed_pib_mar.mar");
+      outMAR.append("sigchanged_signed_pib.mar");
       if (outMAR.exists()) {
         outMAR.remove(false);
       }
 
-      //Run the import operation
+      // Run the import operation
       importMARSignature(inMAR, 0, sigFile, outMAR, wantSuccess);
 
-      // Verify we have a new MAR file and that mycert no longer verifies
-      // and that mycert2 does verify
+      // Verify we have a new MAR file and that the mar file fails to verify
+      // when using a signature for another mar file.
       do_check_true(outMAR.exists());
       verifyMAR(outMAR, wantFailure, ["mycert"], false);
       verifyMAR(outMAR, wantFailure, ["mycert2"], false);
       verifyMAR(outMAR, wantFailure, ["mycert3"], false);
     },
     // Test importing to the second signature in a MAR that has multiple
     // signature
-    test_import_sig_multiple: function() {
+    test_import_sig_multiple: function _test_import_sig_multiple() {
       // Make sure the input MAR was signed with mycert only
-      let inMAR = do_get_file("data/multiple_signed_pib_mar.mar");
+      let inMAR = do_get_file("data/multiple_signed_pib.mar");
       verifyMAR(inMAR, wantSuccess, ["mycert", "mycert2", "mycert3"], false);
       verifyMAR(inMAR, wantFailure, ["mycert", "mycert", "mycert3"], false);
 
       // Get the signature file for this MAR signed with the key from mycert
       let sigFile = do_get_file("data/multiple_signed_pib_mar.sig.0");
       do_check_true(sigFile.exists());
       let outMAR = tempDir.clone();
-      outMAR.append("sigchanged_signed_pib_mar.mar");
+      outMAR.append("sigchanged_signed_pib.mar");
       if (outMAR.exists()) {
         outMAR.remove(false);
       }
 
-      //Run the import operation
+      // Run the import operation
       const secondSigPos = 1;
       importMARSignature(inMAR, secondSigPos, sigFile, outMAR, wantSuccess);
 
       // Verify we have a new MAR file and that mycert no longer verifies
       // and that mycert2 does verify
       do_check_true(outMAR.exists());
       verifyMAR(outMAR, wantSuccess, ["mycert", "mycert", "mycert3"], false);
       verifyMAR(outMAR, wantFailure, ["mycert", "mycert2", "mycert3"], false);
 
       // Compare the binary data to something that was signed originally
       // with the private keys from mycert, mycert, mycert3
-      let refMAR = do_get_file("data/multiple_signed_pib_mar_2.mar");
+      let refMAR = do_get_file("data/multiple_signed_pib_2.mar");
       do_check_true(refMAR.exists());
       let refMARData = getBinaryFileData(refMAR);
       let outMARData = getBinaryFileData(outMAR);
       compareBinaryData(outMARData, refMARData);
     },
-    // Test stripping a MAR that doesn't exist fails 
-    test_bad_path_strip_fails: function() {
-      let noMAR = do_get_file("data/does_not_exist_mar", true);
+    // Test stripping a MAR that doesn't exist fails
+    test_bad_path_strip_fails: function _test_bad_path_strip_fails() {
+      let noMAR = do_get_file("data/does_not_exist.mar", true);
       do_check_false(noMAR.exists());
       let outMAR = tempDir.clone();
       outMAR.append("out.mar");
       stripMARSignature(noMAR, outMAR, wantFailure);
     },
     // Test extracting from a bad path fails
-    test_extract_bad_path: function() {
+    test_extract_bad_path: function _test_extract_bad_path() {
       let noMAR = do_get_file("data/does_not_exist.mar", true);
       let extractedSig = do_get_file("extracted_signature", true);
       do_check_false(noMAR.exists());
       if (extractedSig.exists()) {
         extractedSig.remove(false);
       }
       extractMARSignature(noMAR, 0, extractedSig, wantFailure);
       do_check_false(extractedSig.exists());
     },
     // Between each test make sure the out MAR does not exist.
-    cleanup_per_test: function() {
+    cleanup_per_test: function _cleanup_per_test() {
     }
   };
 
   cleanup();
 
   // Run all the tests
   do_check_eq(run_tests(tests), Object.keys(tests).length - 1);
 
--- a/mozglue/android/APKOpen.cpp
+++ b/mozglue/android/APKOpen.cpp
@@ -64,34 +64,34 @@ extern "C" {
  * depending on the android platform and ndk versions used, it may or may
  * not be defined in libc.so. In the latter case, we fail to link. Defining
  * it here as weak makes us provide the symbol when it's not provided by
  * the crt objects, making the change transparent for future NDKs that
  * would fix the original problem. On older NDKs, it is not a problem
  * either because the way __dso_handle was used was already broken (and
  * the custom linker works around it).
  */
-  NS_EXPORT __attribute__((weak)) void *__dso_handle;
+  APKOPEN_EXPORT __attribute__((weak)) void *__dso_handle;
 }
 
 typedef int mozglueresult;
 
 enum StartupEvent {
 #define mozilla_StartupTimeline_Event(ev, z) ev,
 #include "StartupTimeline.h"
 #undef mozilla_StartupTimeline_Event
   MAX_STARTUP_EVENT_ID
 };
 
 using namespace mozilla;
 
 static const int MAX_MAPPING_INFO = 32;
 static mapping_info lib_mapping[MAX_MAPPING_INFO];
 
-NS_EXPORT const struct mapping_info *
+APKOPEN_EXPORT const struct mapping_info *
 getLibraryMapping()
 {
   return lib_mapping;
 }
 
 void
 JNI_Throw(JNIEnv* jenv, const char* classname, const char* msg)
 {
@@ -149,23 +149,23 @@ abortThroughJava(const char* msg)
 
     if (method && str) {
         env->CallStaticVoidMethod(loader, method, str);
     }
 
     env->PopLocalFrame(nullptr);
 }
 
-NS_EXPORT pthread_t
+APKOPEN_EXPORT pthread_t
 getJavaUiThread()
 {
     return sJavaUiThread;
 }
 
-extern "C" NS_EXPORT void MOZ_JNICALL
+extern "C" APKOPEN_EXPORT void MOZ_JNICALL
 Java_org_mozilla_gecko_GeckoThread_registerUiThread(JNIEnv*, jclass)
 {
     sJavaUiThread = pthread_self();
 }
 
 static void * xul_handle = nullptr;
 #ifndef MOZ_FOLD_LIBS
 static void * sqlite_handle = nullptr;
@@ -320,17 +320,17 @@ loadNSSLibs(const char *apkName)
     __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't get a handle to libplc4!");
     return FAILURE;
   }
 #endif
 
   return setup_nss_functions(nss_handle, nspr_handle, plc_handle);
 }
 
-extern "C" NS_EXPORT void MOZ_JNICALL
+extern "C" APKOPEN_EXPORT void MOZ_JNICALL
 Java_org_mozilla_gecko_mozglue_GeckoLoader_extractGeckoLibsNative(
     JNIEnv *jenv, jclass jGeckoAppShellClass, jstring jApkName)
 {
   MOZ_ALWAYS_TRUE(!jenv->GetJavaVM(&sJavaVM));
 
   const char* apkName = jenv->GetStringUTFChars(jApkName, nullptr);
   if (apkName == nullptr) {
     return;
@@ -345,17 +345,17 @@ Java_org_mozilla_gecko_mozglue_GeckoLoad
     __wrap_dlclose(handle);
   } else {
     JNI_Throw(jenv, "java/lang/Exception", "Error extracting gecko libraries");
   }
 
   jenv->ReleaseStringUTFChars(jApkName, apkName);
 }
 
-extern "C" NS_EXPORT void MOZ_JNICALL
+extern "C" APKOPEN_EXPORT void MOZ_JNICALL
 Java_org_mozilla_gecko_mozglue_GeckoLoader_loadGeckoLibsNative(JNIEnv *jenv, jclass jGeckoAppShellClass, jstring jApkName)
 {
   jenv->GetJavaVM(&sJavaVM);
 
   const char* str;
   // XXX: java doesn't give us true UTF8, we should figure out something
   // better to do here
   str = jenv->GetStringUTFChars(jApkName, nullptr);
@@ -364,17 +364,17 @@ Java_org_mozilla_gecko_mozglue_GeckoLoad
 
   int res = loadGeckoLibs(str);
   if (res != SUCCESS) {
     JNI_Throw(jenv, "java/lang/Exception", "Error loading gecko libraries");
   }
   jenv->ReleaseStringUTFChars(jApkName, str);
 }
 
-extern "C" NS_EXPORT void MOZ_JNICALL
+extern "C" APKOPEN_EXPORT void MOZ_JNICALL
 Java_org_mozilla_gecko_mozglue_GeckoLoader_loadSQLiteLibsNative(JNIEnv *jenv, jclass jGeckoAppShellClass, jstring jApkName) {
   const char* str;
   // XXX: java doesn't give us true UTF8, we should figure out something
   // better to do here
   str = jenv->GetStringUTFChars(jApkName, nullptr);
   if (str == nullptr)
     return;
 
@@ -382,17 +382,17 @@ Java_org_mozilla_gecko_mozglue_GeckoLoad
   mozglueresult rv = loadSQLiteLibs(str);
   if (rv != SUCCESS) {
       JNI_Throw(jenv, "java/lang/Exception", "Error loading sqlite libraries");
   }
   __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Load sqlite done\n");
   jenv->ReleaseStringUTFChars(jApkName, str);
 }
 
-extern "C" NS_EXPORT void MOZ_JNICALL
+extern "C" APKOPEN_EXPORT void MOZ_JNICALL
 Java_org_mozilla_gecko_mozglue_GeckoLoader_loadNSSLibsNative(JNIEnv *jenv, jclass jGeckoAppShellClass, jstring jApkName) {
   const char* str;
   // XXX: java doesn't give us true UTF8, we should figure out something
   // better to do here
   str = jenv->GetStringUTFChars(jApkName, nullptr);
   if (str == nullptr)
     return;
 
@@ -442,17 +442,17 @@ FreeArgv(char** argv, int argc)
     free(argv[ix]);
   }
   delete[](argv);
 }
 
 typedef void (*GeckoStart_t)(JNIEnv*, char**, int, const nsXREAppData*);
 typedef int GeckoProcessType;
 
-extern "C" NS_EXPORT void MOZ_JNICALL
+extern "C" APKOPEN_EXPORT void MOZ_JNICALL
 Java_org_mozilla_gecko_mozglue_GeckoLoader_nativeRun(JNIEnv *jenv, jclass jc, jobjectArray jargs, int crashFd, int ipcFd)
 {
   int argc = 0;
   char** argv = CreateArgvFromObjectArray(jenv, jargs, &argc);
 
   if (ipcFd < 0) {
     GeckoStart_t GeckoStart;
     xul_dlsym("GeckoStart", &GeckoStart);
@@ -480,17 +480,17 @@ Java_org_mozilla_gecko_mozglue_GeckoLoad
 
     XREChildData childData;
     fXRE_InitChildProcess(argc - 1, argv, &childData);
   }
 
   FreeArgv(argv, argc);
 }
 
-extern "C" NS_EXPORT mozglueresult
+extern "C" APKOPEN_EXPORT mozglueresult
 ChildProcessInit(int argc, char* argv[])
 {
   int i;
   for (i = 0; i < (argc - 1); i++) {
     if (strcmp(argv[i], "-greomni"))
       continue;
 
     i = i + 1;
--- a/mozglue/android/APKOpen.h
+++ b/mozglue/android/APKOpen.h
@@ -3,30 +3,30 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef APKOpen_h
 #define APKOpen_h
 
 #include <jni.h>
 #include <pthread.h>
 
-#ifndef NS_EXPORT
-#define NS_EXPORT __attribute__ ((visibility("default")))
+#ifndef APKOPEN_EXPORT
+#define APKOPEN_EXPORT __attribute__ ((visibility("default")))
 #endif
 
 struct mapping_info {
   char * name;
   uintptr_t base;
   size_t len;
   size_t offset;
 };
 
-NS_EXPORT const struct mapping_info * getLibraryMapping();
-NS_EXPORT void abortThroughJava(const char* msg);
-NS_EXPORT pthread_t getJavaUiThread();
+APKOPEN_EXPORT const struct mapping_info * getLibraryMapping();
+APKOPEN_EXPORT void abortThroughJava(const char* msg);
+APKOPEN_EXPORT pthread_t getJavaUiThread();
 
 static const int SUCCESS = 0;
 static const int FAILURE = 1;
 void JNI_Throw(JNIEnv* jenv, const char* classname, const char* msg);
 
 // Bug 1207642 - Work around Dalvik bug by realigning stack on JNI entry
 #ifndef MOZ_JNICALL
 # ifdef __i386__
--- a/mozglue/android/NSSBridge.cpp
+++ b/mozglue/android/NSSBridge.cpp
@@ -83,17 +83,17 @@ throwError(JNIEnv* jenv, const char * fu
     asprintf(&msg, "%s returned error %d: %s\n", funcString, perr, errString);
     LOG("Throwing error: %s\n", msg);
 
     JNI_Throw(jenv, "java/lang/Exception", msg);
     free(msg);
     LOG("Error thrown\n");
 }
 
-extern "C" NS_EXPORT jstring MOZ_JNICALL
+extern "C" APKOPEN_EXPORT jstring MOZ_JNICALL
 Java_org_mozilla_gecko_NSSBridge_nativeEncrypt(JNIEnv* jenv, jclass,
                                                jstring jPath,
                                                jstring jValue)
 {
     jstring ret = jenv->NewStringUTF("");
 
     const char* path;
     path = jenv->GetStringUTFChars(jPath, nullptr);
@@ -109,17 +109,17 @@ Java_org_mozilla_gecko_NSSBridge_nativeE
     }
 
     jenv->ReleaseStringUTFChars(jValue, value);
     jenv->ReleaseStringUTFChars(jPath, path);
 
     return ret;
 }
 
-extern "C" NS_EXPORT jstring MOZ_JNICALL
+extern "C" APKOPEN_EXPORT jstring MOZ_JNICALL
 Java_org_mozilla_gecko_NSSBridge_nativeDecrypt(JNIEnv* jenv, jclass,
                                                jstring jPath,
                                                jstring jValue)
 {
     jstring ret = jenv->NewStringUTF("");
 
     const char* path;
     path = jenv->GetStringUTFChars(jPath, nullptr);
--- a/mozglue/android/SQLiteBridge.cpp
+++ b/mozglue/android/SQLiteBridge.cpp
@@ -131,17 +131,17 @@ JNI_Setup(JNIEnv* jenv)
         || jCursorAddRow == nullptr) {
         throwSqliteException(jenv, "GetMethodId error");
         return;
     }
 
     initialized = true;
 }
 
-extern "C" NS_EXPORT jobject MOZ_JNICALL
+extern "C" APKOPEN_EXPORT jobject MOZ_JNICALL
 Java_org_mozilla_gecko_sqlite_SQLiteBridge_sqliteCall(JNIEnv* jenv, jclass,
                                                       jstring jDb,
                                                       jstring jQuery,
                                                       jobjectArray jParams,
                                                       jlongArray jQueryRes)
 {
     JNI_Setup(jenv);
 
@@ -159,32 +159,32 @@ Java_org_mozilla_gecko_sqlite_SQLiteBrid
         f_sqlite3_close(db); // close db even if open failed
         return nullptr;
     }
     jCursor = sqliteInternalCall(jenv, db, jQuery, jParams, jQueryRes);
     f_sqlite3_close(db);
     return jCursor;
 }
 
-extern "C" NS_EXPORT jobject MOZ_JNICALL
+extern "C" APKOPEN_EXPORT jobject MOZ_JNICALL
 Java_org_mozilla_gecko_sqlite_SQLiteBridge_sqliteCallWithDb(JNIEnv* jenv, jclass,
                                                             jlong jDb,
                                                             jstring jQuery,
                                                             jobjectArray jParams,
                                                             jlongArray jQueryRes)
 {
     JNI_Setup(jenv);
 
     jobject jCursor = nullptr;
     sqlite3 *db = (sqlite3*)jDb;
     jCursor = sqliteInternalCall(jenv, db, jQuery, jParams, jQueryRes);
     return jCursor;
 }
 
-extern "C" NS_EXPORT jlong MOZ_JNICALL
+extern "C" APKOPEN_EXPORT jlong MOZ_JNICALL
 Java_org_mozilla_gecko_sqlite_SQLiteBridge_openDatabase(JNIEnv* jenv, jclass,
                                                         jstring jDb)
 {
     JNI_Setup(jenv);
 
     int rc;
     const char* dbPath;
     sqlite3 *db;
@@ -196,17 +196,17 @@ Java_org_mozilla_gecko_sqlite_SQLiteBrid
         throwSqliteException(jenv,
             "Can't open database: %s", f_sqlite3_errmsg(db));
         f_sqlite3_close(db); // close db even if open failed
         return 0;
     }
     return (jlong)db;
 }
 
-extern "C" NS_EXPORT void MOZ_JNICALL
+extern "C" APKOPEN_EXPORT void MOZ_JNICALL
 Java_org_mozilla_gecko_sqlite_SQLiteBridge_closeDatabase(JNIEnv* jenv, jclass,
                                                         jlong jDb)
 {
     JNI_Setup(jenv);
 
     sqlite3 *db = (sqlite3*)jDb;
     f_sqlite3_close(db);
 }
--- a/netwerk/base/nsUDPSocket.cpp
+++ b/netwerk/base/nsUDPSocket.cpp
@@ -259,23 +259,21 @@ nsUDPSocket::nsUDPSocket()
   if (!gSocketTransportService)
   {
     // This call can fail if we're offline, for example.
     nsCOMPtr<nsISocketTransportService> sts =
         do_GetService(kSocketTransportServiceCID2);
   }
 
   mSts = gSocketTransportService;
-  MOZ_COUNT_CTOR(nsUDPSocket);
 }
 
 nsUDPSocket::~nsUDPSocket()
 {
   CloseSocket();
-  MOZ_COUNT_DTOR(nsUDPSocket);
 }
 
 void
 nsUDPSocket::AddOutputBytes(uint64_t aBytes)
 {
   mByteWriteCount += aBytes;
 }
 
--- a/netwerk/cache2/AppCacheStorage.cpp
+++ b/netwerk/cache2/AppCacheStorage.cpp
@@ -23,23 +23,21 @@ namespace net {
 
 NS_IMPL_ISUPPORTS_INHERITED0(AppCacheStorage, CacheStorage)
 
 AppCacheStorage::AppCacheStorage(nsILoadContextInfo* aInfo,
                                  nsIApplicationCache* aAppCache)
 : CacheStorage(aInfo, true /* disk */, false /* lookup app cache */, false /* skip size check */, false /* pin */)
 , mAppCache(aAppCache)
 {
-  MOZ_COUNT_CTOR(AppCacheStorage);
 }
 
 AppCacheStorage::~AppCacheStorage()
 {
   ProxyReleaseMainThread(mAppCache);
-  MOZ_COUNT_DTOR(AppCacheStorage);
 }
 
 NS_IMETHODIMP AppCacheStorage::AsyncOpenURI(nsIURI *aURI,
                                             const nsACString & aIdExtension,
                                             uint32_t aFlags,
                                             nsICacheEntryOpenCallback *aCallback)
 {
   if (!CacheStorageService::Self())
--- a/netwerk/cache2/CacheEntry.cpp
+++ b/netwerk/cache2/CacheEntry.cpp
@@ -43,18 +43,16 @@ static uint32_t const ENTRY_NOT_WANTED =
 
 NS_IMPL_ISUPPORTS(CacheEntryHandle, nsICacheEntry)
 
 // CacheEntryHandle
 
 CacheEntryHandle::CacheEntryHandle(CacheEntry* aEntry)
 : mEntry(aEntry)
 {
-  MOZ_COUNT_CTOR(CacheEntryHandle);
-
 #ifdef DEBUG
   if (!mEntry->HandlesCount()) {
     // CacheEntry.mHandlesCount must go from zero to one only under
     // the service lock. Can access CacheStorageService::Self() w/o a check
     // since CacheEntry hrefs it.
     CacheStorageService::Self()->Lock().AssertCurrentThreadOwns();
   }
 #endif
@@ -63,18 +61,16 @@ CacheEntryHandle::CacheEntryHandle(Cache
 
   LOG(("New CacheEntryHandle %p for entry %p", this, aEntry));
 }
 
 CacheEntryHandle::~CacheEntryHandle()
 {
   mEntry->ReleaseHandleRef();
   mEntry->OnHandleClosed(this);
-
-  MOZ_COUNT_DTOR(CacheEntryHandle);
 }
 
 // CacheEntry::Callback
 
 CacheEntry::Callback::Callback(CacheEntry* aEntry,
                                nsICacheEntryOpenCallback *aCallback,
                                bool aReadOnly, bool aCheckOnAnyThread,
                                bool aSecret)
@@ -1859,22 +1855,20 @@ void CacheEntry::StoreFrecency(double aF
   }
 }
 
 // CacheOutputCloseListener
 
 CacheOutputCloseListener::CacheOutputCloseListener(CacheEntry* aEntry)
 : mEntry(aEntry)
 {
-  MOZ_COUNT_CTOR(CacheOutputCloseListener);
 }
 
 CacheOutputCloseListener::~CacheOutputCloseListener()
 {
-  MOZ_COUNT_DTOR(CacheOutputCloseListener);
 }
 
 void CacheOutputCloseListener::OnOutputClosed()
 {
   // We need this class and to redispatch since this callback is invoked
   // under the file's lock and to do the job we need to enter the entry's
   // lock too.  That would lead to potential deadlocks.
   NS_DispatchToCurrentThread(this);
--- a/netwerk/cache2/CacheFile.cpp
+++ b/netwerk/cache2/CacheFile.cpp
@@ -34,25 +34,23 @@ public:
                                nsresult aResult,
                                bool aIsNew)
     : mCallback(aCallback)
     , mRV(aResult)
     , mIsNew(aIsNew)
   {
     LOG(("NotifyCacheFileListenerEvent::NotifyCacheFileListenerEvent() "
          "[this=%p]", this));
-    MOZ_COUNT_CTOR(NotifyCacheFileListenerEvent);
   }
 
 protected:
   ~NotifyCacheFileListenerEvent()
   {
     LOG(("NotifyCacheFileListenerEvent::~NotifyCacheFileListenerEvent() "
          "[this=%p]", this));
-    MOZ_COUNT_DTOR(NotifyCacheFileListenerEvent);
   }
 
 public:
   NS_IMETHOD Run() override
   {
     LOG(("NotifyCacheFileListenerEvent::Run() [this=%p]", this));
 
     mCallback->OnFileReady(mRV, mIsNew);
@@ -73,25 +71,23 @@ public:
                            CacheFileChunk *aChunk)
     : mCallback(aCallback)
     , mRV(aResult)
     , mChunkIdx(aChunkIdx)
     , mChunk(aChunk)
   {
     LOG(("NotifyChunkListenerEvent::NotifyChunkListenerEvent() [this=%p]",
          this));
-    MOZ_COUNT_CTOR(NotifyChunkListenerEvent);
   }
 
 protected:
   ~NotifyChunkListenerEvent()
   {
     LOG(("NotifyChunkListenerEvent::~NotifyChunkListenerEvent() [this=%p]",
          this));
-    MOZ_COUNT_DTOR(NotifyChunkListenerEvent);
   }
 
 public:
   NS_IMETHOD Run() override
   {
     LOG(("NotifyChunkListenerEvent::Run() [this=%p]", this));
 
     mCallback->OnChunkAvailable(mRV, mChunkIdx, mChunk);
@@ -109,17 +105,16 @@ protected:
 class DoomFileHelper : public CacheFileIOListener
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
 
   explicit DoomFileHelper(CacheFileListener *aListener)
     : mListener(aListener)
   {
-    MOZ_COUNT_CTOR(DoomFileHelper);
   }
 
 
   NS_IMETHOD OnFileOpened(CacheFileHandle *aHandle, nsresult aResult) override
   {
     MOZ_CRASH("DoomFileHelper::OnFileOpened should not be called!");
     return NS_ERROR_UNEXPECTED;
   }
@@ -154,17 +149,16 @@ public:
   {
     MOZ_CRASH("DoomFileHelper::OnFileRenamed should not be called!");
     return NS_ERROR_UNEXPECTED;
   }
 
 private:
   virtual ~DoomFileHelper()
   {
-    MOZ_COUNT_DTOR(DoomFileHelper);
   }
 
   nsCOMPtr<CacheFileListener>  mListener;
 };
 
 NS_IMPL_ISUPPORTS(DoomFileHelper, CacheFileIOListener)
 
 
--- a/netwerk/cache2/CacheFileChunk.cpp
+++ b/netwerk/cache2/CacheFileChunk.cpp
@@ -246,25 +246,23 @@ class NotifyUpdateListenerEvent : public
 public:
   NotifyUpdateListenerEvent(CacheFileChunkListener *aCallback,
                             CacheFileChunk *aChunk)
     : mCallback(aCallback)
     , mChunk(aChunk)
   {
     LOG(("NotifyUpdateListenerEvent::NotifyUpdateListenerEvent() [this=%p]",
          this));
-    MOZ_COUNT_CTOR(NotifyUpdateListenerEvent);
   }
 
 protected:
   ~NotifyUpdateListenerEvent()
   {
     LOG(("NotifyUpdateListenerEvent::~NotifyUpdateListenerEvent() [this=%p]",
          this));
-    MOZ_COUNT_DTOR(NotifyUpdateListenerEvent);
   }
 
 public:
   NS_IMETHOD Run() override
   {
     LOG(("NotifyUpdateListenerEvent::Run() [this=%p]", this));
 
     mCallback->OnChunkUpdated(mChunk);
@@ -342,25 +340,22 @@ CacheFileChunk::CacheFileChunk(CacheFile
   , mBuffersSize(0)
   , mLimitAllocation(!aFile->mOpenAsMemoryOnly && aInitByWriter)
   , mIsPriority(aFile->mPriority)
   , mExpectedHash(0)
   , mFile(aFile)
 {
   LOG(("CacheFileChunk::CacheFileChunk() [this=%p, index=%u, initByWriter=%d]",
        this, aIndex, aInitByWriter));
-  MOZ_COUNT_CTOR(CacheFileChunk);
-
   mBuf = new CacheFileChunkBuffer(this);
 }
 
 CacheFileChunk::~CacheFileChunk()
 {
   LOG(("CacheFileChunk::~CacheFileChunk() [this=%p]", this));
-  MOZ_COUNT_DTOR(CacheFileChunk);
 }
 
 void
 CacheFileChunk::AssertOwnsLock() const
 {
   mFile->AssertOwnsLock();
 }
 
--- a/netwerk/cache2/CacheFileIOManager.cpp
+++ b/netwerk/cache2/CacheFileIOManager.cpp
@@ -540,23 +540,21 @@ CacheFileHandles::SizeOfExcludingThis(mo
 // Events
 
 class ShutdownEvent : public Runnable {
 public:
   ShutdownEvent()
     : mMonitor("ShutdownEvent.mMonitor")
     , mNotified(false)
   {
-    MOZ_COUNT_CTOR(ShutdownEvent);
   }
 
 protected:
   ~ShutdownEvent()
   {
-    MOZ_COUNT_DTOR(ShutdownEvent);
   }
 
 public:
   NS_IMETHOD Run() override
   {
     MonitorAutoLock mon(mMonitor);
 
     CacheFileIOManager::gInstance->ShutdownInternal();
@@ -596,24 +594,22 @@ protected:
 class OpenFileEvent : public Runnable {
 public:
   OpenFileEvent(const nsACString &aKey, uint32_t aFlags,
                 CacheFileIOListener *aCallback)
     : mFlags(aFlags)
     , mCallback(aCallback)
     , mKey(aKey)
   {
-    MOZ_COUNT_CTOR(OpenFileEvent);
     mIOMan = CacheFileIOManager::gInstance;
   }
 
 protected:
   ~OpenFileEvent()
   {
-    MOZ_COUNT_DTOR(OpenFileEvent);
   }
 
 public:
   NS_IMETHOD Run() override
   {
     nsresult rv = NS_OK;
 
     if (!(mFlags & CacheFileIOManager::SPECIAL_FILE)) {
@@ -658,23 +654,21 @@ public:
   ReadEvent(CacheFileHandle *aHandle, int64_t aOffset, char *aBuf,
             int32_t aCount, CacheFileIOListener *aCallback)
     : mHandle(aHandle)
     , mOffset(aOffset)
     , mBuf(aBuf)
     , mCount(aCount)
     , mCallback(aCallback)
   {
-    MOZ_COUNT_CTOR(ReadEvent);
   }
 
 protected:
   ~ReadEvent()
   {
-    MOZ_COUNT_DTOR(ReadEvent);
   }
 
 public:
   NS_IMETHOD Run() override
   {
     nsresult rv;
 
     if (mHandle->IsClosed() || (mCallback && mCallback->IsKilled())) {
@@ -704,24 +698,21 @@ public:
     : mHandle(aHandle)
     , mOffset(aOffset)
     , mBuf(aBuf)
     , mCount(aCount)
     , mValidate(aValidate)
     , mTruncate(aTruncate)
     , mCallback(aCallback)
   {
-    MOZ_COUNT_CTOR(WriteEvent);
   }
 
 protected:
   ~WriteEvent()
   {
-    MOZ_COUNT_DTOR(WriteEvent);
-
     if (!mCallback && mBuf) {
       free(const_cast<char *>(mBuf));
     }
   }
 
 public:
   NS_IMETHOD Run() override
   {
@@ -765,23 +756,21 @@ protected:
 
 class DoomFileEvent : public Runnable {
 public:
   DoomFileEvent(CacheFileHandle *aHandle,
                 CacheFileIOListener *aCallback)
     : mCallback(aCallback)
     , mHandle(aHandle)
   {
-    MOZ_COUNT_CTOR(DoomFileEvent);
   }
 
 protected:
   ~DoomFileEvent()
   {
-    MOZ_COUNT_DTOR(DoomFileEvent);
   }
 
 public:
   NS_IMETHOD Run() override
   {
     nsresult rv;
 
     if (mHandle->IsClosed()) {
@@ -804,29 +793,26 @@ protected:
 };
 
 class DoomFileByKeyEvent : public Runnable {
 public:
   DoomFileByKeyEvent(const nsACString &aKey,
                      CacheFileIOListener *aCallback)
     : mCallback(aCallback)
   {
-    MOZ_COUNT_CTOR(DoomFileByKeyEvent);
-
     SHA1Sum sum;
     sum.update(aKey.BeginReading(), aKey.Length());
     sum.finish(mHash);
 
     mIOMan = CacheFileIOManager::gInstance;
   }
 
 protected:
   ~DoomFileByKeyEvent()
   {
-    MOZ_COUNT_DTOR(DoomFileByKeyEvent);
   }
 
 public:
   NS_IMETHOD Run() override
   {
     nsresult rv;
 
     if (!mIOMan) {
@@ -849,23 +835,21 @@ protected:
   RefPtr<CacheFileIOManager>    mIOMan;
 };
 
 class ReleaseNSPRHandleEvent : public Runnable {
 public:
   explicit ReleaseNSPRHandleEvent(CacheFileHandle *aHandle)
     : mHandle(aHandle)
   {
-    MOZ_COUNT_CTOR(ReleaseNSPRHandleEvent);
   }
 
 protected:
   ~ReleaseNSPRHandleEvent()
   {
-    MOZ_COUNT_DTOR(ReleaseNSPRHandleEvent);
   }
 
 public:
   NS_IMETHOD Run() override
   {
     if (!mHandle->IsClosed()) {
       CacheFileIOManager::gInstance->MaybeReleaseNSPRHandleInternal(mHandle);
     }
@@ -881,23 +865,21 @@ class TruncateSeekSetEOFEvent : public R
 public:
   TruncateSeekSetEOFEvent(CacheFileHandle *aHandle, int64_t aTruncatePos,
                           int64_t aEOFPos, CacheFileIOListener *aCallback)
     : mHandle(aHandle)
     , mTruncatePos(aTruncatePos)
     , mEOFPos(aEOFPos)
     , mCallback(aCallback)
   {
-    MOZ_COUNT_CTOR(TruncateSeekSetEOFEvent);
   }
 
 protected:
   ~TruncateSeekSetEOFEvent()
   {
-    MOZ_COUNT_DTOR(TruncateSeekSetEOFEvent);
   }
 
 public:
   NS_IMETHOD Run() override
   {
     nsresult rv;
 
     if (mHandle->IsClosed() || (mCallback && mCallback->IsKilled())) {
@@ -924,23 +906,21 @@ protected:
 class RenameFileEvent : public Runnable {
 public:
   RenameFileEvent(CacheFileHandle *aHandle, const nsACString &aNewName,
                   CacheFileIOListener *aCallback)
     : mHandle(aHandle)
     , mNewName(aNewName)
     , mCallback(aCallback)
   {
-    MOZ_COUNT_CTOR(RenameFileEvent);
   }
 
 protected:
   ~RenameFileEvent()
   {
-    MOZ_COUNT_DTOR(RenameFileEvent);
   }
 
 public:
   NS_IMETHOD Run() override
   {
     nsresult rv;
 
     if (mHandle->IsClosed()) {
@@ -968,23 +948,21 @@ public:
   InitIndexEntryEvent(CacheFileHandle *aHandle,
                       OriginAttrsHash aOriginAttrsHash, bool aAnonymous,
                       bool aPinning)
     : mHandle(aHandle)
     , mOriginAttrsHash(aOriginAttrsHash)
     , mAnonymous(aAnonymous)
     , mPinning(aPinning)
   {
-    MOZ_COUNT_CTOR(InitIndexEntryEvent);
   }
 
 protected:
   ~InitIndexEntryEvent()
   {
-    MOZ_COUNT_DTOR(InitIndexEntryEvent);
   }
 
 public:
   NS_IMETHOD Run() override
   {
     if (mHandle->IsClosed() || mHandle->IsDoomed()) {
       return NS_OK;
     }
@@ -1012,31 +990,29 @@ protected:
 class UpdateIndexEntryEvent : public Runnable {
 public:
   UpdateIndexEntryEvent(CacheFileHandle *aHandle, const uint32_t *aFrecency,
                         const uint32_t *aExpirationTime)
     : mHandle(aHandle)
     , mHasFrecency(false)
     , mHasExpirationTime(false)
   {
-    MOZ_COUNT_CTOR(UpdateIndexEntryEvent);
     if (aFrecency) {
       mHasFrecency = true;
       mFrecency = *aFrecency;
     }
     if (aExpirationTime) {
       mHasExpirationTime = true;
       mExpirationTime = *aExpirationTime;
     }
   }
 
 protected:
   ~UpdateIndexEntryEvent()
   {
-    MOZ_COUNT_DTOR(UpdateIndexEntryEvent);
   }
 
 public:
   NS_IMETHOD Run() override
   {
     if (mHandle->IsClosed() || mHandle->IsDoomed()) {
       return NS_OK;
     }
@@ -1109,24 +1085,22 @@ NS_IMPL_ISUPPORTS(CacheFileIOManager, ns
 CacheFileIOManager::CacheFileIOManager()
   : mShuttingDown(false)
   , mTreeCreated(false)
   , mTreeCreationFailed(false)
   , mOverLimitEvicting(false)
   , mRemovingTrashDirs(false)
 {
   LOG(("CacheFileIOManager::CacheFileIOManager [this=%p]", this));
-  MOZ_COUNT_CTOR(CacheFileIOManager);
   MOZ_ASSERT(!gInstance, "multiple CacheFileIOManager instances!");
 }
 
 CacheFileIOManager::~CacheFileIOManager()
 {
   LOG(("CacheFileIOManager::~CacheFileIOManager [this=%p]", this));
-  MOZ_COUNT_DTOR(CacheFileIOManager);
 }
 
 // static
 nsresult
 CacheFileIOManager::Init()
 {
   LOG(("CacheFileIOManager::Init()"));
 
--- a/netwerk/cache2/CacheFileInputStream.cpp
+++ b/netwerk/cache2/CacheFileInputStream.cpp
@@ -52,27 +52,25 @@ CacheFileInputStream::CacheFileInputStre
   , mInReadSegments(false)
   , mWaitingForUpdate(false)
   , mAlternativeData(aAlternativeData)
   , mListeningForChunk(-1)
   , mCallbackFlags(0)
   , mCacheEntryHandle(aEntry)
 {
   LOG(("CacheFileInputStream::CacheFileInputStream() [this=%p]", this));
-  MOZ_COUNT_CTOR(CacheFileInputStream);
 
   if (mAlternativeData) {
     mPos = mFile->mAltDataOffset;
   }
 }
 
 CacheFileInputStream::~CacheFileInputStream()
 {
   LOG(("CacheFileInputStream::~CacheFileInputStream() [this=%p]", this));
-  MOZ_COUNT_DTOR(CacheFileInputStream);
   MOZ_ASSERT(!mInReadSegments);
 }
 
 // nsIInputStream
 NS_IMETHODIMP
 CacheFileInputStream::Close()
 {
   LOG(("CacheFileInputStream::Close() [this=%p]", this));
--- a/netwerk/cache2/CacheFileMetadata.cpp
+++ b/netwerk/cache2/CacheFileMetadata.cpp
@@ -53,17 +53,16 @@ CacheFileMetadata::CacheFileMetadata(Cac
   , mIsDirty(false)
   , mAnonymous(false)
   , mAllocExactSize(false)
   , mFirstRead(true)
 {
   LOG(("CacheFileMetadata::CacheFileMetadata() [this=%p, handle=%p, key=%s]",
        this, aHandle, PromiseFlatCString(aKey).get()));
 
-  MOZ_COUNT_CTOR(CacheFileMetadata);
   memset(&mMetaHdr, 0, sizeof(CacheFileMetadataHeader));
   mMetaHdr.mVersion = kCacheEntryVersion;
   mMetaHdr.mExpirationTime = nsICacheEntry::NO_EXPIRATION_TIME;
   mKey = aKey;
 
   DebugOnly<nsresult> rv;
   rv = ParseKey(aKey);
   MOZ_ASSERT(NS_SUCCEEDED(rv));
@@ -83,17 +82,16 @@ CacheFileMetadata::CacheFileMetadata(boo
   , mIsDirty(true)
   , mAnonymous(false)
   , mAllocExactSize(false)
   , mFirstRead(true)
 {
   LOG(("CacheFileMetadata::CacheFileMetadata() [this=%p, key=%s]",
        this, PromiseFlatCString(aKey).get()));
 
-  MOZ_COUNT_CTOR(CacheFileMetadata);
   memset(&mMetaHdr, 0, sizeof(CacheFileMetadataHeader));
   mMetaHdr.mVersion = kCacheEntryVersion;
   if (aPinned) {
     AddFlags(kCacheEntryIsPinned);
   }
   mMetaHdr.mExpirationTime = nsICacheEntry::NO_EXPIRATION_TIME;
   mKey = aKey;
   mMetaHdr.mKeySize = mKey.Length();
@@ -116,25 +114,23 @@ CacheFileMetadata::CacheFileMetadata()
   , mElementsSize(0)
   , mIsDirty(false)
   , mAnonymous(false)
   , mAllocExactSize(false)
   , mFirstRead(true)
 {
   LOG(("CacheFileMetadata::CacheFileMetadata() [this=%p]", this));
 
-  MOZ_COUNT_CTOR(CacheFileMetadata);
   memset(&mMetaHdr, 0, sizeof(CacheFileMetadataHeader));
 }
 
 CacheFileMetadata::~CacheFileMetadata()
 {
   LOG(("CacheFileMetadata::~CacheFileMetadata() [this=%p]", this));
 
-  MOZ_COUNT_DTOR(CacheFileMetadata);
   MOZ_ASSERT(!mListener);
 
   if (mHashArray) {
     CacheFileUtils::FreeBuffer(mHashArray);
     mHashArray = nullptr;
     mHashArraySize = 0;
   }
 
--- a/netwerk/cache2/CacheFileOutputStream.cpp
+++ b/netwerk/cache2/CacheFileOutputStream.cpp
@@ -51,27 +51,25 @@ CacheFileOutputStream::CacheFileOutputSt
   , mCloseListener(aCloseListener)
   , mPos(0)
   , mClosed(false)
   , mAlternativeData(aAlternativeData)
   , mStatus(NS_OK)
   , mCallbackFlags(0)
 {
   LOG(("CacheFileOutputStream::CacheFileOutputStream() [this=%p]", this));
-  MOZ_COUNT_CTOR(CacheFileOutputStream);
 
   if (mAlternativeData) {
     mPos = mFile->mAltDataOffset;
   }
 }
 
 CacheFileOutputStream::~CacheFileOutputStream()
 {
   LOG(("CacheFileOutputStream::~CacheFileOutputStream() [this=%p]", this));
-  MOZ_COUNT_DTOR(CacheFileOutputStream);
 }
 
 // nsIOutputStream
 NS_IMETHODIMP
 CacheFileOutputStream::Close()
 {
   LOG(("CacheFileOutputStream::Close() [this=%p]", this));
   return CloseWithStatus(NS_OK);
--- a/netwerk/cache2/CacheIndex.cpp
+++ b/netwerk/cache2/CacheIndex.cpp
@@ -273,25 +273,23 @@ CacheIndex::CacheIndex()
   , mRWBufSize(0)
   , mRWBufPos(0)
   , mRWPending(false)
   , mJournalReadSuccessfully(false)
   , mAsyncGetDiskConsumptionBlocked(false)
 {
   sLock.AssertCurrentThreadOwns();
   LOG(("CacheIndex::CacheIndex [this=%p]", this));
-  MOZ_COUNT_CTOR(CacheIndex);
   MOZ_ASSERT(!gInstance, "multiple CacheIndex instances!");
 }
 
 CacheIndex::~CacheIndex()
 {
   sLock.AssertCurrentThreadOwns();
   LOG(("CacheIndex::~CacheIndex [this=%p]", this));
-  MOZ_COUNT_DTOR(CacheIndex);
 
   ReleaseBuffer();
 }
 
 // static
 nsresult
 CacheIndex::Init(nsIFile *aCacheDirectory)
 {
--- a/netwerk/cache2/OldWrappers.cpp
+++ b/netwerk/cache2/OldWrappers.cpp
@@ -36,24 +36,22 @@ namespace {
 // Fires the doom callback back on the main thread
 // after the cache I/O thread is looped.
 
 class DoomCallbackSynchronizer : public Runnable
 {
 public:
   explicit DoomCallbackSynchronizer(nsICacheEntryDoomCallback* cb) : mCB(cb)
   {
-    MOZ_COUNT_CTOR(DoomCallbackSynchronizer);
   }
   nsresult Dispatch();
 
 private:
   virtual ~DoomCallbackSynchronizer()
   {
-    MOZ_COUNT_DTOR(DoomCallbackSynchronizer);
   }
 
   NS_DECL_NSIRUNNABLE
   nsCOMPtr<nsICacheEntryDoomCallback> mCB;
 };
 
 nsresult DoomCallbackSynchronizer::Dispatch()
 {
@@ -89,23 +87,21 @@ NS_IMETHODIMP DoomCallbackSynchronizer::
 
 class DoomCallbackWrapper : public nsICacheListener
 {
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSICACHELISTENER
 
   explicit DoomCallbackWrapper(nsICacheEntryDoomCallback* cb) : mCB(cb)
   {
-    MOZ_COUNT_CTOR(DoomCallbackWrapper);
   }
 
 private:
   virtual ~DoomCallbackWrapper()
   {
-    MOZ_COUNT_DTOR(DoomCallbackWrapper);
   }
 
   nsCOMPtr<nsICacheEntryDoomCallback> mCB;
 };
 
 NS_IMPL_ISUPPORTS(DoomCallbackWrapper, nsICacheListener);
 
 NS_IMETHODIMP DoomCallbackWrapper::OnCacheEntryAvailable(nsICacheEntryDescriptor *descriptor,
@@ -138,18 +134,16 @@ NS_IMPL_ISUPPORTS(_OldVisitCallbackWrapp
     // The device has not been found, to not break the chain, simulate
     // storage info callback.
     mCB->OnCacheStorageInfo(0, 0, 0, nullptr);
   }
 
   if (mVisitEntries) {
     mCB->OnCacheEntryVisitCompleted();
   }
-
-  MOZ_COUNT_DTOR(_OldVisitCallbackWrapper);
 }
 
 NS_IMETHODIMP _OldVisitCallbackWrapper::VisitDevice(const char * deviceID,
                                                     nsICacheDeviceInfo *deviceInfo,
                                                     bool *_retval)
 {
   if (!mCB)
     return NS_ERROR_NULL_POINTER;
@@ -344,30 +338,27 @@ NS_IMETHODIMP
 }
 
 
 // _OldCacheEntryWrapper
 
 _OldCacheEntryWrapper::_OldCacheEntryWrapper(nsICacheEntryDescriptor* desc)
 : mOldDesc(desc), mOldInfo(desc)
 {
-  MOZ_COUNT_CTOR(_OldCacheEntryWrapper);
   LOG(("Creating _OldCacheEntryWrapper %p for descriptor %p", this, desc));
 }
 
 _OldCacheEntryWrapper::_OldCacheEntryWrapper(nsICacheEntryInfo* info)
 : mOldDesc(nullptr), mOldInfo(info)
 {
-  MOZ_COUNT_CTOR(_OldCacheEntryWrapper);
   LOG(("Creating _OldCacheEntryWrapper %p for info %p", this, info));
 }
 
 _OldCacheEntryWrapper::~_OldCacheEntryWrapper()
 {
-  MOZ_COUNT_DTOR(_OldCacheEntryWrapper);
   LOG(("Destroying _OldCacheEntryWrapper %p for descriptor %p", this, mOldInfo.get()));
 }
 
 NS_IMETHODIMP _OldCacheEntryWrapper::GetIsForcedValid(bool *aIsForcedValid)
 {
   // Unused stub
   return NS_ERROR_NOT_IMPLEMENTED;
 }
@@ -675,23 +666,21 @@ NS_IMPL_ISUPPORTS_INHERITED(_OldCacheLoa
   , mWriteToDisk(aWriteToDisk)
   , mNew(true)
   , mOpening(true)
   , mSync(false)
   , mStatus(NS_ERROR_UNEXPECTED)
   , mRunCount(0)
   , mAppCache(aAppCache)
 {
-  MOZ_COUNT_CTOR(_OldCacheLoad);
 }
 
 _OldCacheLoad::~_OldCacheLoad()
 {
   ProxyReleaseMainThread(mAppCache);
-  MOZ_COUNT_DTOR(_OldCacheLoad);
 }
 
 nsresult _OldCacheLoad::Start()
 {
   LOG(("_OldCacheLoad::Start [this=%p, key=%s]", this, mCacheKey.get()));
 
   mLoadStart = mozilla::TimeStamp::Now();
 
@@ -902,22 +891,20 @@ NS_IMPL_ISUPPORTS(_OldStorage, nsICacheS
                          bool aOfflineStorage,
                          nsIApplicationCache* aAppCache)
 : mLoadInfo(GetLoadContextInfo(aInfo))
 , mAppCache(aAppCache)
 , mWriteToDisk(aAllowDisk)
 , mLookupAppCache(aLookupAppCache)
 , mOfflineStorage(aOfflineStorage)
 {
-  MOZ_COUNT_CTOR(_OldStorage);
 }
 
 _OldStorage::~_OldStorage()
 {
-  MOZ_COUNT_DTOR(_OldStorage);
 }
 
 NS_IMETHODIMP _OldStorage::AsyncOpenURI(nsIURI *aURI,
                                         const nsACString & aIdExtension,
                                         uint32_t aFlags,
                                         nsICacheEntryOpenCallback *aCallback)
 {
   NS_ENSURE_ARG(aURI);
--- a/netwerk/cache2/OldWrappers.h
+++ b/netwerk/cache2/OldWrappers.h
@@ -244,17 +244,16 @@ class _OldVisitCallbackWrapper : public 
                            bool visitEntries,
                            nsILoadContextInfo * aInfo)
   : mCB(cb)
   , mVisitEntries(visitEntries)
   , mDeviceID(deviceID)
   , mLoadInfo(aInfo)
   , mHit(false)
   {
-    MOZ_COUNT_CTOR(_OldVisitCallbackWrapper);
   }
 
 private:
   virtual ~_OldVisitCallbackWrapper();
   nsCOMPtr<nsICacheStorageVisitor> mCB;
   bool mVisitEntries;
   char const * mDeviceID;
   nsCOMPtr<nsILoadContextInfo> mLoadInfo;
--- a/netwerk/protocol/ftp/FTPChannelChild.cpp
+++ b/netwerk/protocol/ftp/FTPChannelChild.cpp
@@ -518,22 +518,20 @@ FTPChannelChild::RecvOnStopRequest(const
 
 class nsFtpChildAsyncAlert : public Runnable
 {
 public:
   nsFtpChildAsyncAlert(nsIPrompt *aPrompter, nsString aResponseMsg)
     : mPrompter(aPrompter)
     , mResponseMsg(aResponseMsg)
   {
-    MOZ_COUNT_CTOR(nsFtpChildAsyncAlert);
   }
 protected:
   virtual ~nsFtpChildAsyncAlert()
   {
-    MOZ_COUNT_DTOR(nsFtpChildAsyncAlert);
   }
 public:
   NS_IMETHOD Run() override
   {
     if (mPrompter) {
       mPrompter->Alert(nullptr, mResponseMsg.get());
     }
     return NS_OK;
--- a/netwerk/protocol/ftp/nsFtpConnectionThread.cpp
+++ b/netwerk/protocol/ftp/nsFtpConnectionThread.cpp
@@ -1789,22 +1789,20 @@ nsFtpState::KillControlConnection()
 
 class nsFtpAsyncAlert : public Runnable
 {
 public:
     nsFtpAsyncAlert(nsIPrompt *aPrompter, nsString aResponseMsg)
         : mPrompter(aPrompter)
         , mResponseMsg(aResponseMsg)
     {
-        MOZ_COUNT_CTOR(nsFtpAsyncAlert);
     }
 protected:
     virtual ~nsFtpAsyncAlert()
     {
-        MOZ_COUNT_DTOR(nsFtpAsyncAlert);
     }
 public:
     NS_IMETHOD Run() override
     {
         if (mPrompter) {
             mPrompter->Alert(nullptr, mResponseMsg.get());
         }
         return NS_OK;
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -2505,16 +2505,22 @@ HttpBaseChannel::SetIntegrityMetadata(co
 
 NS_IMETHODIMP
 HttpBaseChannel::GetIntegrityMetadata(nsAString& aIntegrityMetadata)
 {
   aIntegrityMetadata = mIntegrityMetadata;
   return NS_OK;
 }
 
+mozilla::net::nsHttpChannel*
+HttpBaseChannel::QueryHttpChannelImpl(void)
+{
+  return nullptr;
+}
+
 //-----------------------------------------------------------------------------
 // HttpBaseChannel::nsISupportsPriority
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 HttpBaseChannel::GetPriority(int32_t *value)
 {
   *value = mPriority;
--- a/netwerk/protocol/http/HttpBaseChannel.h
+++ b/netwerk/protocol/http/HttpBaseChannel.h
@@ -233,16 +233,17 @@ public:
   NS_IMETHOD GetFetchCacheMode(uint32_t* aFetchCacheMode) override;
   NS_IMETHOD SetFetchCacheMode(uint32_t aFetchCacheMode) override;
   NS_IMETHOD GetTopWindowURI(nsIURI **aTopWindowURI) override;
   NS_IMETHOD GetProxyURI(nsIURI **proxyURI) override;
   virtual void SetCorsPreflightParameters(const nsTArray<nsCString>& unsafeHeaders) override;
   NS_IMETHOD GetConnectionInfoHashKey(nsACString& aConnectionInfoHashKey) override;
   NS_IMETHOD GetIntegrityMetadata(nsAString& aIntegrityMetadata) override;
   NS_IMETHOD SetIntegrityMetadata(const nsAString& aIntegrityMetadata) override;
+  virtual mozilla::net::nsHttpChannel * QueryHttpChannelImpl(void) override;
 
   inline void CleanRedirectCacheChainIfNecessary()
   {
       mRedirectedCachekeys = nullptr;
   }
   NS_IMETHOD HTTPUpgrade(const nsACString & aProtocolName,
                          nsIHttpUpgradeListener *aListener) override;
 
--- a/netwerk/protocol/http/HttpChannelParent.cpp
+++ b/netwerk/protocol/http/HttpChannelParent.cpp
@@ -366,16 +366,18 @@ HttpChannelParent::DoAsyncOpen(  const U
 
   nsCOMPtr<nsIChannel> channel;
   rv = NS_NewChannelInternal(getter_AddRefs(channel), uri, loadInfo,
                              nullptr, nullptr, aLoadFlags, ios);
 
   if (NS_FAILED(rv))
     return SendFailedAsyncOpen(rv);
 
+  // This cast is safe since this is AsyncOpen specific to http.  channel
+  // is ensured to be nsHttpChannel.
   mChannel = static_cast<nsHttpChannel *>(channel.get());
 
   // Set the channelId allocated in child to the parent instance
   mChannel->SetChannelId(aChannelId);
 
   mChannel->SetWarningReporter(this);
   mChannel->SetTimingEnabled(true);
   if (mPBOverride != kPBOverride_Unset) {
@@ -586,16 +588,19 @@ bool
 HttpChannelParent::ConnectChannel(const uint32_t& registrarId, const bool& shouldIntercept)
 {
   nsresult rv;
 
   LOG(("HttpChannelParent::ConnectChannel: Looking for a registered channel "
        "[this=%p, id=%lu]\n", this, registrarId));
   nsCOMPtr<nsIChannel> channel;
   rv = NS_LinkRedirectChannels(registrarId, this, getter_AddRefs(channel));
+  // It's safe to cast here since the found parent-side real channel is ensured
+  // to be http (nsHttpChannel).  ConnectChannel called from HttpChannelParent::Init
+  // can only be called for http channels.  It's bound by ipdl.
   mChannel = static_cast<nsHttpChannel*>(channel.get());
   LOG(("  found channel %p, rv=%08x", mChannel.get(), rv));
 
   nsCOMPtr<nsINetworkInterceptController> controller;
   NS_QueryNotificationCallbacks(channel, controller);
   RefPtr<HttpChannelParentListener> parentListener = do_QueryObject(controller);
   MOZ_ASSERT(parentListener);
   parentListener->SetupInterceptionAfterRedirect(shouldIntercept);
@@ -1084,17 +1089,33 @@ NS_IMETHODIMP
 HttpChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
 {
   LOG(("HttpChannelParent::OnStartRequest [this=%p, aRequest=%p]\n",
        this, aRequest));
 
   MOZ_RELEASE_ASSERT(!mDivertingFromChild,
     "Cannot call OnStartRequest if diverting is set!");
 
-  nsHttpChannel *chan = static_cast<nsHttpChannel *>(aRequest);
+  // We can't cast here since the new channel can be a redirect to a different
+  // schema.  We must query the channel implementation through a special method.
+  nsHttpChannel *chan = nullptr;
+  nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal(do_QueryInterface(aRequest));
+  if (httpChannelInternal) {
+    chan = httpChannelInternal->QueryHttpChannelImpl();
+  }
+
+  if (!chan) {
+    LOG(("  aRequest is not nsHttpChannel"));
+    NS_ERROR("Expecting only nsHttpChannel as aRequest in HttpChannelParent::OnStartRequest");
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  MOZ_ASSERT(mChannel == chan,
+             "HttpChannelParent getting OnStartRequest from a different nsHttpChannel instance");
+
   nsHttpResponseHead *responseHead = chan->GetResponseHead();
   nsHttpRequestHead  *requestHead = chan->GetRequestHead();
   bool isFromCache = false;
   chan->IsFromCache(&isFromCache);
   uint32_t expirationTime = nsICacheEntry::NO_EXPIRATION_TIME;
   chan->GetCacheTokenExpirationTime(&expirationTime);
   nsCString cachedCharset;
   chan->GetCacheTokenCachedCharset(cachedCharset);
@@ -1128,48 +1149,48 @@ HttpChannelParent::OnStartRequest(nsIReq
 
   nsresult channelStatus = NS_OK;
   chan->GetStatus(&channelStatus);
 
   nsCString secInfoSerialization;
   UpdateAndSerializeSecurityInfo(secInfoSerialization);
 
   uint16_t redirectCount = 0;
-  mChannel->GetRedirectCount(&redirectCount);
+  chan->GetRedirectCount(&redirectCount);
 
   nsCOMPtr<nsISupports> cacheKey;
-  mChannel->GetCacheKey(getter_AddRefs(cacheKey));
+  chan->GetCacheKey(getter_AddRefs(cacheKey));
   uint32_t cacheKeyValue = 0;
   if (cacheKey) {
     nsCOMPtr<nsISupportsPRUint32> container = do_QueryInterface(cacheKey);
     if (!container) {
       return NS_ERROR_ILLEGAL_VALUE;
     }
 
     nsresult rv = container->GetData(&cacheKeyValue);
     if (NS_FAILED(rv)) {
       return rv;
     }
   }
 
   nsAutoCString altDataType;
-  mChannel->GetAlternativeDataType(altDataType);
+  chan->GetAlternativeDataType(altDataType);
 
   // !!! We need to lock headers and please don't forget to unlock them !!!
   requestHead->Enter();
   nsresult rv = NS_OK;
   if (mIPCClosed ||
       !SendOnStartRequest(channelStatus,
                           responseHead ? *responseHead : nsHttpResponseHead(),
                           !!responseHead,
                           requestHead->Headers(),
                           isFromCache,
                           mCacheEntry ? true : false,
                           expirationTime, cachedCharset, secInfoSerialization,
-                          mChannel->GetSelfAddr(), mChannel->GetPeerAddr(),
+                          chan->GetSelfAddr(), chan->GetPeerAddr(),
                           redirectCount,
                           cacheKeyValue,
                           altDataType))
   {
     rv = NS_ERROR_UNEXPECTED;
   }
   requestHead->Exit();
   return rv;
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -6118,16 +6118,22 @@ nsHttpChannel::ForceIntercepted(uint64_t
     }
 
     MarkIntercepted();
     mResponseCouldBeSynthesized = true;
     mInterceptionID = aInterceptionID;
     return NS_OK;
 }
 
+mozilla::net::nsHttpChannel*
+nsHttpChannel::QueryHttpChannelImpl(void)
+{
+  return this;
+}
+
 //-----------------------------------------------------------------------------
 // nsHttpChannel::nsISupportsPriority
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 nsHttpChannel::SetPriority(int32_t value)
 {
     int16_t newValue = clamped<int32_t>(value, INT16_MIN, INT16_MAX);
--- a/netwerk/protocol/http/nsHttpChannel.h
+++ b/netwerk/protocol/http/nsHttpChannel.h
@@ -142,16 +142,17 @@ public:
     NS_IMETHOD GetSecurityInfo(nsISupports **aSecurityInfo) override;
     NS_IMETHOD AsyncOpen(nsIStreamListener *listener, nsISupports *aContext) override;
     NS_IMETHOD AsyncOpen2(nsIStreamListener *aListener) override;
     // nsIHttpChannel
     NS_IMETHOD GetEncodedBodySize(uint64_t *aEncodedBodySize) override;
     // nsIHttpChannelInternal
     NS_IMETHOD SetupFallbackChannel(const char *aFallbackKey) override;
     NS_IMETHOD ForceIntercepted(uint64_t aInterceptionID) override;
+    virtual mozilla::net::nsHttpChannel * QueryHttpChannelImpl(void) override;
     // nsISupportsPriority
     NS_IMETHOD SetPriority(int32_t value) override;
     // nsIClassOfService
     NS_IMETHOD SetClassFlags(uint32_t inFlags) override;
     NS_IMETHOD AddClassFlags(uint32_t inFlags) override;
     NS_IMETHOD ClearClassFlags(uint32_t inFlags) override;
 
     // nsIResumableChannel
--- a/netwerk/protocol/http/nsHttpHeaderArray.h
+++ b/netwerk/protocol/http/nsHttpHeaderArray.h
@@ -105,45 +105,33 @@ public:
 
     uint32_t Count() const { return mHeaders.Length(); }
 
     const char *PeekHeaderAt(uint32_t i, nsHttpAtom &header) const;
 
     void Clear();
 
     // Must be copy-constructable and assignable
-#if defined(XP_WIN) && (defined(_M_IX86) || defined(_M_X64))
-#pragma pack(1)
-#endif
     struct nsEntry
     {
         nsHttpAtom header;
-#if defined(XP_WIN) && (defined(_M_IX86) || defined(_M_X64))
-        char padding[4096 -
-                     sizeof(nsTArrayHeader) -
-                     sizeof(nsHttpAtom) -
-                     sizeof(void*)];
-#endif
         nsCString value;
         HeaderVariety variety = eVarietyUnknown;
 
         struct MatchHeader {
           bool Equals(const nsEntry &aEntry, const nsHttpAtom &aHeader) const {
             return aEntry.header == aHeader;
           }
         };
 
         bool operator==(const nsEntry& aOther) const
         {
             return header == aOther.header && value == aOther.value;
         }
     };
-#if defined(XP_WIN) && (defined(_M_IX86) || defined(_M_X64))
-#pragma pack()
-#endif
 
     bool operator==(const nsHttpHeaderArray& aOther) const
     {
         return mHeaders == aOther.mHeaders;
     }
 
 private:
     // LookupEntry function will never return eVarietyResponseNetOriginal.
--- a/netwerk/protocol/http/nsHttpRequestHead.cpp
+++ b/netwerk/protocol/http/nsHttpRequestHead.cpp
@@ -11,57 +11,29 @@
 
 //-----------------------------------------------------------------------------
 // nsHttpRequestHead
 //-----------------------------------------------------------------------------
 
 namespace mozilla {
 namespace net {
 
-#if defined(XP_WIN) && (defined(_M_IX86) || defined(_M_X64))
-void nsHttpRequestHead::DbgReentrantMonitorAutoEnter::Protect(bool aOn)
-{
-    if (XRE_GetProcessType() == GeckoProcessType_Content &&
-        mInst.mHeaders.Count()) {
-        DWORD oldProtect;
-        LPVOID hdr = reinterpret_cast<PUINT8>(mInst.mHeaders.mHeaders.Elements()) -
-                     sizeof(nsTArrayHeader);
-        if (aOn) {
-            VirtualProtect(hdr, 4096, PAGE_READONLY, &oldProtect);
-        } else {
-            VirtualProtect(hdr, 4096, PAGE_READWRITE, &oldProtect);
-        }
-    }
-}
-
-#define ReentrantMonitorAutoEnter DbgReentrantMonitorAutoEnter
-#define mon(x) mon(*this)
-#endif
-
 nsHttpRequestHead::nsHttpRequestHead()
     : mMethod(NS_LITERAL_CSTRING("GET"))
     , mVersion(NS_HTTP_VERSION_1_1)
     , mParsedMethod(kMethod_Get)
     , mHTTPS(false)
     , mReentrantMonitor("nsHttpRequestHead.mReentrantMonitor")
     , mInVisitHeaders(false)
 {
     MOZ_COUNT_CTOR(nsHttpRequestHead);
 }
 
 nsHttpRequestHead::~nsHttpRequestHead()
 {
-#if defined(XP_WIN) && (defined(_M_IX86) || defined(_M_X64))
-    if (XRE_GetProcessType() == GeckoProcessType_Content && mHeaders.Count()) {
-        DWORD oldProtect;
-        LPVOID hdr = reinterpret_cast<PUINT8>(mHeaders.mHeaders.Elements()) -
-                     sizeof(nsTArrayHeader);
-        VirtualProtect(hdr, 4096, PAGE_READWRITE, &oldProtect);
-    }
-#endif
     MOZ_COUNT_DTOR(nsHttpRequestHead);
 }
 
 // Don't use this function. It is only used by HttpChannelParent to avoid
 // copying of request headers!!!
 const nsHttpHeaderArray &
 nsHttpRequestHead::Headers() const
 {
@@ -388,15 +360,10 @@ nsHttpRequestHead::Flatten(nsACString &b
         buf.AppendLiteral("1.0");
     }
 
     buf.AppendLiteral("\r\n");
 
     mHeaders.Flatten(buf, pruneProxyHeaders, false);
 }
 
-#if defined(XP_WIN) && (defined(_M_IX86) || defined(_M_X64))
-#undef ReentrantMonitorAutoEnter
-#undef mon
-#endif
-
 } // namespace net
 } // namespace mozilla
--- a/netwerk/protocol/http/nsHttpRequestHead.h
+++ b/netwerk/protocol/http/nsHttpRequestHead.h
@@ -115,36 +115,14 @@ private:
     bool              mHTTPS;
 
     // We are using ReentrantMonitor instead of a Mutex because VisitHeader
     // function calls nsIHttpHeaderVisitor::VisitHeader while under lock.
     ReentrantMonitor  mReentrantMonitor;
 
     // During VisitHeader we sould not allow cal to SetHeader.
     bool mInVisitHeaders;
-
-#if defined(XP_WIN) && (defined(_M_IX86) || defined(_M_X64))
-    class DbgReentrantMonitorAutoEnter : ReentrantMonitorAutoEnter
-    {
-    public:
-        explicit DbgReentrantMonitorAutoEnter(nsHttpRequestHead& aInst)
-            : ReentrantMonitorAutoEnter(aInst.mReentrantMonitor),
-              mInst(aInst)
-        {
-            Protect(false);
-        }
-        ~DbgReentrantMonitorAutoEnter(void)
-        {
-            Protect(true);
-        }
-
-    private:
-        void Protect(bool aOn);
-
-        nsHttpRequestHead& mInst;
-    };
-#endif
 };
 
 } // namespace net
 } // namespace mozilla
 
 #endif // nsHttpRequestHead_h__
--- a/netwerk/protocol/http/nsIHttpChannelInternal.idl
+++ b/netwerk/protocol/http/nsIHttpChannelInternal.idl
@@ -4,20 +4,22 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 %{C++
 #include "nsTArrayForwardDeclare.h"
 template<class T> class nsCOMArray;
 class nsCString;
+namespace mozilla { namespace net { class nsHttpChannel; } }
 %}
 [ptr] native StringArray(nsTArray<nsCString>);
 [ref] native StringArrayRef(const nsTArray<nsCString>);
 [ref] native securityMessagesArray(nsCOMArray<nsISecurityConsoleMessage>);
+[ptr] native nsHttpChannelPtr(mozilla::net::nsHttpChannel);
 
 interface nsIAsyncInputStream;
 interface nsIAsyncOutputStream;
 interface nsIPrincipal;
 interface nsIProxyInfo;
 interface nsISecurityConsoleMessage;
 interface nsISocketTransport;
 interface nsIURI;
@@ -298,9 +300,15 @@ interface nsIHttpChannelInternal : nsISu
      * Set to indicate Request.integrity.
      */
     attribute AString integrityMetadata;
 
     /**
      * The connection info's hash key. We use it to test connection separation.
      */
     readonly attribute ACString connectionInfoHashKey;
+
+    /**
+     * Returns nsHttpChannel (self) when this actually is implementing nsHttpChannel.
+     */
+    [noscript, notxpcom, nostdcall]
+    nsHttpChannelPtr queryHttpChannelImpl();
 };
--- a/netwerk/protocol/viewsource/nsViewSourceChannel.cpp
+++ b/netwerk/protocol/viewsource/nsViewSourceChannel.cpp
@@ -985,14 +985,20 @@ nsViewSourceChannel::GetIsMainDocumentCh
 
 NS_IMETHODIMP
 nsViewSourceChannel::SetIsMainDocumentChannel(bool aValue)
 {
     return !mHttpChannel ? NS_ERROR_NULL_POINTER :
         mHttpChannel->SetIsMainDocumentChannel(aValue);
 }
 
-// Have to manually forward SetCorsPreflightParameters since it's [notxpcom]
+// Have to manually forward since these are [notxpcom]
 void
 nsViewSourceChannel::SetCorsPreflightParameters(const nsTArray<nsCString>& aUnsafeHeaders)
 {
   mHttpChannelInternal->SetCorsPreflightParameters(aUnsafeHeaders);
 }
+
+mozilla::net::nsHttpChannel *
+nsViewSourceChannel::QueryHttpChannelImpl()
+{
+  return mHttpChannelInternal->QueryHttpChannelImpl();
+}
--- a/netwerk/protocol/websocket/IPCTransportProvider.cpp
+++ b/netwerk/protocol/websocket/IPCTransportProvider.cpp
@@ -14,22 +14,20 @@ namespace mozilla {
 namespace net {
 
 NS_IMPL_ISUPPORTS(TransportProviderParent,
                   nsITransportProvider,
                   nsIHttpUpgradeListener)
 
 TransportProviderParent::TransportProviderParent()
 {
-  MOZ_COUNT_CTOR(TransportProviderParent);
 }
 
 TransportProviderParent::~TransportProviderParent()
 {
-  MOZ_COUNT_DTOR(TransportProviderParent);
 }
 
 NS_IMETHODIMP
 TransportProviderParent::SetListener(nsIHttpUpgradeListener* aListener)
 {
   MOZ_ASSERT(aListener);
   mListener = aListener;
 
@@ -72,22 +70,20 @@ TransportProviderParent::MaybeNotify()
 }
 
 
 NS_IMPL_ISUPPORTS(TransportProviderChild,
                   nsITransportProvider)
 
 TransportProviderChild::TransportProviderChild()
 {
-  MOZ_COUNT_CTOR(TransportProviderChild);
 }
 
 TransportProviderChild::~TransportProviderChild()
 {
-  MOZ_COUNT_DTOR(TransportProviderChild);
   Send__delete__(this);
 }
 
 NS_IMETHODIMP
 TransportProviderChild::SetListener(nsIHttpUpgradeListener* aListener)
 {
   MOZ_CRASH("Don't call this in child process");
   return NS_OK;
--- a/parser/html/nsHtml5OwningUTF16Buffer.cpp
+++ b/parser/html/nsHtml5OwningUTF16Buffer.cpp
@@ -3,31 +3,26 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsHtml5OwningUTF16Buffer.h"
 
 nsHtml5OwningUTF16Buffer::nsHtml5OwningUTF16Buffer(char16_t* aBuffer)
   : nsHtml5UTF16Buffer(aBuffer, 0),
     next(nullptr),
     key(nullptr)
-{
-  MOZ_COUNT_CTOR(nsHtml5OwningUTF16Buffer);
-}
+{}
 
 nsHtml5OwningUTF16Buffer::nsHtml5OwningUTF16Buffer(void* aKey)
   : nsHtml5UTF16Buffer(nullptr, 0),
     next(nullptr),
     key(aKey)
-{
-  MOZ_COUNT_CTOR(nsHtml5OwningUTF16Buffer);
-}
+{}
 
 nsHtml5OwningUTF16Buffer::~nsHtml5OwningUTF16Buffer()
 {
-  MOZ_COUNT_DTOR(nsHtml5OwningUTF16Buffer);
   DeleteBuffer();
 
   // This is to avoid dtor recursion on 'next', bug 706932.
   RefPtr<nsHtml5OwningUTF16Buffer> tail;
   tail.swap(next);
   while (tail && tail->mRefCnt == 1) {
     RefPtr<nsHtml5OwningUTF16Buffer> tmp;
     tmp.swap(tail->next);
--- a/parser/html/nsHtml5StringParser.cpp
+++ b/parser/html/nsHtml5StringParser.cpp
@@ -13,23 +13,21 @@
 
 NS_IMPL_ISUPPORTS0(nsHtml5StringParser)
 
 nsHtml5StringParser::nsHtml5StringParser()
   : mBuilder(new nsHtml5OplessBuilder())
   , mTreeBuilder(new nsHtml5TreeBuilder(mBuilder))
   , mTokenizer(new nsHtml5Tokenizer(mTreeBuilder, false))
 {
-  MOZ_COUNT_CTOR(nsHtml5StringParser);
   mTokenizer->setInterner(&mAtomTable);
 }
 
 nsHtml5StringParser::~nsHtml5StringParser()
 {
-  MOZ_COUNT_DTOR(nsHtml5StringParser);
 }
 
 nsresult
 nsHtml5StringParser::ParseFragment(const nsAString& aSourceBuffer,
                                    nsIContent* aTargetNode,
                                    nsIAtom* aContextLocalName,
                                    int32_t aContextNamespace,
                                    bool aQuirks,
--- a/rdf/base/nsInMemoryDataSource.cpp
+++ b/rdf/base/nsInMemoryDataSource.cpp
@@ -731,17 +731,16 @@ InMemoryDataSource::InMemoryDataSource(n
     : mForwardArcs(PLDHashTable::StubOps(), sizeof(Entry))
     , mReverseArcs(PLDHashTable::StubOps(), sizeof(Entry))
     , mNumObservers(0)
     , mReadCount(0)
 {
     NS_INIT_AGGREGATED(aOuter);
 
     mPropagateChanges = true;
-    MOZ_COUNT_CTOR(InMemoryDataSource);
 }
 
 
 InMemoryDataSource::~InMemoryDataSource()
 {
 #ifdef DEBUG_REFS
     --gInstanceCount;
     fprintf(stdout, "%d - RDF: InMemoryDataSource\n", gInstanceCount);
@@ -763,18 +762,16 @@ InMemoryDataSource::~InMemoryDataSource(
                 doomed->mNext = doomed->u.as.mInvNext = nullptr;
                 doomed->Release();
             }
         }
     }
 
     MOZ_LOG(gLog, LogLevel::Debug,
            ("InMemoryDataSource(%p): destroyed.", this));
-
-    MOZ_COUNT_DTOR(InMemoryDataSource);
 }
 
 
 ////////////////////////////////////////////////////////////////////////
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(InMemoryDataSource)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(InMemoryDataSource)
--- a/rdf/base/nsRDFXMLParser.cpp
+++ b/rdf/base/nsRDFXMLParser.cpp
@@ -33,22 +33,20 @@ nsRDFXMLParser::Create(nsISupports* aOut
     NS_ADDREF(result);
     rv = result->QueryInterface(aIID, aResult);
     NS_RELEASE(result);
     return rv;
 }
 
 nsRDFXMLParser::nsRDFXMLParser()
 {
-    MOZ_COUNT_CTOR(nsRDFXMLParser);
 }
 
 nsRDFXMLParser::~nsRDFXMLParser()
 {
-    MOZ_COUNT_DTOR(nsRDFXMLParser);
 }
 
 NS_IMETHODIMP
 nsRDFXMLParser::ParseAsync(nsIRDFDataSource* aSink, nsIURI* aBaseURI, nsIStreamListener** aResult)
 {
     nsresult rv;
 
     nsCOMPtr<nsIRDFContentSink> sink =
--- a/rdf/base/nsRDFXMLSerializer.cpp
+++ b/rdf/base/nsRDFXMLSerializer.cpp
@@ -90,23 +90,20 @@ nsRDFXMLSerializer::Create(nsISupports* 
         if (NS_FAILED(rv)) break;
     } while (0);
 
     return rv;
 }
 
 nsRDFXMLSerializer::nsRDFXMLSerializer()
 {
-    MOZ_COUNT_CTOR(nsRDFXMLSerializer);
 }
 
 nsRDFXMLSerializer::~nsRDFXMLSerializer()
 {
-    MOZ_COUNT_DTOR(nsRDFXMLSerializer);
-
     if (--gRefCnt == 0) {
         NS_IF_RELEASE(kRDF_Bag);
         NS_IF_RELEASE(kRDF_Seq);
         NS_IF_RELEASE(kRDF_Alt);
         NS_IF_RELEASE(kRDF_instanceOf);
         NS_IF_RELEASE(kRDF_type);
         NS_IF_RELEASE(kRDF_nextVal);
         NS_IF_RELEASE(gRDFC);
--- a/testing/web-platform/tests/webaudio/the-audio-api/the-audiobuffer-interface/idl-test.html
+++ b/testing/web-platform/tests/webaudio/the-audio-api/the-audiobuffer-interface/idl-test.html
@@ -21,17 +21,17 @@ callback interface EventListener {
   void handleEvent(Event event);
 };
 */
 // Callback interfaces are not supported yet, but that's ok
 interface EventListener {};
 </pre>
 
    <pre id="audio-context-idl">callback DecodeSuccessCallback = void (AudioBuffer decodedData);
-callback DecodeErrorCallback = void ();
+callback DecodeErrorCallback = void (DOMException error);
 
 [Constructor]
 interface AudioContext : EventTarget {
 
     readonly attribute AudioDestinationNode destination;
     readonly attribute float sampleRate;
     readonly attribute double currentTime;
     readonly attribute AudioListener listener;
--- a/testing/web-platform/tests/webaudio/the-audio-api/the-audiodestinationnode-interface/idl-test.html
+++ b/testing/web-platform/tests/webaudio/the-audio-api/the-audiodestinationnode-interface/idl-test.html
@@ -22,17 +22,17 @@ callback interface EventListener {
   void handleEvent(Event event);
 };
 */
 // Callback interfaces are not supported yet, but that's ok
 interface EventListener {};
 </pre>
 
    <pre id="audio-context-idl">callback DecodeSuccessCallback = void (AudioBuffer decodedData);
-callback DecodeErrorCallback = void ();
+callback DecodeErrorCallback = void (DOMException error);
 
 [Constructor]
 interface AudioContext : EventTarget {
 
     readonly attribute AudioDestinationNode destination;
     readonly attribute float sampleRate;
     readonly attribute double currentTime;
     readonly attribute AudioListener listener;
--- a/testing/web-platform/tests/webaudio/the-audio-api/the-delaynode-interface/idl-test.html
+++ b/testing/web-platform/tests/webaudio/the-audio-api/the-delaynode-interface/idl-test.html
@@ -23,17 +23,17 @@ callback interface EventListener {
   void handleEvent(Event event);
 };
 */
 // Callback interfaces are not supported yet, but that's ok
 interface EventListener {};
 </pre>
 
    <pre id="audio-context-idl">callback DecodeSuccessCallback = void (AudioBuffer decodedData);
-callback DecodeErrorCallback = void ();
+callback DecodeErrorCallback = void (DOMException error);
 
 [Constructor]
 interface AudioContext : EventTarget {
 
     readonly attribute AudioDestinationNode destination;
     readonly attribute float sampleRate;
     readonly attribute double currentTime;
     readonly attribute AudioListener listener;
--- a/testing/web-platform/tests/webaudio/the-audio-api/the-gainnode-interface/idl-test.html
+++ b/testing/web-platform/tests/webaudio/the-audio-api/the-gainnode-interface/idl-test.html
@@ -23,17 +23,17 @@ callback interface EventListener {
   void handleEvent(Event event);
 };
 */
 // Callback interfaces are not supported yet, but that's ok
 interface EventListener {};
 </pre>
 
    <pre id="audio-context-idl">callback DecodeSuccessCallback = void (AudioBuffer decodedData);
-callback DecodeErrorCallback = void ();
+callback DecodeErrorCallback = void (DOMException error);
 
 [Constructor]
 interface AudioContext : EventTarget {
 
     readonly attribute AudioDestinationNode destination;
     readonly attribute float sampleRate;
     readonly attribute double currentTime;
     readonly attribute AudioListener listener;
--- a/toolkit/components/reader/AboutReader.jsm
+++ b/toolkit/components/reader/AboutReader.jsm
@@ -12,17 +12,18 @@ Cu.import("resource://gre/modules/Reader
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "AsyncPrefs", "resource://gre/modules/AsyncPrefs.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "NarrateControls", "resource://gre/modules/narrate/NarrateControls.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Rect", "resource://gre/modules/Geometry.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Task", "resource://gre/modules/Task.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "UITelemetry", "resource://gre/modules/UITelemetry.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "LanguageDetector", "resource:///modules/translation/LanguageDetector.jsm");
+XPCOMUtils.defineLazyServiceGetter(this, "gChromeRegistry",
+                                   "@mozilla.org/chrome/chrome-registry;1", Ci.nsIXULChromeRegistry);
 
 var gStrings = Services.strings.createBundle("chrome://global/locale/aboutReader.properties");
 
 const gIsFirefoxDesktop = Services.appinfo.ID == "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}";
 
 var AboutReader = function(mm, win, articlePromise) {
   let url = this._getOriginalUrl(win);
   if (!(url.startsWith("http://") || url.startsWith("https://"))) {
@@ -54,16 +55,17 @@ var AboutReader = function(mm, win, arti
 
   if (articlePromise) {
     this._articlePromise = articlePromise;
   }
 
   this._headerElementRef = Cu.getWeakReference(doc.getElementById("reader-header"));
   this._domainElementRef = Cu.getWeakReference(doc.getElementById("reader-domain"));
   this._titleElementRef = Cu.getWeakReference(doc.getElementById("reader-title"));
+  this._readTimeElementRef = Cu.getWeakReference(doc.getElementById("reader-estimated-time"));
   this._creditsElementRef = Cu.getWeakReference(doc.getElementById("reader-credits"));
   this._contentElementRef = Cu.getWeakReference(doc.getElementById("moz-reader-content"));
   this._toolbarElementRef = Cu.getWeakReference(doc.getElementById("reader-toolbar"));
   this._messageElementRef = Cu.getWeakReference(doc.getElementById("reader-message"));
 
   this._scrollOffset = win.pageYOffset;
 
   doc.addEventListener("click", this, false);
@@ -146,16 +148,20 @@ AboutReader.prototype = {
   get _domainElement() {
     return this._domainElementRef.get();
   },
 
   get _titleElement() {
     return this._titleElementRef.get();
   },
 
+  get _readTimeElement() {
+    return this._readTimeElementRef.get();
+  },
+
   get _creditsElement() {
     return this._creditsElementRef.get();
   },
 
   get _contentElement() {
     return this._contentElementRef.get();
   },
 
@@ -717,24 +723,21 @@ AboutReader.prototype = {
     }
   },
 
   _maybeSetTextDirection: function Read_maybeSetTextDirection(article) {
     if (article.dir) {
       // Set "dir" attribute on content
       this._contentElement.setAttribute("dir", article.dir);
       this._headerElement.setAttribute("dir", article.dir);
-    } else {
-      this._languagePromise.then(language => {
-        // TODO: Remove the hardcoded language codes below once bug 1320265 is resolved.
-        if (["ar", "fa", "he", "ug", "ur"].includes(language)) {
-          this._contentElement.setAttribute("dir", "rtl");
-          this._headerElement.setAttribute("dir", "rtl");
-        }
-      });
+
+      // The native locale could be set differently than the article's text direction.
+      var localeDirection = gChromeRegistry.isLocaleRTL("global") ? "rtl" : "ltr";
+      this._readTimeElement.setAttribute("dir", localeDirection);
+      this._readTimeElement.style.textAlign = article.dir == "rtl" ? "right" : "left";
     }
   },
 
   _fixLocalLinks() {
     // We need to do this because preprocessing the content through nsIParserUtils
     // gives back a DOM with a <base> element. That influences how these URLs get
     // resolved, making them no longer match the document URI (which is
     // about:reader?url=...). To fix this, make all the hash URIs absolute. This
@@ -743,16 +746,24 @@ AboutReader.prototype = {
     // absolute, so we pick just fixing these in-document links explicitly.
     let localLinks = this._contentElement.querySelectorAll("a[href^='#']");
     for (let localLink of localLinks) {
       // Have to get the attribute because .href provides an absolute URI.
       localLink.href = this._doc.documentURI + localLink.getAttribute("href");
     }
   },
 
+  _formatReadTime(slowEstimate, fastEstimate) {
+    if (slowEstimate == fastEstimate) {
+      return gStrings.formatStringFromName("aboutReader.estimatedReadTimeValue", [slowEstimate], 1);
+    }
+
+    return gStrings.formatStringFromName("aboutReader.estimatedReadTimeRange", [fastEstimate, slowEstimate], 2);
+  },
+
   _showError: function() {
     this._headerElement.style.display = "none";
     this._contentElement.style.display = "none";
 
     let errorMessage = gStrings.GetStringFromName("aboutReader.loadError");
     this._messageElement.textContent = errorMessage;
     this._messageElement.style.display = "block";
 
@@ -784,52 +795,45 @@ AboutReader.prototype = {
     this._article = article;
 
     this._domainElement.href = article.url;
     let articleUri = Services.io.newURI(article.url, null, null);
     this._domainElement.textContent = this._stripHost(articleUri.host);
     this._creditsElement.textContent = article.byline;
 
     this._titleElement.textContent = article.title;
+    this._readTimeElement.textContent = this._formatReadTime(article.readingTimeMinsSlow, article.readingTimeMinsFast);
     this._doc.title = article.title;
 
     this._headerElement.style.display = "block";
 
     let parserUtils = Cc["@mozilla.org/parserutils;1"].getService(Ci.nsIParserUtils);
     let contentFragment = parserUtils.parseFragment(article.content,
       Ci.nsIParserUtils.SanitizerDropForms | Ci.nsIParserUtils.SanitizerAllowStyle,
       false, articleUri, this._contentElement);
     this._contentElement.innerHTML = "";
     this._contentElement.appendChild(contentFragment);
     this._fixLocalLinks();
-    this._findLanguage(article.textContent);
     this._maybeSetTextDirection(article);
+    this._foundLanguage(article.language);
 
     this._contentElement.style.display = "block";
     this._updateImageMargins();
 
     this._requestFavicon();
     this._doc.body.classList.add("loaded");
 
     this._goToReference(articleUri.ref);
 
     Services.obs.notifyObservers(this._win, "AboutReader:Ready", "");
 
     this._doc.dispatchEvent(
       new this._win.CustomEvent("AboutReaderContentReady", { bubbles: true, cancelable: false }));
   },
 
-  _findLanguage: function(textContent) {
-    if (gIsFirefoxDesktop) {
-      LanguageDetector.detectLanguage(textContent).then(result => {
-        this._foundLanguage(result.confident ? result.language : null);
-      });
-    }
-  },
-
   _hideContent: function() {
     this._headerElement.style.display = "none";
     this._contentElement.style.display = "none";
   },
 
   _showProgressDelayed: function() {
     this._win.setTimeout(function() {
       // No need to show progress if the article has been loaded,
--- a/toolkit/components/reader/ReaderMode.jsm
+++ b/toolkit/components/reader/ReaderMode.jsm
@@ -24,24 +24,27 @@ Cu.import("resource://gre/modules/XPCOMU
 Cu.importGlobalProperties(["XMLHttpRequest"]);
 
 XPCOMUtils.defineLazyModuleGetter(this, "CommonUtils", "resource://services-common/utils.js");
 XPCOMUtils.defineLazyModuleGetter(this, "Messaging", "resource://gre/modules/Messaging.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ReaderWorker", "resource://gre/modules/reader/ReaderWorker.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Task", "resource://gre/modules/Task.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "TelemetryStopwatch", "resource://gre/modules/TelemetryStopwatch.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "LanguageDetector", "resource:///modules/translation/LanguageDetector.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "Readability", function() {
   let scope = {};
   scope.dump = this.dump;
   Services.scriptloader.loadSubScript("resource://gre/modules/reader/Readability.js", scope);
   return scope["Readability"];
 });
 
+const gIsFirefoxDesktop = Services.appinfo.ID == "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}";
+
 this.ReaderMode = {
   // Version of the cache schema.
   CACHE_VERSION: 1,
 
   DEBUG: 0,
 
   // Don't try to parse the page if it has too many elements (for memory and
   // performance reasons)
@@ -456,16 +459,22 @@ this.ReaderMode = {
 
     // Readability returns a URI object, but we only care about the URL.
     article.url = article.uri.spec;
     delete article.uri;
 
     let flags = Ci.nsIDocumentEncoder.OutputSelectionOnly | Ci.nsIDocumentEncoder.OutputAbsoluteLinks;
     article.title = Cc["@mozilla.org/parserutils;1"].getService(Ci.nsIParserUtils)
                                                     .convertToPlainText(article.title, flags, 0);
+    if (gIsFirefoxDesktop) {
+      yield this._assignLanguage(article);
+      this._maybeAssignTextDirection(article);
+    }
+
+    this._assignReadTime(article);
 
     histogram.add(PARSE_SUCCESS);
     return article;
   }),
 
   get _cryptoHash() {
     delete this._cryptoHash;
     return this._cryptoHash = Cc["@mozilla.org/security/hash;1"].createInstance(Ci.nsICryptoHash);
@@ -505,10 +514,78 @@ this.ReaderMode = {
   _ensureCacheDir: function() {
     let dir = OS.Path.join(OS.Constants.Path.profileDir, "readercache");
     return OS.File.exists(dir).then(exists => {
       if (!exists) {
         return OS.File.makeDir(dir);
       }
       return undefined;
     });
-  }
+  },
+
+  /**
+   * Sets a global language string value if the result is confident
+   *
+   * @return Promise
+   * @resolves when the language is detected
+   */
+  _assignLanguage(article) {
+    return LanguageDetector.detectLanguage(article.textContent).then(result => {
+      article.language = result.confident ? result.language : null;
+    });
+  },
+
+  _maybeAssignTextDirection(article) {
+    // TODO: Remove the hardcoded language codes below once bug 1320265 is resolved.
+    if (!article.dir && ["ar", "fa", "he", "ug", "ur"].includes(article.language)) {
+      article.dir = "rtl";
+    }
+  },
+
+  /**
+   * Assigns the estimated reading time range of the article to the article object.
+   *
+   * @param article the article object to assign the reading time estimate to.
+   */
+  _assignReadTime(article) {
+    let lang = article.language || "en";
+    const readingSpeed = this._getReadingSpeedForLanguage(lang);
+    const charactersPerMinuteLow = readingSpeed.cpm - readingSpeed.variance;
+    const charactersPerMinuteHigh = readingSpeed.cpm + readingSpeed.variance;
+    const length = article.length;
+
+    article.readingTimeMinsSlow = Math.ceil(length / charactersPerMinuteLow);
+    article.readingTimeMinsFast  = Math.ceil(length / charactersPerMinuteHigh);
+  },
+
+  /**
+   * Returns the reading speed of a selection of languages with likely variance.
+   *
+   * Reading speed estimated from a study done on reading speeds in various languages.
+   * study can be found here: http://iovs.arvojournals.org/article.aspx?articleid=2166061
+   *
+   * @return object with characters per minute and variance. Defaults to English
+   *         if no suitable language is found in the collection.
+   */
+  _getReadingSpeedForLanguage(lang) {
+    const readingSpeed = new Map([
+      [ "en", {cpm: 987,  variance: 118 } ],
+      [ "ar", {cpm: 612,  variance: 88 } ],
+      [ "de", {cpm: 920,  variance: 86 } ],
+      [ "es", {cpm: 1025, variance: 127 } ],
+      [ "fi", {cpm: 1078, variance: 121 } ],
+      [ "fr", {cpm: 998,  variance: 126 } ],
+      [ "he", {cpm: 833,  variance: 130 } ],
+      [ "it", {cpm: 950,  variance: 140 } ],
+      [ "jw", {cpm: 357,  variance: 56 } ],
+      [ "nl", {cpm: 978,  variance: 143 } ],
+      [ "pl", {cpm: 916,  variance: 126 } ],
+      [ "pt", {cpm: 913,  variance: 145 } ],
+      [ "ru", {cpm: 986,  variance: 175 } ],
+      [ "sk", {cpm: 885,  variance: 145 } ],
+      [ "sv", {cpm: 917,  variance: 156 } ],
+      [ "tr", {cpm: 1054, variance: 156 } ],
+      [ "zh", {cpm: 255,  variance: 29 } ],
+    ]);
+
+    return readingSpeed.get(lang) || readingSpeed.get("en");
+  },
 };
--- a/toolkit/components/reader/content/aboutReader.html
+++ b/toolkit/components/reader/content/aboutReader.html
@@ -15,18 +15,23 @@
     <div id="reader-header" class="header">
       <style scoped>
         @import url("chrome://global/skin/aboutReaderControls.css");
       </style>
       <a id="reader-domain" class="domain"></a>
       <div class="domain-border"></div>
       <h1 id="reader-title"></h1>
       <div id="reader-credits" class="credits"></div>
+      <div id="meta-data" class="meta-data">
+        <div id="reader-estimated-time"></div>
+      </div>
     </div>
 
+    <hr>
+
     <div class="content">
       <style scoped>
         @import url("chrome://global/skin/aboutReaderContent.css");
       </style>
       <div id="moz-reader-content"></div>
     </div>
 
     <div>
@@ -41,33 +46,33 @@
     <style scoped>
       @import url("chrome://global/skin/aboutReaderControls.css");
     </style>
     <li><button id="close-button" class="button close-button"/></li>
     <ul id="style-dropdown" class="dropdown">
       <li><button class="dropdown-toggle button style-button"/></li>
       <li id="reader-popup" class="dropdown-popup">
         <div id="font-type-buttons"></div>
-        <hr></hr>
+        <hr>
         <div id="font-size-buttons">
           <button id="font-size-minus" class="minus-button"/>
           <button id="font-size-sample"/>
           <button id="font-size-plus" class="plus-button"/>
         </div>
-        <hr></hr>
+        <hr>
         <div id="content-width-buttons">
           <button id="content-width-minus" class="content-width-minus-button"/>
           <button id="content-width-plus" class="content-width-plus-button"/>
         </div>
-        <hr></hr>
+        <hr>
         <div id="line-height-buttons">
           <button id="line-height-minus" class="line-height-minus-button"/>
           <button id="line-height-plus" class="line-height-plus-button"/>
         </div>
-        <hr></hr>
+        <hr>
         <div id="color-scheme-buttons"></div>
         <div class="dropdown-arrow"/>
       </li>
     </ul>
   </ul>
 
 </body>
 
--- a/toolkit/components/reader/test/browser.ini
+++ b/toolkit/components/reader/test/browser.ini
@@ -8,8 +8,12 @@ support-files =
 support-files =
   readerModeArticleHiddenNodes.html
 [browser_readerMode_with_anchor.js]
 support-files =
   readerModeArticle.html
 [browser_bug1124271_readerModePinnedTab.js]
 support-files =
   readerModeArticle.html
+[browser_readerMode_readingTime.js]
+support-files =
+  readerModeArticle.html
+  readerModeArticleShort.html
new file mode 100644
--- /dev/null
+++ b/toolkit/components/reader/test/browser_readerMode_readingTime.js
@@ -0,0 +1,45 @@
+/* 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/. */
+
+"use strict";
+
+const TEST_PATH = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "http://example.com");
+
+/**
+ * Test that the reader mode correctly calculates and displays the
+ * estimated reading time for a normal length article
+ */
+add_task(function* () {
+  yield BrowserTestUtils.withNewTab(TEST_PATH + "readerModeArticle.html", function* (browser) {
+    let pageShownPromise = BrowserTestUtils.waitForContentEvent(browser, "AboutReaderContentReady");
+    let readerButton = document.getElementById("reader-mode-button");
+    readerButton.click();
+    yield pageShownPromise;
+    yield ContentTask.spawn(browser, null, function* () {
+      // make sure there is a reading time on the page and that it displays the correct information
+      let readingTimeElement = content.document.getElementById("reader-estimated-time");
+      ok(readingTimeElement, "Reading time element should be in document");
+      is(readingTimeElement.textContent, "9-12 min", "Reading time should be '9-12 min'");
+    });
+  });
+});
+
+/**
+ * Test that the reader mode correctly calculates and displays the
+ * estimated reading time for a short article
+ */
+add_task(function* () {
+  yield BrowserTestUtils.withNewTab(TEST_PATH + "readerModeArticleShort.html", function* (browser) {
+    let pageShownPromise = BrowserTestUtils.waitForContentEvent(browser, "AboutReaderContentReady");
+    let readerButton = document.getElementById("reader-mode-button");
+    readerButton.click();
+    yield pageShownPromise;
+    yield ContentTask.spawn(browser, null, function* () {
+      // make sure there is a reading time on the page and that it displays the correct information
+      let readingTimeElement = content.document.getElementById("reader-estimated-time");
+      ok(readingTimeElement, "Reading time element should be in document");
+      is(readingTimeElement.textContent, "1 min", "Reading time should be '1 min'");
+    });
+  });
+});
new file mode 100644
--- /dev/null
+++ b/toolkit/components/reader/test/readerModeArticleShort.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Article title</title>
+<meta name="description" content="This is the article description." />
+</head>
+<body>
+<header>Site header</header>
+<div>
+<h1>Article title</h1>
+<h2 class="author">by Jane Doe</h2>
+<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id dolor. Pellentesque auctor nisi id magna consequat sagittis. Curabitur dapibus enim sit amet elit pharetra tincidunt feugiat nisl imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed odio eros. Donec viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetu</p>
+</body>
+</html>
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -181,16 +181,26 @@
   },
   "COMPOSITE_FRAME_ROUNDTRIP_TIME" : {
     "expires_in_version": "never",
     "description": "Time from vsync to finishing a composite in milliseconds.",
     "kind": "exponential",
     "high": 1000,
     "n_buckets": 50
   },
+  "CONTENT_PROCESS_LAUNCH_TIME_MS" : {
+    "alert_emails": ["bsmedberg@mozilla.com", "mconley@mozilla.com"],
+    "expires_in_version": "57",
+    "bug_numbers": [1304790],
+    "kind": "exponential",
+    "high": 64000,
+    "n_buckets": 100,
+    "releaseChannelCollection": "opt-out",
+    "description": "Content process launch time until the GetXPCOMProcessAttributes message is received, in milliseconds"
+  },
   "CONTENT_RESPONSE_DURATION" : {
     "alert_emails": ["kgupta@mozilla.com"],
     "bug_numbers": [1261373],
     "expires_in_version": "55",
     "description": "Main thread response times for APZ notifications about input events (ms)",
     "kind" : "exponential",
     "high": 60000,
     "n_buckets": 50
--- a/toolkit/locales/en-US/chrome/global/aboutReader.properties
+++ b/toolkit/locales/en-US/chrome/global/aboutReader.properties
@@ -8,16 +8,19 @@
 aboutReader.loading2=Loading…
 aboutReader.loadError=Failed to load article from page
 
 aboutReader.colorScheme.light=Light
 aboutReader.colorScheme.dark=Dark
 aboutReader.colorScheme.sepia=Sepia
 aboutReader.colorScheme.auto=Auto
 
+aboutReader.estimatedReadTimeValue=%S min
+aboutReader.estimatedReadTimeRange=%S-%S min
+
 # LOCALIZATION NOTE (aboutReader.fontType.serif, aboutReader.fontType.sans-serif):
 # These are the styles of typeface that are options in the reader view controls.
 aboutReader.fontType.serif=Serif
 aboutReader.fontType.sans-serif=Sans-serif
 
 # LOCALIZATION NOTE (aboutReader.fontTypeSample): String used to sample font types.
 aboutReader.fontTypeSample=Aa
 
--- a/toolkit/themes/shared/aboutReaderControls.css
+++ b/toolkit/themes/shared/aboutReaderControls.css
@@ -58,21 +58,26 @@
   width: 100%;
   margin: 30px 0;
   padding: 0;
 }
 
 .header > .credits {
   font-size: 0.9em;
   line-height: 1.48em;
-  margin: 0 0 30px 0;
+  margin: 0 0 10px 0;
   padding: 0;
   font-style: italic;
 }
 
+.header > .meta-data {
+  font-size: 0.65em;
+  margin: 0 0 15px 0;
+}
+
 /*======= Controls toolbar =======*/
 
 .toolbar {
   font-family: Helvetica, Arial, sans-serif;
   position: fixed;
   height: 100%;
   top: 0;
   left: 0;
--- a/tools/profiler/gecko/ThreadResponsiveness.cpp
+++ b/tools/profiler/gecko/ThreadResponsiveness.cpp
@@ -20,23 +20,21 @@ class CheckResponsivenessTask : public m
                                 public nsITimerCallback {
 public:
   CheckResponsivenessTask()
     : mLastTracerTime(TimeStamp::Now())
     , mMonitor("CheckResponsivenessTask")
     , mTimer(nullptr)
     , mStop(false)
   {
-    MOZ_COUNT_CTOR(CheckResponsivenessTask);
   }
 
 protected:
   ~CheckResponsivenessTask()
   {
-    MOZ_COUNT_DTOR(CheckResponsivenessTask);
   }
 
 public:
   NS_IMETHOD Run() override
   {
     MonitorAutoLock mon(mMonitor);
     if (mStop)
       return NS_OK;
--- a/widget/PuppetWidget.cpp
+++ b/widget/PuppetWidget.cpp
@@ -80,30 +80,26 @@ PuppetWidget::PuppetWidget(TabChild* aTa
   , mMemoryPressureObserver(nullptr)
   , mDPI(-1)
   , mRounding(-1)
   , mDefaultScale(-1)
   , mCursorHotspotX(0)
   , mCursorHotspotY(0)
   , mNativeKeyCommandsValid(false)
 {
-  MOZ_COUNT_CTOR(PuppetWidget);
-
   mSingleLineCommands.SetCapacity(4);
   mMultiLineCommands.SetCapacity(4);
   mRichTextCommands.SetCapacity(4);
 
   // Setting 'Unknown' means "not yet cached".
   mInputContext.mIMEState.mEnabled = IMEState::UNKNOWN;
 }
 
 PuppetWidget::~PuppetWidget()
 {
-  MOZ_COUNT_DTOR(PuppetWidget);
-
   Destroy();
 }
 
 void
 PuppetWidget::InfallibleCreate(nsIWidget* aParent,
                                nsNativeWidget aNativeParent,
                                const LayoutDeviceIntRect& aRect,
                                nsWidgetInitData* aInitData)
--- a/widget/android/EventDispatcher.cpp
+++ b/widget/android/EventDispatcher.cpp
@@ -233,17 +233,21 @@ BoxObject(JSContext* aCx, JS::HandleValu
         const JS::RootedId id(aCx, ids[i]);
         JS::RootedValue idVal(aCx);
         JS::RootedValue val(aCx);
         jni::Object::LocalRef key(aOut.Env());
         jni::Object::LocalRef value(aOut.Env());
 
         NS_ENSURE_TRUE(CheckJS(aCx, JS_IdToValue(aCx, id, &idVal)),
                        NS_ERROR_FAILURE);
-        NS_ENSURE_TRUE(idVal.isString(), NS_ERROR_FAILURE);
+
+        JS::RootedString idStr(aCx, JS::ToString(aCx, idVal));
+        NS_ENSURE_TRUE(CheckJS(aCx, !!idStr), NS_ERROR_FAILURE);
+
+        idVal.setString(idStr);
         NS_ENSURE_SUCCESS(BoxString(aCx, idVal, key), NS_ERROR_FAILURE);
         NS_ENSURE_TRUE(CheckJS(aCx, JS_GetPropertyById(aCx, obj, id, &val)),
                        NS_ERROR_FAILURE);
 
         nsresult rv = BoxValue(aCx, val, value);
         if (rv == NS_ERROR_INVALID_ARG && !JS_IsExceptionPending(aCx)) {
             nsAutoJSString autoStr;
             if (CheckJS(aCx, autoStr.init(aCx, idVal.toString()))) {
--- a/widget/gtk/gtk2drawing.c
+++ b/widget/gtk/gtk2drawing.c
@@ -1788,17 +1788,17 @@ moz_gtk_treeview_expander_paint(GdkDrawa
 }
 
 static gint
 moz_gtk_combo_box_paint(GdkDrawable* drawable, GdkRectangle* rect,
                         GdkRectangle* cliprect, GtkWidgetState* state,
                         gboolean ishtml, GtkTextDirection direction)
 {
     GdkRectangle arrow_rect, real_arrow_rect;
-    gint arrow_size, separator_width;
+    gint separator_width;
     gboolean wide_separators;
     GtkStateType state_type = ConvertGtkState(state);
     GtkShadowType shadow_type = state->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
     GtkStyle* style;
     GtkRequisition arrow_req;
 
     ensure_combo_box_widgets();
 
--- a/widget/windows/WidgetTraceEvent.cpp
+++ b/widget/windows/WidgetTraceEvent.cpp
@@ -29,22 +29,17 @@ namespace {
 
 // Used for signaling the background thread from the main thread.
 HANDLE sEventHandle = nullptr;
 
 // We need a runnable in order to find the hidden window on the main
 // thread.
 class HWNDGetter : public mozilla::Runnable {
 public:
-  HWNDGetter() : hidden_window_hwnd(nullptr) {
-    MOZ_COUNT_CTOR(HWNDGetter);
-  }
-  ~HWNDGetter() {
-    MOZ_COUNT_DTOR(HWNDGetter);
-  }
+  HWNDGetter() : hidden_window_hwnd(nullptr) {}
 
   HWND hidden_window_hwnd;
 
   NS_IMETHOD Run() override {
     // Jump through some hoops to locate the hidden window.
     nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
     nsCOMPtr<nsIXULWindow> hiddenWindow;
 
--- a/xpcom/glue/nsISupportsImpl.h
+++ b/xpcom/glue/nsISupportsImpl.h
@@ -84,47 +84,55 @@ private:
 #define NS_LOG_RELEASE(_p, _rc, _type) \
   NS_LogRelease((_p), (_rc), (_type))
 
 #include "mozilla/TypeTraits.h"
 #define MOZ_ASSERT_CLASSNAME(_type)                         \
   static_assert(mozilla::IsClass<_type>::value,             \
                 "Token '" #_type "' is not a class type.")
 
+#define MOZ_ASSERT_NOT_ISUPPORTS(_type)                        \
+  static_assert(!mozilla::IsBaseOf<nsISupports, _type>::value, \
+                "nsISupports classes don't need to call MOZ_COUNT_CTOR or MOZ_COUNT_DTOR");
+
 // Note that the following constructor/destructor logging macros are redundant
 // for refcounted objects that log via the NS_LOG_ADDREF/NS_LOG_RELEASE macros.
 // Refcount logging is preferred.
 #define MOZ_COUNT_CTOR(_type)                                 \
 do {                                                          \
   MOZ_ASSERT_CLASSNAME(_type);                                \
+  MOZ_ASSERT_NOT_ISUPPORTS(_type);                            \
   NS_LogCtor((void*)this, #_type, sizeof(*this));             \
 } while (0)
 
 #define MOZ_COUNT_CTOR_INHERITED(_type, _base)                    \
 do {                                                              \
   MOZ_ASSERT_CLASSNAME(_type);                                    \
   MOZ_ASSERT_CLASSNAME(_base);                                    \
+  MOZ_ASSERT_NOT_ISUPPORTS(_type);                                \
   NS_LogCtor((void*)this, #_type, sizeof(*this) - sizeof(_base)); \
 } while (0)
 
 #define MOZ_LOG_CTOR(_ptr, _name, _size) \
 do {                                     \
   NS_LogCtor((void*)_ptr, _name, _size); \
 } while (0)
 
 #define MOZ_COUNT_DTOR(_type)                                 \
 do {                                                          \
   MOZ_ASSERT_CLASSNAME(_type);                                \
+  MOZ_ASSERT_NOT_ISUPPORTS(_type);                            \
   NS_LogDtor((void*)this, #_type, sizeof(*this));             \
 } while (0)
 
 #define MOZ_COUNT_DTOR_INHERITED(_type, _base)                    \
 do {                                                              \
   MOZ_ASSERT_CLASSNAME(_type);                                    \
   MOZ_ASSERT_CLASSNAME(_base);                                    \
+  MOZ_ASSERT_NOT_ISUPPORTS(_type);                                \
   NS_LogDtor((void*)this, #_type, sizeof(*this) - sizeof(_base)); \
 } while (0)
 
 #define MOZ_LOG_DTOR(_ptr, _name, _size) \
 do {                                     \
   NS_LogDtor((void*)_ptr, _name, _size); \
 } while (0)
 
--- a/xpcom/reflect/xptcall/xptcprivate.h
+++ b/xpcom/reflect/xptcall/xptcprivate.h
@@ -42,22 +42,22 @@ public:
 class nsXPTCStubBase final : public nsIXPTCStubBase
 {
 public:
     NS_DECL_ISUPPORTS_INHERITED
 
 #include "xptcstubsdef.inc"
 
     nsXPTCStubBase(nsIXPTCProxy* aOuter, xptiInterfaceEntry *aEntry)
-        : mOuter(aOuter), mEntry(aEntry) { MOZ_COUNT_CTOR(nsXPTCStubBase); }
+        : mOuter(aOuter), mEntry(aEntry) {}
 
     nsIXPTCProxy*          mOuter;
     xptiInterfaceEntry*    mEntry;
 
-    ~nsXPTCStubBase() { MOZ_COUNT_DTOR(nsXPTCStubBase); }
+    ~nsXPTCStubBase() {}
 };
 
 #undef STUB_ENTRY
 #undef SENTINEL_ENTRY
 
 #if defined(__clang__) || defined(__GNUC__)
 #define ATTRIBUTE_USED __attribute__ ((__used__))
 #else
--- a/xpcom/threads/SharedThreadPool.cpp
+++ b/xpcom/threads/SharedThreadPool.cpp
@@ -154,23 +154,21 @@ NS_IMETHODIMP_(MozExternalRefCountType) 
 NS_IMPL_QUERY_INTERFACE(SharedThreadPool, nsIThreadPool, nsIEventTarget)
 
 SharedThreadPool::SharedThreadPool(const nsCString& aName,
                                    nsIThreadPool* aPool)
   : mName(aName)
   , mPool(aPool)
   , mRefCnt(0)
 {
-  MOZ_COUNT_CTOR(SharedThreadPool);
   mEventTarget = do_QueryInterface(aPool);
 }
 
 SharedThreadPool::~SharedThreadPool()
 {
-  MOZ_COUNT_DTOR(SharedThreadPool);
 }
 
 nsresult
 SharedThreadPool::EnsureThreadLimitIsAtLeast(uint32_t aLimit)
 {
   // We limit the number of threads that we use. Note that we
   // set the thread limit to the same as the idle limit so that we're not
   // constantly creating and destroying threads (see Bug 881954). When the
--- a/xpcom/threads/nsTimerImpl.cpp
+++ b/xpcom/threads/nsTimerImpl.cpp
@@ -138,26 +138,24 @@ nsTimer::Release(void)
 nsTimerImpl::nsTimerImpl(nsITimer* aTimer) :
   mClosure(nullptr),
   mName(nsTimerImpl::Nothing),
   mCallbackType(CallbackType::Unknown),
   mGeneration(0),
   mDelay(0),
   mITimer(aTimer)
 {
-  MOZ_COUNT_CTOR(nsTimerImpl);
   // XXXbsmedberg: shouldn't this be in Init()?
   mEventTarget = static_cast<nsIEventTarget*>(NS_GetCurrentThread());
 
   mCallback.c = nullptr;
 }
 
 nsTimerImpl::~nsTimerImpl()
 {
-  MOZ_COUNT_DTOR(nsTimerImpl);
   ReleaseCallback();
 }
 
 //static
 nsresult
 nsTimerImpl::Startup()
 {
   nsresult rv;