Bug 1257208 - Use the nsTextNode concrete type in several places in DirectionalityUtils.cpp instead of nsINode and nsIContent; r=peterv
authorEhsan Akhgari <ehsan@mozilla.com>
Fri, 18 Mar 2016 17:21:50 -0400
changeset 290109 337789a5f9c6
parent 290108 180f3f0494a7
child 290110 f188815f4dbd
push id30114
push usercbook@mozilla.com
push date2016-03-24 15:15 +0000
treeherdermozilla-central@24c5fbde4488 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv
bugs1257208
milestone48.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 1257208 - Use the nsTextNode concrete type in several places in DirectionalityUtils.cpp instead of nsINode and nsIContent; r=peterv
dom/base/DirectionalityUtils.cpp
dom/base/DirectionalityUtils.h
dom/base/nsGenericDOMDataNode.cpp
dom/base/nsINode.h
dom/base/nsTextNode.h
--- a/dom/base/DirectionalityUtils.cpp
+++ b/dom/base/DirectionalityUtils.cpp
@@ -381,17 +381,17 @@ GetDirectionFromText(const nsTextFragmen
  * Set the directionality of a node with dir=auto as defined in
  * http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-directionality
  *
  * @param[in] changedNode If we call this method because the content of a text
  *            node is about to change, pass in the changed node, so that we
  *            know not to return it
  * @return the text node containing the character that determined the direction
  */
-static nsINode*
+static nsTextNode*
 WalkDescendantsSetDirectionFromText(Element* aElement, bool aNotify = true,
                                     nsINode* aChangedNode = nullptr)
 {
   MOZ_ASSERT(aElement, "Must have an element");
   MOZ_ASSERT(aElement->HasDirAuto(), "Element must have dir=auto");
 
   if (DoesNotParticipateInAutoDirection(aElement)) {
     return nullptr;
@@ -407,17 +407,17 @@ WalkDescendantsSetDirectionFromText(Elem
 
     if (child->NodeType() == nsIDOMNode::TEXT_NODE &&
         child != aChangedNode) {
       Directionality textNodeDir = GetDirectionFromText(child->GetText());
       if (textNodeDir != eDir_NotSet) {
         // We found a descendant text node with strong directional characters.
         // Set the directionality of aElement to the corresponding value.
         aElement->SetDirectionality(textNodeDir, aNotify);
-        return child;
+        return static_cast<nsTextNode*>(child);
       }
     }
     child = child->GetNextNode(aElement);
   }
 
   // We walked all the descendants without finding a text node with strong
   // directional characters. Set the directionality to LTR
   aElement->SetDirectionality(eDir_LTR, aNotify);
@@ -449,26 +449,26 @@ public:
     aTextNode->SetHasTextNodeDirectionalityMap();
   }
 
   ~nsTextNodeDirectionalityMap()
   {
     MOZ_COUNT_DTOR(nsTextNodeDirectionalityMap);
   }
 
-  void AddEntry(nsINode* aTextNode, Element* aElement)
+  void AddEntry(nsTextNode* aTextNode, Element* aElement)
   {
     if (!mElements.Contains(aElement)) {
       mElements.Put(aElement);
       aElement->SetProperty(nsGkAtoms::dirAutoSetBy, aTextNode);
       aElement->SetHasDirAutoSet();
     }
   }
 
-  void RemoveEntry(nsINode* aTextNode, Element* aElement)
+  void RemoveEntry(nsTextNode* aTextNode, Element* aElement)
   {
     NS_ASSERTION(mElements.Contains(aElement),
                  "element already removed from map");
 
     mElements.Remove(aElement);
     aElement->ClearHasDirAutoSet();
     aElement->UnsetProperty(nsGkAtoms::dirAutoSetBy);
   }
@@ -500,17 +500,17 @@ private:
 
   static nsCheapSetOperator ResetNodeDirection(nsPtrHashKey<Element>* aEntry, void* aData)
   {
     MOZ_ASSERT(aEntry->GetKey()->IsElement(), "Must be an Element");
     // run the downward propagation algorithm
     // and remove the text node from the map
     nsINode* oldTextNode = static_cast<Element*>(aData);
     Element* rootNode = aEntry->GetKey();
-    nsINode* newTextNode = nullptr;
+    nsTextNode* newTextNode = nullptr;
     if (rootNode->GetParentNode() && rootNode->HasDirAuto()) {
       newTextNode = WalkDescendantsSetDirectionFromText(rootNode, true,
                                                         oldTextNode);
     }
     if (newTextNode) {
       nsTextNodeDirectionalityMap::AddEntryToMap(newTextNode, rootNode);
     } else {
       rootNode->ClearHasDirAutoSet();
@@ -540,24 +540,24 @@ public:
 
   void EnsureMapIsClear(nsINode* aTextNode)
   {
     DebugOnly<uint32_t> clearedEntries =
       mElements.EnumerateEntries(ClearEntry, aTextNode);
     MOZ_ASSERT(clearedEntries == 0, "Map should be empty already");
   }
 
-  static void RemoveElementFromMap(nsINode* aTextNode, Element* aElement)
+  static void RemoveElementFromMap(nsTextNode* aTextNode, Element* aElement)
   {
     if (aTextNode->HasTextNodeDirectionalityMap()) {
       GetDirectionalityMap(aTextNode)->RemoveEntry(aTextNode, aElement);
     }
   }
 
-  static void AddEntryToMap(nsINode* aTextNode, Element* aElement)
+  static void AddEntryToMap(nsTextNode* aTextNode, Element* aElement)
   {
     nsTextNodeDirectionalityMap* map = GetDirectionalityMap(aTextNode);
     if (!map) {
       map = new nsTextNodeDirectionalityMap(aTextNode);
     }
 
     map->AddEntry(aTextNode, aElement);
   }
@@ -565,18 +565,18 @@ public:
   static uint32_t UpdateTextNodeDirection(nsINode* aTextNode,
                                           Directionality aDir)
   {
     MOZ_ASSERT(aTextNode->HasTextNodeDirectionalityMap(),
                "Map missing in UpdateTextNodeDirection");
     return GetDirectionalityMap(aTextNode)->UpdateAutoDirection(aDir);
   }
 
-  static void ResetTextNodeDirection(nsINode* aTextNode,
-                                     nsINode* aChangedTextNode)
+  static void ResetTextNodeDirection(nsTextNode* aTextNode,
+                                     nsTextNode* aChangedTextNode)
   {
     MOZ_ASSERT(aTextNode->HasTextNodeDirectionalityMap(),
                "Map missing in ResetTextNodeDirection");
     GetDirectionalityMap(aTextNode)->ResetAutoDirection(aChangedTextNode);
   }
 
   static void EnsureMapIsClearFor(nsINode* aTextNode)
   {
@@ -640,27 +640,27 @@ SetDirectionalityOnDescendants(Element* 
 /**
  * Walk the parent chain of a text node whose dir attribute has been removed and
  * reset the direction of any of its ancestors which have dir=auto and whose
  * directionality is determined by a text node descendant.
  */
 void
 WalkAncestorsResetAutoDirection(Element* aElement, bool aNotify)
 {
-  nsINode* setByNode;
+  nsTextNode* setByNode;
   Element* parent = aElement->GetParentElement();
 
   while (parent && parent->NodeOrAncestorHasDirAuto()) {
     if (parent->HasDirAutoSet()) {
       // If the parent has the DirAutoSet flag, its direction is determined by
       // some text node descendant.
       // Remove it from the map and reset its direction by the downward
       // propagation algorithm
       setByNode =
-        static_cast<nsINode*>(parent->GetProperty(nsGkAtoms::dirAutoSetBy));
+        static_cast<nsTextNode*>(parent->GetProperty(nsGkAtoms::dirAutoSetBy));
       if (setByNode) {
         nsTextNodeDirectionalityMap::RemoveElementFromMap(setByNode, parent);
       }
     }
     if (parent->HasDirAuto()) {
       setByNode = WalkDescendantsSetDirectionFromText(parent, aNotify);
       if (setByNode) {
         nsTextNodeDirectionalityMap::AddEntryToMap(setByNode, parent);
@@ -676,18 +676,19 @@ WalkDescendantsResetAutoDirection(Elemen
 {
   nsIContent* child = aElement->GetFirstChild();
   while (child) {
     if (child->HasDirAuto()) {
       child = child->GetNextNonChildNode(aElement);
       continue;
     }
 
-    if (child->HasTextNodeDirectionalityMap()) {
-      nsTextNodeDirectionalityMap::ResetTextNodeDirection(child, nullptr);
+    if (child->NodeType() == nsIDOMNode::TEXT_NODE &&
+        child->HasTextNodeDirectionalityMap()) {
+      nsTextNodeDirectionalityMap::ResetTextNodeDirection(static_cast<nsTextNode*>(child), nullptr);
       nsTextNodeDirectionalityMap::EnsureMapIsClearFor(child);
     }
     child = child->GetNextNode(aElement);
   }
 }
 
 void
 WalkDescendantsSetDirAuto(Element* aElement, bool aNotify)
@@ -720,17 +721,17 @@ WalkDescendantsSetDirAuto(Element* aElem
                    child->AncestorHasDirAuto(),
                    "AncestorHasDirAuto set on node but not its children");
         child->SetAncestorHasDirAuto();
         child = child->GetNextNode(aElement);
       }
     }
   }
 
-  nsINode* textNode = WalkDescendantsSetDirectionFromText(aElement, aNotify);
+  nsTextNode* textNode = WalkDescendantsSetDirectionFromText(aElement, aNotify);
   if (textNode) {
     nsTextNodeDirectionalityMap::AddEntryToMap(textNode, aElement);
   }
 }
 
 void
 WalkDescendantsClearAncestorDirAuto(Element* aElement)
 {
@@ -741,32 +742,32 @@ WalkDescendantsClearAncestorDirAuto(Elem
       continue;
     }
 
     child->ClearAncestorHasDirAuto();
     child = child->GetNextNode(aElement);
   }
 }
 
-void SetAncestorDirectionIfAuto(nsINode* aTextNode, Directionality aDir,
+void SetAncestorDirectionIfAuto(nsTextNode* aTextNode, Directionality aDir,
                                 bool aNotify = true)
 {
   MOZ_ASSERT(aTextNode->NodeType() == nsIDOMNode::TEXT_NODE,
              "Must be a text node");
 
   Element* parent = aTextNode->GetParentElement();
   while (parent && parent->NodeOrAncestorHasDirAuto()) {
     if (DoesNotParticipateInAutoDirection(parent) || parent->HasFixedDir()) {
       break;
     }
 
     if (parent->HasDirAuto()) {
       bool resetDirection = false;
-      nsINode* directionWasSetByTextNode =
-        static_cast<nsINode*>(parent->GetProperty(nsGkAtoms::dirAutoSetBy));
+      nsTextNode* directionWasSetByTextNode =
+        static_cast<nsTextNode*>(parent->GetProperty(nsGkAtoms::dirAutoSetBy));
 
       if (!parent->HasDirAutoSet()) {
         // Fast path if parent's direction is not yet set by any descendant
         MOZ_ASSERT(!directionWasSetByTextNode,
                    "dirAutoSetBy property should be null");
         resetDirection = true;
       } else {
         // If parent's direction is already set, we need to know if
@@ -827,17 +828,17 @@ TextNodeWillChangeDirection(nsIContent* 
   }
 
   uint32_t firstStrong;
   *aOldDir = GetDirectionFromText(aTextNode->GetText(), &firstStrong);
   return (aOffset <= firstStrong);
 }
 
 void
-TextNodeChangedDirection(nsIContent* aTextNode, Directionality aOldDir,
+TextNodeChangedDirection(nsTextNode* aTextNode, Directionality aOldDir,
                          bool aNotify)
 {
   Directionality newDir = GetDirectionFromText(aTextNode->GetText());
   if (newDir == eDir_NotSet) {
     if (aOldDir != eDir_NotSet && aTextNode->HasTextNodeDirectionalityMap()) {
       // This node used to have a strong directional character but no
       // longer does. ResetTextNodeDirection() will re-resolve the
       // directionality of any elements whose directionality was
@@ -857,17 +858,17 @@ TextNodeChangedDirection(nsIContent* aTe
                                                              newDir)) {
       return;
     }
     SetAncestorDirectionIfAuto(aTextNode, newDir, aNotify);
   }
 }
 
 void
-SetDirectionFromNewTextNode(nsIContent* aTextNode)
+SetDirectionFromNewTextNode(nsTextNode* aTextNode)
 {
   if (!NodeAffectsDirAutoAncestor(aTextNode)) {
     return;
   }
 
   Element* parent = aTextNode->GetParentElement();
   if (parent && parent->NodeOrAncestorHasDirAuto()) {
     aTextNode->SetAncestorHasDirAuto();
@@ -944,18 +945,18 @@ OnSetDirAttr(Element* aElement, const ns
     //      here is simpler.
     WalkDescendantsClearAncestorDirAuto(aElement);
   }
 
   if (aElement->HasDirAuto()) {
     WalkDescendantsSetDirAuto(aElement, aNotify);
   } else {
     if (aElement->HasDirAutoSet()) {
-      nsINode* setByNode =
-        static_cast<nsINode*>(aElement->GetProperty(nsGkAtoms::dirAutoSetBy));
+      nsTextNode* setByNode =
+        static_cast<nsTextNode*>(aElement->GetProperty(nsGkAtoms::dirAutoSetBy));
       nsTextNodeDirectionalityMap::RemoveElementFromMap(setByNode, aElement);
     }
     SetDirectionalityOnDescendants(aElement,
                                    RecomputeDirectionality(aElement, aNotify),
                                    aNotify);
   }
 }
 
@@ -996,18 +997,18 @@ SetDirOnBind(mozilla::dom::Element* aEle
     // the dir attribute or by inheriting from its ancestors.
     RecomputeDirectionality(aElement, false);
   }
 }
 
 void ResetDir(mozilla::dom::Element* aElement)
 {
   if (aElement->HasDirAutoSet()) {
-    nsINode* setByNode =
-      static_cast<nsINode*>(aElement->GetProperty(nsGkAtoms::dirAutoSetBy));
+    nsTextNode* setByNode =
+      static_cast<nsTextNode*>(aElement->GetProperty(nsGkAtoms::dirAutoSetBy));
     nsTextNodeDirectionalityMap::RemoveElementFromMap(setByNode, aElement);
   }
 
   if (!aElement->HasDirAuto()) {
     RecomputeDirectionality(aElement, false);
   }
 }
 
--- a/dom/base/DirectionalityUtils.h
+++ b/dom/base/DirectionalityUtils.h
@@ -84,24 +84,24 @@ void WalkDescendantsClearAncestorDirAuto
  */
 bool TextNodeWillChangeDirection(nsIContent* aTextNode, Directionality* aOldDir,
                                  uint32_t aOffset);
 
 /**
  * After the contents of a text node have changed, change the directionality
  * of any elements whose directionality is determined by that node
  */
-void TextNodeChangedDirection(nsIContent* aTextNode, Directionality aOldDir,
+void TextNodeChangedDirection(nsTextNode* aTextNode, Directionality aOldDir,
                               bool aNotify);
 
 /**
  * When a text node is appended to an element, find any ancestors with dir=auto
  * whose directionality will be determined by the text node
  */
-void SetDirectionFromNewTextNode(nsIContent* aTextNode);
+void SetDirectionFromNewTextNode(nsTextNode* aTextNode);
 
 /**
  * When a text node is removed from a document, find any ancestors whose
  * directionality it determined and redetermine their directionality
  *
  * @param aTextNode the text node
  */
 void ResetDirectionSetByTextNode(nsTextNode* aTextNode);
--- a/dom/base/nsGenericDOMDataNode.cpp
+++ b/dom/base/nsGenericDOMDataNode.cpp
@@ -366,17 +366,20 @@ nsGenericDOMDataNode::SetTextInternal(ui
 
   if (document && mText.IsBidi()) {
     // If we found bidi characters in mText.SetTo() above, indicate that the
     // document contains bidi characters.
     document->SetBidiEnabled();
   }
 
   if (dirAffectsAncestor) {
-    TextNodeChangedDirection(this, oldDir, aNotify);
+    // dirAffectsAncestor being true implies that we have a text node, see
+    // above.
+    MOZ_ASSERT(NodeType() == nsIDOMNode::TEXT_NODE);
+    TextNodeChangedDirection(static_cast<nsTextNode*>(this), oldDir, aNotify);
   }
 
   // Notify observers
   if (aNotify) {
     CharacterDataChangeInfo info = {
       aOffset == textLength,
       aOffset,
       endOffset,
--- a/dom/base/nsINode.h
+++ b/dom/base/nsINode.h
@@ -1619,18 +1619,21 @@ public:
                "SetHasTextNodeDirectionalityMap on non-text node");
     SetBoolFlag(NodeHasTextNodeDirectionalityMap);
   }
   void ClearHasTextNodeDirectionalityMap() {
     MOZ_ASSERT(NodeType() == nsIDOMNode::TEXT_NODE,
                "ClearHasTextNodeDirectionalityMap on non-text node");
     ClearBoolFlag(NodeHasTextNodeDirectionalityMap);
   }
-  bool HasTextNodeDirectionalityMap() const
-    { return GetBoolFlag(NodeHasTextNodeDirectionalityMap); }
+  bool HasTextNodeDirectionalityMap() const {
+    MOZ_ASSERT(NodeType() == nsIDOMNode::TEXT_NODE,
+               "HasTextNodeDirectionalityMap on non-text node");
+    return GetBoolFlag(NodeHasTextNodeDirectionalityMap);
+  }
 
   void SetHasDirAuto() { SetBoolFlag(NodeHasDirAuto); }
   void ClearHasDirAuto() { ClearBoolFlag(NodeHasDirAuto); }
   bool HasDirAuto() const { return GetBoolFlag(NodeHasDirAuto); }
 
   void SetAncestorHasDirAuto() { SetBoolFlag(NodeAncestorHasDirAuto); }
   void ClearAncestorHasDirAuto() { ClearBoolFlag(NodeAncestorHasDirAuto); }
   bool AncestorHasDirAuto() const { return GetBoolFlag(NodeAncestorHasDirAuto); }
--- a/dom/base/nsTextNode.h
+++ b/dom/base/nsTextNode.h
@@ -44,16 +44,17 @@ public:
     Init();
   }
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
+  using mozilla::dom::Text::GetParentElement;
 
   // nsIDOMCharacterData
   NS_FORWARD_NSIDOMCHARACTERDATA(nsGenericDOMDataNode::)
   using nsGenericDOMDataNode::SetData; // Prevent hiding overloaded virtual function.
 
   // nsIDOMText
   NS_FORWARD_NSIDOMTEXT(nsGenericDOMDataNode::)