Make sure not to return the old text node in ResetNodeDirection. Bug 845093, r=ehsan
authorSimon Montagu <smontagu@smontagu.org>
Thu, 07 Mar 2013 22:53:08 +0200
changeset 124150 ac291d349daaaa6dfd6eca8a2e099c3fdc380e3f
parent 124149 e81b56f0c6897785916db0f2e69a1c1aa18fe04b
child 124151 9f15cf555746e337b15e12b118913a5c194c65bd
push id24254
push usersmontagu@mozilla.com
push dateThu, 07 Mar 2013 20:53:41 +0000
treeherdermozilla-inbound@9f15cf555746 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs845093
milestone22.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
Make sure not to return the old text node in ResetNodeDirection. Bug 845093, r=ehsan
content/base/src/DirectionalityUtils.cpp
--- a/content/base/src/DirectionalityUtils.cpp
+++ b/content/base/src/DirectionalityUtils.cpp
@@ -371,35 +371,40 @@ GetDirectionFromText(const nsTextFragmen
   return GetDirectionFromText(aFrag->Get1b(), aFrag->GetLength(),
                                  aFirstStrong);
 }
 
 /**
  * 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*
-WalkDescendantsSetDirectionFromText(Element* aElement, bool aNotify = true)
+WalkDescendantsSetDirectionFromText(Element* aElement, bool aNotify = true,
+                                    nsINode* aChangedNode = nullptr)
 {
   MOZ_ASSERT(aElement, "aElement is null");
   if (DoesNotParticipateInAutoDirection(aElement)) {
     return nullptr;
   }
 
   nsIContent* child = aElement->GetFirstChild();
   while (child) {
     if (child->IsElement() &&
         DoesNotAffectDirectionOfAncestors(child->AsElement())) {
       child = child->GetNextNonChildNode(aElement);
       continue;
     }
 
-    if (child->NodeType() == nsIDOMNode::TEXT_NODE) {
+    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;
       }
     }
@@ -485,36 +490,38 @@ private:
     return PL_DHASH_NEXT;
   }
 
   static PLDHashOperator 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* textNode = WalkDescendantsSetDirectionFromText(rootNode, true);
-    if (textNode) {
-      nsTextNodeDirectionalityMap::AddEntryToMap(textNode, rootNode);
+    nsINode* newTextNode = WalkDescendantsSetDirectionFromText(rootNode, true,
+                                                               oldTextNode);
+    if (newTextNode) {
+      nsTextNodeDirectionalityMap::AddEntryToMap(newTextNode, rootNode);
     } else {
       rootNode->ClearHasDirAutoSet();
       rootNode->UnsetProperty(nsGkAtoms::dirAutoSetBy);
     }
     return PL_DHASH_REMOVE;
   }
 
 public:
   void UpdateAutoDirection(Directionality aDir)
   {
     mElements.EnumerateEntries(SetNodeDirection, &aDir);
   }
 
-  void ResetAutoDirection()
+  void ResetAutoDirection(nsINode* aTextNode)
   {
-    mElements.EnumerateEntries(ResetNodeDirection, nullptr);
+    mElements.EnumerateEntries(ResetNodeDirection, aTextNode);
   }
 
   static void RemoveElementFromMap(nsINode* aTextNode, Element* aElement)
   {
     if (aTextNode->HasTextNodeDirectionalityMap()) {
       GetDirectionalityMap(aTextNode)->RemoveEntry(aTextNode, aElement);
     }
   }
@@ -535,17 +542,17 @@ public:
                "Map missing in UpdateTextNodeDirection");
     GetDirectionalityMap(aTextNode)->UpdateAutoDirection(aDir);
   }
 
   static void ResetTextNodeDirection(nsINode* aTextNode)
   {
     MOZ_ASSERT(aTextNode->HasTextNodeDirectionalityMap(),
                "Map missing in ResetTextNodeDirection");
-    GetDirectionalityMap(aTextNode)->ResetAutoDirection();
+    GetDirectionalityMap(aTextNode)->ResetAutoDirection(aTextNode);
   }
 };
 
 Directionality
 RecomputeDirectionality(Element* aElement, bool aNotify)
 {
   MOZ_ASSERT(!aElement->HasDirAuto(),
              "RecomputeDirectionality called with dir=auto");