Merge mozilla-inbound to mozilla-central. a=merge
authorCosmin Sabou <csabou@mozilla.com>
Sun, 30 Dec 2018 11:31:03 +0200
changeset 509260 19fc512f3c95
parent 509237 592d38d2892f (current diff)
parent 509259 8c39d7d39ea5 (diff)
child 509262 bf82f8b197f3
child 509267 51576a3495f5
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone66.0a1
first release with
nightly linux32
19fc512f3c95 / 66.0a1 / 20181230093119 / files
nightly linux64
19fc512f3c95 / 66.0a1 / 20181230093119 / files
nightly mac
19fc512f3c95 / 66.0a1 / 20181230093119 / files
nightly win32
19fc512f3c95 / 66.0a1 / 20181230093119 / files
nightly win64
19fc512f3c95 / 66.0a1 / 20181230093119 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-inbound to mozilla-central. a=merge
dom/base/nsDOMWindowUtils.cpp
dom/base/nsDocument.cpp
layout/base/MobileViewportManager.cpp
layout/base/PresShell.cpp
layout/generic/nsGfxScrollFrame.cpp
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -11061,24 +11061,17 @@ nsDocShell::AddState(JS::Handle<JS::Valu
           0;
       if (NS_FAILED(secMan->CheckSameOriginURI(currentURI, newURI, true,
                                                isPrivateWin)) ||
           !currentUserPass.Equals(newUserPass)) {
         return NS_ERROR_DOM_SECURITY_ERR;
       }
     } else {
       // It's a file:// URI
-      nsCOMPtr<nsIScriptObjectPrincipal> docScriptObj =
-          do_QueryInterface(document);
-
-      if (!docScriptObj) {
-        return NS_ERROR_DOM_SECURITY_ERR;
-      }
-
-      nsCOMPtr<nsIPrincipal> principal = docScriptObj->GetPrincipal();
+      nsCOMPtr<nsIPrincipal> principal = document->GetPrincipal();
 
       if (!principal ||
           NS_FAILED(principal->CheckMayLoad(newURI, true, false))) {
         return NS_ERROR_DOM_SECURITY_ERR;
       }
     }
 
     if (currentURI) {
--- a/dom/animation/AnimationEffect.h
+++ b/dom/animation/AnimationEffect.h
@@ -36,17 +36,17 @@ class AnimationEffect : public nsISuppor
 
   virtual KeyframeEffect* AsKeyframeEffect() { return nullptr; }
 
   virtual ElementPropertyTransition* AsTransition() { return nullptr; }
   virtual const ElementPropertyTransition* AsTransition() const {
     return nullptr;
   }
 
-  nsISupports* GetParentObject() const { return mDocument; }
+  nsISupports* GetParentObject() const { return ToSupports(mDocument); }
 
   bool IsCurrent() const;
   bool IsInEffect() const;
   bool HasFiniteActiveDuration() const {
     return SpecifiedTiming().ActiveDuration() != TimeDuration::Forever();
   }
 
   // AnimationEffect interface
--- a/dom/animation/AnimationTimeline.cpp
+++ b/dom/animation/AnimationTimeline.cpp
@@ -6,16 +6,18 @@
 
 #include "AnimationTimeline.h"
 #include "mozilla/AnimationComparator.h"
 #include "mozilla/dom/Animation.h"
 
 namespace mozilla {
 namespace dom {
 
+AnimationTimeline::~AnimationTimeline() { mAnimationOrder.clear(); }
+
 NS_IMPL_CYCLE_COLLECTION_CLASS(AnimationTimeline)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AnimationTimeline)
   tmp->mAnimationOrder.clear();
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow, mAnimations)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
--- a/dom/animation/AnimationTimeline.h
+++ b/dom/animation/AnimationTimeline.h
@@ -26,17 +26,17 @@ class Animation;
 
 class AnimationTimeline : public nsISupports, public nsWrapperCache {
  public:
   explicit AnimationTimeline(nsIGlobalObject* aWindow) : mWindow(aWindow) {
     MOZ_ASSERT(mWindow);
   }
 
  protected:
-  virtual ~AnimationTimeline() { mAnimationOrder.clear(); }
+  virtual ~AnimationTimeline();
 
  public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(AnimationTimeline)
 
   nsIGlobalObject* GetParentObject() const { return mWindow; }
 
   // AnimationTimeline methods
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -14,16 +14,17 @@
 
 #include "AnimationCommon.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/StaticPrefs.h"
 #include "mozilla/dom/Animation.h"
 #include "mozilla/dom/Attr.h"
 #include "mozilla/dom/Flex.h"
 #include "mozilla/dom/Grid.h"
+#include "mozilla/dom/ScriptLoader.h"
 #include "mozilla/dom/Text.h"
 #include "mozilla/gfx/Matrix.h"
 #include "nsAtom.h"
 #include "nsDOMAttributeMap.h"
 #include "nsIContentInlines.h"
 #include "mozilla/dom/NodeInfo.h"
 #include "nsIDocumentInlines.h"
 #include "mozilla/dom/DocumentTimeline.h"
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -26,16 +26,17 @@
 #include "mozilla/TextEditor.h"
 #include "mozilla/TouchEvents.h"
 #include "mozilla/URLExtraData.h"
 #include "mozilla/dom/Attr.h"
 #include "nsDOMAttributeMap.h"
 #include "nsAtom.h"
 #include "mozilla/dom/NodeInfo.h"
 #include "mozilla/dom/Event.h"
+#include "mozilla/dom/ScriptLoader.h"
 #include "mozilla/dom/TouchEvent.h"
 #include "nsIDocumentInlines.h"
 #include "nsIDocumentEncoder.h"
 #include "nsIContentIterator.h"
 #include "nsFocusManager.h"
 #include "nsILinkHandler.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIURL.h"
--- a/dom/base/nsContentSink.cpp
+++ b/dom/base/nsContentSink.cpp
@@ -906,21 +906,16 @@ void nsContentSink::Preconnect(const nsA
 
 nsresult nsContentSink::SelectDocAppCache(
     nsIApplicationCache* aLoadApplicationCache, nsIURI* aManifestURI,
     bool aFetchedWithHTTPGetOrEquiv, CacheSelectionAction* aAction) {
   nsresult rv;
 
   *aAction = CACHE_SELECTION_NONE;
 
-  nsCOMPtr<nsIApplicationCacheContainer> applicationCacheDocument =
-      do_QueryInterface(mDocument);
-  NS_ASSERTION(applicationCacheDocument,
-               "mDocument must implement nsIApplicationCacheContainer.");
-
   if (aLoadApplicationCache) {
     nsCOMPtr<nsIURI> groupURI;
     rv = aLoadApplicationCache->GetManifestURI(getter_AddRefs(groupURI));
     NS_ENSURE_SUCCESS(rv, rv);
 
     bool equal = false;
     rv = groupURI->Equals(aManifestURI, &equal);
     NS_ENSURE_SUCCESS(rv, rv);
@@ -939,17 +934,17 @@ nsresult nsContentSink::SelectDocAppCach
       mDocumentURI->GetAsciiSpec(docURISpec);
       aLoadApplicationCache->GetClientID(clientID);
       SINK_TRACE(static_cast<LogModule*>(gContentSinkLogModuleInfo),
                  SINK_TRACE_CALLS,
                  ("Selection: assigning app cache %s to document %s",
                   clientID.get(), docURISpec.get()));
 #endif
 
-      rv = applicationCacheDocument->SetApplicationCache(aLoadApplicationCache);
+      rv = mDocument->SetApplicationCache(aLoadApplicationCache);
       NS_ENSURE_SUCCESS(rv, rv);
 
       // Document will be added as implicit entry to the cache as part of
       // the update process.
       *aAction = CACHE_SELECTION_UPDATE;
     }
   } else {
     // The document was not loaded from an application cache
@@ -976,32 +971,27 @@ nsresult nsContentSink::SelectDocAppCach
   *aManifestURI = nullptr;
   *aAction = CACHE_SELECTION_NONE;
 
   nsresult rv;
 
   if (aLoadApplicationCache) {
     // The document was loaded from an application cache, use that
     // application cache as the document's application cache.
-    nsCOMPtr<nsIApplicationCacheContainer> applicationCacheDocument =
-        do_QueryInterface(mDocument);
-    NS_ASSERTION(applicationCacheDocument,
-                 "mDocument must implement nsIApplicationCacheContainer.");
-
 #ifdef DEBUG
     nsAutoCString docURISpec, clientID;
     mDocumentURI->GetAsciiSpec(docURISpec);
     aLoadApplicationCache->GetClientID(clientID);
     SINK_TRACE(static_cast<LogModule*>(gContentSinkLogModuleInfo),
                SINK_TRACE_CALLS,
                ("Selection, no manifest: assigning app cache %s to document %s",
                 clientID.get(), docURISpec.get()));
 #endif
 
-    rv = applicationCacheDocument->SetApplicationCache(aLoadApplicationCache);
+    rv = mDocument->SetApplicationCache(aLoadApplicationCache);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Return the uri and invoke the update process for the selected
     // application cache.
     rv = aLoadApplicationCache->GetManifestURI(aManifestURI);
     NS_ENSURE_SUCCESS(rv, rv);
 
     *aAction = CACHE_SELECTION_UPDATE;
@@ -1558,22 +1548,22 @@ void nsContentSink::WillBuildModelImpl()
 
 /* static */
 void nsContentSink::NotifyDocElementCreated(nsIDocument* aDoc) {
   MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
 
   nsCOMPtr<nsIObserverService> observerService =
       mozilla::services::GetObserverService();
   if (observerService) {
-    observerService->NotifyObservers(aDoc, "document-element-inserted",
-                                     EmptyString().get());
+    observerService->NotifyObservers(
+        ToSupports(aDoc), "document-element-inserted", EmptyString().get());
   }
 
   nsContentUtils::DispatchChromeEvent(
-      aDoc, aDoc, NS_LITERAL_STRING("DOMDocElementInserted"), CanBubble::eYes,
-      Cancelable::eNo);
+      aDoc, ToSupports(aDoc), NS_LITERAL_STRING("DOMDocElementInserted"),
+      CanBubble::eYes, Cancelable::eNo);
 }
 
 NS_IMETHODIMP
 nsContentSink::GetName(nsACString& aName) {
   aName.AssignLiteral("nsContentSink_timer");
   return NS_OK;
 }
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -4,16 +4,17 @@
  * 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 "nsDOMWindowUtils.h"
 
 #include "mozilla/layers/CompositorBridgeChild.h"
 #include "mozilla/layers/LayerTransactionChild.h"
 #include "nsPresContext.h"
+#include "nsContentList.h"
 #include "nsError.h"
 #include "nsQueryContentEventResult.h"
 #include "nsGlobalWindow.h"
 #include "nsIDocument.h"
 #include "nsFocusManager.h"
 #include "nsFrameManager.h"
 #include "nsRefreshDriver.h"
 #include "mozilla/dom/Animation.h"
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -38,43 +38,48 @@
 #include "nsILoadContext.h"
 #include "nsITextControlFrame.h"
 #include "nsNumberControlFrame.h"
 #include "nsUnicharUtils.h"
 #include "nsContentList.h"
 #include "nsCSSPseudoElements.h"
 #include "nsIObserver.h"
 #include "nsIBaseWindow.h"
+#include "nsILayoutHistoryState.h"
 #include "mozilla/css/Loader.h"
 #include "mozilla/css/ImageLoader.h"
 #include "nsDocShell.h"
 #include "nsDocShellLoadTypes.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsCOMArray.h"
 #include "nsQueryObject.h"
 #include "mozilla/Services.h"
 #include "nsScreen.h"
 #include "ChildIterator.h"
 
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/BasicEvents.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/FullscreenChange.h"
+#include "mozilla/PendingAnimationTracker.h"
 
 #include "mozilla/dom/Attr.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/FeaturePolicy.h"
 #include "mozilla/dom/FramingChecker.h"
 #include "mozilla/dom/HTMLSharedElement.h"
 #include "mozilla/dom/Navigator.h"
+#include "mozilla/dom/Performance.h"
 #include "mozilla/dom/ServiceWorkerContainer.h"
+#include "mozilla/dom/ScriptLoader.h"
+#include "mozilla/dom/StyleSheetList.h"
 #include "mozilla/dom/SVGUseElement.h"
 #include "nsGenericHTMLElement.h"
 #include "mozilla/dom/CDATASection.h"
 #include "mozilla/dom/ProcessingInstruction.h"
 #include "nsDOMString.h"
 #include "nsNodeUtils.h"
 #include "nsLayoutUtils.h"  // for GetFrameForPoint
 #include "nsIFrame.h"
@@ -668,17 +673,27 @@ size_t nsIdentifierMapEntry::SizeOfExclu
 
 class SubDocMapEntry : public PLDHashEntryHdr {
  public:
   // Both of these are strong references
   Element* mKey;  // must be first, to look like PLDHashEntryStub
   nsIDocument* mSubDocument;
 };
 
-// nsOnloadBlocker implementation
+class nsOnloadBlocker final : public nsIRequest {
+ public:
+  nsOnloadBlocker() {}
+
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIREQUEST
+
+ private:
+  ~nsOnloadBlocker() {}
+};
+
 NS_IMPL_ISUPPORTS(nsOnloadBlocker, nsIRequest)
 
 NS_IMETHODIMP
 nsOnloadBlocker::GetName(nsACString& aResult) {
   aResult.AssignLiteral("about:document-onload-blocker");
   return NS_OK;
 }
 
@@ -787,17 +802,17 @@ void nsExternalResourceMap::Traverse(
   // mPendingLoads will get cleared out as the requests complete, so
   // no need to worry about those here.
   for (auto iter = mMap.ConstIter(); !iter.Done(); iter.Next()) {
     nsExternalResourceMap::ExternalResource* resource = iter.UserData();
 
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*aCallback,
                                        "mExternalResourceMap.mMap entry"
                                        "->mDocument");
-    aCallback->NoteXPCOMChild(resource->mDocument);
+    aCallback->NoteXPCOMChild(ToSupports(resource->mDocument));
 
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*aCallback,
                                        "mExternalResourceMap.mMap entry"
                                        "->mViewer");
     aCallback->NoteXPCOMChild(resource->mViewer);
 
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*aCallback,
                                        "mExternalResourceMap.mMap entry"
@@ -894,17 +909,18 @@ nsresult nsExternalResourceMap::AddExter
   newResource->mLoadGroup = aLoadGroup;
   if (doc) {
     TransferZoomLevels(aDisplayDocument, doc);
     TransferShowingState(aDisplayDocument, doc);
   }
 
   const nsTArray<nsCOMPtr<nsIObserver>>& obs = load->Observers();
   for (uint32_t i = 0; i < obs.Length(); ++i) {
-    obs[i]->Observe(doc, "external-resource-document-created", nullptr);
+    obs[i]->Observe(ToSupports(doc), "external-resource-document-created",
+                    nullptr);
   }
 
   return rv;
 }
 
 NS_IMPL_ISUPPORTS(nsExternalResourceMap::PendingLoad, nsIStreamListener,
                   nsIRequestObserver)
 
@@ -1619,41 +1635,41 @@ nsDocument::~nsDocument() {
 
   ClearAllBoxObjects();
 
   mPendingTitleChangeEvent.Revoke();
 
   mPlugins.Clear();
 }
 
-NS_INTERFACE_TABLE_HEAD(nsDocument)
+NS_INTERFACE_TABLE_HEAD(nsIDocument)
   NS_WRAPPERCACHE_INTERFACE_TABLE_ENTRY
   NS_INTERFACE_TABLE_BEGIN
-    NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(nsDocument, nsISupports, nsINode)
-    NS_INTERFACE_TABLE_ENTRY(nsDocument, nsINode)
-    NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDocument)
-    NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIScriptObjectPrincipal)
-    NS_INTERFACE_TABLE_ENTRY(nsDocument, mozilla::dom::EventTarget)
-    NS_INTERFACE_TABLE_ENTRY(nsDocument, nsISupportsWeakReference)
-    NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIRadioGroupContainer)
-    NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIMutationObserver)
-    NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIApplicationCacheContainer)
+    NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(nsIDocument, nsISupports, nsINode)
+    NS_INTERFACE_TABLE_ENTRY(nsIDocument, nsINode)
+    NS_INTERFACE_TABLE_ENTRY(nsIDocument, nsIDocument)
+    NS_INTERFACE_TABLE_ENTRY(nsIDocument, nsIScriptObjectPrincipal)
+    NS_INTERFACE_TABLE_ENTRY(nsIDocument, mozilla::dom::EventTarget)
+    NS_INTERFACE_TABLE_ENTRY(nsIDocument, nsISupportsWeakReference)
+    NS_INTERFACE_TABLE_ENTRY(nsIDocument, nsIRadioGroupContainer)
+    NS_INTERFACE_TABLE_ENTRY(nsIDocument, nsIMutationObserver)
+    NS_INTERFACE_TABLE_ENTRY(nsIDocument, nsIApplicationCacheContainer)
   NS_INTERFACE_TABLE_END
-  NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsDocument)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsIDocument)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDocument)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsIDocument)
 NS_IMETHODIMP_(MozExternalRefCountType)
-nsDocument::Release() {
+nsIDocument::Release() {
   MOZ_ASSERT(0 != mRefCnt, "dup release");
-  NS_ASSERT_OWNINGTHREAD(nsDocument);
-  nsISupports* base = NS_CYCLE_COLLECTION_CLASSNAME(nsDocument)::Upcast(this);
+  NS_ASSERT_OWNINGTHREAD(nsIDocument);
+  nsISupports* base = NS_CYCLE_COLLECTION_CLASSNAME(nsIDocument)::Upcast(this);
   bool shouldDelete = false;
   nsrefcnt count = mRefCnt.decr(base, &shouldDelete);
-  NS_LOG_RELEASE(this, count, "nsDocument");
+  NS_LOG_RELEASE(this, count, "nsIDocument");
   if (count == 0) {
     if (mStackRefCnt && !mNeedsReleaseAfterStackRefCntRelease) {
       mNeedsReleaseAfterStackRefCntRelease = true;
       NS_ADDREF_THIS();
       return mRefCnt.get();
     }
     mRefCnt.incr(base);
     nsNodeUtils::LastRelease(this);
@@ -1662,61 +1678,61 @@ nsDocument::Release() {
       mRefCnt.stabilizeForDeletion();
       DeleteCycleCollectable();
     }
   }
   return count;
 }
 
 NS_IMETHODIMP_(void)
-nsDocument::DeleteCycleCollectable() { delete this; }
-
-NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsDocument)
+nsIDocument::DeleteCycleCollectable() { delete this; }
+
+NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsIDocument)
   if (Element::CanSkip(tmp, aRemovingAllowed)) {
     EventListenerManager* elm = tmp->GetExistingListenerManager();
     if (elm) {
       elm->MarkForCC();
     }
     return true;
   }
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
 
-NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsDocument)
+NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsIDocument)
   return Element::CanSkipInCC(tmp);
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
 
-NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsDocument)
+NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsIDocument)
   return Element::CanSkipThis(tmp);
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
 
 static const char* kNSURIs[] = {"([none])", "(xmlns)", "(xml)", "(xhtml)",
                                 "(XLink)",  "(XSLT)",  "(XBL)", "(MathML)",
                                 "(RDF)",    "(XUL)"};
 
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsIDocument)
   if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
     char name[512];
     nsAutoCString loadedAsData;
     if (tmp->IsLoadedAsData()) {
       loadedAsData.AssignLiteral("data");
     } else {
       loadedAsData.AssignLiteral("normal");
     }
     uint32_t nsid = tmp->GetDefaultNamespaceID();
     nsAutoCString uri;
     if (tmp->mDocumentURI) uri = tmp->mDocumentURI->GetSpecOrDefault();
     if (nsid < ArrayLength(kNSURIs)) {
-      SprintfLiteral(name, "nsDocument %s %s %s", loadedAsData.get(),
+      SprintfLiteral(name, "nsIDocument %s %s %s", loadedAsData.get(),
                      kNSURIs[nsid], uri.get());
     } else {
-      SprintfLiteral(name, "nsDocument %s %s", loadedAsData.get(), uri.get());
+      SprintfLiteral(name, "nsIDocument %s %s", loadedAsData.get(), uri.get());
     }
     cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name);
   } else {
-    NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsDocument, tmp->mRefCnt.get())
+    NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsIDocument, tmp->mRefCnt.get())
   }
 
   if (!nsINode::Traverse(tmp, cb)) {
     return NS_SUCCESS_INTERRUPTED_TRAVERSE;
   }
 
   if (tmp->mMaybeEndOutermostXBLUpdateRunner) {
     // The cached runnable keeps a reference to the document object..
@@ -1755,17 +1771,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
       NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mBoxObjectTable entry");
       cb.NoteXPCOMChild(iter.UserData());
     }
   }
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChannel)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLayoutHistoryState)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOnloadBlocker)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFirstBaseNodeWithHref)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMImplementation)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mImageMaps)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOrientationPendingPromise)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOriginalDocument)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCachedEncoder)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStateObjectCached)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentTimeline)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingAnimationTracker)
@@ -1799,17 +1814,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   if (tmp->mSubDocuments) {
     for (auto iter = tmp->mSubDocuments->Iter(); !iter.Done(); iter.Next()) {
       auto entry = static_cast<SubDocMapEntry*>(iter.Get());
 
       NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSubDocuments entry->mKey");
       cb.NoteXPCOMChild(entry->mKey);
       NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
                                          "mSubDocuments entry->mSubDocument");
-      cb.NoteXPCOMChild(entry->mSubDocument);
+      cb.NoteXPCOMChild(ToSupports(entry->mSubDocument));
     }
   }
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCSSLoader)
 
   // We own only the items in mDOMMediaQueryLists that have listeners;
   // this reference is managed by their AddListener and RemoveListener
   // methods.
@@ -1818,45 +1833,44 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
     if (mql->HasListeners() &&
         NS_SUCCEEDED(mql->CheckInnerWindowCorrectness())) {
       NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mDOMMediaQueryLists item");
       cb.NoteXPCOMChild(mql);
     }
   }
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsDocument)
-
-NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(nsDocument)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsIDocument)
+
+NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(nsIDocument)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsIDocument)
   tmp->mInUnlinkOrDeletion = true;
 
   // Clear out our external resources
   tmp->mExternalResourceMap.Shutdown();
 
   nsAutoScriptBlocker scriptBlocker;
 
   nsINode::Unlink(tmp);
 
   while (tmp->HasChildren()) {
     // Hold a strong ref to the node when we remove it, because we may be
     // the last reference to it.
-    // If this code changes, change the corresponding code in nsDocument's
+    // If this code changes, change the corresponding code in nsIDocument's
     // unlink impl and ContentUnbinder::UnbindSubtree.
     nsCOMPtr<nsIContent> child = tmp->GetLastChild();
     tmp->DisconnectChild(child);
     child->UnbindFromTree();
   }
 
   tmp->UnlinkOriginalDocumentIfStatic();
 
   tmp->mCachedRootElement = nullptr;  // Avoid a dangling pointer
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDisplayDocument)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mFirstBaseNodeWithHref)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mMaybeEndOutermostXBLUpdateRunner)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDOMImplementation)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mImageMaps)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mCachedEncoder)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentTimeline)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingAnimationTracker)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mTemplateContentsOwner)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mChildrenCollection)
@@ -1900,17 +1914,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
 
   tmp->mFrameRequestCallbacks.Clear();
   MOZ_RELEASE_ASSERT(!tmp->mFrameRequestCallbacksScheduled,
                      "How did we get here without our presshell going away "
                      "first?");
 
   DocumentOrShadowRoot::Unlink(tmp);
 
