Bug 1465478: Introduce Element::FromNode. r=smaug
authorEmilio Cobos Álvarez <emilio@crisal.io>
Wed, 30 May 2018 16:56:24 +0200
changeset 420627 6417e4379b41dac26525186bc0688612d28e9bd3
parent 420626 7d0c7ab489646115f784a7f5b3a119d57d9077ae
child 420628 0bd6e3f079f12dd1a1b5f12034cebaf37454a762
push id34075
push userapavel@mozilla.com
push dateThu, 31 May 2018 10:04:49 +0000
treeherdermozilla-central@763f30c34212 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1465478
milestone62.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 1465478: Introduce Element::FromNode. r=smaug And use it in a couple places I noticed. MozReview-Commit-ID: 8baSMrbdEbF
accessible/base/ARIAMap.h
accessible/generic/Accessible.h
accessible/generic/HyperTextAccessible.cpp
dom/base/CharacterData.h
dom/base/Element.h
dom/base/nsDocument.cpp
dom/base/nsDocumentEncoder.cpp
dom/base/nsNodeUtils.cpp
dom/html/HTMLLabelElement.cpp
dom/svg/SVGAnimationElement.cpp
dom/xbl/nsXBLService.cpp
dom/xul/XULDocument.cpp
dom/xul/XULPopupElement.cpp
editor/libeditor/EditorBase.cpp
editor/libeditor/EditorDOMPoint.h
editor/libeditor/EditorUtils.h
editor/libeditor/HTMLEditor.cpp
layout/base/AccessibleCaretManager.cpp
layout/generic/nsFrame.cpp
toolkit/components/find/nsWebBrowserFind.cpp
--- a/accessible/base/ARIAMap.h
+++ b/accessible/base/ARIAMap.h
@@ -285,17 +285,17 @@ bool HasDefinedARIAHidden(nsIContent* aC
  /**
   * Represents a simple enumerator for iterating through ARIA attributes
   * exposed as object attributes on a given accessible.
   */
 class AttrIterator
 {
 public:
   explicit AttrIterator(nsIContent* aContent)
-    : mElement(aContent->IsElement() ? aContent->AsElement() : nullptr)
+    : mElement(Element::FromNode(aContent))
     , mAttrIdx(0)
   {
     mAttrCount = mElement ? mElement->GetAttrCount() : 0;
   }
 
   bool Next(nsAString& aAttrName, nsAString& aAttrValue);
 
 private:
--- a/accessible/generic/Accessible.h
+++ b/accessible/generic/Accessible.h
@@ -163,18 +163,18 @@ public:
   virtual nsIFrame* GetFrame() const;
 
   /**
    * Return DOM node associated with the accessible.
    */
   virtual nsINode* GetNode() const;
 
   nsIContent* GetContent() const { return mContent; }
-  mozilla::dom::Element* Elm() const
-    { return mContent && mContent->IsElement() ? mContent->AsElement() : nullptr; }
+  dom::Element* Elm() const
+    { return dom::Element::FromNodeOrNull(mContent); }
 
   /**
    * Return node type information of DOM node associated with the accessible.
    */
   bool IsContent() const
     { return GetNode() && GetNode()->IsContent(); }
 
   /**
--- a/accessible/generic/HyperTextAccessible.cpp
+++ b/accessible/generic/HyperTextAccessible.cpp
@@ -329,21 +329,20 @@ HyperTextAccessible::TransformOffset(Acc
  * or includes aNode.
  *
  * XXX This method is enough to retrieve ::before or ::after pseudo element.
  *     So, if you want to use this for other purpose, you might need to check
  *     ancestors too.
  */
 static nsIContent* GetElementAsContentOf(nsINode* aNode)
 {
-  if (aNode->IsElement()) {
-    return aNode->AsContent();
+  if (Element* element = Element::FromNode(aNode)) {
+    return element;
   }
-  nsIContent* parent = aNode->GetParent();
-  return parent && parent->IsElement() ? parent : nullptr;
+  return aNode->GetParentElement();
 }
 
 bool
 HyperTextAccessible::OffsetsToDOMRange(int32_t aStartOffset, int32_t aEndOffset,
                                        nsRange* aRange)
 {
   DOMPoint startPoint = OffsetToDOMPoint(aStartOffset);
   if (!startPoint.node)
--- a/dom/base/CharacterData.h
+++ b/dom/base/CharacterData.h
@@ -220,19 +220,17 @@ public:
   NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_INHERITED(CharacterData,
                                                                    nsIContent)
 
 protected:
   virtual ~CharacterData();
 
   virtual Element* GetNameSpaceElement() override
   {
-    nsINode *parent = GetParentNode();
-
-    return parent && parent->IsElement() ? parent->AsElement() : nullptr;
+    return Element::FromNodeOrNull(GetParentNode());
   }
 
   nsresult SetTextInternal(uint32_t aOffset, uint32_t aCount,
                            const char16_t* aBuffer, uint32_t aLength,
                            bool aNotify,
                            CharacterDataChangeInfo::Details* aDetails = nullptr);
 
   /**
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -162,16 +162,18 @@ public:
   }
 
 #endif // MOZILLA_INTERNAL_API
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ELEMENT_IID)
 
   NS_DECL_ADDSIZEOFEXCLUDINGTHIS
 
+  NS_IMPL_FROMNODE_HELPER(Element, IsElement())
+
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
 
   /**
    * Method to get the full state of this element.  See mozilla/EventStates.h
    * for the possible bits that could be set here.
    */
   EventStates State() const
   {
@@ -2043,17 +2045,17 @@ inline mozilla::dom::Element* nsINode::A
 inline const mozilla::dom::Element* nsINode::AsElement() const
 {
   MOZ_ASSERT(IsElement());
   return static_cast<const mozilla::dom::Element*>(this);
 }
 
 inline mozilla::dom::Element* nsINode::GetParentElement() const
 {
-  return mParent && mParent->IsElement() ? mParent->AsElement() : nullptr;
+  return mozilla::dom::Element::FromNodeOrNull(mParent);
 }
 
 /**
  * Macros to implement Clone(). _elementName is the class for which to implement
  * Clone.
  */
 #define NS_IMPL_ELEMENT_CLONE(_elementName)                                 \
 nsresult                                                                    \
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -3798,24 +3798,25 @@ nsDocument::TryChannelCharset(nsIChannel
 
 static inline void
 AssertNoStaleServoDataIn(const nsINode& aSubtreeRoot)
 {
 #ifdef DEBUG
   for (const nsINode* node = &aSubtreeRoot;
        node;
        node = node->GetNextNode(&aSubtreeRoot)) {
-    if (!node->IsElement()) {
+    Element* element = Element::FromNode(node);
+    if (!element) {
       continue;
     }
-    MOZ_ASSERT(!node->AsElement()->HasServoData());
-    if (auto* shadow = node->AsElement()->GetShadowRoot()) {
+    MOZ_ASSERT(!element->HasServoData());
+    if (auto* shadow = element->GetShadowRoot()) {
       AssertNoStaleServoDataIn(*shadow);
     }
-    if (nsXBLBinding* binding = node->AsElement()->GetXBLBinding()) {
+    if (nsXBLBinding* binding = element->GetXBLBinding()) {
       if (nsXBLBinding* bindingWithContent = binding->GetBindingWithContent()) {
         nsIContent* content = bindingWithContent->GetAnonymousContent();
         MOZ_ASSERT(!content->AsElement()->HasServoData());
         for (nsINode* child = content->GetFirstChild();
              child;
              child = child->GetNextSibling()) {
           AssertNoStaleServoDataIn(*child);
         }
@@ -4139,20 +4140,19 @@ nsIDocument::GetRootElementInternal() co
   // We invoke GetRootElement() immediately before the servo traversal, so we
   // should always have a cache hit from Servo.
   MOZ_ASSERT(NS_IsMainThread());
 
   // Loop backwards because any non-elements, such as doctypes and PIs
   // are likely to appear before the root element.
   uint32_t i;
   for (i = mChildren.ChildCount(); i > 0; --i) {
-    nsIContent* child = mChildren.ChildAt(i - 1);
-    if (child->IsElement()) {
-      const_cast<nsIDocument*>(this)->mCachedRootElement = child->AsElement();
-      return child->AsElement();
+    if (Element* element = Element::FromNode(mChildren.ChildAt(i - 1))) {
+      const_cast<nsIDocument*>(this)->mCachedRootElement = element;
+      return element;
     }
   }
 
   const_cast<nsIDocument*>(this)->mCachedRootElement = nullptr;
   return nullptr;
 }
 
 nsresult
@@ -5548,17 +5548,17 @@ nsIDocument::GetAnonRootIfInAnonymousCon
 
   // An arbitrary number of elements can be inserted as children of the custom
   // container frame.  We want the one that was added that contains aNode, so
   // we need to keep track of the last child separately using |child| here.
   nsINode* child = aNode;
   nsINode* parent = aNode->GetParentNode();
   while (parent && parent->IsInNativeAnonymousSubtree()) {
     if (parent == customContainer) {
-      return child->IsElement() ? child->AsElement() : nullptr;
+      return Element::FromNode(child);
     }
     child = parent;
     parent = child->GetParentNode();
   }
   return nullptr;
 }
 
 Maybe<ClientInfo>
@@ -6119,24 +6119,23 @@ nsIDocument::GetAnonymousElementByAttrib
   if (!nodeList)
     return nullptr;
 
   uint32_t length = nodeList->Length();
 
   bool universalMatch = aAttrValue.EqualsLiteral("*");
 
   for (uint32_t i = 0; i < length; ++i) {
-    nsIContent* current = nodeList->Item(i);
-    if (!current->IsElement()) {
+    Element* current = Element::FromNode(nodeList->Item(i));
+    if (!current) {
       continue;
     }
 
     Element* matchedElm =
-      GetElementByAttribute(current->AsElement(), aAttrName, aAttrValue,
-                            universalMatch);
+      GetElementByAttribute(current, aAttrName, aAttrValue, universalMatch);
     if (matchedElm)
       return matchedElm;
   }
 
   return nullptr;
 }
 
 Element*
@@ -6928,22 +6927,20 @@ nsIDocument::GetCompatMode(nsString& aCo
   if (mCompatMode == eCompatibility_NavQuirks) {
     aCompatMode.AssignLiteral("BackCompat");
   } else {
     aCompatMode.AssignLiteral("CSS1Compat");
   }
 }
 
 void
-nsDOMAttributeMap::BlastSubtreeToPieces(nsINode *aNode)
-{
-  if (aNode->IsElement()) {
-    Element *element = aNode->AsElement();
-    const nsDOMAttributeMap *map = element->GetAttributeMap();
-    if (map) {
+nsDOMAttributeMap::BlastSubtreeToPieces(nsINode* aNode)
+{
+  if (Element* element = Element::FromNode(aNode)) {
+    if (const nsDOMAttributeMap* map = element->GetAttributeMap()) {
       while (true) {
         nsCOMPtr<nsIAttribute> attr;
         {
           // Use an iterator to get an arbitrary attribute from the
           // cache. The iterator must be destroyed before any other
           // operations on mAttributeCache, to avoid hash table
           // assertions.
           auto iter = map->mAttributeCache.ConstIter();
@@ -7057,18 +7054,18 @@ nsIDocument::AdoptNode(nsINode& aAdopted
         parent->RemoveChildNode(adoptedNode->AsContent(), true);
       } else {
         MOZ_ASSERT(!adoptedNode->IsInUncomposedDoc());
 
         // If we're adopting a node that's not in a document, it might still
         // have a binding applied. Remove the binding from the element now
         // that it's getting adopted into a new document.
         // TODO Fully tear down the binding.
-        if (adoptedNode->IsElement()) {
-          adoptedNode->AsElement()->SetXBLBinding(nullptr);
+        if (Element* element = Element::FromNode(adoptedNode)) {
+          element->SetXBLBinding(nullptr);
         }
       }
 
       break;
     }
     case DOCUMENT_NODE:
     {
       rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
--- a/dom/base/nsDocumentEncoder.cpp
+++ b/dom/base/nsDocumentEncoder.cpp
@@ -368,21 +368,18 @@ nsDocumentEncoder::SerializeNodeStart(ns
     node = aNode;
 
   if (node->IsElement()) {
     if ((mFlags & (nsIDocumentEncoder::OutputPreformatted |
                    nsIDocumentEncoder::OutputDropInvisibleBreak)) &&
         nsLayoutUtils::IsInvisibleBreak(node)) {
       return NS_OK;
     }
-    Element* originalElement =
-      aOriginalNode && aOriginalNode->IsElement() ?
-        aOriginalNode->AsElement() : nullptr;
-    mSerializer->AppendElementStart(node->AsElement(),
-                                    originalElement, aStr);
+    Element* originalElement = Element::FromNodeOrNull(aOriginalNode);
+    mSerializer->AppendElementStart(node->AsElement(), originalElement, aStr);
     return NS_OK;
   }
 
   switch (node->NodeType()) {
     case nsINode::TEXT_NODE:
     {
       mSerializer->AppendText(static_cast<nsIContent*>(node),
                               aStartOffset, aEndOffset, aStr);
--- a/dom/base/nsNodeUtils.cpp
+++ b/dom/base/nsNodeUtils.cpp
@@ -349,23 +349,19 @@ nsNodeUtils::LastRelease(nsINode* aNode)
       }
     }
 #endif
 
     nsContentUtils::RemoveListenerManager(aNode);
     aNode->UnsetFlags(NODE_HAS_LISTENERMANAGER);
   }
 
-  if (aNode->IsElement()) {
-    nsIDocument* ownerDoc = aNode->OwnerDoc();
-    Element* elem = aNode->AsElement();
-    ownerDoc->ClearBoxObjectFor(elem);
-
-    NS_ASSERTION(!elem->GetXBLBinding(),
-                 "Node has binding on destruction");
+  if (Element* element = Element::FromNode(aNode)) {
+    element->OwnerDoc()->ClearBoxObjectFor(element);
+    NS_ASSERTION(!element->GetXBLBinding(), "Node has binding on destruction");
   }
 
   aNode->ReleaseWrapper(aNode);
 
   FragmentOrElement::RemoveBlackMarkedNode(aNode);
 }
 
 /* static */
@@ -424,17 +420,17 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNod
                                                nodeInfo->GetPrefixAtom(),
                                                nodeInfo->NamespaceID(),
                                                nodeInfo->NodeType(),
                                                nodeInfo->GetExtraName());
 
     nodeInfo = newNodeInfo;
   }
 
-  Element *elem = aNode->IsElement() ? aNode->AsElement() : nullptr;
+  Element* elem = Element::FromNode(aNode);
 
   nsCOMPtr<nsINode> clone;
   if (aClone) {
     nsresult rv = aNode->Clone(nodeInfo, getter_AddRefs(clone), aDeep);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       aError.Throw(rv);
       return nullptr;
     }
@@ -491,43 +487,39 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNod
       // the cloned document (somewhat like cloning and importing them into the
       // cloned document).
       nodeInfoManager = clone->mNodeInfo->NodeInfoManager();
     }
   }
   else if (nodeInfoManager) {
     nsIDocument* oldDoc = aNode->OwnerDoc();
     bool wasRegistered = false;
-    if (aNode->IsElement()) {
-      Element* element = aNode->AsElement();
-      oldDoc->ClearBoxObjectFor(element);
-      wasRegistered = oldDoc->UnregisterActivityObserver(element);
+    if (elem) {
+      oldDoc->ClearBoxObjectFor(elem);
+      wasRegistered = oldDoc->UnregisterActivityObserver(elem);
     }
 
     aNode->mNodeInfo.swap(newNodeInfo);
     if (elem) {
       elem->NodeInfoChanged(oldDoc);
     }
 
     nsIDocument* newDoc = aNode->OwnerDoc();
     if (newDoc) {
-      if (CustomElementRegistry::IsCustomElementEnabled(newDoc)) {
+      if (elem && CustomElementRegistry::IsCustomElementEnabled(newDoc)) {
         // Adopted callback must be enqueued whenever a node’s
         // shadow-including inclusive descendants that is custom.
-        Element* element = aNode->IsElement() ? aNode->AsElement() : nullptr;
-        if (element) {
-          CustomElementData* data = element->GetCustomElementData();
-          if (data && data->mState == CustomElementData::State::eCustom) {
-            LifecycleAdoptedCallbackArgs args = {
-              oldDoc,
-              newDoc
-            };
-            nsContentUtils::EnqueueLifecycleCallback(nsIDocument::eAdopted,
-                                                     element, nullptr, &args);
-          }
+        CustomElementData* data = elem->GetCustomElementData();
+        if (data && data->mState == CustomElementData::State::eCustom) {
+          LifecycleAdoptedCallbackArgs args = {
+            oldDoc,
+            newDoc
+          };
+          nsContentUtils::EnqueueLifecycleCallback(nsIDocument::eAdopted,
+                                                   elem, nullptr, &args);
         }
       }
 
       // XXX what if oldDoc is null, we don't know if this should be
       // registered or not! Can that really happen?
       if (wasRegistered) {
         newDoc->RegisterActivityObserver(aNode->AsElement());
       }
--- a/dom/html/HTMLLabelElement.cpp
+++ b/dom/html/HTMLLabelElement.cpp
@@ -252,17 +252,17 @@ HTMLLabelElement::GetLabeledElement() co
   return nullptr;
 }
 
 nsGenericHTMLElement*
 HTMLLabelElement::GetFirstLabelableDescendant() const
 {
   for (nsIContent* cur = nsINode::GetFirstChild(); cur;
        cur = cur->GetNextNode(this)) {
-    Element* element = cur->IsElement() ? cur->AsElement() : nullptr;
+    Element* element = Element::FromNode(cur);
     if (element && element->IsLabelable()) {
       return static_cast<nsGenericHTMLElement*>(element);
     }
   }
 
   return nullptr;
 }
 
--- 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/ElementInlines.h"
 #include "nsSMILTimeContainer.h"
 #include "nsSMILAnimationController.h"
 #include "nsSMILAnimationFunction.h"
 #include "nsContentUtils.h"
 #include "nsIContentInlines.h"
 #include "nsIURI.h"
 #include "prtime.h"
 
@@ -66,18 +67,17 @@ SVGAnimationElement::GetTargetElementCon
       HasAttr(kNameSpaceID_None, nsGkAtoms::href)) {
     return mHrefTarget.get();
   }
   MOZ_ASSERT(!mHrefTarget.get(),
              "We shouldn't have a href target "
              "if we don't have an xlink:href or href attribute");
 
   // No "href" or "xlink:href" attribute --> I should target my parent.
-  nsIContent* parent = GetFlattenedTreeParent();
-  return parent && parent->IsElement() ? parent->AsElement() : nullptr;
+  return GetFlattenedTreeParentElement();
 }
 
 bool
 SVGAnimationElement::GetTargetAttributeName(int32_t *aNamespaceID,
                                             nsAtom **aLocalName) const
 {
   const nsAttrValue* nameAttr
     = mAttrsAndChildren.GetAttr(nsGkAtoms::attributeName);
--- a/dom/xbl/nsXBLService.cpp
+++ b/dom/xbl/nsXBLService.cpp
@@ -399,27 +399,28 @@ EnsureSubtreeStyled(Element* aElement)
     return;
   }
 
   ServoStyleSet* servoSet = presShell->StyleSet();
   StyleChildrenIterator iter(aElement);
   for (nsIContent* child = iter.GetNextChild();
        child;
        child = iter.GetNextChild()) {
-    if (!child->IsElement()) {
+    Element* element = Element::FromNode(child);
+    if (!element) {
       continue;
     }
 
-    if (child->AsElement()->HasServoData()) {
+    if (element->HasServoData()) {
       // If any child was styled, all of them should be styled already, so we
       // can bail out.
       return;
     }
 
-    servoSet->StyleNewSubtree(child->AsElement());
+    servoSet->StyleNewSubtree(element);
   }
 }
 
 // Ensures that EnsureSubtreeStyled is called on the element on destruction.
 class MOZ_RAII AutoEnsureSubtreeStyled
 {
 public:
   explicit AutoEnsureSubtreeStyled(Element* aElement)
@@ -610,18 +611,17 @@ nsXBLService::AttachGlobalKeyHandler(Eve
   EventListenerManager* manager = piTarget->GetOrCreateListenerManager();
   if (!manager)
     return NS_ERROR_FAILURE;
 
   // the listener already exists, so skip this
   if (contentNode && contentNode->GetProperty(nsGkAtoms::listener))
     return NS_OK;
 
-  Element* elt =
-   contentNode && contentNode->IsElement() ? contentNode->AsElement() : nullptr;
+  Element* elt = Element::FromNodeOrNull(contentNode);
 
   // Create the key handler
   RefPtr<nsXBLWindowKeyHandler> handler =
     NS_NewXBLWindowKeyHandler(elt, piTarget);
 
   handler->InstallKeyboardEventListenersTo(manager);
 
   if (contentNode)
--- a/dom/xul/XULDocument.cpp
+++ b/dom/xul/XULDocument.cpp
@@ -1414,22 +1414,21 @@ XULDocument::AddElementToDocumentPost(El
     return NS_OK;
 }
 
 nsresult
 XULDocument::AddSubtreeToDocument(nsIContent* aContent)
 {
     NS_ASSERTION(aContent->GetUncomposedDoc() == this, "Element not in doc!");
     // From here on we only care about elements.
-    if (!aContent->IsElement()) {
+    Element* aElement = Element::FromNode(aContent);
+    if (!aElement) {
         return NS_OK;
     }
 
-    Element* aElement = aContent->AsElement();
-
     // Do pre-order addition magic
     nsresult rv = AddElementToDocumentPre(aElement);
     if (NS_FAILED(rv)) return rv;
 
     // Recurse to children
     for (nsIContent* child = aElement->GetLastChild();
          child;
          child = child->GetPreviousSibling()) {
@@ -1442,22 +1441,21 @@ XULDocument::AddSubtreeToDocument(nsICon
     // Do post-order addition magic
     return AddElementToDocumentPost(aElement);
 }
 
 nsresult
 XULDocument::RemoveSubtreeFromDocument(nsIContent* aContent)
 {
     // From here on we only care about elements.
-    if (!aContent->IsElement()) {
+    Element* aElement = Element::FromNode(aContent);
+    if (!aElement) {
         return NS_OK;
     }
 
-    Element* aElement = aContent->AsElement();
-
     // Do a bunch of cleanup to remove an element from the XUL
     // document.
     nsresult rv;
 
     if (aElement->NodeInfo()->Equals(nsGkAtoms::keyset, kNameSpaceID_XUL)) {
         nsXBLService::DetachGlobalKeyHandler(aElement);
     }
 
@@ -3704,17 +3702,17 @@ XULDocument::FindBroadcaster(Element* aE
 
         // If we're still parented by an 'overlay' tag, then we haven't
         // made it into the real document yet. Defer hookup.
         if (parent->NodeInfo()->Equals(nsGkAtoms::overlay,
                                        kNameSpaceID_XUL)) {
             return NS_FINDBROADCASTER_AWAIT_OVERLAYS;
         }
 
-        *aListener = parent->IsElement() ? parent->AsElement() : nullptr;
+        *aListener = Element::FromNode(parent);
         NS_IF_ADDREF(*aListener);
 
         aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::element, aBroadcasterID);
         if (aBroadcasterID.IsEmpty()) {
             return NS_FINDBROADCASTER_NOT_FOUND;
         }
         aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::attribute, aAttribute);
     }
@@ -3836,24 +3834,24 @@ XULDocument::InsertElement(nsINode* aPar
 {
     // Insert aChild appropriately into aParent, accounting for a
     // 'pos' attribute set on aChild.
 
     nsAutoString posStr;
     bool wasInserted = false;
 
     // insert after an element of a given id
-    if (aChild->IsElement()) {
-        aChild->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::insertafter, posStr);
+    if (Element* element = Element::FromNode(aChild)) {
+        element->GetAttr(kNameSpaceID_None, nsGkAtoms::insertafter, posStr);
     }
 
     bool isInsertAfter = true;
     if (posStr.IsEmpty()) {
-        if (aChild->IsElement()) {
-            aChild->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::insertbefore, posStr);
+        if (Element* element = Element::FromNode(aChild)) {
+            element->GetAttr(kNameSpaceID_None, nsGkAtoms::insertbefore, posStr);
         }
         isInsertAfter = false;
     }
 
     if (!posStr.IsEmpty()) {
         nsIDocument *document = aParent->OwnerDoc();
 
         nsIContent *content = nullptr;
--- a/dom/xul/XULPopupElement.cpp
+++ b/dom/xul/XULPopupElement.cpp
@@ -221,26 +221,26 @@ XULPopupElement::GetState(nsString& aSta
 
 nsINode*
 XULPopupElement::GetTriggerNode() const
 {
   nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetPrimaryFrame());
   return nsMenuPopupFrame::GetTriggerContent(menuPopupFrame);
 }
 
+// FIXME(emilio): should probably be renamed to GetAnchorElement?
 Element*
 XULPopupElement::GetAnchorNode() const
 {
-  nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetPrimaryFrame());
+  nsMenuPopupFrame* menuPopupFrame = do_QueryFrame(GetPrimaryFrame());
   if (!menuPopupFrame) {
     return nullptr;
   }
 
-  nsIContent* anchor = menuPopupFrame->GetAnchor();
-  return anchor && anchor->IsElement() ? anchor->AsElement() : nullptr;
+  return Element::FromNodeOrNull(menuPopupFrame->GetAnchor());
 }
 
 already_AddRefed<DOMRect>
 XULPopupElement::GetOuterScreenRect()
 {
   RefPtr<DOMRect> rect = new DOMRect(ToSupports(this));
 
   // Return an empty rectangle if the popup is not open.
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -1261,18 +1261,17 @@ EditorBase::RemoveAttributeWithTransacti
 
 NS_IMETHODIMP
 EditorBase::MarkNodeDirty(nsINode* aNode)
 {
   // Mark the node dirty, but not for webpages (bug 599983)
   if (!OutputsMozDirty()) {
     return NS_OK;
   }
-  if (aNode && aNode->IsElement()) {
-    RefPtr<Element> element = aNode->AsElement();
+  if (RefPtr<Element> element = Element::FromNodeOrNull(aNode)) {
     element->SetAttr(kNameSpaceID_None, nsGkAtoms::mozdirty, EmptyString(),
                      false);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 EditorBase::GetInlineSpellChecker(bool autoCreate,
@@ -3915,26 +3914,25 @@ EditorBase::GetEndChildNode(Selection* a
 bool
 EditorBase::IsPreformatted(nsINode* aNode)
 {
   if (NS_WARN_IF(!aNode)) {
     return false;
   }
   // Look at the node (and its parent if it's not an element), and grab its
   // ComputedStyle.
-  RefPtr<ComputedStyle> elementStyle;
-  Element* element = aNode->IsElement() ? aNode->AsElement() : nullptr;
+  Element* element = Element::FromNode(aNode);
   if (!element) {
     element = aNode->GetParentElement();
     if (!element) {
       return false;
     }
   }
 
-  elementStyle =
+  RefPtr<ComputedStyle> elementStyle =
     nsComputedDOMStyle::GetComputedStyleNoFlush(element, nullptr);
   if (!elementStyle) {
     // Consider nodes without a ComputedStyle to be NOT preformatted:
     // For instance, this is true of JS tags inside the body (which show
     // up as #text nodes but have no ComputedStyle).
     return false;
   }
 
--- a/editor/libeditor/EditorDOMPoint.h
+++ b/editor/libeditor/EditorDOMPoint.h
@@ -165,17 +165,17 @@ public:
   GetContainerAsContent() const
   {
     return mParent && mParent->IsContent() ? mParent->AsContent() : nullptr;
   }
 
   dom::Element*
   GetContainerAsElement() const
   {
-    return mParent && mParent->IsElement() ? mParent->AsElement() : nullptr;
+    return Element::FromNodeOrNull(mParent);
   }
 
   dom::Text*
   GetContainerAsText() const
   {
     return mParent ? mParent->GetAsText() : nullptr;
   }
 
--- a/editor/libeditor/EditorUtils.h
+++ b/editor/libeditor/EditorUtils.h
@@ -372,42 +372,39 @@ public:
   /**
    * GetLeftContent() returns new created node before the part of quarried out.
    * This may return nullptr if the method didn't split at start edge of
    * the node.
    */
   nsIContent* GetLeftContent() const { return mLeftContent; }
   dom::Element* GetLeftContentAsElement() const
   {
-    return mLeftContent && mLeftContent->IsElement() ?
-             mLeftContent->AsElement() : nullptr;
+    return Element::FromNodeOrNull(mLeftContent);
   }
 
   /**
    * GetMiddleContent() returns new created node between left node and right
    * node.  I.e., this is quarried out from the node.  This may return nullptr
    * if the method unwrapped the middle node.
    */
   nsIContent* GetMiddleContent() const { return mMiddleContent; }
   dom::Element* GetMiddleContentAsElement() const
   {
-    return mMiddleContent && mMiddleContent->IsElement() ?
-             mMiddleContent->AsElement() : nullptr;
+    return Element::FromNodeOrNull(mMiddleContent);
   }
 
   /**
    * GetRightContent() returns the right node after the part of quarried out.
    * This may return nullptr it the method didn't split at end edge of the
    * node.
    */
   nsIContent* GetRightContent() const { return mRightContent; }
   dom::Element* GetRightContentAsElement() const
   {
-    return mRightContent && mRightContent->IsElement() ?
-             mRightContent->AsElement() : nullptr;
+    return Element::FromNodeOrNull(mRightContent);
   }
 
   SplitRangeOffFromNodeResult(nsIContent* aLeftContent, nsIContent* aMiddleContent,
                    nsIContent* aRightContent)
     : mLeftContent(aLeftContent)
     , mMiddleContent(aMiddleContent)
     , mRightContent(aRightContent)
     , mRv(NS_OK)
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -2588,28 +2588,26 @@ HTMLEditor::GetSelectedElement(const nsA
       NS_ENSURE_SUCCESS(rv, rv);
 
       iter->Init(currange);
       // loop through the content iterator for each content node
       while (!iter->IsDone()) {
         // Query interface to cast nsIContent to Element
         //  then get tagType to compare to  aTagName
         // Clone node of each desired type and append it to the aDomFrag
-        nsINode* currentNode = iter->GetCurrentNode();
-        selectedElement = currentNode && currentNode->IsElement() ?
-          currentNode->AsElement() : nullptr;
+        selectedElement = Element::FromNodeOrNull(iter->GetCurrentNode());
         if (selectedElement) {
           // If we already found a node, then we have another element,
           //  thus there's not just one element selected
           if (bNodeFound) {
             bNodeFound = false;
             break;
           }
 
-          domTagName = currentNode->NodeName();
+          domTagName = selectedElement->NodeName();
           ToLowerCase(domTagName);
 
           if (anyTag) {
             // Get name of first selected element
             selectedElement->GetTagName(TagName);
             ToLowerCase(TagName);
             anyTag = false;
           }
--- a/layout/base/AccessibleCaretManager.cpp
+++ b/layout/base/AccessibleCaretManager.cpp
@@ -856,18 +856,17 @@ void
 AccessibleCaretManager::ChangeFocusToOrClearOldFocus(nsIFrame* aFrame) const
 {
   nsFocusManager* fm = nsFocusManager::GetFocusManager();
   MOZ_ASSERT(fm);
 
   if (aFrame) {
     nsIContent* focusableContent = aFrame->GetContent();
     MOZ_ASSERT(focusableContent, "Focusable frame must have content!");
-    RefPtr<Element> focusableElement =
-      focusableContent->IsElement() ? focusableContent->AsElement() : nullptr;
+    RefPtr<Element> focusableElement = Element::FromNode(focusableContent);
     fm->SetFocus(focusableElement, nsIFocusManager::FLAG_BYMOUSE);
   } else {
     nsPIDOMWindowOuter* win = mPresShell->GetDocument()->GetWindow();
     if (win) {
       fm->ClearFocus(win);
       fm->SetFocusedWindow(win);
     }
   }
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -9826,19 +9826,17 @@ GetCorrectedParent(const nsIFrame* aFram
   if (pseudo == nsCSSAnonBoxes::tableWrapper) {
     pseudo = aFrame->PrincipalChildList().FirstChild()->Style()->GetPseudo();
   }
 
   // Prevent a NAC pseudo-element from inheriting from its NAC parent, and
   // inherit from the NAC generator element instead.
   if (pseudo) {
     MOZ_ASSERT(aFrame->GetContent());
-    Element* element =
-      aFrame->GetContent()->IsElement()
-        ? aFrame->GetContent()->AsElement() : nullptr;
+    Element* element = Element::FromNode(aFrame->GetContent());
     // Make sure to avoid doing the fixup for non-element-backed pseudos like
     // ::first-line and such.
     if (element &&
         !element->IsRootOfNativeAnonymousSubtree() &&
         element->GetPseudoElementType() == aFrame->Style()->GetPseudoType()) {
       while (parent->GetContent() &&
              !parent->GetContent()->IsRootOfAnonymousSubtree()) {
         parent = parent->GetInFlowParent();
--- a/toolkit/components/find/nsWebBrowserFind.cpp
+++ b/toolkit/components/find/nsWebBrowserFind.cpp
@@ -393,18 +393,17 @@ nsWebBrowserFind::SetSelectionAndScroll(
     selCon->GetSelection(nsISelectionController::SELECTION_NORMAL);
   if (selection) {
     selection->RemoveAllRanges(IgnoreErrors());
     selection->AddRange(*aRange, IgnoreErrors());
 
     nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
     if (fm) {
       if (tcFrame) {
-        RefPtr<Element> newFocusedElement =
-          content->IsElement() ? content->AsElement() : nullptr;
+        RefPtr<Element> newFocusedElement = Element::FromNode(content);
         fm->SetFocus(newFocusedElement, nsIFocusManager::FLAG_NOSCROLL);
       } else {
         RefPtr<Element> result;
         fm->MoveFocus(aWindow, nullptr, nsIFocusManager::MOVEFOCUS_CARET,
                       nsIFocusManager::FLAG_NOSCROLL, getter_AddRefs(result));
       }
     }