Bug 1555216 - Cache owner doc in the BindContext. r=bzbarsky
authorEmilio Cobos Álvarez <emilio@crisal.io>
Fri, 31 May 2019 16:33:33 +0200
changeset 476479 eebaba0f3ed72502813faeabc7a7b219423be310
parent 476478 5ec67eb98069f77fd468e2abba71bbb7bed66a1c
child 476480 c0e4eca9427eaf2a8c3fefa1116d8b6f56646ac9
push id86877
push useremilio@crisal.io
push dateFri, 31 May 2019 21:32:17 +0000
treeherderautoland@c0e4eca9427e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky
bugs1555216
milestone69.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1555216 - Cache owner doc in the BindContext. r=bzbarsky And use it to avoid some pointer chases per the review comments of D32949. Differential Revision: https://phabricator.services.mozilla.com/D33288
dom/base/BindContext.h
dom/base/CharacterData.cpp
dom/base/Element.cpp
dom/base/nsImageLoadingContent.cpp
dom/base/nsObjectLoadingContent.cpp
dom/html/HTMLAnchorElement.cpp
dom/html/HTMLAreaElement.cpp
dom/html/HTMLBodyElement.cpp
dom/html/HTMLEmbedElement.cpp
dom/html/HTMLFormElement.cpp
dom/html/HTMLImageElement.cpp
dom/html/HTMLLinkElement.cpp
dom/html/HTMLMetaElement.cpp
dom/html/HTMLObjectElement.cpp
dom/html/HTMLScriptElement.cpp
dom/html/HTMLSharedElement.cpp
dom/html/nsGenericHTMLElement.cpp
dom/mathml/nsMathMLElement.cpp
dom/svg/SVGAElement.cpp
dom/svg/SVGAnimationElement.cpp
dom/svg/SVGSVGElement.cpp
dom/xul/nsXULElement.cpp
--- a/dom/base/BindContext.h
+++ b/dom/base/BindContext.h
@@ -13,58 +13,70 @@
 #include "nsXBLBinding.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/ShadowRoot.h"
 
 namespace mozilla {
 namespace dom {
 
 struct MOZ_STACK_CLASS BindContext final {
+  // The document that owns the tree we're getting bound to.
+  //
+  // This is mostly an optimization to avoid silly pointer-chases to get the
+  // OwnerDoc().
+  Document& OwnerDoc() const { return mDoc; }
+
   // Whether our subtree root is changing as a result of this operation.
   bool SubtreeRootChanges() const { return mSubtreeRootChanges; }
 
   // Returns the binding parent of the subtree to be inserted.
   //
   // This can be null.
   Element* GetBindingParent() const { return mBindingParent; }
 
   // This constructor should be used for regular appends to content.
   //
   // FIXME(emilio, bug 1555944): nsIContent::GetBindingParent() should return an
   // Element*.
   explicit BindContext(nsINode& aParentNode)
-      : mSubtreeRootChanges(true),
+      : mDoc(*aParentNode.OwnerDoc()),
+        mSubtreeRootChanges(true),
         mBindingParent(aParentNode.IsContent()
                            ? static_cast<Element*>(
                                  aParentNode.AsContent()->GetBindingParent())
                            : nullptr) {}
 
   // When re-binding a shadow host into a tree, we re-bind all the shadow tree
   // from the root. In that case, the shadow tree contents remain within the
   // same subtree root.  So children should avoid doing silly things like adding
   // themselves to the ShadowRoot's id table twice or what not.
   //
   // This constructor is only meant to be used in that situation.
   explicit BindContext(ShadowRoot& aShadowRoot)
-      : mSubtreeRootChanges(false),
+      : mDoc(*aShadowRoot.OwnerDoc()),
+        mSubtreeRootChanges(false),
         mBindingParent(aShadowRoot.Host()) {}
 
   // This constructor is meant to be used when inserting native-anonymous
   // children into a subtree.
   enum ForNativeAnonymous { ForNativeAnonymous };
   BindContext(Element& aParentElement, enum ForNativeAnonymous)
-      : mSubtreeRootChanges(true),
+      : mDoc(*aParentElement.OwnerDoc()),
+        mSubtreeRootChanges(true),
         mBindingParent(&aParentElement) {}
 
   // This is meant to be used to bind XBL anonymous content.
   BindContext(nsXBLBinding& aBinding, Element& aParentElement)
-      : mSubtreeRootChanges(true),
+      : mDoc(*aParentElement.OwnerDoc()),
+        mSubtreeRootChanges(true),
         mBindingParent(aBinding.GetBoundElement()) {}
 
  private:
+  Document& mDoc;
+
   // Whether the bind operation will change the subtree root of the content
   // we're binding.
   const bool mSubtreeRootChanges;
   Element* const mBindingParent;
 };
 
 }  // namespace dom
 }  // namespace mozilla