-  // nsDocument has a pretty complex destructor, so we're going to
+  // nsIDocument has a pretty complex destructor, so we're going to
   // assume that *most* cycles you actually want to break somewhere
   // else, and not unlink an awful lot here.
 
   tmp->mIdentifierMap.Clear();
   tmp->mExpandoAndGeneration.OwnerUnlinked();
 
   if (tmp->mAnimationController) {
     tmp->mAnimationController->Unlink();
@@ -1931,17 +1945,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
         static_cast<LinkedListElement<MediaQueryList>*>(mql)->getNext();
     mql->Disconnect();
     mql = next;
   }
 
   tmp->mInUnlinkOrDeletion = false;
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
-nsresult nsDocument::Init() {
+nsresult nsIDocument::Init() {
   if (mCSSLoader || mStyleImageLoader || mNodeInfoManager || mScriptLoader) {
     return NS_ERROR_ALREADY_INITIALIZED;
   }
 
   // Force initialization.
   nsINode::nsSlots* slots = Slots();
 
   // Prepend self as mutation-observer whether we need it or not (some
@@ -2456,28 +2470,28 @@ static void WarnIfSandboxIneffective(nsI
 }
 
 bool nsIDocument::IsSynthesized() {
   nsCOMPtr<nsILoadInfo> loadInfo = mChannel ? mChannel->GetLoadInfo() : nullptr;
   return loadInfo && loadInfo->GetServiceWorkerTaintingSynthesized();
 }
 
 // static
-bool nsDocument::IsCallerChromeOrAddon(JSContext* aCx, JSObject* aObject) {
+bool nsIDocument::IsCallerChromeOrAddon(JSContext* aCx, JSObject* aObject) {
   nsIPrincipal* principal = nsContentUtils::SubjectPrincipal(aCx);
   return principal && (nsContentUtils::IsSystemPrincipal(principal) ||
                        principal->GetIsAddonOrExpandedAddonPrincipal());
 }
 
-nsresult nsDocument::StartDocumentLoad(const char* aCommand,
-                                       nsIChannel* aChannel,
-                                       nsILoadGroup* aLoadGroup,
-                                       nsISupports* aContainer,
-                                       nsIStreamListener** aDocListener,
-                                       bool aReset, nsIContentSink* aSink) {
+nsresult nsIDocument::StartDocumentLoad(const char* aCommand,
+                                        nsIChannel* aChannel,
+                                        nsILoadGroup* aLoadGroup,
+                                        nsISupports* aContainer,
+                                        nsIStreamListener** aDocListener,
+                                        bool aReset, nsIContentSink* aSink) {
   if (MOZ_LOG_TEST(gDocumentLeakPRLog, LogLevel::Debug)) {
     nsCOMPtr<nsIURI> uri;
     aChannel->GetURI(getter_AddRefs(uri));
     MOZ_LOG(gDocumentLeakPRLog, LogLevel::Debug,
             ("DOCUMENT %p StartDocumentLoad %s", this,
              uri ? uri->GetSpecOrDefault().get() : ""));
   }
 
@@ -2865,17 +2879,17 @@ nsresult nsIDocument::InitFeaturePolicy(
   if (NS_SUCCEEDED(rv)) {
     mFeaturePolicy->SetDeclaredPolicy(this, NS_ConvertUTF8toUTF16(value),
                                       NodePrincipal(), nullptr);
   }
 
   return NS_OK;
 }
 
-void nsDocument::StopDocumentLoad() {
+void nsIDocument::StopDocumentLoad() {
   if (mParser) {
     mParserAborted = true;
     mParser->Terminate();
   }
 }
 
 void nsIDocument::SetDocumentURI(nsIURI* aURI) {
   nsCOMPtr<nsIURI> oldBase = GetDocBaseURI();
@@ -2931,17 +2945,17 @@ void nsIDocument::GetLastModified(nsAStr
   if (!mLastModified.IsEmpty()) {
     aLastModified.Assign(mLastModified);
   } else {
     GetFormattedTimeString(PR_Now(), aLastModified);
   }
 }
 
 static void IncrementExpandoGeneration(nsIDocument& aDoc) {
-  ++static_cast<nsDocument&>(aDoc).mExpandoAndGeneration.generation;
+  ++aDoc.mExpandoAndGeneration.generation;
 }
 
 void nsIDocument::AddToNameTable(Element* aElement, nsAtom* aName) {
   MOZ_ASSERT(
       nsGenericHTMLElement::ShouldExposeNameAsHTMLDocumentProperty(aElement),
       "Only put elements that need to be exposed as document['name'] in "
       "the named table.");
 
@@ -3003,18 +3017,16 @@ void nsIDocument::RemoveFromIdTable(Elem
       !entry->HasIdElementExposedAsHTMLDocumentProperty()) {
     IncrementExpandoGeneration(*this);
   }
   if (entry->IsEmpty()) {
     mIdentifierMap.RemoveEntry(entry);
   }
 }
 
-nsIPrincipal* nsDocument::GetPrincipal() { return NodePrincipal(); }
-
 extern bool sDisablePrefetchHTTPSPref;
 
 void nsIDocument::SetPrincipal(nsIPrincipal* aNewPrincipal) {
   if (aNewPrincipal && mAllowDNSPrefetch && sDisablePrefetchHTTPSPref) {
     nsCOMPtr<nsIURI> uri;
     aNewPrincipal->GetURI(getter_AddRefs(uri));
     bool isHTTPS;
     if (!uri || NS_FAILED(uri->SchemeIs("https", &isHTTPS)) || isHTTPS) {
@@ -3091,26 +3103,24 @@ void nsIDocument::NoteScriptTrackingStat
   }
 }
 
 bool nsIDocument::IsScriptTracking(const nsACString& aURL) const {
   return mTrackingScripts.Contains(aURL);
 }
 
 NS_IMETHODIMP
-nsDocument::GetApplicationCache(nsIApplicationCache** aApplicationCache) {
+nsIDocument::GetApplicationCache(nsIApplicationCache** aApplicationCache) {
   NS_IF_ADDREF(*aApplicationCache = mApplicationCache);
-
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDocument::SetApplicationCache(nsIApplicationCache* aApplicationCache) {
+nsIDocument::SetApplicationCache(nsIApplicationCache* aApplicationCache) {
   mApplicationCache = aApplicationCache;
-
   return NS_OK;
 }
 
 void nsIDocument::GetContentType(nsAString& aContentType) {
   CopyUTF8toUTF16(GetContentTypeInternal(), aContentType);
 }
 
 void nsIDocument::SetContentType(const nsAString& aContentType) {
@@ -3148,17 +3158,17 @@ void nsIDocument::InitializeLocalization
 
   DocumentL10n* l10n = new DocumentL10n(this);
   MOZ_ALWAYS_TRUE(l10n->Init(aResourceIds));
   mDocumentL10n = l10n;
 }
 
 DocumentL10n* nsIDocument::GetL10n() { return mDocumentL10n; }
 
-bool nsDocument::DocumentSupportsL10n(JSContext* aCx, JSObject* aObject) {
+bool nsIDocument::DocumentSupportsL10n(JSContext* aCx, JSObject* aObject) {
   nsCOMPtr<nsIPrincipal> callerPrincipal =
       nsContentUtils::SubjectPrincipal(aCx);
   return PrincipalAllowsL10n(callerPrincipal);
 }
 
 void nsIDocument::LocalizationLinkAdded(Element* aLinkElement) {
   if (!PrincipalAllowsL10n(NodePrincipal())) {
     return;
@@ -3227,50 +3237,50 @@ void nsIDocument::OnL10nResourceContaine
 }
 
 void nsIDocument::TriggerInitialDocumentTranslation() {
   if (mDocumentL10n) {
     mDocumentL10n->TriggerInitialDocumentTranslation();
   }
 }
 
-bool nsDocument::IsWebAnimationsEnabled(JSContext* aCx, JSObject* /*unused*/) {
+bool nsIDocument::IsWebAnimationsEnabled(JSContext* aCx, JSObject* /*unused*/) {
   MOZ_ASSERT(NS_IsMainThread());
 
   return nsContentUtils::IsSystemCaller(aCx) ||
          nsContentUtils::AnimationsAPICoreEnabled();
 }
 
-bool nsDocument::IsWebAnimationsEnabled(CallerType aCallerType) {
+bool nsIDocument::IsWebAnimationsEnabled(CallerType aCallerType) {
   MOZ_ASSERT(NS_IsMainThread());
 
   return aCallerType == dom::CallerType::System ||
          nsContentUtils::AnimationsAPICoreEnabled();
 }
 
-bool nsDocument::IsWebAnimationsGetAnimationsEnabled(JSContext* aCx,
-                                                     JSObject* /*unused*/
+bool nsIDocument::IsWebAnimationsGetAnimationsEnabled(JSContext* aCx,
+                                                      JSObject* /*unused*/
 ) {
   MOZ_ASSERT(NS_IsMainThread());
 
   return nsContentUtils::IsSystemCaller(aCx) ||
          StaticPrefs::dom_animations_api_getAnimations_enabled();
 }
 
-bool nsDocument::AreWebAnimationsImplicitKeyframesEnabled(JSContext* aCx,
-                                                          JSObject* /*unused*/
+bool nsIDocument::AreWebAnimationsImplicitKeyframesEnabled(JSContext* aCx,
+                                                           JSObject* /*unused*/
 ) {
   MOZ_ASSERT(NS_IsMainThread());
 
   return nsContentUtils::IsSystemCaller(aCx) ||
          StaticPrefs::dom_animations_api_implicit_keyframes_enabled();
 }
 
-bool nsDocument::AreWebAnimationsTimelinesEnabled(JSContext* aCx,
-                                                  JSObject* /*unused*/
+bool nsIDocument::AreWebAnimationsTimelinesEnabled(JSContext* aCx,
+                                                   JSObject* /*unused*/
 ) {
   MOZ_ASSERT(NS_IsMainThread());
 
   return nsContentUtils::IsSystemCaller(aCx) ||
          StaticPrefs::dom_animations_api_timelines_enabled();
 }
 
 DocumentTimeline* nsIDocument::Timeline() {
@@ -3575,20 +3585,20 @@ void nsIDocument::SetHeaderData(nsAtom* 
     enum mozilla::net::ReferrerPolicy policy =
         nsContentUtils::GetReferrerPolicyFromHeader(aData);
     if (policy != mozilla::net::RP_Unset) {
       mReferrerPolicy = policy;
       mReferrerPolicySet = true;
     }
   }
 }
-void nsDocument::TryChannelCharset(nsIChannel* aChannel,
-                                   int32_t& aCharsetSource,
-                                   NotNull<const Encoding*>& aEncoding,
-                                   nsHtml5TreeOpExecutor* aExecutor) {
+void nsIDocument::TryChannelCharset(nsIChannel* aChannel,
+                                    int32_t& aCharsetSource,
+                                    NotNull<const Encoding*>& aEncoding,
+                                    nsHtml5TreeOpExecutor* aExecutor) {
   if (aChannel) {
     nsAutoCString charsetVal;
     nsresult rv = aChannel->GetContentCharset(charsetVal);
     if (NS_SUCCEEDED(rv)) {
       const Encoding* preferred = Encoding::ForLabel(charsetVal);
       if (preferred) {
         aEncoding = WrapNotNull(preferred);
         aCharsetSource = kCharsetFromChannel;
@@ -4089,17 +4099,17 @@ void nsIDocument::SetStyleSheetApplicabl
 }
 
 void nsIDocument::NotifyStyleSheetApplicableStateChanged() {
   mSSApplicableStateNotificationPending = false;
   nsCOMPtr<nsIObserverService> observerService =
       mozilla::services::GetObserverService();
   if (observerService) {
     observerService->NotifyObservers(
-        this, "style-sheet-applicable-state-changed", nullptr);
+        ToSupports(this), "style-sheet-applicable-state-changed", nullptr);
   }
 }
 
 static SheetType ConvertAdditionalSheetType(
     nsIDocument::additionalSheetType aType) {
   switch (aType) {
     case nsIDocument::eAgentSheet:
       return SheetType::Agent;
@@ -4340,20 +4350,20 @@ void nsIDocument::SetContainer(nsDocShel
     // check if same type root
     nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
     aContainer->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
     NS_ASSERTION(
         sameTypeRoot,
         "No document shell root tree item from document shell tree item!");
 
     if (sameTypeRoot == aContainer) {
-      static_cast<nsDocument*>(this)->SetIsTopLevelContentDocument(true);
-    }
-
-    static_cast<nsDocument*>(this)->SetIsContentDocument(true);
+      SetIsTopLevelContentDocument(true);
+    }
+
+    SetIsContentDocument(true);
   }
 
   mAncestorPrincipals = aContainer->AncestorPrincipals();
   mAncestorOuterWindowIDs = aContainer->AncestorOuterWindowIDs();
 }
 
 nsISupports* nsIDocument::GetContainer() const {
   return static_cast<nsIDocShell*>(mDocumentContainer);
@@ -4631,34 +4641,34 @@ void nsIDocument::BeginUpdate() {
     BindingManager()->BeginOutermostUpdate();
   }
 
   ++mUpdateNestLevel;
   nsContentUtils::AddScriptBlocker();
   NS_DOCUMENT_NOTIFY_OBSERVERS(BeginUpdate, (this));
 }
 
-void nsDocument::EndUpdate() {
+void nsIDocument::EndUpdate() {
   NS_DOCUMENT_NOTIFY_OBSERVERS(EndUpdate, (this));
 
   nsContentUtils::RemoveScriptBlocker();
 
   --mUpdateNestLevel;
 
   // This set of updates may have created XBL bindings.  Let the
   // binding manager know we're done.
   MaybeEndOutermostXBLUpdate();
 
   MaybeInitializeFinalizeFrameLoaders();
   if (mXULBroadcastManager) {
     mXULBroadcastManager->MaybeBroadcast();
   }
 }
 
-void nsDocument::BeginLoad() {
+void nsIDocument::BeginLoad() {
   MOZ_ASSERT(!mDidCallBeginLoad);
   mDidCallBeginLoad = true;
 
   // Block onload here to prevent having to deal with blocking and
   // unblocking it while we know the document is loading.
   BlockOnload();
   mDidFireDOMContentLoaded = false;
   BlockDOMContentLoaded();
@@ -4701,27 +4711,27 @@ void nsIDocument::DispatchContentLoadedE
   if (mTiming) {
     mTiming->NotifyDOMContentLoadedStart(nsIDocument::GetDocumentURI());
   }
 
   // Dispatch observer notification to notify observers document is interactive.
   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
   if (os) {
     nsIPrincipal* principal = NodePrincipal();
-    os->NotifyObservers(this,
+    os->NotifyObservers(ToSupports(this),
                         nsContentUtils::IsSystemPrincipal(principal)
                             ? "chrome-document-interactive"
                             : "content-document-interactive",
                         nullptr);
   }
 
   // Fire a DOM event notifying listeners that this document has been
   // loaded (excluding images and other loads initiated by this
   // document).
-  nsContentUtils::DispatchTrustedEvent(this, this,
+  nsContentUtils::DispatchTrustedEvent(this, ToSupports(this),
                                        NS_LITERAL_STRING("DOMContentLoaded"),
                                        CanBubble::eYes, Cancelable::eNo);
 
   if (auto* const window = GetInnerWindow()) {
     const RefPtr<ServiceWorkerContainer> serviceWorker =
         window->Navigator()->ServiceWorker();
 
     // This could cause queued messages from a service worker to get
@@ -4782,35 +4792,33 @@ void nsIDocument::DispatchContentLoadedE
         // target is not in the same document, so the event would never reach
         // the ancestor document if we used the normal event
         // dispatching code.
 
         WidgetEvent* innerEvent = event->WidgetEventPtr();
         if (innerEvent) {
           nsEventStatus status = nsEventStatus_eIgnore;
 
-          RefPtr<nsPresContext> context = parent->GetPresContext();
-
-          if (context) {
-            EventDispatcher::Dispatch(parent, context, innerEvent, event,
-                                      &status);
+          if (RefPtr<nsPresContext> context = parent->GetPresContext()) {
+            EventDispatcher::Dispatch(ToSupports(parent), context, innerEvent,
+                                      event, &status);
           }
         }
       }
 
       parent = parent->GetParentDocument();
     } while (parent);
   }
 
   // If the document has a manifest attribute, fire a MozApplicationManifest
   // event.
   Element* root = GetRootElement();
   if (root && root->HasAttr(kNameSpaceID_None, nsGkAtoms::manifest)) {
     nsContentUtils::DispatchChromeEvent(
-        this, this, NS_LITERAL_STRING("MozApplicationManifest"),
+        this, ToSupports(this), NS_LITERAL_STRING("MozApplicationManifest"),
         CanBubble::eYes, Cancelable::eYes);
   }
 
   nsPIDOMWindowInner* inner = GetInnerWindow();
   if (inner) {
     inner->NoteDOMContentLoaded();
   }
 
@@ -4899,17 +4907,17 @@ static void AssertAboutPageHasCSP(nsIURI
                  "about: page must have a CSP");
     return;
   }
   MOZ_ASSERT(parsedPolicyStr.Find("default-src") >= 0,
              "about: page must contain a CSP including default-src");
 }
 #endif
 
-void nsDocument::EndLoad() {
+void nsIDocument::EndLoad() {
 #if defined(DEBUG) && !defined(ANDROID)
   // only assert if nothing stopped the load on purpose
   if (!mParserAborted) {
     AssertAboutPageHasCSP(mDocumentURI, NodePrincipal());
   }
 #endif
 
   // EndLoad may have been called without a matching call to BeginLoad, in the
@@ -5915,17 +5923,17 @@ void nsIDocument::DoNotifyPossibleTitleC
       nsCOMPtr<nsIBaseWindow> docShellWin = do_QueryInterface(container);
       if (docShellWin) {
         docShellWin->SetTitle(title);
       }
     }
   }
 
   // Fire a DOM event for the title change.
-  nsContentUtils::DispatchChromeEvent(this, static_cast<nsIDocument*>(this),
+  nsContentUtils::DispatchChromeEvent(this, ToSupports(this),
                                       NS_LITERAL_STRING("DOMTitleChanged"),
                                       CanBubble::eYes, Cancelable::eYes);
 }
 
 already_AddRefed<BoxObject> nsIDocument::GetBoxObjectFor(Element* aElement,
                                                          ErrorResult& aRv) {
   if (!aElement) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
@@ -6486,17 +6494,17 @@ nsINode* nsIDocument::AdoptNode(nsINode&
     if (!newScope && GetScopeObject() &&
         GetScopeObject()->GetGlobalJSObject()) {
       // Make sure cx is in a semi-sane compartment before we call WrapNative.
       // It's kind of irrelevant, given that we're passing aAllowWrapping =
       // false, and documents should always insist on being wrapped in an
       // canonical scope. But we try to pass something sane anyway.
       JSAutoRealm ar(cx, GetScopeObject()->GetGlobalJSObject());
       JS::Rooted<JS::Value> v(cx);
-      rv = nsContentUtils::WrapNative(cx, this, this, &v,
+      rv = nsContentUtils::WrapNative(cx, ToSupports(this), this, &v,
                                       /* aAllowWrapping = */ false);
       if (rv.Failed()) return nullptr;
       newScope = &v.toObject();
     }
   }
 
   nsCOMArray<nsINode> nodesWithProperties;
   nsNodeUtils::Adopt(adoptedNode, sameDocument ? nullptr : mNodeInfoManager,
@@ -6970,31 +6978,31 @@ void nsIDocument::UpdateViewportOverflow
     if (aScrolledWidth * minScale.scale < aScrollportWidth) {
       mViewportOverflowType = ViewportOverflowType::ButNotMinScaleSize;
     } else {
       mViewportOverflowType = ViewportOverflowType::MinScaleSize;
     }
   }
 }
 
-EventListenerManager* nsDocument::GetOrCreateListenerManager() {
+EventListenerManager* nsIDocument::GetOrCreateListenerManager() {
   if (!mListenerManager) {
     mListenerManager =
         new EventListenerManager(static_cast<EventTarget*>(this));
     SetFlags(NODE_HAS_LISTENERMANAGER);
   }
 
   return mListenerManager;
 }
 
-EventListenerManager* nsDocument::GetExistingListenerManager() const {
+EventListenerManager* nsIDocument::GetExistingListenerManager() const {
   return mListenerManager;
 }
 
-void nsDocument::GetEventTargetParent(EventChainPreVisitor& aVisitor) {
+void nsIDocument::GetEventTargetParent(EventChainPreVisitor& aVisitor) {
   if (mDocGroup && aVisitor.mEvent->mMessage != eVoidEvent &&
       !mIgnoreDocGroupMismatches) {
     mDocGroup->ValidateAccess();
   }
 
   aVisitor.mCanHandle = true;
   // FIXME! This is a hack to make middle mouse paste working also in Editor.
   // Bug 329119
@@ -7027,16 +7035,27 @@ already_AddRefed<Event> nsIDocument::Cre
   return ev.forget();
 }
 
 void nsIDocument::FlushPendingNotifications(FlushType aType) {
   mozilla::ChangesToFlush flush(aType, aType >= FlushType::Style);
   FlushPendingNotifications(flush);
 }
 
+class nsDocumentOnStack {
+ public:
+  explicit nsDocumentOnStack(nsIDocument* aDoc) : mDoc(aDoc) {
+    mDoc->IncreaseStackRefCnt();
+  }
+  ~nsDocumentOnStack() { mDoc->DecreaseStackRefCnt(); }
+
+ private:
+  nsIDocument* mDoc;
+};
+
 void nsIDocument::FlushPendingNotifications(mozilla::ChangesToFlush aFlush) {
   FlushType flushType = aFlush.mFlushType;
 
   nsDocumentOnStack dos(this);
 
   // We need to flush the sink for non-HTML documents (because the XML
   // parser still does insertion with deferred notifications).  We
   // also need to flush the sink if this is a layout-related flush, to
@@ -7174,17 +7193,17 @@ bool nsIDocument::IsScriptEnabled() {
       do_QueryInterface(GetInnerWindow());
   if (!globalObject || !globalObject->GetGlobalJSObject()) {
     return false;
   }
 
   return xpc::Scriptability::Get(globalObject->GetGlobalJSObject()).Allowed();
 }
 
-void nsDocument::RetrieveRelevantHeaders(nsIChannel* aChannel) {
+void nsIDocument::RetrieveRelevantHeaders(nsIChannel* aChannel) {
   PRTime modDate = 0;
   nsresult rv;
 
   nsCOMPtr<nsIHttpChannel> httpChannel;
   rv = GetHttpChannelHelper(aChannel, getter_AddRefs(httpChannel));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
@@ -7507,17 +7526,17 @@ bool nsIDocument::CanSavePresentation(ns
     if (globalWindow->HasUsedVR()) {
       return false;
     }
   }
 
   return true;
 }
 
-void nsDocument::Destroy() {
+void nsIDocument::Destroy() {
   // The ContentViewer wants to release the document now.  So, tell our content
   // to drop any references to the document so that it can be destroyed.
   if (mIsGoingAway) return;
 
   mIsGoingAway = true;
 
   ScriptLoader()->Destroy();
   SetScriptGlobalObject(nullptr);
@@ -7542,17 +7561,17 @@ void nsDocument::Destroy() {
   mLayoutHistoryState = nullptr;
 
   // Shut down our external resource map.  We might not need this for
   // leak-fixing if we fix nsDocumentViewer to do cycle-collection, but
   // tearing down all those frame trees right now is the right thing to do.
   mExternalResourceMap.Shutdown();
 }
 
-void nsDocument::RemovedFromDocShell() {
+void nsIDocument::RemovedFromDocShell() {
   if (mRemovedFromDocShell) return;
 
   mRemovedFromDocShell = true;
   EnumerateActivityObservers(NotifyActivityChanged, nullptr);
 
   for (nsIContent* child = GetFirstChild(); child;
        child = child->GetNextSibling()) {
     child->SaveSubtreeState();
@@ -7595,52 +7614,52 @@ void nsIDocument::EnsureOnloadBlocker() 
       }
 
       // Not in the loadgroup, so add it.
       loadGroup->AddRequest(mOnloadBlocker, nullptr);
     }
   }
 }
 
-void nsDocument::AsyncBlockOnload() {
+void nsIDocument::AsyncBlockOnload() {
   while (mAsyncOnloadBlockCount) {
     --mAsyncOnloadBlockCount;
     BlockOnload();
   }
 }
 
-void nsDocument::BlockOnload() {
+void nsIDocument::BlockOnload() {
   if (mDisplayDocument) {
     mDisplayDocument->BlockOnload();
     return;
   }
 
   // If mScriptGlobalObject is null, we shouldn't be messing with the loadgroup
   // -- it's not ours.
   if (mOnloadBlockCount == 0 && mScriptGlobalObject) {
     if (!nsContentUtils::IsSafeToRunScript()) {
       // Because AddRequest may lead to OnStateChange calls in chrome,
       // block onload only when there are no script blockers.
       ++mAsyncOnloadBlockCount;
       if (mAsyncOnloadBlockCount == 1) {
         nsContentUtils::AddScriptRunner(
-            NewRunnableMethod("nsDocument::AsyncBlockOnload", this,
-                              &nsDocument::AsyncBlockOnload));
+            NewRunnableMethod("nsIDocument::AsyncBlockOnload", this,
+                              &nsIDocument::AsyncBlockOnload));
       }
       return;
     }
     nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
     if (loadGroup) {
       loadGroup->AddRequest(mOnloadBlocker, nullptr);
     }
   }
   ++mOnloadBlockCount;
 }
 
-void nsDocument::UnblockOnload(bool aFireSync) {
+void nsIDocument::UnblockOnload(bool aFireSync) {
   if (mDisplayDocument) {
     mDisplayDocument->UnblockOnload(aFireSync);
     return;
   }
 
   if (mOnloadBlockCount == 0 && mAsyncOnloadBlockCount == 0) {
     MOZ_ASSERT_UNREACHABLE(
         "More UnblockOnload() calls than BlockOnload() "
@@ -7818,17 +7837,17 @@ void nsIDocument::OnPageShow(bool aPersi
 
   UpdateVisibilityState();
 
   if (!mIsBeingUsedAsImage) {
     // Dispatch observer notification to notify observers page is shown.
     nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
     if (os) {
       nsIPrincipal* principal = NodePrincipal();
-      os->NotifyObservers(this,
+      os->NotifyObservers(ToSupports(this),
                           nsContentUtils::IsSystemPrincipal(principal)
                               ? "chrome-page-shown"
                               : "content-page-shown",
                           nullptr);
     }
 
     nsCOMPtr<EventTarget> target = aDispatchStartTarget;
     if (!target) {
@@ -7915,17 +7934,17 @@ void nsIDocument::OnPageHide(bool aPersi
 
   ExitPointerLock();
 
   if (!mIsBeingUsedAsImage) {
     // Dispatch observer notification to notify observers page is hidden.
     nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
     if (os) {
       nsIPrincipal* principal = NodePrincipal();
-      os->NotifyObservers(this,
+      os->NotifyObservers(ToSupports(this),
                           nsContentUtils::IsSystemPrincipal(principal)
                               ? "chrome-page-hidden"
                               : "content-page-hidden",
                           nullptr);
     }
 
     // Now send out a PageHide event.
     nsCOMPtr<EventTarget> target = aDispatchStartTarget;
@@ -8061,17 +8080,17 @@ void nsIDocument::RefreshLinkHrefs() {
 
   // Reset all of our styled links.
   nsAutoScriptBlocker scriptBlocker;
   for (LinkArray::size_type i = 0; i < linksToNotify.Length(); i++) {
     linksToNotify[i]->ResetLinkState(true, linksToNotify[i]->ElementHasHref());
   }
 }
 
-nsresult nsDocument::CloneDocHelper(nsDocument* clone) const {
+nsresult nsIDocument::CloneDocHelper(nsIDocument* clone) const {
   clone->mIsStaticDocument = mCreatingStaticClone;
 
   // Init document
   nsresult rv = clone->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (mCreatingStaticClone) {
     nsCOMPtr<nsILoadGroup> loadGroup;
@@ -8098,17 +8117,17 @@ nsresult nsDocument::CloneDocHelper(nsDo
   }
 
   // Now ensure that our clone has the same URI, base URI, and principal as us.
   // We do this after the mCreatingStaticClone block above, because that block
   // can set the base URI to an incorrect value in cases when base URI
   // information came from the channel.  So we override explicitly, and do it
   // for all these properties, in case ResetToURI messes with any of the rest of
   // them.
-  clone->nsDocument::SetDocumentURI(nsIDocument::GetDocumentURI());
+  clone->SetDocumentURI(nsIDocument::GetDocumentURI());
   clone->SetChromeXHRDocURI(mChromeXHRDocURI);
   clone->SetPrincipal(NodePrincipal());
   clone->mDocumentBaseURI = mDocumentBaseURI;
   clone->SetChromeXHRDocBaseURI(mChromeXHRDocBaseURI);
 
   bool hasHadScriptObject = true;
   nsIScriptGlobalObject* scriptObject =
       GetScriptHandlingObject(hasHadScriptObject);
@@ -10882,17 +10901,17 @@ void nsIDocument::UnlockPointer(nsIDocum
       CanBubble::eYes, ChromeOnlyDispatch::eYes);
   asyncDispatcher->RunDOMEventWhenSafe();
 }
 
 void nsIDocument::UpdateVisibilityState() {
   dom::VisibilityState oldState = mVisibilityState;
   mVisibilityState = ComputeVisibilityState();
   if (oldState != mVisibilityState) {
-    nsContentUtils::DispatchTrustedEvent(this, static_cast<nsIDocument*>(this),
+    nsContentUtils::DispatchTrustedEvent(this, ToSupports(this),
                                          NS_LITERAL_STRING("visibilitychange"),
                                          CanBubble::eYes, Cancelable::eNo);
     EnumerateActivityObservers(NotifyActivityChanged, nullptr);
   }
 
   if (mVisibilityState == dom::VisibilityState::Visible) {
     MaybeActiveMediaComponents();
   }
@@ -10924,55 +10943,86 @@ void nsIDocument::PostVisibilityUpdateEv
 void nsIDocument::MaybeActiveMediaComponents() {
   if (!mWindow) {
     return;
   }
 
   GetWindow()->MaybeActiveMediaComponents();
 }
 
-/* virtual */ void nsIDocument::DocAddSizeOfExcludingThis(
-    nsWindowSizes& aSizes) const {
+void nsIDocument::DocAddSizeOfExcludingThis(nsWindowSizes& aWindowSizes) const {
+  nsINode::AddSizeOfExcludingThis(aWindowSizes, &aWindowSizes.mDOMOtherSize);
+
+  for (nsIContent* kid = GetFirstChild(); kid; kid = kid->GetNextSibling()) {
+    AddSizeOfNodeTree(*kid, aWindowSizes);
+  }
+
+  // IMPORTANT: for our ComputedValues measurements, we want to measure
+  // ComputedValues accessible from DOM elements before ComputedValues not
+  // accessible from DOM elements (i.e. accessible only from the frame tree).
+  //
+  // Therefore, the measurement of the nsIDocument superclass must happen after
+  // the measurement of DOM nodes (above), because nsIDocument contains the
+  // PresShell, which contains the frame tree.
   if (mPresShell) {
-    mPresShell->AddSizeOfIncludingThis(aSizes);
-  }
-
-  aSizes.mPropertyTablesSize +=
-      mPropertyTable.SizeOfExcludingThis(aSizes.mState.mMallocSizeOf);
+    mPresShell->AddSizeOfIncludingThis(aWindowSizes);
+  }
+
+  aWindowSizes.mPropertyTablesSize +=
+      mPropertyTable.SizeOfExcludingThis(aWindowSizes.mState.mMallocSizeOf);
 
   if (EventListenerManager* elm = GetExistingListenerManager()) {
-    aSizes.mDOMEventListenersCount += elm->ListenerCount();
+    aWindowSizes.mDOMEventListenersCount += elm->ListenerCount();
   }
 
   if (mNodeInfoManager) {
-    mNodeInfoManager->AddSizeOfIncludingThis(aSizes);
-  }
-
-  aSizes.mDOMMediaQueryLists +=
-      mDOMMediaQueryLists.sizeOfExcludingThis(aSizes.mState.mMallocSizeOf);
+    mNodeInfoManager->AddSizeOfIncludingThis(aWindowSizes);
+  }
+
+  aWindowSizes.mDOMMediaQueryLists += mDOMMediaQueryLists.sizeOfExcludingThis(
+      aWindowSizes.mState.mMallocSizeOf);
 
   for (const MediaQueryList* mql : mDOMMediaQueryLists) {
-    aSizes.mDOMMediaQueryLists +=
-        mql->SizeOfExcludingThis(aSizes.mState.mMallocSizeOf);
-  }
-
-  mContentBlockingLog.AddSizeOfExcludingThis(aSizes);
+    aWindowSizes.mDOMMediaQueryLists +=
+        mql->SizeOfExcludingThis(aWindowSizes.mState.mMallocSizeOf);
+  }
+
+  mContentBlockingLog.AddSizeOfExcludingThis(aWindowSizes);
+
+  DocumentOrShadowRoot::AddSizeOfExcludingThis(aWindowSizes);
+
+  for (auto& sheetArray : mAdditionalSheets) {
+    AddSizeOfOwnedSheetArrayExcludingThis(aWindowSizes, sheetArray);
+  }
+  // Lumping in the loader with the style-sheets size is not ideal,
+  // but most of the things in there are in fact stylesheets, so it
+  // doesn't seem worthwhile to separate it out.
+  aWindowSizes.mLayoutStyleSheetsSize +=
+      CSSLoader()->SizeOfIncludingThis(aWindowSizes.mState.mMallocSizeOf);
+
+  aWindowSizes.mDOMOtherSize += mAttrStyleSheet
+                                    ? mAttrStyleSheet->DOMSizeOfIncludingThis(
+                                          aWindowSizes.mState.mMallocSizeOf)
+                                    : 0;
+
+  aWindowSizes.mDOMOtherSize += mStyledLinks.ShallowSizeOfExcludingThis(
+      aWindowSizes.mState.mMallocSizeOf);
 
   // Measurement of the following members may be added later if DMD finds it
   // is worthwhile:
   // - many!
 }
 
 void nsIDocument::DocAddSizeOfIncludingThis(nsWindowSizes& aWindowSizes) const {
   aWindowSizes.mDOMOtherSize += aWindowSizes.mState.mMallocSizeOf(this);
   DocAddSizeOfExcludingThis(aWindowSizes);
 }
 
-void nsDocument::AddSizeOfExcludingThis(nsWindowSizes& aSizes,
-                                        size_t* aNodeSize) const {
+void nsIDocument::AddSizeOfExcludingThis(nsWindowSizes& aSizes,
+                                         size_t* aNodeSize) const {
   // This AddSizeOfExcludingThis() overrides the one from nsINode.  But
   // nsDocuments can only appear at the top of the DOM tree, and we use the
   // specialized DocAddSizeOfExcludingThis() in that case.  So this should never
   // be called.
   MOZ_CRASH();
 }
 
 /* static */ void nsIDocument::AddSizeOfNodeTree(nsINode& aNode,
@@ -11031,55 +11081,16 @@ void nsDocument::AddSizeOfExcludingThis(
   // sane way, and kids of <content> won't point to the parent, so we'd never
   // find the root node where we should stop at.
   for (nsIContent* kid = aNode.GetFirstChild(); kid;
        kid = kid->GetNextSibling()) {
     AddSizeOfNodeTree(*kid, aWindowSizes);
   }
 }
 
-void nsDocument::DocAddSizeOfExcludingThis(nsWindowSizes& aWindowSizes) const {
-  nsINode::AddSizeOfExcludingThis(aWindowSizes, &aWindowSizes.mDOMOtherSize);
-
-  for (nsIContent* kid = GetFirstChild(); kid; kid = kid->GetNextSibling()) {
-    AddSizeOfNodeTree(*kid, aWindowSizes);
-  }
-
-  // IMPORTANT: for our ComputedValues measurements, we want to measure
-  // ComputedValues accessible from DOM elements before ComputedValues not
-  // accessible from DOM elements (i.e. accessible only from the frame tree).
-  //
-  // Therefore, the measurement of the nsIDocument superclass must happen after
-  // the measurement of DOM nodes (above), because nsIDocument contains the
-  // PresShell, which contains the frame tree.
-  nsIDocument::DocAddSizeOfExcludingThis(aWindowSizes);
-
-  DocumentOrShadowRoot::AddSizeOfExcludingThis(aWindowSizes);
-  for (auto& sheetArray : mAdditionalSheets) {
-    AddSizeOfOwnedSheetArrayExcludingThis(aWindowSizes, sheetArray);
-  }
-  // Lumping in the loader with the style-sheets size is not ideal,
-  // but most of the things in there are in fact stylesheets, so it
-  // doesn't seem worthwhile to separate it out.
-  aWindowSizes.mLayoutStyleSheetsSize +=
-      CSSLoader()->SizeOfIncludingThis(aWindowSizes.mState.mMallocSizeOf);
-
-  aWindowSizes.mDOMOtherSize += mAttrStyleSheet
-                                    ? mAttrStyleSheet->DOMSizeOfIncludingThis(
-                                          aWindowSizes.mState.mMallocSizeOf)
-                                    : 0;
-
-  aWindowSizes.mDOMOtherSize += mStyledLinks.ShallowSizeOfExcludingThis(
-      aWindowSizes.mState.mMallocSizeOf);
-
-  // Measurement of the following members may be added later if DMD finds it
-  // is worthwhile:
-  // - many!
-}
-
 already_AddRefed<nsIDocument> nsIDocument::Constructor(
     const GlobalObject& aGlobal, ErrorResult& rv) {
   nsCOMPtr<nsIScriptGlobalObject> global =
       do_QueryInterface(aGlobal.GetAsSupports());
   if (!global) {
     rv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
@@ -11562,24 +11573,23 @@ already_AddRefed<Element> nsIDocument::C
       NS_NewHTMLElement(getter_AddRefs(element), nodeInfo.forget(),
                         mozilla::dom::NOT_FROM_PARSER);
 
   MOZ_ASSERT(NS_SUCCEEDED(rv), "NS_NewHTMLElement should never fail");
   return element.forget();
 }
 
 bool MarkDocumentTreeToBeInSyncOperation(nsIDocument* aDoc, void* aData) {
-  nsCOMArray<nsIDocument>* documents =
-      static_cast<nsCOMArray<nsIDocument>*>(aData);
+  auto* documents = static_cast<nsTArray<nsCOMPtr<nsIDocument>>*>(aData);
   if (aDoc) {
     aDoc->SetIsInSyncOperation(true);
     if (nsCOMPtr<nsPIDOMWindowInner> window = aDoc->GetInnerWindow()) {
       window->TimeoutManager().BeginSyncOperation();
     }
-    documents->AppendObject(aDoc);
+    documents->AppendElement(aDoc);
     aDoc->EnumerateSubDocuments(MarkDocumentTreeToBeInSyncOperation, aData);
   }
   return true;
 }
 
 nsAutoSyncOperation::nsAutoSyncOperation(nsIDocument* aDoc) {
   mMicroTaskLevel = 0;
   CycleCollectedJSContext* ccjs = CycleCollectedJSContext::Get();
@@ -11593,21 +11603,21 @@ nsAutoSyncOperation::nsAutoSyncOperation
         nsCOMPtr<nsIDocument> doc = top->GetExtantDoc();
         MarkDocumentTreeToBeInSyncOperation(doc, &mDocuments);
       }
     }
   }
 }
 
 nsAutoSyncOperation::~nsAutoSyncOperation() {
-  for (int32_t i = 0; i < mDocuments.Count(); ++i) {
-    if (nsCOMPtr<nsPIDOMWindowInner> window = mDocuments[i]->GetInnerWindow()) {
+  for (nsCOMPtr<nsIDocument>& doc : mDocuments) {
+    if (nsCOMPtr<nsPIDOMWindowInner> window = doc->GetInnerWindow()) {
       window->TimeoutManager().EndSyncOperation();
     }
-    mDocuments[i]->SetIsInSyncOperation(false);
+    doc->SetIsInSyncOperation(false);
   }
   CycleCollectedJSContext* ccjs = CycleCollectedJSContext::Get();
   if (ccjs) {
     ccjs->SetMicroTaskLevel(mMicroTaskLevel);
   }
 }
 
 gfxUserFontSet* nsIDocument::GetUserFontSet(bool aFlushUserFontSet) {
@@ -12528,24 +12538,17 @@ bool nsIDocument::IsThirdParty() {
   }
 
   if (parentDocument->IsThirdParty()) {
     mIsThirdParty.emplace(true);
     return mIsThirdParty.value();
   }
 
   nsCOMPtr<nsIPrincipal> principal = NodePrincipal();
-  nsCOMPtr<nsIScriptObjectPrincipal> sop =
-      do_QueryInterface(parentDocument, &rv);
-  if (NS_WARN_IF(NS_FAILED(rv) || !sop)) {
-    // Failure
-    mIsThirdParty.emplace(true);
-    return mIsThirdParty.value();
-  }
-  nsCOMPtr<nsIPrincipal> parentPrincipal = sop->GetPrincipal();
+  nsCOMPtr<nsIPrincipal> parentPrincipal = parentDocument->GetPrincipal();
 
   bool principalsMatch = false;
   rv = principal->Equals(parentPrincipal, &principalsMatch);
 
   if (NS_WARN_IF(NS_FAILED(rv))) {
     // Failure
     mIsThirdParty.emplace(true);
     return mIsThirdParty.value();
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -8,289 +8,28 @@
  * Base class for all our document implementations.
  */
 
 #ifndef nsDocument_h___
 #define nsDocument_h___
 
 #include "nsIDocument.h"
 
-#include "jsfriendapi.h"
-#include "nsCOMPtr.h"
-#include "nsAutoPtr.h"
-#include "nsCRT.h"
-#include "nsIWeakReferenceUtils.h"
-#include "nsTArray.h"
-#include "nsIdentifierMapEntry.h"
-#include "nsStubDocumentObserver.h"
-#include "nsIScriptGlobalObject.h"
-#include "nsIContent.h"
-#include "nsIPrincipal.h"
-#include "nsIParser.h"
-#include "nsBindingManager.h"
-#include "nsRefPtrHashtable.h"
-#include "nsJSThingHashtable.h"
-#include "nsIScriptObjectPrincipal.h"
-#include "nsIRadioGroupContainer.h"
-#include "nsILayoutHistoryState.h"
-#include "nsIRequest.h"
-#include "nsILoadGroup.h"
-#include "nsTObserverArray.h"
-#include "nsStubMutationObserver.h"
-#include "nsIChannel.h"
-#include "nsCycleCollectionParticipant.h"
-#include "nsContentList.h"
-#include "nsGkAtoms.h"
-#include "PLDHashTable.h"
-#include "nsDOMAttributeMap.h"
-#include "imgIRequest.h"
-#include "mozilla/EventStates.h"
-#include "mozilla/MemoryReporting.h"
-#include "mozilla/PendingAnimationTracker.h"
-#include "mozilla/dom/BoxObject.h"
-#include "mozilla/dom/DOMImplementation.h"
-#include "mozilla/dom/ScriptLoader.h"
-#include "mozilla/dom/StyleSheetList.h"
-#include "nsDataHashtable.h"
-#include "mozilla/TimeStamp.h"
-#include "mozilla/Attributes.h"
-#include "CustomElementRegistry.h"
-#include "mozilla/dom/Performance.h"
-#include "mozilla/Maybe.h"
-#include "nsIURIClassifier.h"
-
 #define XML_DECLARATION_BITS_DECLARATION_EXISTS (1 << 0)
 #define XML_DECLARATION_BITS_ENCODING_EXISTS (1 << 1)
 #define XML_DECLARATION_BITS_STANDALONE_EXISTS (1 << 2)
 #define XML_DECLARATION_BITS_STANDALONE_YES (1 << 3)
 
-class nsDOMStyleSheetSetList;
-class nsDocument;
-class nsIFormControl;
-class nsOnloadBlocker;
-class nsDOMNavigationTiming;
-class nsWindowSizes;
-class nsHtml5TreeOpExecutor;
-class nsDocumentOnStack;
-class nsISecurityConsoleMessage;
-
-namespace mozilla {
-class EventChainPreVisitor;
-namespace dom {
-class ImageTracker;
-struct LifecycleCallbacks;
-class CallbackFunction;
-class DOMIntersectionObserver;
-class Performance;
-}  // namespace dom
-}  // namespace mozilla
-
-class nsOnloadBlocker final : public nsIRequest {
- public:
-  nsOnloadBlocker() {}
-
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIREQUEST
-
- private:
-  ~nsOnloadBlocker() {}
-};
-
 // Base class for our document implementations.
-class nsDocument : public nsIDocument,
-                   public nsSupportsWeakReference,
-                   public nsIScriptObjectPrincipal,
-                   public nsIRadioGroupContainer,
-                   public nsIApplicationCacheContainer,
-                   public nsStubMutationObserver {
-  friend class nsIDocument;
-
- public:
-  typedef mozilla::dom::Element Element;
-  typedef mozilla::net::ReferrerPolicy ReferrerPolicy;
-
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-
-  NS_DECL_ADDSIZEOFEXCLUDINGTHIS
-
-  // StartDocumentLoad is pure virtual so that subclasses must override it.
-  // The nsDocument StartDocumentLoad does some setup, but does NOT set
-  // *aDocListener; this is the job of subclasses.
-  virtual nsresult StartDocumentLoad(
-      const char* aCommand, nsIChannel* aChannel, nsILoadGroup* aLoadGroup,
-      nsISupports* aContainer, nsIStreamListener** aDocListener,
-      bool aReset = true, nsIContentSink* aContentSink = nullptr) override = 0;
-
-  virtual void StopDocumentLoad() override;
-
-  static bool DocumentSupportsL10n(JSContext* aCx, JSObject* aObject);
-  static bool IsWebAnimationsEnabled(JSContext* aCx, JSObject* aObject);
-  static bool IsWebAnimationsEnabled(mozilla::dom::CallerType aCallerType);
-  static bool IsWebAnimationsGetAnimationsEnabled(JSContext* aCx,
-                                                  JSObject* aObject);
-  static bool AreWebAnimationsImplicitKeyframesEnabled(JSContext* aCx,
-                                                       JSObject* aObject);
-  static bool AreWebAnimationsTimelinesEnabled(JSContext* aCx,
-                                               JSObject* aObject);
-
-  virtual void EndUpdate() override;
-  virtual void BeginLoad() override;
-  virtual void EndLoad() override;
-
-  // nsIRadioGroupContainer
-  NS_IMETHOD WalkRadioGroup(const nsAString& aName, nsIRadioVisitor* aVisitor,
-                            bool aFlushContent) override {
-    return DocumentOrShadowRoot::WalkRadioGroup(aName, aVisitor, aFlushContent);
-  }
-  virtual void SetCurrentRadioButton(
-      const nsAString& aName, mozilla::dom::HTMLInputElement* aRadio) override {
-    DocumentOrShadowRoot::SetCurrentRadioButton(aName, aRadio);
-  }
-  virtual mozilla::dom::HTMLInputElement* GetCurrentRadioButton(
-      const nsAString& aName) override {
-    return DocumentOrShadowRoot::GetCurrentRadioButton(aName);
-  }
-  NS_IMETHOD
-  GetNextRadioButton(const nsAString& aName, const bool aPrevious,
-                     mozilla::dom::HTMLInputElement* aFocusedRadio,
-                     mozilla::dom::HTMLInputElement** aRadioOut) override {
-    return DocumentOrShadowRoot::GetNextRadioButton(aName, aPrevious,
-                                                    aFocusedRadio, aRadioOut);
-  }
-  virtual void AddToRadioGroup(
-      const nsAString& aName, mozilla::dom::HTMLInputElement* aRadio) override {
-    DocumentOrShadowRoot::AddToRadioGroup(aName, aRadio);
-  }
-  virtual void RemoveFromRadioGroup(
-      const nsAString& aName, mozilla::dom::HTMLInputElement* aRadio) override {
-    DocumentOrShadowRoot::RemoveFromRadioGroup(aName, aRadio);
-  }
-  virtual uint32_t GetRequiredRadioCount(
-      const nsAString& aName) const override {
-    return DocumentOrShadowRoot::GetRequiredRadioCount(aName);
-  }
-  virtual void RadioRequiredWillChange(const nsAString& aName,
-                                       bool aRequiredAdded) override {
-    DocumentOrShadowRoot::RadioRequiredWillChange(aName, aRequiredAdded);
-  }
-  virtual bool GetValueMissingState(const nsAString& aName) const override {
-    return DocumentOrShadowRoot::GetValueMissingState(aName);
-  }
-  virtual void SetValueMissingState(const nsAString& aName,
-                                    bool aValue) override {
-    return DocumentOrShadowRoot::SetValueMissingState(aName, aValue);
-  }
-
-  // Check whether shadow DOM is enabled for the document this node belongs to.
-  // Same as above, but also checks that the caller is either chrome or some
-  // addon.
-  static bool IsCallerChromeOrAddon(JSContext* aCx, JSObject* aObject);
-
- public:
-  using mozilla::dom::DocumentOrShadowRoot::GetElementById;
-  using mozilla::dom::DocumentOrShadowRoot::GetElementsByClassName;
-  using mozilla::dom::DocumentOrShadowRoot::GetElementsByTagName;
-  using mozilla::dom::DocumentOrShadowRoot::GetElementsByTagNameNS;
-
-  // EventTarget
-  void GetEventTargetParent(mozilla::EventChainPreVisitor& aVisitor) override;
-  virtual mozilla::EventListenerManager* GetOrCreateListenerManager() override;
-  virtual mozilla::EventListenerManager* GetExistingListenerManager()
-      const override;
-
-  // nsIScriptObjectPrincipal
-  virtual nsIPrincipal* GetPrincipal() override;
-
-  // nsIApplicationCacheContainer
-  NS_DECL_NSIAPPLICATIONCACHECONTAINER
-
-  virtual nsresult Init();
-
-  virtual void Destroy() override;
-  virtual void RemovedFromDocShell() override;
-
-  virtual void BlockOnload() override;
-  virtual void UnblockOnload(bool aFireSync) override;
-
-  NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsDocument,
-                                                                   nsIDocument)
-
-  void SetLoadedAsData(bool aLoadedAsData) { mLoadedAsData = aLoadedAsData; }
-  void SetLoadedAsInteractiveData(bool aLoadedAsInteractiveData) {
-    mLoadedAsInteractiveData = aLoadedAsInteractiveData;
-  }
-
-  nsresult CloneDocHelper(nsDocument* clone) const;
-
-  // Only BlockOnload should call this!
-  void AsyncBlockOnload();
-
-  virtual void DocAddSizeOfExcludingThis(
-      nsWindowSizes& aWindowSizes) const override;
-  // DocAddSizeOfIncludingThis is inherited from nsIDocument.
-
+class nsDocument : public nsIDocument {
  protected:
-  friend class nsNodeUtils;
-
-  void RetrieveRelevantHeaders(nsIChannel* aChannel);
-
-  void TryChannelCharset(nsIChannel* aChannel, int32_t& aCharsetSource,
-                         NotNull<const Encoding*>& aEncoding,
-                         nsHtml5TreeOpExecutor* aExecutor);
-
-  nsIContent* GetFirstBaseNodeWithHref();
-  nsresult SetFirstBaseNodeWithHref(nsIContent* node);
-
-#define NS_DOCUMENT_NOTIFY_OBSERVERS(func_, params_)                          \
-  do {                                                                        \
-    NS_OBSERVER_ARRAY_NOTIFY_XPCOM_OBSERVERS(mObservers, nsIDocumentObserver, \
-                                             func_, params_);                 \
-    /* FIXME(emilio): Apparently we can keep observing from the BFCache? That \
-       looks bogus. */                                                        \
-    if (nsIPresShell* shell = GetObservingShell()) {                          \
-      shell->func_ params_;                                                   \
-    }                                                                         \
-  } while (0)
-
-#ifdef DEBUG
-  void VerifyRootContentState();
-#endif
 
   explicit nsDocument(const char* aContentType);
   virtual ~nsDocument();
 
- public:
-  // FIXME(emilio): This needs to be here instead of in nsIDocument because Rust
-  // can't represent alignas(8) values on 32-bit architectures, which would
-  // cause nsIDocument's layout to be wrong in the Rust side.
-  //
-  // This can be fixed after updating to rust 1.25 and updating bindgen to
-  // include https://github.com/rust-lang-nursery/rust-bindgen/pull/1271.
-  js::ExpandoAndGeneration mExpandoAndGeneration;
-
-  friend class nsCallRequestFullscreen;
-
-  // The application cache that this document is associated with, if
-  // any.  This can change during the lifetime of the document.
-  nsCOMPtr<nsIApplicationCache> mApplicationCache;
-
-  nsCOMPtr<nsIContent> mFirstBaseNodeWithHref;
+  // Don't add stuff here, add to nsIDocument instead.
 
  private:
-  friend class nsUnblockOnloadEvent;
-
-  // These are not implemented and not supported.
-  nsDocument(const nsDocument& aOther);
-  nsDocument& operator=(const nsDocument& aOther);
-};
-
-class nsDocumentOnStack {
- public:
-  explicit nsDocumentOnStack(nsIDocument* aDoc) : mDoc(aDoc) {
-    mDoc->IncreaseStackRefCnt();
-  }
-  ~nsDocumentOnStack() { mDoc->DecreaseStackRefCnt(); }
-
- private:
-  nsIDocument* mDoc;
+  nsDocument(const nsDocument& aOther) = delete;
+  nsDocument& operator=(const nsDocument& aOther) = delete;
 };
 
 #endif /* nsDocument_h___ */
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -1682,17 +1682,18 @@ bool nsFocusManager::Blur(nsPIDOMWindowO
 
     SetFocusedWindowInternal(nullptr);
     mFocusedElement = nullptr;
 
     // pass 1 for the focus method when calling SendFocusOrBlurEvent just so
     // that the check is made for suppressed documents. Check to ensure that
     // the document isn't null in case someone closed it during the blur above
     nsIDocument* doc = window->GetExtantDoc();
-    if (doc) SendFocusOrBlurEvent(eBlur, presShell, doc, doc, 1, false);
+    if (doc)
+      SendFocusOrBlurEvent(eBlur, presShell, doc, ToSupports(doc), 1, false);
     if (mFocusedWindow == nullptr)
       SendFocusOrBlurEvent(eBlur, presShell, doc,
                            window->GetCurrentInnerWindow(), 1, false);
 
     // check if a different window was focused
     result = (mFocusedWindow == nullptr && mActiveWindow);
   } else if (mActiveWindow) {
     // Otherwise, the blur of the element without blurring the document
@@ -1799,17 +1800,17 @@ void nsFocusManager::Focus(nsPIDOMWindow
     // The focus change should be notified to IMEStateManager from here if
     // the focused element is a designMode editor since any content won't
     // receive focus event.
     if (doc && doc->HasFlag(NODE_IS_EDITABLE)) {
       IMEStateManager::OnChangeFocus(presShell->GetPresContext(), nullptr,
                                      GetFocusMoveActionCause(aFlags));
     }
     if (doc) {
-      SendFocusOrBlurEvent(eFocus, presShell, doc, doc,
+      SendFocusOrBlurEvent(eFocus, presShell, doc, ToSupports(doc),
                            aFlags & FOCUSMETHOD_MASK, aWindowRaised);
     }
     if (mFocusedWindow == aWindow && mFocusedElement == nullptr) {
       SendFocusOrBlurEvent(eFocus, presShell, doc,
                            aWindow->GetCurrentInnerWindow(),
                            aFlags & FOCUSMETHOD_MASK, aWindowRaised);
     }
   }
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -2054,17 +2054,17 @@ void nsGlobalWindowOuter::PreloadLocalSt
 }
 
 void nsGlobalWindowOuter::DispatchDOMWindowCreated() {
   if (!mDoc) {
     return;
   }
 
   // Fire DOMWindowCreated at chrome event listeners
-  nsContentUtils::DispatchChromeEvent(mDoc, mDoc,
+  nsContentUtils::DispatchChromeEvent(mDoc, ToSupports(mDoc),
                                       NS_LITERAL_STRING("DOMWindowCreated"),
                                       CanBubble::eYes, Cancelable::eNo);
 
   nsCOMPtr<nsIObserverService> observerService =
       mozilla::services::GetObserverService();
 
   // The event dispatching could possibly cause docshell destory, and
   // consequently cause mDoc to be set to nullptr by DropOuterWindowDocs(),
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -20,26 +20,29 @@
 #include "nsIInterfaceRequestor.h"
 #include "nsILoadContext.h"
 #include "nsILoadGroup.h"  // for member (in nsCOMPtr)
 #include "nsINode.h"       // for base class
 #include "nsIParser.h"
 #include "nsIPresShell.h"
 #include "nsIChannelEventSink.h"
 #include "nsIProgressEventSink.h"
+#include "nsIRadioGroupContainer.h"
+#include "nsIScriptObjectPrincipal.h"
 #include "nsISecurityEventSink.h"
 #include "nsIScriptGlobalObject.h"  // for member (in nsCOMPtr)
 #include "nsIServiceManager.h"
 #include "nsIURI.h"  // for use in inline functions
 #include "nsIUUIDGenerator.h"
 #include "nsIWebProgressListener.h"  // for nsIWebProgressListener
 #include "nsIWeakReferenceUtils.h"   // for nsWeakPtr
 #include "nsPIDOMWindow.h"           // for use in inline functions
 #include "nsPropertyTable.h"         // for member
 #include "nsStringFwd.h"
+#include "nsStubMutationObserver.h"
 #include "nsTHashtable.h"  // for member
 #include "nsURIHashKey.h"
 #include "mozilla/net/ReferrerPolicy.h"  // for member
 #include "mozilla/UseCounter.h"
 #include "mozilla/WeakPtr.h"
 #include "Units.h"
 #include "nsContentListDeclarations.h"
 #include "nsExpirationTracker.h"
@@ -77,16 +80,17 @@ class imgIRequest;
 class nsBindingManager;
 class nsCachableElementsByNameNodeList;
 class nsIDocShell;
 class nsDocShell;
 class nsDOMNavigationTiming;
 class nsDOMStyleSheetSetList;
 class nsFrameLoader;
 class nsGlobalWindowInner;
+class nsHtml5TreeOpExecutor;
 class nsHTMLCSSStyleSheet;
 class nsHTMLDocument;
 class nsHTMLStyleSheet;
 class nsGenericHTMLElement;
 class nsAtom;
 class nsIBFCacheEntry;
 class nsIChannel;
 class nsIContent;
@@ -429,16 +433,21 @@ class nsExternalResourceMap {
 
 // For classifying a flash document based on its principal.
 class PrincipalFlashClassifier;
 
 // Document interface.  This is implemented by all document objects in
 // Gecko.
 class nsIDocument : public nsINode,
                     public mozilla::dom::DocumentOrShadowRoot,
+                    public nsSupportsWeakReference,
+                    public nsIRadioGroupContainer,
+                    public nsIScriptObjectPrincipal,
+                    public nsIApplicationCacheContainer,
+                    public nsStubMutationObserver,
                     public mozilla::dom::DispatcherTrait {
   typedef mozilla::dom::GlobalObject GlobalObject;
 
  protected:
   using Encoding = mozilla::Encoding;
   template <typename T>
   using NotNull = mozilla::NotNull<T>;
 
@@ -446,20 +455,94 @@ class nsIDocument : public nsINode,
   typedef nsExternalResourceMap::ExternalResourceLoad ExternalResourceLoad;
   typedef mozilla::FullscreenRequest FullscreenRequest;
   typedef mozilla::net::ReferrerPolicy ReferrerPolicyEnum;
   typedef mozilla::dom::Element Element;
   typedef mozilla::dom::SVGElement SVGElement;
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDOCUMENT_IID)
 
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+
+  NS_DECL_ADDSIZEOFEXCLUDINGTHIS
+
+  NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsIDocument,
+                                                                   nsINode)
+
+#define NS_DOCUMENT_NOTIFY_OBSERVERS(func_, params_)                          \
+  do {                                                                        \
+    NS_OBSERVER_ARRAY_NOTIFY_XPCOM_OBSERVERS(mObservers, nsIDocumentObserver, \
+                                             func_, params_);                 \
+    /* FIXME(emilio): Apparently we can keep observing from the BFCache? That \
+       looks bogus. */                                                        \
+    if (nsIPresShell* shell = GetObservingShell()) {                          \
+      shell->func_ params_;                                                   \
+    }                                                                         \
+  } while (0)
+
 #ifdef MOZILLA_INTERNAL_API
   nsIDocument();
 #endif
 
+  // nsIApplicationCacheContainer
+  NS_DECL_NSIAPPLICATIONCACHECONTAINER
+
+  // nsIRadioGroupContainer
+  NS_IMETHOD WalkRadioGroup(const nsAString& aName, nsIRadioVisitor* aVisitor,
+                            bool aFlushContent) final {
+    return DocumentOrShadowRoot::WalkRadioGroup(aName, aVisitor, aFlushContent);
+  }
+
+  void SetCurrentRadioButton(const nsAString& aName,
+                             mozilla::dom::HTMLInputElement* aRadio) final {
+    DocumentOrShadowRoot::SetCurrentRadioButton(aName, aRadio);
+  }
+
+  mozilla::dom::HTMLInputElement* GetCurrentRadioButton(
+      const nsAString& aName) final {
+    return DocumentOrShadowRoot::GetCurrentRadioButton(aName);
+  }
+
+  NS_IMETHOD
+  GetNextRadioButton(const nsAString& aName, const bool aPrevious,
+                     mozilla::dom::HTMLInputElement* aFocusedRadio,
+                     mozilla::dom::HTMLInputElement** aRadioOut) final {
+    return DocumentOrShadowRoot::GetNextRadioButton(aName, aPrevious,
+                                                    aFocusedRadio, aRadioOut);
+  }
+  void AddToRadioGroup(const nsAString& aName,
+                       mozilla::dom::HTMLInputElement* aRadio) final {
+    DocumentOrShadowRoot::AddToRadioGroup(aName, aRadio);
+  }
+  void RemoveFromRadioGroup(const nsAString& aName,
+                            mozilla::dom::HTMLInputElement* aRadio) final {
+    DocumentOrShadowRoot::RemoveFromRadioGroup(aName, aRadio);
+  }
+  uint32_t GetRequiredRadioCount(const nsAString& aName) const final {
+    return DocumentOrShadowRoot::GetRequiredRadioCount(aName);
+  }
+  void RadioRequiredWillChange(const nsAString& aName,
+                               bool aRequiredAdded) final {
+    DocumentOrShadowRoot::RadioRequiredWillChange(aName, aRequiredAdded);
+  }
+  bool GetValueMissingState(const nsAString& aName) const final {
+    return DocumentOrShadowRoot::GetValueMissingState(aName);
+  }
+  void SetValueMissingState(const nsAString& aName, bool aValue) final {
+    return DocumentOrShadowRoot::SetValueMissingState(aName, aValue);
+  }
+
+  // nsIScriptObjectPrincipal
+  nsIPrincipal* GetPrincipal() final { return NodePrincipal(); }
+
+  // EventTarget
+  void GetEventTargetParent(mozilla::EventChainPreVisitor& aVisitor) override;
+  mozilla::EventListenerManager* GetOrCreateListenerManager() override;
+  mozilla::EventListenerManager* GetExistingListenerManager() const override;
+
   // This helper class must be set when we dispatch beforeunload and unload
   // events in order to avoid unterminate sync XHRs.
   class MOZ_RAII PageUnloadingEventTimeStamp {
     nsCOMPtr<nsIDocument> mDocument;
     bool mSet;
 
    public:
     explicit PageUnloadingEventTimeStamp(nsIDocument* aDocument)
@@ -505,40 +588,44 @@ class nsIDocument : public nsINode,
    *              This MUST be null if the underlying document is an HTML
    *              document. Even in the XML case, please don't add new calls
    *              with non-null sink.
    *
    * Once this has been called, the document will return false for
    * MayStartLayout() until SetMayStartLayout(true) is called on it.  Making
    * sure this happens is the responsibility of the caller of
    * StartDocumentLoad().
+   *
+   * This function has an implementation, and does some setup, but does NOT set
+   * *aDocListener; this is the job of subclasses.
    */
   virtual nsresult StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
                                      nsILoadGroup* aLoadGroup,
                                      nsISupports* aContainer,
                                      nsIStreamListener** aDocListener,
                                      bool aReset,
                                      nsIContentSink* aSink = nullptr) = 0;
-  virtual void StopDocumentLoad() = 0;
+  virtual void StopDocumentLoad();
 
   virtual void SetSuppressParserErrorElement(bool aSuppress) {}
   virtual bool SuppressParserErrorElement() { return false; }
 
   virtual void SetSuppressParserErrorConsoleMessages(bool aSuppress) {}
   virtual bool SuppressParserErrorConsoleMessages() { return false; }
 
   // nsINode
   bool IsNodeOfType(uint32_t aFlags) const final;
   nsresult InsertChildBefore(nsIContent* aKid, nsIContent* aBeforeThis,
                              bool aNotify) override;
   void RemoveChildNode(nsIContent* aKid, bool aNotify) final;
   nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo,
                  nsINode** aResult) const override {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
+  nsresult CloneDocHelper(nsIDocument* clone) const;
 
   /**
    * Signal that the document title may have changed
    * (see nsDocument::GetTitle).
    * @param aBoundTitleElement true if an HTML or SVG <title> element
    * has just been bound to the document.
    */
   virtual void NotifyPossibleTitleChange(bool aBoundTitleElement);
@@ -783,16 +870,21 @@ class nsIDocument : public nsINode,
   /**
    * Tell this document that it's the initial document in its window.  See
    * comments on mIsInitialDocumentInWindow for when this should be called.
    */
   void SetIsInitialDocument(bool aIsInitialDocument) {
     mIsInitialDocumentInWindow = aIsInitialDocument;
   }
 
+  void SetLoadedAsData(bool aLoadedAsData) { mLoadedAsData = aLoadedAsData; }
+  void SetLoadedAsInteractiveData(bool aLoadedAsInteractiveData) {
+    mLoadedAsInteractiveData = aLoadedAsInteractiveData;
+  }
+
   /**
    * Normally we assert if a runnable labeled with one DocGroup touches data
    * from another DocGroup. Calling IgnoreDocGroupMismatches() on a document
    * means that we can touch that document from any DocGroup without asserting.
    */
   void IgnoreDocGroupMismatches() { mIgnoreDocGroupMismatches = true; }
 
   /**
@@ -1313,16 +1405,22 @@ class nsIDocument : public nsINode,
   void PostUnblockOnloadEvent();
 
   void DoUnblockOnload();
 
   void ClearAllBoxObjects();
 
   void MaybeEndOutermostXBLUpdate();
 
+  void RetrieveRelevantHeaders(nsIChannel* aChannel);
+
+  void TryChannelCharset(nsIChannel* aChannel, int32_t& aCharsetSource,
+                         NotNull<const Encoding*>& aEncoding,
+                         nsHtml5TreeOpExecutor* aExecutor);
+
   void DispatchContentLoadedEvents();
 
   void DispatchPageTransition(mozilla::dom::EventTarget* aDispatchTarget,
                               const nsAString& aType, bool aPersisted,
                               bool aOnlySystemGroup = false);
 
   // Call this before the document does something that will unbind all content.
   // That will stop us from doing a lot of work as each element is removed.
@@ -1777,21 +1875,21 @@ class nsIDocument : public nsINode,
    */
   bool RemoveObserver(nsIDocumentObserver* aObserver);
 
   // Observation hooks used to propagate notifications to document observers.
   // BeginUpdate must be called before any batch of modifications of the
   // content model or of style data, EndUpdate must be called afterward.
   // To make this easy and painless, use the mozAutoDocUpdate helper class.
   void BeginUpdate();
-  virtual void EndUpdate() = 0;
+  virtual void EndUpdate();
   uint32_t UpdateNestingLevel() { return mUpdateNestLevel; }
 
-  virtual void BeginLoad() = 0;
-  virtual void EndLoad() = 0;
+  virtual void BeginLoad();
+  virtual void EndLoad();
 
   enum ReadyState {
     READYSTATE_UNINITIALIZED = 0,
     READYSTATE_LOADING = 1,
     READYSTATE_INTERACTIVE = 3,
     READYSTATE_COMPLETE = 4
   };
   void SetReadyStateInternal(ReadyState rs);
@@ -2031,53 +2129,58 @@ class nsIDocument : public nsINode,
    *
    * |aNewRequest| should be the request for a new document which will
    * replace this document in the docshell.  The new document's request
    * will be ignored when checking for active requests.  If there is no
    * request associated with the new document, this parameter may be null.
    */
   virtual bool CanSavePresentation(nsIRequest* aNewRequest);
 
+  virtual nsresult Init();
+
   /**
    * Notify the document that its associated ContentViewer is being destroyed.
    * This releases circular references so that the document can go away.
    * Destroy() is only called on documents that have a content viewer.
    */
-  virtual void Destroy() = 0;
+  virtual void Destroy();
 
   /**
    * Notify the document that its associated ContentViewer is no longer
    * the current viewer for the docshell. The document might still
    * be rendered in "zombie state" until the next document is ready.
    * The document should save form control state.
    */
-  virtual void RemovedFromDocShell() = 0;
+  virtual void RemovedFromDocShell();
 
   /**
    * Get the layout history state that should be used to save and restore state
    * for nodes in this document.  This may return null; if that happens state
    * saving and restoration is not possible.
    */
   already_AddRefed<nsILayoutHistoryState> GetLayoutHistoryState() const;
 
   /**
    * Methods that can be used to prevent onload firing while an event that
    * should block onload is posted.  onload is guaranteed to not fire until
    * either all calls to BlockOnload() have been matched by calls to
    * UnblockOnload() or the load has been stopped altogether (by the user
    * pressing the Stop button, say).
    */
-  virtual void BlockOnload() = 0;
+  void BlockOnload();
   /**
    * @param aFireSync whether to fire onload synchronously.  If false,
    * onload will fire asynchronously after all onload blocks have been
    * removed.  It will NOT fire from inside UnblockOnload.  If true,
    * onload may fire from inside UnblockOnload.
    */
-  virtual void UnblockOnload(bool aFireSync) = 0;
+  void UnblockOnload(bool aFireSync);
+
+  // Only BlockOnload should call this!
+  void AsyncBlockOnload();
 
   void BlockDOMContentLoaded() { ++mBlockDOMContentLoaded; }
 
   void UnblockDOMContentLoaded();
 
   /**
    * Notification that the page has been shown, for documents which are loaded
    * into a DOM window.  This corresponds to the completion of document load,
@@ -2990,16 +3093,27 @@ class nsIDocument : public nsINode,
   // Not const because all the fullscreen goop is not const
   bool FullscreenEnabled(mozilla::dom::CallerType aCallerType);
   Element* FullscreenStackTop();
   bool Fullscreen() { return !!GetFullscreenElement(); }
   already_AddRefed<mozilla::dom::Promise> ExitFullscreen(ErrorResult&);
   void ExitPointerLock() { UnlockPointer(this); }
 
   static bool IsUnprefixedFullscreenEnabled(JSContext* aCx, JSObject* aObject);
+  static bool DocumentSupportsL10n(JSContext* aCx, JSObject* aObject);
+  static bool IsWebAnimationsEnabled(JSContext* aCx, JSObject* aObject);
+  static bool IsWebAnimationsEnabled(mozilla::dom::CallerType aCallerType);
+  static bool IsWebAnimationsGetAnimationsEnabled(JSContext* aCx,
+                                                  JSObject* aObject);
+  static bool AreWebAnimationsImplicitKeyframesEnabled(JSContext* aCx,
+                                                       JSObject* aObject);
+  static bool AreWebAnimationsTimelinesEnabled(JSContext* aCx,
+                                               JSObject* aObject);
+  // Checks that the caller is either chrome or some addon.
+  static bool IsCallerChromeOrAddon(JSContext* aCx, JSObject* aObject);
 
 #ifdef MOZILLA_INTERNAL_API
   bool Hidden() const {
     return mVisibilityState != mozilla::dom::VisibilityState::Visible;
   }
   mozilla::dom::VisibilityState VisibilityState() const {
     return mVisibilityState;
   }
@@ -3318,16 +3432,20 @@ class nsIDocument : public nsINode,
   void InitializeLocalization(nsTArray<nsString>& aResourceIds);
 
   void ParseWidthAndHeightInMetaViewport(const nsAString& aWidthString,
                                          const nsAString& aHeightString,
                                          const nsAString& aScaleString);
 
   nsTArray<nsString> mL10nResources;
 
+  // The application cache that this document is associated with, if
+  // any.  This can change during the lifetime of the document.
+  nsCOMPtr<nsIApplicationCache> mApplicationCache;
+
  public:
   bool IsThirdParty();
 
   bool IsScopedStyleEnabled();
 
   nsINode* GetServoRestyleRoot() const { return mServoRestyleRoot; }
 
   uint32_t GetServoRestyleRootDirtyBits() const {
@@ -4333,16 +4451,20 @@ class nsIDocument : public nsINode,
   RefPtr<mozilla::dom::XULPersist> mXULPersist;
 
   // document lightweight theme for use with :-moz-lwtheme,
   // :-moz-lwtheme-brighttext and :-moz-lwtheme-darktext
   DocumentTheme mDocLWTheme;
 
   // Pres shell resolution saved before entering fullscreen mode.
   float mSavedResolution;
+
+ public:
+  // Needs to be public because the bindings code pokes at it.
+  js::ExpandoAndGeneration mExpandoAndGeneration;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocument, NS_IDOCUMENT_IID)
 
 /**
  * mozAutoSubtreeModified batches DOM mutations so that a DOMSubtreeModified
  * event is dispatched, if necessary, when the outermost mozAutoSubtreeModified
  * object is deleted.
@@ -4379,17 +4501,17 @@ class MOZ_STACK_CLASS mozAutoSubtreeModi
 };
 
 class MOZ_STACK_CLASS nsAutoSyncOperation {
  public:
   explicit nsAutoSyncOperation(nsIDocument* aDocument);
   ~nsAutoSyncOperation();
 
  private:
-  nsCOMArray<nsIDocument> mDocuments;
+  nsTArray<nsCOMPtr<nsIDocument>> mDocuments;
   uint32_t mMicroTaskLevel;
 };
 
 class MOZ_RAII AutoSetThrowOnDynamicMarkupInsertionCounter final {
  public:
   explicit AutoSetThrowOnDynamicMarkupInsertionCounter(nsIDocument* aDocument)
       : mDocument(aDocument) {
     mDocument->IncrementThrowOnDynamicMarkupInsertionCounter();
@@ -4492,9 +4614,13 @@ inline nsIDocument* nsINode::AsDocument(
   return static_cast<nsIDocument*>(this);
 }
 
 inline const nsIDocument* nsINode::AsDocument() const {
   MOZ_ASSERT(IsDocument());
   return static_cast<const nsIDocument*>(this);
 }
 
+inline nsISupports* ToSupports(nsIDocument* aDoc) {
+  return static_cast<nsINode*>(aDoc);
+}
+
 #endif /* nsIDocument_h___ */
--- a/dom/base/nsImageLoadingContent.cpp
+++ b/dom/base/nsImageLoadingContent.cpp
@@ -783,18 +783,18 @@ nsImageLoadingContent::LoadImageWithChan
   // Shouldn't that be done before the start of the load?
   // XXX what about shouldProcess?
 
   // Our state might change. Watch it.
   AutoStateChanger changer(this, true);
 
   // Do the load.
   RefPtr<imgRequestProxy>& req = PrepareNextRequest(eImageLoadType_Normal);
-  nsresult rv = loader->LoadImageWithChannel(aChannel, this, doc, aListener,
-                                             getter_AddRefs(req));
+  nsresult rv = loader->LoadImageWithChannel(aChannel, this, ToSupports(doc),
+                                             aListener, getter_AddRefs(req));
   if (NS_SUCCEEDED(rv)) {
     CloneScriptedRequests(req);
     TrackImage(req);
     ResetAnimationIfNeeded();
     return NS_OK;
   }
 
   MOZ_ASSERT(!req, "Shouldn't have non-null request here");
--- a/dom/base/nsNodeUtils.cpp
+++ b/dom/base/nsNodeUtils.cpp
@@ -30,16 +30,17 @@
 #include "mozilla/dom/Animation.h"
 #include "mozilla/dom/HTMLImageElement.h"
 #include "mozilla/dom/HTMLMediaElement.h"
 #include "mozilla/dom/KeyframeEffect.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsObjectLoadingContent.h"
 #include "nsDOMMutationObserver.h"
 #include "mozilla/dom/BindingUtils.h"
+#include "mozilla/dom/CustomElementRegistry.h"
 #include "mozilla/dom/HTMLTemplateElement.h"
 #include "mozilla/dom/ShadowRoot.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using mozilla::AutoJSContext;
 
 enum class IsRemoveNotification {
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -257,17 +257,17 @@ class nsSimplePluginEvent : public Runna
         mTarget(aTarget),
         mDocument(aTarget->GetComposedDoc()),
         mEvent(aEvent) {
     MOZ_ASSERT(aTarget && mDocument);
   }
 
   nsSimplePluginEvent(nsIDocument* aTarget, const nsAString& aEvent)
       : mozilla::Runnable("nsSimplePluginEvent"),
-        mTarget(aTarget),
+        mTarget(ToSupports(aTarget)),
         mDocument(aTarget),
         mEvent(aEvent) {
     MOZ_ASSERT(aTarget);
   }
 
   nsSimplePluginEvent(nsIContent* aTarget, nsIDocument* aDocument,
                       const nsAString& aEvent)
       : mozilla::Runnable("nsSimplePluginEvent"),
--- a/dom/bindings/BindingDeclarations.h
+++ b/dom/bindings/BindingDeclarations.h
@@ -420,17 +420,17 @@ inline nsWrapperCache* GetWrapperCache(c
   return GetWrapperCache(aObject.get());
 }
 
 enum class ReflectionScope { Content, XBL, UAWidget };
 
 struct MOZ_STACK_CLASS ParentObject {
   template <class T>
   MOZ_IMPLICIT ParentObject(T* aObject)
-      : mObject(aObject),
+      : mObject(ToSupports(aObject)),
         mWrapperCache(GetWrapperCache(aObject)),
         mReflectionScope(ReflectionScope::Content) {}
 
   template <class T, template <typename> class SmartPtr>
   MOZ_IMPLICIT ParentObject(const SmartPtr<T>& aObject)
       : mObject(aObject.get()),
         mWrapperCache(GetWrapperCache(aObject.get())),
         mReflectionScope(ReflectionScope::Content) {}
--- a/dom/console/Console.cpp
+++ b/dom/console/Console.cpp
@@ -10,16 +10,17 @@
 #include "ConsoleCommon.h"
 
 #include "mozilla/dom/BlobBinding.h"
 #include "mozilla/dom/DOMPrefs.h"
 #include "mozilla/dom/Exceptions.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/FunctionBinding.h"
 #include "mozilla/dom/Performance.h"
+#include "mozilla/dom/PromiseBinding.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/StructuredCloneHolder.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "mozilla/dom/WorkerPrivate.h"
 #include "mozilla/dom/WorkerRunnable.h"
 #include "mozilla/dom/WorkerScope.h"
 #include "mozilla/dom/WorkletGlobalScope.h"
 #include "mozilla/dom/WorkletImpl.h"
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -2097,17 +2097,17 @@ void EventStateManager::DoScrollZoom(nsI
     EnsureDocument(mPresContext);
     if (Preferences::GetBool("browser.zoom.full") ||
         content->OwnerDoc()->IsSyntheticDocument()) {
       ChangeFullZoom(change);
     } else {
       ChangeTextSize(change);
     }
     nsContentUtils::DispatchChromeEvent(
-        mDocument, static_cast<nsIDocument*>(mDocument),
+        mDocument, ToSupports(mDocument),
         NS_LITERAL_STRING("ZoomChangeUsingMouseWheel"), CanBubble::eYes,
         Cancelable::eYes);
   }
 }
 
 static nsIFrame* GetParentFrameToScroll(nsIFrame* aFrame) {
   if (!aFrame) return nullptr;
 
--- a/dom/html/ImageDocument.cpp
+++ b/dom/html/ImageDocument.cpp
@@ -126,17 +126,17 @@ ImageListener::OnStartRequest(nsIRequest
 
   return MediaDocumentStreamListener::OnStartRequest(request, ctxt);
 }
 
 NS_IMETHODIMP
 ImageListener::OnStopRequest(nsIRequest* aRequest, nsISupports* aCtxt,
                              nsresult aStatus) {
   ImageDocument* imgDoc = static_cast<ImageDocument*>(mDocument.get());
-  nsContentUtils::DispatchChromeEvent(imgDoc, static_cast<nsIDocument*>(imgDoc),
+  nsContentUtils::DispatchChromeEvent(imgDoc, ToSupports(imgDoc),
                                       NS_LITERAL_STRING("ImageContentLoaded"),
                                       CanBubble::eYes, Cancelable::eYes);
   return MediaDocumentStreamListener::OnStopRequest(aRequest, aCtxt, aStatus);
 }
 
 ImageDocument::ImageDocument()
     : MediaDocument(),
       mVisibleWidth(0.0),
--- a/dom/html/nsHTMLContentSink.cpp
+++ b/dom/html/nsHTMLContentSink.cpp
@@ -945,17 +945,17 @@ nsresult HTMLContentSink::FlushTags() {
 
   return mCurrentContext ? mCurrentContext->FlushTags() : NS_OK;
 }
 
 void HTMLContentSink::SetDocumentCharset(NotNull<const Encoding*> aEncoding) {
   MOZ_ASSERT_UNREACHABLE("<meta charset> case doesn't occur with about:blank");
 }
 
-nsISupports* HTMLContentSink::GetTarget() { return mDocument; }
+nsISupports* HTMLContentSink::GetTarget() { return ToSupports(mDocument); }
 
 bool HTMLContentSink::IsScriptExecuting() { return IsScriptExecutingImpl(); }
 
 void HTMLContentSink::ContinueInterruptedParsingIfEnabled() {
   if (mParser && mParser->IsParserEnabled()) {
     static_cast<nsIParser*>(mParser.get())->ContinueInterruptedParsing();
   }
 }
--- a/dom/html/nsHTMLDocument.h
+++ b/dom/html/nsHTMLDocument.h
@@ -2,16 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef nsHTMLDocument_h___
 #define nsHTMLDocument_h___
 
 #include "mozilla/Attributes.h"
+#include "nsContentList.h"
 #include "nsDocument.h"
 #include "nsIHTMLDocument.h"
 #include "nsIHTMLCollection.h"
 #include "nsIScriptElement.h"
 #include "nsTArray.h"
 
 #include "PLDHashTable.h"
 #include "nsIHttpChannel.h"
@@ -28,16 +29,18 @@ class nsILoadGroup;
 
 namespace mozilla {
 namespace dom {
 class HTMLAllCollection;
 }  // namespace dom
 }  // namespace mozilla
 
 class nsHTMLDocument : public nsDocument, public nsIHTMLDocument {
+  typedef mozilla::net::ReferrerPolicy ReferrerPolicy;
+
  public:
   using nsDocument::GetPlugins;
   using nsDocument::SetDocumentURI;
 
   nsHTMLDocument();
   virtual nsresult Init() override;
 
   NS_DECL_ISUPPORTS_INHERITED
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -439,17 +439,17 @@ bool TabChild::AsyncPanZoomEnabled() con
 NS_IMETHODIMP
 TabChild::Observe(nsISupports* aSubject, const char* aTopic,
                   const char16_t* aData) {
   if (!strcmp(aTopic, BEFORE_FIRST_PAINT)) {
     if (AsyncPanZoomEnabled()) {
       nsCOMPtr<nsIDocument> subject(do_QueryInterface(aSubject));
       nsCOMPtr<nsIDocument> doc(GetDocument());
 
-      if (SameCOMIdentity(subject, doc)) {
+      if (subject == doc) {
         nsCOMPtr<nsIPresShell> shell(doc->GetShell());
         if (shell) {
           shell->SetIsFirstPaint(true);
         }
 
         APZCCallbackHelper::InitializeRootDisplayport(shell);
       }
     }
--- a/dom/svg/SVGAngle.cpp
+++ b/dom/svg/SVGAngle.cpp
@@ -11,16 +11,22 @@
 using namespace mozilla;
 using namespace mozilla::dom;
 
 NS_SVG_VAL_IMPL_CYCLE_COLLECTION_WRAPPERCACHED(SVGAngle, mSVGElement)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(SVGAngle, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(SVGAngle, Release)
 
+SVGAngle::SVGAngle(SVGElement* aSVGElement)
+    : mSVGElement(aSVGElement), mType(SVGAngle::CreatedValue) {
+  mVal = new nsSVGAngle();
+  mVal->Init();
+}
+
 JSObject* SVGAngle::WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aGivenProto) {
   return SVGAngle_Binding::Wrap(aCx, this, aGivenProto);
 }
 
 uint16_t SVGAngle::UnitType() const {
   if (mType == AnimValue) {
     return mVal->mAnimValUnit;
--- a/dom/svg/SVGAngle.h
+++ b/dom/svg/SVGAngle.h
@@ -18,19 +18,28 @@ namespace dom {
 
 class SVGAngle final : public nsWrapperCache {
  public:
   typedef enum { BaseValue, AnimValue, CreatedValue } AngleType;
 
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(SVGAngle)
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(SVGAngle)
 
+  /**
+   * Generic ctor for SVGAngle objects that are created for an attribute.
+   */
   SVGAngle(nsSVGAngle* aVal, SVGElement* aSVGElement, AngleType aType)
       : mVal(aVal), mSVGElement(aSVGElement), mType(aType) {}
 
+  /**
+   * Ctor for creating the objects returned by SVGSVGElement.createSVGAngle(),
+   * which do not initially belong to an attribute.
+   */
+  explicit SVGAngle(SVGElement* aSVGElement);
+
   // WebIDL
   SVGElement* GetParentObject() { return mSVGElement; }
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aGivenProto) override;
   uint16_t UnitType() const;
   float Value() const;
   void GetValueAsString(nsAString& aValue);
   void SetValue(float aValue, ErrorResult& rv);
--- a/dom/svg/SVGSVGElement.cpp
+++ b/dom/svg/SVGSVGElement.cpp
@@ -17,17 +17,16 @@
 #include "DOMSVGLength.h"
 #include "DOMSVGNumber.h"
 #include "DOMSVGPoint.h"
 #include "nsFrameSelection.h"
 #include "nsLayoutStylesheetCache.h"
 #include "nsIFrame.h"
 #include "nsISVGSVGFrame.h"
 #include "nsSMILTimeContainer.h"
-#include "nsSVGAngle.h"
 #include "SVGAngle.h"
 #include "nsSVGDisplayableFrame.h"
 #include "nsSVGUtils.h"
 
 NS_IMPL_NS_NEW_SVG_ELEMENT_CHECK_PARSER(SVG)
 
 using namespace mozilla::gfx;
 
@@ -258,20 +257,17 @@ already_AddRefed<DOMSVGNumber> SVGSVGEle
 }
 
 already_AddRefed<DOMSVGLength> SVGSVGElement::CreateSVGLength() {
   nsCOMPtr<DOMSVGLength> length = new DOMSVGLength();
   return length.forget();
 }
 
 already_AddRefed<SVGAngle> SVGSVGElement::CreateSVGAngle() {
-  nsSVGAngle* angle = new nsSVGAngle();
-  angle->Init();
-  RefPtr<SVGAngle> svgangle = new SVGAngle(angle, this, SVGAngle::CreatedValue);
-  return svgangle.forget();
+  return do_AddRef(new SVGAngle(this));
 }
 
 already_AddRefed<nsISVGPoint> SVGSVGElement::CreateSVGPoint() {
   nsCOMPtr<nsISVGPoint> point = new DOMSVGPoint(0, 0);
   return point.forget();
 }
 
 already_AddRefed<SVGMatrix> SVGSVGElement::CreateSVGMatrix() {
--- a/dom/xbl/nsXBLProtoImplField.cpp
+++ b/dom/xbl/nsXBLProtoImplField.cpp
@@ -12,16 +12,17 @@
 #include "js/CharacterEncoding.h"
 #include "nsUnicharUtils.h"
 #include "nsReadableUtils.h"
 #include "nsXBLProtoImplField.h"
 #include "nsIScriptContext.h"
 #include "nsIURI.h"
 #include "nsXBLSerialize.h"
 #include "nsXBLPrototypeBinding.h"
+#include "mozilla/CycleCollectedJSContext.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/ElementBinding.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "nsGlobalWindow.h"
 #include "xpcpublic.h"
 #include "WrapperFactory.h"
 
 using namespace mozilla;
--- a/dom/xbl/nsXBLProtoImplMethod.cpp
+++ b/dom/xbl/nsXBLProtoImplMethod.cpp
@@ -14,16 +14,17 @@
 #include "nsReadableUtils.h"
 #include "nsXBLProtoImplMethod.h"
 #include "nsJSUtils.h"
 #include "nsContentUtils.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIXPConnect.h"
 #include "xpcpublic.h"
 #include "nsXBLPrototypeBinding.h"
+#include "mozilla/CycleCollectedJSContext.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/ScriptSettings.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 nsXBLProtoImplMethod::nsXBLProtoImplMethod(const char16_t* aName)
     : nsXBLProtoImplMember(aName), mMethod() {
--- a/dom/xhr/XMLHttpRequestMainThread.cpp
+++ b/dom/xhr/XMLHttpRequestMainThread.cpp
@@ -19,16 +19,17 @@
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/FileBinding.h"
 #include "mozilla/dom/FileCreatorHelper.h"
 #include "mozilla/dom/FetchUtil.h"
 #include "mozilla/dom/FormData.h"
 #include "mozilla/dom/MutableBlobStorage.h"
 #include "mozilla/dom/XMLDocument.h"
 #include "mozilla/dom/URLSearchParams.h"
+#include "mozilla/dom/Promise.h"
 #include "mozilla/dom/PromiseNativeHandler.h"
 #include "mozilla/Encoding.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/LoadInfo.h"
 #include "mozilla/LoadContext.h"
 #include "mozilla/MemoryReporting.h"
@@ -704,17 +705,18 @@ void XMLHttpRequestMainThread::GetRespon
       return;
     }
     case XMLHttpRequestResponseType::Document: {
       if (!mResponseXML || mState != XMLHttpRequest_Binding::DONE) {
         aResponse.setNull();
         return;
       }
 
-      aRv = nsContentUtils::WrapNative(aCx, mResponseXML, aResponse);
+      aRv =
+          nsContentUtils::WrapNative(aCx, ToSupports(mResponseXML), aResponse);
       return;
     }
     case XMLHttpRequestResponseType::Json: {
       if (mState != XMLHttpRequest_Binding::DONE) {
         aResponse.setNull();
         return;
       }
 
--- a/dom/xml/XMLDocument.cpp
+++ b/dom/xml/XMLDocument.cpp
@@ -540,17 +540,17 @@ void XMLDocument::EndLoad() {
   nsDocument::EndLoad();
   if (mSynchronousDOMContentLoaded) {
     mSynchronousDOMContentLoaded = false;
     nsDocument::SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE);
     // Generate a document load event for the case when an XML
     // document was loaded as pure data without any presentation
     // attached to it.
     WidgetEvent event(true, eLoad);
-    EventDispatcher::Dispatch(static_cast<nsIDocument*>(this), nullptr, &event);
+    EventDispatcher::Dispatch(ToSupports(this), nullptr, &event);
   }
 }
 
 /* virtual */ void XMLDocument::DocAddSizeOfExcludingThis(
     nsWindowSizes& aWindowSizes) const {
   nsDocument::DocAddSizeOfExcludingThis(aWindowSizes);
 }
 
--- a/dom/xml/nsXMLContentSink.cpp
+++ b/dom/xml/nsXMLContentSink.cpp
@@ -732,17 +732,17 @@ nsresult nsXMLContentSink::MaybeProcessX
 }
 
 void nsXMLContentSink::SetDocumentCharset(NotNull<const Encoding*> aEncoding) {
   if (mDocument) {
     mDocument->SetDocumentCharacterSet(aEncoding);
   }
 }
 
-nsISupports* nsXMLContentSink::GetTarget() { return mDocument; }
+nsISupports* nsXMLContentSink::GetTarget() { return ToSupports(mDocument); }
 
 bool nsXMLContentSink::IsScriptExecuting() { return IsScriptExecutingImpl(); }
 
 nsresult nsXMLContentSink::FlushText(bool aReleaseTextNode) {
   nsresult rv = NS_OK;
 
   if (mTextLength != 0) {
     if (mLastTextNode) {
--- a/dom/xml/nsXMLFragmentContentSink.cpp
+++ b/dom/xml/nsXMLFragmentContentSink.cpp
@@ -163,17 +163,19 @@ nsXMLFragmentContentSink::DidBuildModel(
   return NS_OK;
 }
 
 void nsXMLFragmentContentSink::SetDocumentCharset(
     NotNull<const Encoding*> aEncoding) {
   MOZ_ASSERT_UNREACHABLE("fragments shouldn't set charset");
 }
 
-nsISupports* nsXMLFragmentContentSink::GetTarget() { return mTargetDocument; }
+nsISupports* nsXMLFragmentContentSink::GetTarget() {
+  return ToSupports(mTargetDocument);
+}
 
 ////////////////////////////////////////////////////////////////////////
 
 bool nsXMLFragmentContentSink::SetDocElement(int32_t aNameSpaceID,
                                              nsAtom* aTagName,
                                              nsIContent* aContent) {
   // this is a fragment, not a document
   return false;
--- a/dom/xul/XULDocument.cpp
+++ b/dom/xul/XULDocument.cpp
@@ -73,16 +73,17 @@
 #include "nsIStyleSheetLinkingElement.h"
 #include "nsIObserverService.h"
 #include "nsNodeUtils.h"
 #include "nsIXULWindow.h"
 #include "nsXULPopupManager.h"
 #include "nsCCUncollectableMarker.h"
 #include "nsURILoader.h"
 #include "mozilla/BasicEvents.h"
+#include "mozilla/CycleCollectedJSContext.h"
 #include "mozilla/dom/DocumentL10n.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/NodeInfoInlines.h"
 #include "mozilla/dom/ProcessingInstruction.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/XULDocumentBinding.h"
 #include "mozilla/dom/XULPersist.h"
 #include "mozilla/EventDispatcher.h"
@@ -984,19 +985,18 @@ nsresult XULDocument::DoneWalking() {
 
     // For performance reasons, we want to trigger the DocumentL10n's
     // `TriggerInitialDocumentTranslation` within the same microtask that will
     // be created for a `MozBeforeInitialXULLayout` event listener.
     AddEventListener(NS_LITERAL_STRING("MozBeforeInitialXULLayout"),
                      mDocumentL10n, true, false);
 
     nsContentUtils::DispatchTrustedEvent(
-        this, static_cast<nsIDocument*>(this),
-        NS_LITERAL_STRING("MozBeforeInitialXULLayout"), CanBubble::eYes,
-        Cancelable::eNo);
+        this, ToSupports(this), NS_LITERAL_STRING("MozBeforeInitialXULLayout"),
+        CanBubble::eYes, Cancelable::eNo);
 
     RemoveEventListener(NS_LITERAL_STRING("MozBeforeInitialXULLayout"),
                         mDocumentL10n, true);
 
     // Before starting layout, check whether we're a toplevel chrome
     // window.  If we are, setup some state so that we don't have to restyle
     // the whole tree after StartLayout.
     if (nsCOMPtr<nsIXULWindow> win = GetXULWindowIfToplevelChrome()) {
--- a/dom/xul/nsXULContentSink.cpp
+++ b/dom/xul/nsXULContentSink.cpp
@@ -227,17 +227,17 @@ void XULContentSinkImpl::SetDocumentChar
   nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
   if (doc) {
     doc->SetDocumentCharacterSet(aEncoding);
   }
 }
 
 nsISupports* XULContentSinkImpl::GetTarget() {
   nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
-  return doc;
+  return ToSupports(doc);
 }
 
 //----------------------------------------------------------------------
 
 nsresult XULContentSinkImpl::Init(nsIDocument* aDocument,
                                   nsXULPrototypeDocument* aPrototype) {
   MOZ_ASSERT(aDocument != nullptr, "null ptr");
   if (!aDocument) return NS_ERROR_NULL_POINTER;
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -730,16 +730,17 @@ mozilla::ipc::IPCResult WebRenderBridgeP
     size_t fileLength = wcsnlen_s(files, remaining);
     MOZ_ASSERT(fileLength < remaining && files[fileLength] == 0);
     DWORD attribs = GetFileAttributesW(files);
     if (!exists || attribs == INVALID_FILE_ATTRIBUTES) {
       gfxCriticalNote << (exists ? "found" : "MISSING") << " font family \""
                       << family << "\" has "
                       << (attribs == INVALID_FILE_ATTRIBUTES ? "INVALID"
                                                              : "valid")
+                      << "(" << hexa(attribs) << ")"
                       << " file \"" << files << "\"";
     }
     remaining -= fileLength + 1;
     files += fileLength + 1;
   }
 #endif
   return IPC_OK();
 }
--- a/image/VectorImage.cpp
+++ b/image/VectorImage.cpp
@@ -12,16 +12,17 @@
 #include "gfxUtils.h"
 #include "imgFrame.h"
 #include "mozilla/AutoRestore.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/SVGSVGElement.h"
 #include "mozilla/dom/SVGDocument.h"
 #include "mozilla/gfx/2D.h"
+#include "mozilla/PendingAnimationTracker.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/Tuple.h"
 #include "nsIPresShell.h"
 #include "nsIStreamListener.h"
 #include "nsMimeTypes.h"
 #include "nsPresContext.h"
 #include "nsRect.h"
 #include "nsString.h"
@@ -31,17 +32,17 @@
 #include "ImageRegion.h"
 #include "ISurfaceProvider.h"
 #include "LookupResult.h"
 #include "Orientation.h"
 #include "SVGDocumentWrapper.h"
 #include "SVGDrawingParameters.h"
 #include "nsIDOMEventListener.h"
 #include "SurfaceCache.h"
-#include "nsDocument.h"
+#include "nsIDocument.h"
 
 namespace mozilla {
 
 using namespace dom;
 using namespace dom::SVGPreserveAspectRatio_Binding;
 using namespace gfx;
 using namespace layers;
 
@@ -1474,19 +1475,18 @@ void VectorImage::InvalidateObserversOnN
 void VectorImage::PropagateUseCounters(nsIDocument* aParentDocument) {
   nsIDocument* doc = mSVGDocumentWrapper->GetDocument();
   if (doc) {
     doc->PropagateUseCounters(aParentDocument);
   }
 }
 
 void VectorImage::ReportUseCounters() {
-  nsIDocument* doc = mSVGDocumentWrapper->GetDocument();
-  if (doc) {
-    static_cast<nsDocument*>(doc)->ReportUseCounters();
+  if (nsIDocument* doc = mSVGDocumentWrapper->GetDocument()) {
+    doc->ReportUseCounters();
   }
 }
 
 nsIntSize VectorImage::OptimalImageSizeForDest(const gfxSize& aDest,
                                                uint32_t aWhichFrame,
                                                SamplingFilter aSamplingFilter,
                                                uint32_t aFlags) {
   MOZ_ASSERT(aDest.width >= 0 || ceil(aDest.width) <= INT32_MAX ||
--- a/image/imgLoader.cpp
+++ b/image/imgLoader.cpp
@@ -2150,21 +2150,21 @@ nsresult imgLoader::LoadImage(
     attrs = aTriggeringPrincipal->OriginAttributesRef();
   }
   ImageCacheKey key(aURI, attrs, aLoadingDocument, rv);
   NS_ENSURE_SUCCESS(rv, rv);
   imgCacheTable& cache = GetCache(key);
 
   if (cache.Get(key, getter_AddRefs(entry)) && entry) {
     bool newChannelCreated = false;
-    if (ValidateEntry(entry, aURI, aInitialDocumentURI, aReferrerURI,
-                      aReferrerPolicy, aLoadGroup, aObserver, aLoadingDocument,
-                      aLoadingDocument, requestFlags, aContentPolicyType, true,
-                      &newChannelCreated, _retval, aTriggeringPrincipal,
-                      corsmode)) {
+    if (ValidateEntry(
+            entry, aURI, aInitialDocumentURI, aReferrerURI, aReferrerPolicy,
+            aLoadGroup, aObserver, ToSupports(aLoadingDocument),
+            aLoadingDocument, requestFlags, aContentPolicyType, true,
+            &newChannelCreated, _retval, aTriggeringPrincipal, corsmode)) {
       request = entry->GetRequest();
 
       // If this entry has no proxies, its request has no reference to the
       // entry.
       if (entry->HasNoProxies()) {
         LOG_FUNC_WITH_PARAM(gImgLog,
                             "imgLoader::LoadImage() adding proxyless entry",
                             "uri", key.URI());
@@ -2180,19 +2180,20 @@ nsresult imgLoader::LoadImage(
       entry->Touch();
 
       if (!newChannelCreated) {
         // This is ugly but it's needed to report CSP violations. We have 3
         // scenarios:
         // - we don't have cache. We are not in this if() stmt. A new channel is
         //   created and that triggers the CSP checks.
         // - We have a cache entry and this is blocked by CSP directives.
-        DebugOnly<bool> shouldLoad = ShouldLoadCachedImage(
-            request, aLoadingDocument, aTriggeringPrincipal, aContentPolicyType,
-            /* aSendCSPViolationReports */ true);
+        DebugOnly<bool> shouldLoad =
+            ShouldLoadCachedImage(request, ToSupports(aLoadingDocument),
+                                  aTriggeringPrincipal, aContentPolicyType,
+                                  /* aSendCSPViolationReports */ true);
         MOZ_ASSERT(shouldLoad);
       }
     } else {
       // We can't use this entry. We'll try to load it off the network, and if
       // successful, overwrite the old entry in the cache with a new one.
       entry = nullptr;
     }
   }
@@ -2239,18 +2240,19 @@ nsresult imgLoader::LoadImage(
           Unused << httpChannel->SetRequestContextID(aRequestContextID);
         }
       }
     }
 
     nsCOMPtr<nsILoadGroup> channelLoadGroup;
     newChannel->GetLoadGroup(getter_AddRefs(channelLoadGroup));
     rv = request->Init(aURI, aURI, /* aHadInsecureRedirect = */ false,
-                       channelLoadGroup, newChannel, entry, aLoadingDocument,
-                       aTriggeringPrincipal, corsmode, aReferrerPolicy);
+                       channelLoadGroup, newChannel, entry,
+                       ToSupports(aLoadingDocument), aTriggeringPrincipal,
+                       corsmode, aReferrerPolicy);
     if (NS_FAILED(rv)) {
       return NS_ERROR_FAILURE;
     }
 
     // Add the initiator type for this image load
     nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(newChannel);
     if (timedChannel) {
       timedChannel->SetInitiatorType(initiatorType);
--- a/layout/base/GeometryUtils.cpp
+++ b/layout/base/GeometryUtils.cpp
@@ -152,22 +152,22 @@ static nsRect GetBoxRectForFrame(nsIFram
       return r;
   }
 
   return r;
 }
 
 class AccumulateQuadCallback : public nsLayoutUtils::BoxCallback {
  public:
-  AccumulateQuadCallback(nsISupports* aParentObject,
+  AccumulateQuadCallback(nsIDocument* aParentObject,
                          nsTArray<RefPtr<DOMQuad> >& aResult,
                          nsIFrame* aRelativeToFrame,
                          const nsPoint& aRelativeToBoxTopLeft,
                          CSSBoxType aBoxType)
-      : mParentObject(aParentObject),
+      : mParentObject(ToSupports(aParentObject)),
         mResult(aResult),
         mRelativeToFrame(aRelativeToFrame),
         mRelativeToBoxTopLeft(aRelativeToBoxTopLeft),
         mBoxType(aBoxType) {
     if (mBoxType == CSSBoxType::Margin) {
       // Don't include the caption margin when computing margins for a
       // table
       mIncludeCaptionBoxForTable = false;
--- a/layout/base/MobileViewportManager.cpp
+++ b/layout/base/MobileViewportManager.cpp
@@ -154,17 +154,17 @@ MobileViewportManager::HandleEvent(dom::
     }
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 MobileViewportManager::Observe(nsISupports* aSubject, const char* aTopic,
                                const char16_t* aData) {
-  if (SameCOMIdentity(aSubject, mDocument) &&
+  if (SameCOMIdentity(aSubject, ToSupports(mDocument)) &&
       BEFORE_FIRST_PAINT.EqualsASCII(aTopic)) {
     MVM_LOG("%p: got a before-first-paint event\n", this);
     if (!mPainted) {
       // before-first-paint message arrived before load event
       SetInitialViewport();
     }
   }
   return NS_OK;
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -515,18 +515,18 @@ class nsBeforeFirstPaintDispatcher : pub
         mDocument(aDocument) {}
 
   // Fires the "before-first-paint" event so that interested parties (right now,
   // the mobile browser) are aware of it.
   NS_IMETHOD Run() override {
     nsCOMPtr<nsIObserverService> observerService =
         mozilla::services::GetObserverService();
     if (observerService) {
-      observerService->NotifyObservers(mDocument, "before-first-paint",
-                                       nullptr);
+      observerService->NotifyObservers(ToSupports(mDocument),
+                                       "before-first-paint", nullptr);
     }
     return NS_OK;
   }
 
  private:
   nsCOMPtr<nsIDocument> mDocument;
 };
 
@@ -1439,17 +1439,17 @@ void nsIPresShell::SetAuthorStyleDisable
   if (aStyleDisabled != mStyleSet->GetAuthorStyleDisabled()) {
     mStyleSet->SetAuthorStyleDisabled(aStyleDisabled);
     ApplicableStylesChanged();
 
     nsCOMPtr<nsIObserverService> observerService =
         mozilla::services::GetObserverService();
     if (observerService) {
       observerService->NotifyObservers(
-          mDocument, "author-style-disabled-changed", nullptr);
+          ToSupports(mDocument), "author-style-disabled-changed", nullptr);
     }
   }
 }
 
 bool nsIPresShell::GetAuthorStyleDisabled() const {
   return mStyleSet->GetAuthorStyleDisabled();
 }
 
--- a/layout/base/ZoomConstraintsClient.cpp
+++ b/layout/base/ZoomConstraintsClient.cpp
@@ -139,17 +139,17 @@ ZoomConstraintsClient::HandleEvent(dom::
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 ZoomConstraintsClient::Observe(nsISupports* aSubject, const char* aTopic,
                                const char16_t* aData) {
-  if (SameCOMIdentity(aSubject, mDocument) &&
+  if (SameCOMIdentity(aSubject, ToSupports(mDocument)) &&
       BEFORE_FIRST_PAINT.EqualsASCII(aTopic)) {
     ZCC_LOG("Got a before-first-paint event in %p\n", this);
     RefreshZoomConstraints();
   } else if (NS_PREF_CHANGED.EqualsASCII(aTopic)) {
     ZCC_LOG("Got a pref-change event in %p\n", this);
     // We need to run this later because all the pref change listeners need
     // to execute before we can be guaranteed that gfxPrefs::ForceUserScalable()
     // returns the updated value.
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -483,28 +483,29 @@ class AutoPrintEventDispatcher {
     DispatchEventToWindowTree(NS_LITERAL_STRING("beforeprint"));
   }
   ~AutoPrintEventDispatcher() {
     DispatchEventToWindowTree(NS_LITERAL_STRING("afterprint"));
   }
 
  private:
   void DispatchEventToWindowTree(const nsAString& aEvent) {
-    nsCOMArray<nsIDocument> targets;
+    nsTArray<nsCOMPtr<nsIDocument>> targets;
     CollectDocuments(mTop, &targets);
-    for (int32_t i = 0; i < targets.Count(); ++i) {
-      nsIDocument* d = targets[i];
-      nsContentUtils::DispatchTrustedEvent(
-          d, d->GetWindow(), aEvent, CanBubble::eNo, Cancelable::eNo, nullptr);
+    for (nsCOMPtr<nsIDocument>& doc : targets) {
+      nsContentUtils::DispatchTrustedEvent(doc, doc->GetWindow(), aEvent,
+                                           CanBubble::eNo, Cancelable::eNo,
+                                           nullptr);
     }
   }
 
   static bool CollectDocuments(nsIDocument* aDocument, void* aData) {
     if (aDocument) {
-      static_cast<nsCOMArray<nsIDocument>*>(aData)->AppendObject(aDocument);
+      static_cast<nsTArray<nsCOMPtr<nsIDocument>>*>(aData)->AppendElement(
+          aDocument);
       aDocument->EnumerateSubDocuments(CollectDocuments, aData);
     }
     return true;
   }
 
   nsCOMPtr<nsIDocument> mTop;
 };
 
@@ -1080,17 +1081,17 @@ nsDocumentViewer::LoadComplete(nsresult 
         timing->NotifyLoadEventStart();
       }
 
       // Dispatch observer notification to notify observers document load is
       // complete.
       nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
       if (os) {
         nsIPrincipal* principal = d->NodePrincipal();
-        os->NotifyObservers(d,
+        os->NotifyObservers(ToSupports(d),
                             nsContentUtils::IsSystemPrincipal(principal)
                                 ? "chrome-document-loaded"
                                 : "content-document-loaded",
                             nullptr);
       }
 
       // Notify any devtools about the load.
       RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get();
@@ -2846,19 +2847,19 @@ nsDocumentViewer::SetTextZoom(float aTex
     pc->SetTextZoom(aTextZoom);
   }
 
   // And do the external resources
   mDocument->EnumerateExternalResources(SetExtResourceTextZoom, &ZoomInfo);
 
   // Dispatch TextZoomChange event only if text zoom value has changed.
   if (textZoomChange) {
-    nsContentUtils::DispatchChromeEvent(
-        mDocument, static_cast<nsIDocument*>(mDocument),
-        NS_LITERAL_STRING("TextZoomChange"), CanBubble::eYes, Cancelable::eYes);
+    nsContentUtils::DispatchChromeEvent(mDocument, ToSupports(mDocument),
+                                        NS_LITERAL_STRING("TextZoomChange"),
+                                        CanBubble::eYes, Cancelable::eYes);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocumentViewer::GetTextZoom(float* aTextZoom) {
   NS_ENSURE_ARG_POINTER(aTextZoom);
@@ -2963,19 +2964,19 @@ nsDocumentViewer::SetFullZoom(float aFul
   }
 
   // And do the external resources
   mDocument->EnumerateExternalResources(SetExtResourceFullZoom, &ZoomInfo);
 
   // Dispatch FullZoomChange event only if fullzoom value really was been
   // changed
   if (fullZoomChange) {
-    nsContentUtils::DispatchChromeEvent(
-        mDocument, static_cast<nsIDocument*>(mDocument),
-        NS_LITERAL_STRING("FullZoomChange"), CanBubble::eYes, Cancelable::eYes);
+    nsContentUtils::DispatchChromeEvent(mDocument, ToSupports(mDocument),
+                                        NS_LITERAL_STRING("FullZoomChange"),
+                                        CanBubble::eYes, Cancelable::eYes);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocumentViewer::GetFullZoom(float* aFullZoom) {
   NS_ENSURE_ARG_POINTER(aFullZoom);
@@ -4376,12 +4377,13 @@ void nsDocumentViewer::SetPrintPreviewPr
 }
 
 // Fires the "document-shown" event so that interested parties are aware of it.
 NS_IMETHODIMP
 nsDocumentShownDispatcher::Run() {
   nsCOMPtr<nsIObserverService> observerService =
       mozilla::services::GetObserverService();
   if (observerService) {
-    observerService->NotifyObservers(mDocument, "document-shown", nullptr);
+    observerService->NotifyObservers(ToSupports(mDocument), "document-shown",
+                                     nullptr);
   }
   return NS_OK;
 }
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -8567,18 +8567,18 @@ void MaybeSetupTransactionIdAllocator(la
   aMetrics.BSize(aLineWM) += aFramePadding.BStartEnd(aFrameWM);
 }
 
 /* static */ bool nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(
     nsIPresShell* aShell) {
   if (nsIDocument* doc = aShell->GetDocument()) {
     WidgetEvent event(true, eVoidEvent);
     nsTArray<EventTarget*> targets;
-    nsresult rv = EventDispatcher::Dispatch(doc, nullptr, &event, nullptr,
-                                            nullptr, nullptr, &targets);
+    nsresult rv = EventDispatcher::Dispatch(
+        ToSupports(doc), nullptr, &event, nullptr, nullptr, nullptr, &targets);
     NS_ENSURE_SUCCESS(rv, false);
     for (size_t i = 0; i < targets.Length(); i++) {
       if (targets[i]->IsApzAware()) {
         return true;
       }
     }
   }
   return false;
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -4909,19 +4909,19 @@ void ScrollFrameHelper::FireScrollEvent(
   ActiveLayerTracker::SetCurrentScrollHandlerFrame(mOuter);
   WidgetGUIEvent event(true, eScroll, nullptr);
   nsEventStatus status = nsEventStatus_eIgnore;
   // Fire viewport scroll events at the document (where they
   // will bubble to the window)
   mozilla::layers::ScrollLinkedEffectDetector detector(
       content->GetComposedDoc());
   if (mIsRoot) {
-    nsIDocument* doc = content->GetUncomposedDoc();
-    if (doc) {
-      EventDispatcher::Dispatch(doc, prescontext, &event, nullptr, &status);
+    if (nsIDocument* doc = content->GetUncomposedDoc()) {
+      EventDispatcher::Dispatch(ToSupports(doc), prescontext, &event, nullptr,
+                                &status);
     }
   } else {
     // scroll events fired at elements don't bubble (although scroll events
     // fired at documents do, to the window)
     event.mFlags.mBubbles = false;
     EventDispatcher::Dispatch(content, prescontext, &event, nullptr, &status);
   }
   ActiveLayerTracker::SetCurrentScrollHandlerFrame(nullptr);
@@ -6188,20 +6188,18 @@ ScrollFrameHelper::ScrolledAreaEvent::Ru
 void ScrollFrameHelper::FireScrolledAreaEvent() {
   mScrolledAreaEvent.Forget();
 
   InternalScrollAreaEvent event(true, eScrolledAreaChanged, nullptr);
   nsPresContext* prescontext = mOuter->PresContext();
   nsIContent* content = mOuter->GetContent();
 
   event.mArea = mScrolledFrame->GetScrollableOverflowRectRelativeToParent();
-
-  nsIDocument* doc = content->GetUncomposedDoc();
-  if (doc) {
-    EventDispatcher::Dispatch(doc, prescontext, &event, nullptr);
+  if (nsIDocument* doc = content->GetUncomposedDoc()) {
+    EventDispatcher::Dispatch(ToSupports(doc), prescontext, &event, nullptr);
   }
 }
 
 uint32_t nsIScrollableFrame::GetPerceivedScrollingDirections() const {
   nscoord oneDevPixel =
       GetScrolledFrame()->PresContext()->AppUnitsPerDevPixel();
   uint32_t directions = GetScrollbarVisibility();
   nsRect scrollRange = GetScrollRange();
--- a/layout/style/MediaQueryList.cpp
+++ b/layout/style/MediaQueryList.cpp
@@ -138,17 +138,19 @@ void MediaQueryList::RecomputeMatches() 
     // XXXbz What's the right behavior here?  Spec doesn't say.
     return;
   }
 
   mMatches = mMediaList->Matches(presContext);
   mMatchesValid = true;
 }
 
-nsISupports* MediaQueryList::GetParentObject() const { return mDocument; }
+nsISupports* MediaQueryList::GetParentObject() const {
+  return ToSupports(mDocument);
+}
 
 JSObject* MediaQueryList::WrapObject(JSContext* aCx,
                                      JS::Handle<JSObject*> aGivenProto) {
   return MediaQueryList_Binding::Wrap(aCx, this, aGivenProto);
 }
 
 void MediaQueryList::MaybeNotify() {
   mMatchesValid = false;
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -44,21 +44,16 @@ raw-lines = [
     "pub use self::root::mozilla::dom::*;",
     "use atomic_refcell::AtomicRefCell;",
     "use data::ElementData;",
 ]
 hide-types = [
     "nsString",
     ".*char_traits",
     ".*incompatible_char_type",
-    # JS::Value uses alignas(8) which bindgen can't represent correctly on Linux
-    # 32-bit.  See https://github.com/rust-lang-nursery/rust-bindgen/issues/917.
-    # It's also not used by Stylo.  The following types are also hidden for
-    # making use of it and being similarly unused by Stylo.
-    "JS::Value",
     "mozilla::binding_danger::TErrorResult.*",
     "mozilla::ErrorResult.*", # Causes JSWhyMagic to be included & handled incorrectly.
     "mozilla::dom::CallbackFunction",
     "mozilla::dom::CallbackObject.*",
     "nsINode_ErrorResult",
     "nsDOMAttributeMap_ErrorResult",
     # End of JS::Value related types
     # This is generated by cbindgen, and we map it to its original rust type.
--- a/parser/html/nsHtml5TreeOpExecutor.cpp
+++ b/parser/html/nsHtml5TreeOpExecutor.cpp
@@ -229,17 +229,19 @@ nsHtml5TreeOpExecutor::SetParser(nsParse
 
 void nsHtml5TreeOpExecutor::FlushPendingNotifications(FlushType aType) {
   if (aType >= FlushType::EnsurePresShellInitAndFrames) {
     // Bug 577508 / 253951
     nsContentSink::StartLayout(true);
   }
 }
 
-nsISupports* nsHtml5TreeOpExecutor::GetTarget() { return mDocument; }
+nsISupports* nsHtml5TreeOpExecutor::GetTarget() {
+  return ToSupports(mDocument);
+}
 
 nsresult nsHtml5TreeOpExecutor::MarkAsBroken(nsresult aReason) {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   mBroken = aReason;
   if (mStreamParser) {
     mStreamParser->Terminate();
   }
   // We are under memory pressure, but let's hope the following allocation
--- a/toolkit/components/browser/nsWebBrowser.cpp
+++ b/toolkit/components/browser/nsWebBrowser.cpp
@@ -882,17 +882,17 @@ nsWebBrowser::SaveDocument(nsISupports* 
   // attached to the web browser.
 
   nsCOMPtr<nsISupports> doc;
   if (aDocumentish) {
     doc = aDocumentish;
   } else {
     nsCOMPtr<nsIDocument> domDoc;
     GetDocument(getter_AddRefs(domDoc));
-    doc = domDoc.forget();
+    doc = already_AddRefed<nsISupports>(ToSupports(domDoc.forget().take()));
   }
   if (!doc) {
     return NS_ERROR_FAILURE;
   }
 
   // Create a throwaway persistence object to do the work
   nsresult rv;
   mPersist = do_CreateInstance(NS_WEBBROWSERPERSIST_CONTRACTID, &rv);
--- a/toolkit/content/tests/widgets/xbl/mochitest.ini
+++ b/toolkit/content/tests/widgets/xbl/mochitest.ini
@@ -21,17 +21,17 @@ support-files =
   ../videocontrols_direction-2d.html
   ../videocontrols_direction-2e.html
   ../videocontrols_direction_test.js
   ../videomask.css
 
 [test_audiocontrols_dimensions.html]
 [test_videocontrols.html]
 tags = fullscreen
-skip-if = toolkit == 'android' || (verify && debug && (os == 'linux')) #TIMED_OUT
+skip-if = toolkit == 'android' || (verify && debug && (os == 'linux')) || (os == 'linux') #TIMED_OUT, Bug 1511256
 [test_videocontrols_keyhandler.html]
 skip-if = (toolkit == 'android') || (os == 'linux') #Bug 1366957
 [test_videocontrols_vtt.html]
 [test_videocontrols_iframe_fullscreen.html]
 [test_videocontrols_size.html]
 [test_videocontrols_audio.html]
 [test_videocontrols_audio_direction.html]
 [test_videocontrols_jsdisabled.html]
--- a/uriloader/prefetch/OfflineCacheUpdateChild.cpp
+++ b/uriloader/prefetch/OfflineCacheUpdateChild.cpp
@@ -129,35 +129,31 @@ void OfflineCacheUpdateChild::SetDocumen
   mDocument = aDocument;
 }
 
 nsresult OfflineCacheUpdateChild::AssociateDocument(
     nsIDocument *aDocument, nsIApplicationCache *aApplicationCache) {
   // Check that the document that requested this update was
   // previously associated with an application cache.  If not, it
   // should be associated with the new one.
-  nsCOMPtr<nsIApplicationCacheContainer> container =
-      do_QueryInterface(aDocument);
-  if (!container) return NS_OK;
-
   nsCOMPtr<nsIApplicationCache> existingCache;
-  nsresult rv = container->GetApplicationCache(getter_AddRefs(existingCache));
+  nsresult rv = aDocument->GetApplicationCache(getter_AddRefs(existingCache));
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!existingCache) {
     if (LOG_ENABLED()) {
       nsAutoCString clientID;
       if (aApplicationCache) {
         aApplicationCache->GetClientID(clientID);
       }
       LOG(("Update %p: associating app cache %s to document %p", this,
            clientID.get(), aDocument));
     }
 
-    rv = container->SetApplicationCache(aApplicationCache);
+    rv = aDocument->SetApplicationCache(aApplicationCache);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // OfflineCacheUpdateChild::nsIOfflineCacheUpdate
--- a/uriloader/prefetch/OfflineCacheUpdateGlue.cpp
+++ b/uriloader/prefetch/OfflineCacheUpdateGlue.cpp
@@ -178,35 +178,35 @@ OfflineCacheUpdateGlue::UpdateStateChang
 NS_IMETHODIMP
 OfflineCacheUpdateGlue::ApplicationCacheAvailable(
     nsIApplicationCache *aApplicationCache) {
   NS_ENSURE_ARG(aApplicationCache);
 
   // Check that the document that requested this update was
   // previously associated with an application cache.  If not, it
   // should be associated with the new one.
-  nsCOMPtr<nsIApplicationCacheContainer> container =
-      do_QueryInterface(mDocument);
-  if (!container) return NS_OK;
+  if (!mDocument) {
+    return NS_OK;
+  }
 
   nsCOMPtr<nsIApplicationCache> existingCache;
-  nsresult rv = container->GetApplicationCache(getter_AddRefs(existingCache));
+  nsresult rv = mDocument->GetApplicationCache(getter_AddRefs(existingCache));
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!existingCache) {
     if (LOG_ENABLED()) {
       nsAutoCString clientID;
       if (aApplicationCache) {
         aApplicationCache->GetClientID(clientID);
       }
       LOG(("Update %p: associating app cache %s to document %p", this,
            clientID.get(), mDocument.get()));
     }
 
-    rv = container->SetApplicationCache(aApplicationCache);
+    rv = mDocument->SetApplicationCache(aApplicationCache);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
 }  // namespace docshell
 }  // namespace mozilla
--- a/uriloader/prefetch/nsOfflineCacheUpdateService.cpp
+++ b/uriloader/prefetch/nsOfflineCacheUpdateService.cpp
@@ -161,19 +161,17 @@ nsOfflineCachePendingUpdate::OnStateChan
   nsCOMPtr<mozIDOMWindowProxy> windowProxy;
   aWebProgress->GetDOMWindow(getter_AddRefs(windowProxy));
   if (!windowProxy) return NS_OK;
 
   auto *outerWindow = nsPIDOMWindowOuter::From(windowProxy);
   nsPIDOMWindowInner *innerWindow = outerWindow->GetCurrentInnerWindow();
 
   nsCOMPtr<nsIDocument> progressDoc = outerWindow->GetDoc();
-  if (!progressDoc) return NS_OK;
-
-  if (!SameCOMIdentity(progressDoc, updateDoc)) {
+  if (!progressDoc || progressDoc != updateDoc) {
     return NS_OK;
   }
 
   LOG(("nsOfflineCachePendingUpdate::OnStateChange [%p, doc=%p]", this,
        progressDoc.get()));
 
   // Only schedule the update if the document loaded successfully
   if (NS_SUCCEEDED(aStatus)) {
--- a/xpcom/base/nsCOMPtr.h
+++ b/xpcom/base/nsCOMPtr.h
@@ -159,17 +159,18 @@ class MOZ_STACK_CLASS nsQueryInterfaceIS
   nsISupports* MOZ_OWNING_REF mRawPtr;
 };
 
 #ifndef NSCAP_FEATURE_USE_BASE
 template <typename T>
 class MOZ_STACK_CLASS nsQueryInterface final
     : public nsQueryInterfaceISupports {
  public:
-  explicit nsQueryInterface(T* aRawPtr) : nsQueryInterfaceISupports(aRawPtr) {}
+  explicit nsQueryInterface(T* aRawPtr)
+      : nsQueryInterfaceISupports(ToSupports(aRawPtr)) {}
 
   nsresult NS_FASTCALL operator()(const nsIID& aIID, void** aAnswer) const {
     return nsQueryInterfaceISupports::operator()(aIID, aAnswer);
   }
 };
 #endif  // #ifndef NSCAP_FEATURE_USE_BASE
 
 class MOZ_STACK_CLASS nsQueryInterfaceISupportsWithError {
@@ -185,56 +186,58 @@ class MOZ_STACK_CLASS nsQueryInterfaceIS
 };
 
 #ifndef NSCAP_FEATURE_USE_BASE
 template <typename T>
 class MOZ_STACK_CLASS nsQueryInterfaceWithError final
     : public nsQueryInterfaceISupportsWithError {
  public:
   explicit nsQueryInterfaceWithError(T* aRawPtr, nsresult* aError)
-      : nsQueryInterfaceISupportsWithError(aRawPtr, aError) {}
+      : nsQueryInterfaceISupportsWithError(ToSupports(aRawPtr), aError) {}
 
   nsresult NS_FASTCALL operator()(const nsIID& aIID, void** aAnswer) const {
     return nsQueryInterfaceISupportsWithError::operator()(aIID, aAnswer);
   }
 };
 #endif  // #ifndef NSCAP_FEATURE_USE_BASE
 
-#ifdef NSCAP_FEATURE_USE_BASE
-
-inline nsQueryInterfaceISupports do_QueryInterface(nsISupports* aRawPtr) {
-  return nsQueryInterfaceISupports(aRawPtr);
-}
-
-inline nsQueryInterfaceISupportsWithError do_QueryInterface(
-    nsISupports* aRawPtr, nsresult* aError) {
-  return nsQueryInterfaceISupportsWithError(aRawPtr, aError);
-}
-
-#else
-
 namespace mozilla {
 // PointedToType<> is needed so that do_QueryInterface() will work with a
 // variety of smart pointer types in addition to raw pointers. These types
 // include RefPtr<>, nsCOMPtr<>, and OwningNonNull<>.
 template <class T>
 using PointedToType =
     typename mozilla::RemovePointer<decltype(&*mozilla::DeclVal<T>())>::Type;
 }  // namespace mozilla
 
+#ifdef NSCAP_FEATURE_USE_BASE
+template <class T>
+inline nsQueryInterfaceISupports do_QueryInterface(T aPtr) {
+  return nsQueryInterfaceISupports(
+      ToSupports(static_cast<mozilla::PointedToType<T>*>(aPtr)));
+}
+
+template <class T>
+inline nsQueryInterfaceISupportsWithError do_QueryInterface(T aPtr,
+                                                            nsresult* aError) {
+  return nsQueryInterfaceISupportsWithError(
+      ToSupports(static_cast<mozilla::PointedToType<T>*>(aPtr)), aError);
+}
+#else
 template <class T>
 inline nsQueryInterface<mozilla::PointedToType<T> > do_QueryInterface(T aPtr) {
   return nsQueryInterface<mozilla::PointedToType<T> >(aPtr);
 }
 
 template <class T>
 inline nsQueryInterfaceWithError<mozilla::PointedToType<T> > do_QueryInterface(
     T aRawPtr, nsresult* aError) {
   return nsQueryInterfaceWithError<mozilla::PointedToType<T> >(aRawPtr, aError);
 }
+
 #endif  // ! #ifdef NSCAP_FEATURE_USE_BASE
 
 template <class T>
 inline void do_QueryInterface(already_AddRefed<T>&) {
   // This signature exists solely to _stop_ you from doing the bad thing.
   // Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
   // someone else is an automatic leak. See bug 8221.
 }
@@ -375,23 +378,25 @@ template <class T>
 char TestForIID(...);
 
 template <class T>
 class MOZ_IS_REFPTR nsCOMPtr final
 #ifdef NSCAP_FEATURE_USE_BASE
     : private nsCOMPtr_base
 #endif
 {
-
+ private:
 #ifdef NSCAP_FEATURE_USE_BASE
-#define NSCAP_CTOR_BASE(x) nsCOMPtr_base(x)
+#define NSCAP_CTOR_BASE(x) nsCOMPtr_base(ToSupports(x))
+  void assign_assuming_AddRef(T* aNewPtr) {
+    nsCOMPtr_base::assign_assuming_AddRef(ToSupports(aNewPtr));
+  }
 #else
 #define NSCAP_CTOR_BASE(x) mRawPtr(x)
 
- private:
   void assign_with_AddRef(nsISupports*);
   template <typename U>
   void assign_from_qi(const nsQueryInterface<U>, const nsIID&);
   template <typename U>
   void assign_from_qi_with_error(const nsQueryInterfaceWithError<U>&,
                                  const nsIID&);
   void assign_from_gs_cid(const nsGetServiceByCID, const nsIID&);
   void assign_from_gs_cid_with_error(const nsGetServiceByCIDWithError&,
@@ -630,26 +635,26 @@ class MOZ_IS_REFPTR nsCOMPtr final
 
   // Defined in OwningNonNull.h
   template <class U>
   MOZ_IMPLICIT nsCOMPtr(const mozilla::OwningNonNull<U>& aOther);
 
   // Assignment operators
 
   nsCOMPtr<T>& operator=(const nsCOMPtr<T>& aRhs) {
-    assign_with_AddRef(aRhs.mRawPtr);
+    assign_with_AddRef(ToSupports(aRhs.mRawPtr));
     return *this;
   }
 
   template <class U>
   nsCOMPtr<T>& operator=(const nsCOMPtr<U>& aRhs) {
     // Make sure that U actually inherits from T
     static_assert(mozilla::IsBaseOf<T, U>::value,
                   "U should be a subclass of T");
-    assign_with_AddRef(static_cast<T*>(aRhs.get()));
+    assign_with_AddRef(ToSupports(static_cast<T*>(aRhs.get())));
     return *this;
   }
 
   nsCOMPtr<T>& operator=(nsCOMPtr<T>&& aRhs) {
     assign_assuming_AddRef(aRhs.forget().take());
     return *this;
   }
 
@@ -659,17 +664,17 @@ class MOZ_IS_REFPTR nsCOMPtr final
     static_assert(mozilla::IsBaseOf<T, U>::value,
                   "U should be a subclass of T");
     assign_assuming_AddRef(aRhs.forget().template downcast<T>().take());
     NSCAP_ASSERT_NO_QUERY_NEEDED();
     return *this;
   }
 
   nsCOMPtr<T>& operator=(T* aRhs) {
-    assign_with_AddRef(aRhs);
+    assign_with_AddRef(ToSupports(aRhs));
     NSCAP_ASSERT_NO_QUERY_NEEDED();
     return *this;
   }
 
   nsCOMPtr<T>& operator=(decltype(nullptr)) {
     assign_assuming_AddRef(nullptr);
     return *this;
   }
@@ -775,17 +780,17 @@ class MOZ_IS_REFPTR nsCOMPtr final
     mRawPtr = temp;
     // |aRhs| maintains the same invariants, so we don't need to
     // |NSCAP_ASSERT_NO_QUERY_NEEDED|
   }
 
   // Exchange ownership with |aRhs|; can save a pair of refcount operations.
   void swap(T*& aRhs) {
 #ifdef NSCAP_FEATURE_USE_BASE
-    nsISupports* temp = aRhs;
+    nsISupports* temp = ToSupports(aRhs);
 #else
     T* temp = aRhs;
 #endif
     NSCAP_LOG_ASSIGNMENT(this, temp);
     NSCAP_LOG_RELEASE(this, mRawPtr);
     aRhs = reinterpret_cast<T*>(mRawPtr);
     mRawPtr = temp;
     NSCAP_ASSERT_NO_QUERY_NEEDED();
--- a/xpcom/base/nsISupportsImpl.h
+++ b/xpcom/base/nsISupportsImpl.h
@@ -29,16 +29,18 @@
 #include "mozilla/TypeTraits.h"
 
 #define MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(X)            \
   static_assert(!mozilla::IsDestructible<X>::value,      \
                 "Reference-counted class " #X            \
                 " should not have a public destructor. " \
                 "Make this class's destructor non-public");
 
+inline nsISupports* ToSupports(decltype(nullptr)) { return nullptr; }
+
 inline nsISupports* ToSupports(nsISupports* aSupports) { return aSupports; }
 
 ////////////////////////////////////////////////////////////////////////////////
 // Macros to help detect thread-safety:
 
 #ifdef MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED
 
 #include "prthread.h" /* needed for thread-safety checks */
@@ -142,20 +144,20 @@ class nsAutoOwningThread {
   } while (0)
 
 /* nsCOMPtr.h allows these macros to be defined by clients
  * These logging functions require dynamic_cast<void*>, so they don't
  * do anything useful if we don't have dynamic_cast<void*>.
  * Note: The explicit comparison to nullptr is needed to avoid warnings
  *       when _p is a nullptr itself. */
 #define NSCAP_LOG_ASSIGNMENT(_c, _p) \
-  if (_p != nullptr) NS_LogCOMPtrAddRef((_c), static_cast<nsISupports*>(_p))
+  if (_p != nullptr) NS_LogCOMPtrAddRef((_c), ToSupports(_p))
 
 #define NSCAP_LOG_RELEASE(_c, _p) \
-  if (_p) NS_LogCOMPtrRelease((_c), static_cast<nsISupports*>(_p))
+  if (_p) NS_LogCOMPtrRelease((_c), ToSupports(_p))
 
 #else /* !NS_BUILD_REFCNT_LOGGING */
 
 #define NS_LOG_ADDREF(_p, _rc, _type, _size)
 #define NS_LOG_RELEASE(_p, _rc, _type)
 #define MOZ_COUNT_CTOR(_type)
 #define MOZ_COUNT_CTOR_INHERITED(_type, _base)
 #define MOZ_LOG_CTOR(_ptr, _name, _size)
--- a/xpfe/appshell/nsContentTreeOwner.cpp
+++ b/xpfe/appshell/nsContentTreeOwner.cpp
@@ -644,18 +644,17 @@ NS_IMETHODIMP nsContentTreeOwner::SetTit
       //
       // location bar is turned off, find the browser location
       //
       // use the document's ContentPrincipal to find the true owner
       // in case of javascript: or data: documents
       //
       nsCOMPtr<nsIDocShellTreeItem> dsitem;
       GetPrimaryContentShell(getter_AddRefs(dsitem));
-      nsCOMPtr<nsIScriptObjectPrincipal> doc =
-          do_QueryInterface(dsitem ? dsitem->GetDocument() : nullptr);
+      nsCOMPtr<nsIDocument> doc = dsitem ? dsitem->GetDocument() : nullptr;
       if (doc) {
         nsCOMPtr<nsIURI> uri;
         nsIPrincipal* principal = doc->GetPrincipal();
         if (principal) {
           principal->GetURI(getter_AddRefs(uri));
           if (uri) {
             //
             // remove any user:pass information
--- a/xpfe/appshell/nsWebShellWindow.cpp
+++ b/xpfe/appshell/nsWebShellWindow.cpp
@@ -2,16 +2,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/. */
 
 #include "nsWebShellWindow.h"
 
 #include "nsLayoutCID.h"
 #include "nsContentCID.h"
+#include "nsContentList.h"
 #include "nsIWeakReference.h"
 #include "nsIContentViewer.h"
 #include "nsIComponentManager.h"
 #include "nsIServiceManager.h"
 #include "nsIURL.h"
 #include "nsIIOService.h"
 #include "nsIURL.h"
 #include "nsNetCID.h"