Bug 1465478: Introduce Element::FromNode. r?smaug draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Wed, 30 May 2018 16:56:24 +0200
changeset 801472 6a99e19b740597576c9ac80ffba1422e8594f654
parent 801471 d5b62c0da2e69aef3bcb29e5b4111ab2735e6fdf
child 801616 11892d89e0938b98bcbed50d9afddaffe1604818
push id111692
push userbmo:emilio@crisal.io
push dateWed, 30 May 2018 14:57:21 +0000
reviewerssmaug
bugs1465478
milestone62.0a1
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 (auto* 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()) {
+    auto* 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 (auto* 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()) {
+    auto* 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 (auto* 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 (auto* 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 (auto* 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
@@ -66,18 +66,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()) {
+    auto* 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 (auto* 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 (auto* 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
@@ -9838,19 +9838,17 @@ GetCorrectedParent(const nsIFrame* aFram
   // since CorrectStyleParentFrame only knows about the prospective _parent_.
   // This duplication and complexity will go away when we fully switch to the
   // Servo style system, where all this can be handled much more naturally.
   //
   // We need to take special care not to disrupt the style inheritance of frames
   // whose content is NAC but who implement a pseudo (like an anonymous
   // box, or a non-NAC-backed pseudo like ::first-line) that does not match the
   // one that the NAC implements, if any.
-  nsIContent* content = aFrame->GetContent();
-  Element* element =
-    content && content->IsElement() ? content->AsElement() : nullptr;
+  Element* element = Element::FromNodeOrNull(aFrame->GetContent());
   if (element && element->IsNativeAnonymous() && !element->IsNativeScrollbarContent() &&
       element->GetPseudoElementType() == aFrame->Style()->GetPseudoType()) {
     while (parent->GetContent() && parent->GetContent()->IsNativeAnonymous()) {
       parent = parent->GetInFlowParent();
     }
   }
 
   return nsFrame::CorrectStyleParentFrame(parent, pseudo);
--- 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));
       }
     }