--- a/dom/base/CharacterData.cpp
+++ b/dom/base/CharacterData.cpp
@@ -387,16 +387,17 @@ void CharacterData::ToCString(nsAString&
 }
 #endif
 
 nsresult CharacterData::BindToTree(BindContext& aContext, nsINode& aParent) {
   MOZ_ASSERT(aParent.IsContent() || aParent.IsDocument(),
              "Must have content or document parent!");
   MOZ_ASSERT(aParent.OwnerDoc() == OwnerDoc(),
              "Must have the same owner document");
+  MOZ_ASSERT(OwnerDoc() == &aContext.OwnerDoc(), "These should match too");
   MOZ_ASSERT(!IsInUncomposedDoc(), "Already have a document.  Unbind first!");
   MOZ_ASSERT(!IsInComposedDoc(), "Already have a document.  Unbind first!");
   // Note that as we recurse into the kids, they'll have a non-null parent.  So
   // only assert if our parent is _changing_ while we have a parent.
   MOZ_ASSERT(!GetParentNode() || &aParent == GetParentNode(),
              "Already have a parent.  Unbind first!");
   MOZ_ASSERT(
       !GetBindingParent() ||
@@ -450,17 +451,17 @@ nsresult CharacterData::BindToTree(BindC
     ClearSubtreeRootPointer();
     SetIsConnected(aParent.IsInComposedDoc());
 
     if (aParent.IsInUncomposedDoc()) {
       SetIsInDocument();
       // FIXME(emilio): This should probably be dependent on composed doc, not
       // uncomposed.
       if (mText.IsBidi()) {
-        OwnerDoc()->SetBidiEnabled();
+        aContext.OwnerDoc().SetBidiEnabled();
       }
     } else {
       SetFlags(NODE_IS_IN_SHADOW_TREE);
       MOZ_ASSERT(aParent.IsContent() &&
                  aParent.AsContent()->GetContainingShadow());
       ExtendedContentSlots()->mContainingShadow =
           aParent.AsContent()->GetContainingShadow();
     }
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -1576,16 +1576,17 @@ void Element::GetElementsWithGrid(nsTArr
   }
 }
 
 nsresult Element::BindToTree(BindContext& aContext, nsINode& aParent) {
   MOZ_ASSERT(aParent.IsContent() || aParent.IsDocument(),
              "Must have content or document parent!");
   MOZ_ASSERT(aParent.OwnerDoc() == OwnerDoc(),
              "Must have the same owner document");
+  MOZ_ASSERT(OwnerDoc() == &aContext.OwnerDoc(), "These should match too");
   MOZ_ASSERT(!IsInUncomposedDoc(), "Already have a document.  Unbind first!");
   MOZ_ASSERT(!IsInComposedDoc(), "Already have a document.  Unbind first!");
   // Note that as we recurse into the kids, they'll have a non-null parent.  So
   // only assert if our parent is _changing_ while we have a parent.
   MOZ_ASSERT(!GetParentNode() || &aParent == GetParentNode(),
              "Already have a parent.  Unbind first!");
   MOZ_ASSERT(
       !GetBindingParent() ||
@@ -1689,17 +1690,17 @@ nsresult Element::BindToTree(BindContext
   }
 
   UpdateEditableState(false);
 
   // If we had a pre-existing XBL binding, we might have anonymous children that
   // also need to be told that they are moving.
   if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
     nsXBLBinding* binding =
-        OwnerDoc()->BindingManager()->GetBindingWithContent(this);
+        aContext.OwnerDoc().BindingManager()->GetBindingWithContent(this);
 
     if (binding) {
       binding->BindAnonymousContent(binding->GetAnonymousContent(), this);
     }
   }
 
   // Now recurse into our kids
   nsresult rv;
@@ -1740,17 +1741,17 @@ nsresult Element::BindToTree(BindContext
   // to account for Shadow DOM.
   if (aParent.IsInUncomposedDoc() && MayHaveAnimations()) {
     PseudoStyleType pseudoType = GetPseudoElementType();
     if ((pseudoType == PseudoStyleType::NotPseudo ||
          pseudoType == PseudoStyleType::before ||
          pseudoType == PseudoStyleType::after ||
          pseudoType == PseudoStyleType::marker) &&
         EffectSet::GetEffectSet(this, pseudoType)) {
-      if (nsPresContext* presContext = OwnerDoc()->GetPresContext()) {
+      if (nsPresContext* presContext = aContext.OwnerDoc().GetPresContext()) {
         presContext->EffectCompositor()->RequestRestyle(
             this, pseudoType, EffectCompositor::RestyleType::Standard,
             EffectCompositor::CascadeLevel::Animations);
       }
     }
   }
 
   // XXXbz script execution during binding can trigger some of these
--- a/dom/base/nsImageLoadingContent.cpp
+++ b/dom/base/nsImageLoadingContent.cpp
@@ -1608,17 +1608,18 @@ void nsImageLoadingContent::NotifyOwnerD
   if (!GetOurOwnerDoc()->IsCurrentActiveDocument()) {
     RejectDecodePromises(NS_ERROR_DOM_IMAGE_INACTIVE_DOCUMENT);
   }
 }
 
 void nsImageLoadingContent::BindToTree(BindContext& aContext,
                                        nsINode& aParent) {
   // We may be getting connected, if so our image should be tracked,
-  if (GetOurCurrentDoc()) {
+  // NOTE(emilio): Using aParent to avoid silly virtual call.
+  if (aParent.IsInComposedDoc()) {
     TrackImage(mCurrentRequest);
     TrackImage(mPendingRequest);
   }
 }
 
 void nsImageLoadingContent::UnbindFromTree(bool aNullParent) {
   // We may be leaving the document, so if our image is tracked, untrack it.
   nsCOMPtr<Document> doc = GetOurCurrentDoc();
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -11,16 +11,17 @@
 
 // Interface headers
 #include "imgLoader.h"
 #include "nsIClassOfService.h"
 #include "nsIConsoleService.h"
 #include "nsIContent.h"
 #include "nsIContentInlines.h"
 #include "nsIDocShell.h"
+#include "mozilla/dom/BindContext.h"
 #include "mozilla/dom/Document.h"
 #include "nsIExternalProtocolHandler.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIObjectFrame.h"
 #include "nsIOService.h"
 #include "nsIPermissionManager.h"
 #include "nsPluginHost.h"
 #include "nsPluginInstanceOwner.h"
@@ -563,18 +564,18 @@ already_AddRefed<nsIDocShell> nsObjectLo
   return docShell.forget();
 }
 
 nsresult nsObjectLoadingContent::BindToTree(BindContext& aContext,
                                             nsINode& aParent) {
   nsImageLoadingContent::BindToTree(aContext, aParent);
   // NOTE(emilio): Using aParent to avoid silly QI.
   // FIXME(emilio): Should probably use composed doc?
-  if (Document* doc = aParent.GetUncomposedDoc()) {
-    doc->AddPlugin(this);
+  if (aParent.IsInUncomposedDoc()) {
+    aContext.OwnerDoc().AddPlugin(this);
   }
   return NS_OK;
 }
 
 void nsObjectLoadingContent::UnbindFromTree(bool aNullParent) {
   nsImageLoadingContent::UnbindFromTree(aNullParent);
 
   nsCOMPtr<Element> thisElement =
--- a/dom/html/HTMLAnchorElement.cpp
+++ b/dom/html/HTMLAnchorElement.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/HTMLAnchorElement.h"
 
+#include "mozilla/dom/BindContext.h"
 #include "mozilla/dom/HTMLAnchorElementBinding.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/MemoryReporting.h"
 #include "nsCOMPtr.h"
 #include "nsContentUtils.h"
 #include "nsGkAtoms.h"
 #include "nsHTMLDNSPrefetch.h"
@@ -96,19 +97,18 @@ bool HTMLAnchorElement::HasDeferredDNSPr
 nsresult HTMLAnchorElement::BindToTree(BindContext& aContext,
                                        nsINode& aParent) {
   Link::ResetLinkState(false, Link::ElementHasHref());
 
   nsresult rv = nsGenericHTMLElement::BindToTree(aContext, aParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Prefetch links
-  Document* doc = GetComposedDoc();
-  if (doc) {
-    doc->RegisterPendingLinkUpdate(this);
+  if (IsInComposedDoc()) {
+    aContext.OwnerDoc().RegisterPendingLinkUpdate(this);
     TryDNSPrefetch();
   }
 
   return rv;
 }
 
 void HTMLAnchorElement::UnbindFromTree(bool aNullParent) {
   // Cancel any DNS prefetches
--- a/dom/html/HTMLAreaElement.cpp
+++ b/dom/html/HTMLAreaElement.cpp
@@ -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/. */
 
 #include "mozilla/dom/HTMLAreaElement.h"
 
 #include "mozilla/Attributes.h"
+#include "mozilla/dom/BindContext.h"
 #include "mozilla/dom/HTMLAnchorElement.h"
 #include "mozilla/dom/HTMLAreaElementBinding.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/MemoryReporting.h"
 #include "nsWindowSizes.h"
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Area)
@@ -66,19 +67,18 @@ nsDOMTokenList* HTMLAreaElement::RelList
   return mRelList;
 }
 
 nsresult HTMLAreaElement::BindToTree(BindContext& aContext, nsINode& aParent) {
   Link::ResetLinkState(false, Link::ElementHasHref());
   nsresult rv = nsGenericHTMLElement::BindToTree(aContext, aParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  Document* doc = GetComposedDoc();
-  if (doc) {
-    doc->RegisterPendingLinkUpdate(this);
+  if (IsInComposedDoc()) {
+    aContext.OwnerDoc().RegisterPendingLinkUpdate(this);
   }
   return rv;
 }
 
 void HTMLAreaElement::UnbindFromTree(bool aNullParent) {
   // Without removing the link state we risk a dangling pointer
   // in the mStyledLinks hashtable
   Link::ResetLinkState(false, Link::ElementHasHref());
--- a/dom/html/HTMLBodyElement.cpp
+++ b/dom/html/HTMLBodyElement.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "HTMLBodyElement.h"
+#include "mozilla/dom/BindContext.h"
 #include "mozilla/dom/HTMLBodyElementBinding.h"
 #include "mozilla/MappedDeclarations.h"
 #include "mozilla/HTMLEditor.h"
 #include "mozilla/TextEditor.h"
 #include "nsAttrValueInlines.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsPresContext.h"
@@ -281,17 +282,17 @@ already_AddRefed<TextEditor> HTMLBodyEle
 bool HTMLBodyElement::IsEventAttributeNameInternal(nsAtom* aName) {
   return nsContentUtils::IsEventAttributeName(
       aName, EventNameType_HTML | EventNameType_HTMLBodyOrFramesetOnly);
 }
 
 nsresult HTMLBodyElement::BindToTree(BindContext& aContext, nsINode& aParent) {
   nsresult rv = nsGenericHTMLElement::BindToTree(aContext, aParent);
   NS_ENSURE_SUCCESS(rv, rv);
-  return mAttrs.ForceMapped(this, OwnerDoc());
+  return mAttrs.ForceMapped(this, &aContext.OwnerDoc());
 }
 
 nsresult HTMLBodyElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                        const nsAttrValue* aValue,
                                        const nsAttrValue* aOldValue,
                                        nsIPrincipal* aSubjectPrincipal,
                                        bool aNotify) {
   nsresult rv = nsGenericHTMLElement::AfterSetAttr(
--- a/dom/html/HTMLEmbedElement.cpp
+++ b/dom/html/HTMLEmbedElement.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/EventStates.h"
+#include "mozilla/dom/BindContext.h"
 #include "mozilla/dom/HTMLEmbedElement.h"
 #include "mozilla/dom/HTMLEmbedElementBinding.h"
 #include "mozilla/dom/ElementInlines.h"
 
 #include "mozilla/dom/Document.h"
 #include "nsIPluginDocument.h"
 #include "nsThreadUtils.h"
 #include "nsIScriptError.h"
@@ -75,27 +76,27 @@ void HTMLEmbedElement::AsyncEventRunning
 
 nsresult HTMLEmbedElement::BindToTree(BindContext& aContext, nsINode& aParent) {
   nsresult rv = nsGenericHTMLElement::BindToTree(aContext, aParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = nsObjectLoadingContent::BindToTree(aContext, aParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  // Don't kick off load from being bound to a plugin document - the plugin
-  // document will call nsObjectLoadingContent::InitializeFromChannel() for the
-  // initial load.
-  //
-  // FIXME(emilio): Seems a bit wasteful to add the runnable unconditionally
-  // otherwise?
-  nsCOMPtr<nsIPluginDocument> pluginDoc = do_QueryInterface(GetUncomposedDoc());
-  if (!pluginDoc) {
-    void (HTMLEmbedElement::*start)() = &HTMLEmbedElement::StartObjectLoad;
-    nsContentUtils::AddScriptRunner(
-        NewRunnableMethod("dom::HTMLEmbedElement::BindToTree", this, start));
+  if (IsInComposedDoc()) {
+    // Don't kick off load from being bound to a plugin document - the plugin
+    // document will call nsObjectLoadingContent::InitializeFromChannel() for the
+    // initial load.
+    nsCOMPtr<nsIPluginDocument> pluginDoc =
+        do_QueryInterface(&aContext.OwnerDoc());
+    if (!pluginDoc) {
+      void (HTMLEmbedElement::*start)() = &HTMLEmbedElement::StartObjectLoad;
+      nsContentUtils::AddScriptRunner(
+          NewRunnableMethod("dom::HTMLEmbedElement::BindToTree", this, start));
+    }
   }
 
   return NS_OK;
 }
 
 void HTMLEmbedElement::UnbindFromTree(bool aNullParent) {
 #ifdef XP_MACOSX
   // When a page is reloaded (when an Document's content is removed), the
--- a/dom/html/HTMLFormElement.cpp
+++ b/dom/html/HTMLFormElement.cpp
@@ -5,31 +5,33 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/HTMLFormElement.h"
 
 #include "jsapi.h"
 #include "mozilla/ContentEvents.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventStates.h"
+#include "mozilla/dom/BindContext.h"
 #include "mozilla/dom/nsCSPUtils.h"
 #include "mozilla/dom/nsCSPContext.h"
 #include "mozilla/dom/nsMixedContentBlocker.h"
 #include "mozilla/dom/CustomEvent.h"
 #include "mozilla/dom/HTMLFormControlsCollection.h"
 #include "mozilla/dom/HTMLFormElementBinding.h"
 #include "mozilla/Move.h"
 #include "nsIHTMLDocument.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsPresContext.h"
 #include "mozilla/dom/Document.h"
 #include "nsIFormControlFrame.h"
 #include "nsError.h"
 #include "nsContentUtils.h"
+#include "nsHTMLDocument.h"
 #include "nsInterfaceHashtable.h"
 #include "nsContentList.h"
 #include "nsCOMArray.h"
 #include "nsAutoPtr.h"
 #include "nsTArray.h"
 #include "nsIMutableArray.h"
 #include "mozilla/BinarySearch.h"
 #include "nsQueryObject.h"
@@ -250,19 +252,18 @@ bool HTMLFormElement::ParseAttribute(int
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aMaybeScriptedPrincipal, aResult);
 }
 
 nsresult HTMLFormElement::BindToTree(BindContext& aContext, nsINode& aParent) {
   nsresult rv = nsGenericHTMLElement::BindToTree(aContext, aParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsIHTMLDocument> htmlDoc(do_QueryInterface(GetUncomposedDoc()));
-  if (htmlDoc) {
-    htmlDoc->AddedForm();
+  if (IsInUncomposedDoc() && aContext.OwnerDoc().IsHTMLOrXHTML()) {
+    aContext.OwnerDoc().AsHTMLDocument()->AddedForm();
   }
 
   return rv;
 }
 
 template <typename T>
 static void MarkOrphans(const nsTArray<T*>& aArray) {
   uint32_t length = aArray.Length();
--- a/dom/html/HTMLImageElement.cpp
+++ b/dom/html/HTMLImageElement.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/HTMLImageElement.h"
 #include "mozilla/dom/HTMLImageElementBinding.h"
+#include "mozilla/dom/BindContext.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsPresContext.h"
 #include "nsMappedAttributes.h"
 #include "nsSize.h"
 #include "mozilla/dom/Document.h"
 #include "nsImageFrame.h"
 #include "nsIScriptContext.h"
@@ -495,19 +496,18 @@ nsresult HTMLImageElement::BindToTree(Bi
   nsresult rv = nsGenericHTMLElement::BindToTree(aContext, aParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsImageLoadingContent::BindToTree(aContext, aParent);
 
   UpdateFormOwner();
 
   if (HaveSrcsetOrInPicture()) {
-    Document* doc = GetComposedDoc();
-    if (doc && !mInDocResponsiveContent) {
-      doc->AddResponsiveContent(this);
+    if (IsInComposedDoc() && !mInDocResponsiveContent) {
+      aContext.OwnerDoc().AddResponsiveContent(this);
       mInDocResponsiveContent = true;
     }
 
     // Mark channel as urgent-start before load image if the image load is
     // initaiated by a user interaction.
     mUseUrgentStartForChannel = EventStateManager::IsHandlingUserInput();
 
     // Run selection algorithm when an img element is inserted into a document
@@ -528,17 +528,17 @@ nsresult HTMLImageElement::BindToTree(Bi
 
     // We still act synchronously for the non-responsive case (Bug
     // 1076583), but still need to delay if it is unsafe to run
     // script.
 
     // If loading is temporarily disabled, don't even launch MaybeLoadImage.
     // Otherwise MaybeLoadImage may run later when someone has reenabled
     // loading.
-    if (LoadingEnabled() && OwnerDoc()->ShouldLoadImages()) {
+    if (LoadingEnabled() && aContext.OwnerDoc().ShouldLoadImages()) {
       nsContentUtils::AddScriptRunner(
           NewRunnableMethod<bool>("dom::HTMLImageElement::MaybeLoadImage", this,
                                   &HTMLImageElement::MaybeLoadImage, false));
     }
   }
 
   return rv;
 }
--- a/dom/html/HTMLLinkElement.cpp
+++ b/dom/html/HTMLLinkElement.cpp
@@ -7,16 +7,17 @@
 #include "mozilla/dom/HTMLLinkElement.h"
 
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/dom/BindContext.h"
 #include "mozilla/dom/DocumentInlines.h"
 #include "mozilla/dom/HTMLLinkElementBinding.h"
 #include "nsContentUtils.h"
 #include "nsGenericHTMLElement.h"
 #include "nsGkAtoms.h"
 #include "nsDOMTokenList.h"
 #include "nsIContentInlines.h"
 #include "mozilla/dom/Document.h"
@@ -117,34 +118,34 @@ bool HTMLLinkElement::HasDeferredDNSPref
 }
 
 nsresult HTMLLinkElement::BindToTree(BindContext& aContext, nsINode& aParent) {
   Link::ResetLinkState(false, Link::ElementHasHref());
 
   nsresult rv = nsGenericHTMLElement::BindToTree(aContext, aParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  if (Document* doc = GetComposedDoc()) {
-    if (!doc->NodePrincipal()->IsSystemPrincipal()) {
-      doc->RegisterPendingLinkUpdate(this);
+  if (IsInComposedDoc()) {
+    if (!aContext.OwnerDoc().NodePrincipal()->IsSystemPrincipal()) {
+      aContext.OwnerDoc().RegisterPendingLinkUpdate(this);
     }
     TryDNSPrefetchOrPreconnectOrPrefetchOrPreloadOrPrerender();
   }
 
   void (HTMLLinkElement::*update)() =
       &HTMLLinkElement::UpdateStyleSheetInternal;
   nsContentUtils::AddScriptRunner(
       NewRunnableMethod("dom::HTMLLinkElement::BindToTree", this, update));
 
   // FIXME(emilio, bug 1555947): Why does this use the uncomposed doc but the
   // attribute change code the composed doc?
   if (IsInUncomposedDoc() &&
       AttrValueIs(kNameSpaceID_None, nsGkAtoms::rel, nsGkAtoms::localization,
                   eIgnoreCase)) {
-    OwnerDoc()->LocalizationLinkAdded(this);
+    aContext.OwnerDoc().LocalizationLinkAdded(this);
   }
 
   LinkAdded();
 
   return rv;
 }
 
 void HTMLLinkElement::LinkAdded() {
--- a/dom/html/HTMLMetaElement.cpp
+++ b/dom/html/HTMLMetaElement.cpp
@@ -69,75 +69,74 @@ nsresult HTMLMetaElement::AfterSetAttr(i
 
   return nsGenericHTMLElement::AfterSetAttr(
       aNameSpaceID, aName, aValue, aOldValue, aSubjectPrincipal, aNotify);
 }
 
 nsresult HTMLMetaElement::BindToTree(BindContext& aContext, nsINode& aParent) {
   nsresult rv = nsGenericHTMLElement::BindToTree(aContext, aParent);
   NS_ENSURE_SUCCESS(rv, rv);
-  Document* document = GetUncomposedDoc();
-  if (!document) {
+  if (!IsInUncomposedDoc()) {
     return rv;
   }
+  Document& doc = aContext.OwnerDoc();
   if (AttrValueIs(kNameSpaceID_None, nsGkAtoms::name, nsGkAtoms::viewport,
                   eIgnoreCase)) {
     nsAutoString content;
     GetContent(content);
-    nsContentUtils::ProcessViewportInfo(document, content);
+    nsContentUtils::ProcessViewportInfo(&doc, content);
   }
 
-  if (StaticPrefs::security_csp_enable() && !document->IsLoadedAsData() &&
+  if (StaticPrefs::security_csp_enable() && !doc.IsLoadedAsData() &&
       AttrValueIs(kNameSpaceID_None, nsGkAtoms::httpEquiv, nsGkAtoms::headerCSP,
                   eIgnoreCase)) {
     // only accept <meta http-equiv="Content-Security-Policy" content=""> if it
     // appears in the <head> element.
-    Element* headElt = document->GetHeadElement();
+    Element* headElt = doc.GetHeadElement();
     if (headElt && nsContentUtils::ContentIsDescendantOf(this, headElt)) {
       nsAutoString content;
       GetContent(content);
       content =
           nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
               content);
 
-      if (nsCOMPtr<nsIContentSecurityPolicy> csp = document->GetCsp()) {
+      if (nsCOMPtr<nsIContentSecurityPolicy> csp = doc.GetCsp()) {
         if (LOG_ENABLED()) {
           nsAutoCString documentURIspec;
-          nsIURI* documentURI = document->GetDocumentURI();
-          if (documentURI) {
+          if (nsIURI* documentURI = doc.GetDocumentURI()) {
             documentURI->GetAsciiSpec(documentURIspec);
           }
 
           LOG(
               ("HTMLMetaElement %p sets CSP '%s' on document=%p, "
                "document-uri=%s",
-               this, NS_ConvertUTF16toUTF8(content).get(), document,
+               this, NS_ConvertUTF16toUTF8(content).get(), &doc,
                documentURIspec.get()));
         }
 
         // Multiple CSPs (delivered through either header of meta tag) need to
         // be joined together, see:
         // https://w3c.github.io/webappsec/specs/content-security-policy/#delivery-html-meta-element
         rv =
             csp->AppendPolicy(content,
                               false,  // csp via meta tag can not be report only
                               true);  // delivered through the meta tag
         NS_ENSURE_SUCCESS(rv, rv);
-        if (nsPIDOMWindowInner* inner = document->GetInnerWindow()) {
+        if (nsPIDOMWindowInner* inner = doc.GetInnerWindow()) {
           inner->SetCsp(csp);
         }
-        document->ApplySettingsFromCSP(false);
+        doc.ApplySettingsFromCSP(false);
       }
     }
   }
 
   // Referrer Policy spec requires a <meta name="referrer" tag to be in the
   // <head> element.
-  SetMetaReferrer(document);
-  CreateAndDispatchEvent(document, NS_LITERAL_STRING("DOMMetaAdded"));
+  SetMetaReferrer(&doc);
+  CreateAndDispatchEvent(&doc, NS_LITERAL_STRING("DOMMetaAdded"));
   return rv;
 }
 
 void HTMLMetaElement::UnbindFromTree(bool aNullParent) {
   nsCOMPtr<Document> oldDoc = GetUncomposedDoc();
   CreateAndDispatchEvent(oldDoc, NS_LITERAL_STRING("DOMMetaRemoved"));
   nsGenericHTMLElement::UnbindFromTree(aNullParent);
 }
--- a/dom/html/HTMLObjectElement.cpp
+++ b/dom/html/HTMLObjectElement.cpp
@@ -203,25 +203,25 @@ nsresult HTMLObjectElement::BindToTree(B
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = nsObjectLoadingContent::BindToTree(aContext, aParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Don't kick off load from being bound to a plugin document - the plugin
   // document will call nsObjectLoadingContent::InitializeFromChannel() for the
   // initial load.
-  //
-  // FIXME(emilio): Seems wasteful to queue the runnable unconditionally
-  // otherwise.
-  nsCOMPtr<nsIPluginDocument> pluginDoc = do_QueryInterface(GetUncomposedDoc());
-  // If we already have all the children, start the load.
-  if (mIsDoneAddingChildren && !pluginDoc) {
-    void (HTMLObjectElement::*start)() = &HTMLObjectElement::StartObjectLoad;
-    nsContentUtils::AddScriptRunner(
-        NewRunnableMethod("dom::HTMLObjectElement::BindToTree", this, start));
+  if (IsInComposedDoc()) {
+    nsCOMPtr<nsIPluginDocument> pluginDoc =
+        do_QueryInterface(&aContext.OwnerDoc());
+    // If we already have all the children, start the load.
+    if (mIsDoneAddingChildren && !pluginDoc) {
+      void (HTMLObjectElement::*start)() = &HTMLObjectElement::StartObjectLoad;
+      nsContentUtils::AddScriptRunner(
+          NewRunnableMethod("dom::HTMLObjectElement::BindToTree", this, start));
+    }
   }
 
   return NS_OK;
 }
 
 void HTMLObjectElement::UnbindFromTree(bool aNullParent) {
 #ifdef XP_MACOSX
   // When a page is reloaded (when an Document's content is removed), the
--- a/dom/html/HTMLScriptElement.cpp
+++ b/dom/html/HTMLScriptElement.cpp
@@ -47,17 +47,17 @@ NS_IMPL_ISUPPORTS_INHERITED(HTMLScriptEl
                             nsIScriptLoaderObserver, nsIScriptElement,
                             nsIMutationObserver)
 
 nsresult HTMLScriptElement::BindToTree(BindContext& aContext,
                                        nsINode& aParent) {
   nsresult rv = nsGenericHTMLElement::BindToTree(aContext, aParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  if (GetComposedDoc()) {
+  if (IsInComposedDoc()) {
     MaybeProcessScript();
   }
 
   return NS_OK;
 }
 
 bool HTMLScriptElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
                                        const nsAString& aValue,
--- a/dom/html/HTMLSharedElement.cpp
+++ b/dom/html/HTMLSharedElement.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/HTMLSharedElement.h"
+#include "mozilla/dom/BindContext.h"
 #include "mozilla/dom/HTMLBaseElementBinding.h"
 #include "mozilla/dom/HTMLDirectoryElementBinding.h"
 #include "mozilla/dom/HTMLHeadElementBinding.h"
 #include "mozilla/dom/HTMLHtmlElementBinding.h"
 #include "mozilla/dom/HTMLParamElementBinding.h"
 #include "mozilla/dom/HTMLQuoteElementBinding.h"
 
 #include "mozilla/AsyncEventDispatcher.h"
@@ -228,20 +229,20 @@ nsresult HTMLSharedElement::BindToTree(B
                                        nsINode& aParent) {
   nsresult rv = nsGenericHTMLElement::BindToTree(aContext, aParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // The document stores a pointer to its base URI and base target, which we may
   // need to update here.
   if (mNodeInfo->Equals(nsGkAtoms::base) && IsInUncomposedDoc()) {
     if (HasAttr(kNameSpaceID_None, nsGkAtoms::href)) {
-      SetBaseURIUsingFirstBaseWithHref(OwnerDoc(), this);
+      SetBaseURIUsingFirstBaseWithHref(&aContext.OwnerDoc(), this);
     }
     if (HasAttr(kNameSpaceID_None, nsGkAtoms::target)) {
-      SetBaseTargetUsingFirstBaseWithTarget(OwnerDoc(), this);
+      SetBaseTargetUsingFirstBaseWithTarget(&aContext.OwnerDoc(), this);
     }
   }
 
   return NS_OK;
 }
 
 void HTMLSharedElement::UnbindFromTree(bool aNullParent) {
   Document* doc = GetUncomposedDoc();
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -20,16 +20,17 @@
 #include "nscore.h"
 #include "nsGenericHTMLElement.h"
 #include "nsAttrValueInlines.h"
 #include "nsCOMPtr.h"
 #include "nsAtom.h"
 #include "nsQueryObject.h"
 #include "nsIContentInlines.h"
 #include "nsIContentViewer.h"
+#include "mozilla/dom/BindContext.h"
 #include "mozilla/dom/Document.h"
 #include "nsIDocumentEncoder.h"
 #include "nsIDOMWindow.h"
 #include "nsMappedAttributes.h"
 #include "nsHTMLStyleSheet.h"
 #include "nsIHTMLDocument.h"
 #include "nsPIDOMWindow.h"
 #include "nsIURL.h"
@@ -417,27 +418,27 @@ EventStates nsGenericHTMLElement::Intrin
   return state;
 }
 
 nsresult nsGenericHTMLElement::BindToTree(BindContext& aContext,
                                           nsINode& aParent) {
   nsresult rv = nsGenericHTMLElementBase::BindToTree(aContext, aParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  if (Document* doc = GetUncomposedDoc()) {
+  if (IsInUncomposedDoc()) {
     RegAccessKey();
     if (HasName() && CanHaveName(NodeInfo()->NameAtom())) {
-      doc->AddToNameTable(this, GetParsedAttr(nsGkAtoms::name)->GetAtomValue());
+      aContext.OwnerDoc().AddToNameTable(
+          this, GetParsedAttr(nsGkAtoms::name)->GetAtomValue());
     }
   }
 
-  if (HasFlag(NODE_IS_EDITABLE) && GetContentEditableValue() == eTrue) {
-    if (Document* doc = GetComposedDoc()) {
-      doc->ChangeContentEditableCount(this, +1);
-    }
+  if (HasFlag(NODE_IS_EDITABLE) && GetContentEditableValue() == eTrue &&
+      IsInComposedDoc()) {
+    aContext.OwnerDoc().ChangeContentEditableCount(this, +1);
   }
 
   // We need to consider a labels element is moved to another subtree
   // with different root, it needs to update labels list and its root
   // as well.
   nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
   if (slots && slots->mLabelsList) {
     slots->mLabelsList->MaybeResetRoot(SubtreeRoot());
@@ -1594,17 +1595,17 @@ nsresult nsGenericHTMLFormElement::BindT
   NS_ENSURE_SUCCESS(rv, rv);
 
   // An autofocus event has to be launched if the autofocus attribute is
   // specified and the element accept the autofocus attribute. In addition,
   // the document should not be already loaded and the "browser.autofocus"
   // preference should be 'true'.
   if (IsAutofocusable() && HasAttr(kNameSpaceID_None, nsGkAtoms::autofocus) &&
       StaticPrefs::browser_autofocus() && IsInUncomposedDoc()) {
-    OwnerDoc()->SetAutoFocusElement(this);
+    aContext.OwnerDoc().SetAutoFocusElement(this);
   }
 
   // If @form is set, the element *has* to be in a composed document, otherwise
   // it wouldn't be possible to find an element with the corresponding id.
   // If @form isn't set, the element *has* to have a parent, otherwise it
   // wouldn't be possible to find a form ancestor.
   // We should not call UpdateFormOwner if none of these conditions are
   // fulfilled.
--- a/dom/mathml/nsMathMLElement.cpp
+++ b/dom/mathml/nsMathMLElement.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsMathMLElement.h"
 #include "base/compiler_specific.h"
+#include "mozilla/dom/BindContext.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/FontPropertyTypes.h"
 #include "mozilla/TextUtils.h"
 #include "nsGkAtoms.h"
 #include "nsITableCellLayout.h"  // for MAX_COLSPAN / MAX_ROWSPAN
 #include "nsLayoutStylesheetCache.h"
 #include "nsCSSValue.h"
 #include "nsMappedAttributes.h"
@@ -76,23 +77,23 @@ nsMathMLElement::nsMathMLElement(
 nsresult nsMathMLElement::BindToTree(BindContext& aContext, nsINode& aParent) {
   Link::ResetLinkState(false, Link::ElementHasHref());
 
   nsresult rv = nsMathMLElementBase::BindToTree(aContext, aParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // FIXME(emilio): Probably should be composed, this uses all the other link
   // infrastructure.
-  if (Document* doc = GetUncomposedDoc()) {
-    doc->RegisterPendingLinkUpdate(this);
+  if (IsInUncomposedDoc()) {
+    aContext.OwnerDoc().RegisterPendingLinkUpdate(this);
   }
 
   // Set the bit in the document for telemetry.
-  if (Document* doc = GetComposedDoc()) {
-    doc->SetMathMLEnabled();
+  if (IsInComposedDoc()) {
+    aContext.OwnerDoc().SetMathMLEnabled();
   }
 
   return rv;
 }
 
 void nsMathMLElement::UnbindFromTree(bool aNullParent) {
   // Without removing the link state we risk a dangling pointer
   // in the mStyledLinks hashtable
--- a/dom/svg/SVGAElement.cpp
+++ b/dom/svg/SVGAElement.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 "mozilla/dom/SVGAElement.h"
 
 #include "mozilla/Attributes.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventStates.h"
+#include "mozilla/dom/BindContext.h"
 #include "mozilla/dom/DocumentInlines.h"
 #include "mozilla/dom/SVGAElementBinding.h"
 #include "nsCOMPtr.h"
 #include "nsContentUtils.h"
 #include "nsGkAtoms.h"
 #include "nsIContentInlines.h"
 #include "nsIURI.h"
 
@@ -155,19 +156,18 @@ void SVGAElement::SetText(const nsAStrin
 // nsIContent methods
 
 nsresult SVGAElement::BindToTree(BindContext& aContext, nsINode& aParent) {
   Link::ResetLinkState(false, Link::ElementHasHref());
 
   nsresult rv = SVGAElementBase::BindToTree(aContext, aParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  Document* doc = GetComposedDoc();
-  if (doc) {
-    doc->RegisterPendingLinkUpdate(this);
+  if (IsInComposedDoc()) {
+    aContext.OwnerDoc().RegisterPendingLinkUpdate(this);
   }
 
   return NS_OK;
 }
 
 void SVGAElement::UnbindFromTree(bool aNullParent) {
   // Without removing the link state we risk a dangling pointer
   // in the mStyledLinks hashtable
--- a/dom/svg/SVGAnimationElement.cpp
+++ b/dom/svg/SVGAnimationElement.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/SVGAnimationElement.h"
 #include "mozilla/dom/SVGSVGElement.h"
+#include "mozilla/dom/BindContext.h"
 #include "mozilla/dom/ElementInlines.h"
 #include "mozilla/SMILAnimationController.h"
 #include "mozilla/SMILAnimationFunction.h"
 #include "mozilla/SMILTimeContainer.h"
 #include "nsContentUtils.h"
 #include "nsIContentInlines.h"
 #include "nsIURI.h"
 #include "prtime.h"
@@ -134,18 +135,19 @@ float SVGAnimationElement::GetSimpleDura
 nsresult SVGAnimationElement::BindToTree(BindContext& aContext,
                                          nsINode& aParent) {
   MOZ_ASSERT(!mHrefTarget.get(),
              "Shouldn't have href-target yet (or it should've been cleared)");
   nsresult rv = SVGAnimationElementBase::BindToTree(aContext, aParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Add myself to the animation controller's master set of animation elements.
-  if (Document* doc = GetComposedDoc()) {
-    if (SMILAnimationController* controller = doc->GetAnimationController()) {
+  if (IsInComposedDoc()) {
+    if (SMILAnimationController* controller =
+            aContext.OwnerDoc().GetAnimationController()) {
       controller->RegisterAnimationElement(this);
     }
     const nsAttrValue* href =
         HasAttr(kNameSpaceID_None, nsGkAtoms::href)
             ? mAttrs.GetAttr(nsGkAtoms::href, kNameSpaceID_None)
             : mAttrs.GetAttr(nsGkAtoms::href, kNameSpaceID_XLink);
     if (href) {
       nsAutoString hrefStr;
--- a/dom/svg/SVGSVGElement.cpp
+++ b/dom/svg/SVGSVGElement.cpp
@@ -368,17 +368,17 @@ SMILTimeContainer* SVGSVGElement::GetTim
 //----------------------------------------------------------------------
 // SVGElement
 nsresult SVGSVGElement::BindToTree(BindContext& aContext, nsINode& aParent) {
   SMILAnimationController* smilController = nullptr;
 
   // NOTE(emilio): Using aParent because we still haven't called our base class.
   // FIXME(emilio, bug 1555948): Should probably use IsInComposedDoc()?
   if (aParent.IsInUncomposedDoc()) {
-    if ((smilController = OwnerDoc()->GetAnimationController())) {
+    if ((smilController = aContext.OwnerDoc().GetAnimationController())) {
       // SMIL is enabled in this document
       if (WillBeOutermostSVG(aParent, aContext.GetBindingParent())) {
         // We'll be the outermost <svg> element.  We'll need a time container.
         if (!mTimedDocumentRoot) {
           mTimedDocumentRoot = new SMILTimeContainer();
         }
       } else {
         // We're a child of some other <svg> element, so we don't need our own
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -616,26 +616,26 @@ void nsXULElement::UpdateEditableState(b
   nsIContent* parent = GetParent();
 
   SetEditableFlag(parent && parent->HasFlag(NODE_IS_EDITABLE));
   UpdateState(aNotify);
 }
 
 class XULInContentErrorReporter : public Runnable {
  public:
-  explicit XULInContentErrorReporter(Document* aDocument)
+  explicit XULInContentErrorReporter(Document& aDocument)
       : mozilla::Runnable("XULInContentErrorReporter"), mDocument(aDocument) {}
 
   NS_IMETHOD Run() override {
     mDocument->WarnOnceAbout(Document::eImportXULIntoContent, false);
     return NS_OK;
   }
 
  private:
-  nsCOMPtr<Document> mDocument;
+  OwningNonNull<Document> mDocument;
 };
 
 static bool NeedTooltipSupport(const nsXULElement& aXULElement) {
   if (aXULElement.NodeInfo()->Equals(nsGkAtoms::treechildren)) {
     // treechildren always get tooltip support, since cropped tree cells show
     // their full text in a tooltip.
     return true;
   }
@@ -643,30 +643,31 @@ static bool NeedTooltipSupport(const nsX
   return aXULElement.GetBoolAttr(nsGkAtoms::tooltip) ||
          aXULElement.GetBoolAttr(nsGkAtoms::tooltiptext);
 }
 
 nsresult nsXULElement::BindToTree(BindContext& aContext, nsINode& aParent) {
   nsresult rv = nsStyledElement::BindToTree(aContext, aParent);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  Document& doc = aContext.OwnerDoc();
+
   // FIXME(emilio): Could use IsInComposedDoc().
-  Document* doc = OwnerDoc();
   if (!aContext.GetBindingParent() && IsInUncomposedDoc() &&
-      !doc->IsLoadedAsInteractiveData() && !doc->AllowXULXBL() &&
-      !doc->HasWarnedAbout(Document::eImportXULIntoContent)) {
+      !doc.IsLoadedAsInteractiveData() && !doc.AllowXULXBL() &&
+      !doc.HasWarnedAbout(Document::eImportXULIntoContent)) {
     nsContentUtils::AddScriptRunner(new XULInContentErrorReporter(doc));
   }
 
   if (!IsInComposedDoc()) {
     return rv;
   }
 
 #ifdef DEBUG
-  if (!doc->AllowXULXBL() && !doc->IsUnstyledDocument()) {
+  if (!doc.AllowXULXBL() && !doc.IsUnstyledDocument()) {
     // To save CPU cycles and memory, non-XUL documents only load the user
     // agent style sheet rules for a minimal set of XUL elements such as
     // 'scrollbar' that may be created implicitly for their content (those
     // rules being in minimal-xul.css).
     //
     // This assertion makes sure no other XUL element is used in a non-XUL
     // document.
     nsAtom* tag = NodeInfo()->NameAtom();
@@ -686,20 +687,20 @@ nsresult nsXULElement::BindToTree(BindCo
     nsXBLService::AttachGlobalKeyHandler(this);
   }
 
   if (NeedTooltipSupport(*this)) {
     AddTooltipSupport();
   }
 
   if (XULBroadcastManager::MayNeedListener(*this)) {
-    if (!doc->HasXULBroadcastManager()) {
-      doc->InitializeXULBroadcastManager();
+    if (!doc.HasXULBroadcastManager()) {
+      doc.InitializeXULBroadcastManager();
     }
-    XULBroadcastManager* broadcastManager = doc->GetXULBroadcastManager();
+    XULBroadcastManager* broadcastManager = doc.GetXULBroadcastManager();
     broadcastManager->AddListener(this);
   }
   return rv;
 }
 
 void nsXULElement::UnbindFromTree(bool aNullParent) {
   if (NodeInfo()->Equals(nsGkAtoms::keyset, kNameSpaceID_XUL)) {
     nsXBLService::DetachGlobalKeyHandler(this);