Bug 1037641 - Split SetDirectionFromChangedTextNode into TextNodeWillChangeDirection and TextNodeChangedDirection. r=ehsan, a=abillings
authorSimon Montagu <smontagu@smontagu.org>
Wed, 06 Aug 2014 12:02:59 +0300
changeset 208316 9e94aa2f0ae7
parent 208315 6a2810252cf8
child 208317 c6e134b4ed52
push id3821
push userryanvm@gmail.com
push date2014-08-17 13:12 +0000
treeherdermozilla-beta@9e94aa2f0ae7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan, abillings
bugs1037641
milestone32.0
Bug 1037641 - Split SetDirectionFromChangedTextNode into TextNodeWillChangeDirection and TextNodeChangedDirection. r=ehsan, a=abillings
content/base/public/DirectionalityUtils.h
content/base/src/DirectionalityUtils.cpp
content/base/src/nsGenericDOMDataNode.cpp
--- a/content/base/public/DirectionalityUtils.h
+++ b/content/base/public/DirectionalityUtils.h
@@ -74,22 +74,30 @@ void WalkDescendantsSetDirAuto(mozilla::
 /**
  * After unsetting dir=auto on an element, walk its descendants in tree order,
  * skipping any that have dir=auto themselves, and unset the
  * NODE_ANCESTOR_HAS_DIR_AUTO flag
  */
 void WalkDescendantsClearAncestorDirAuto(mozilla::dom::Element* aElement);
 
 /**
- * When the contents of a text node have changed, deal with any elements whose
- * directionality needs to change
+ * When the contents of a text node are about to change, retrieve the current
+ * directionality of the text
+ *
+ * @return whether the text node affects the directionality of any element
  */
-void SetDirectionFromChangedTextNode(nsIContent* aTextNode, uint32_t aOffset,
-                                     const char16_t* aBuffer, uint32_t aLength,
-                                     bool aNotify);
+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,
+                              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);
 
 /**
--- a/content/base/src/DirectionalityUtils.cpp
+++ b/content/base/src/DirectionalityUtils.cpp
@@ -312,16 +312,17 @@ GetDirectionFromText(const char16_t* aTe
   while (start < end) {
     uint32_t current = start - aText;
     uint32_t ch = *start++;
 
     if (NS_IS_HIGH_SURROGATE(ch) &&
         start < end &&
         NS_IS_LOW_SURROGATE(*start)) {
       ch = SURROGATE_TO_UCS4(ch, *start++);
+      current++;
     }
 
     Directionality dir = GetDirectionFromChar(ch);
     if (dir != eDir_NotSet) {
       if (aFirstStrong) {
         *aFirstStrong = current;
       }
       return dir;
@@ -818,36 +819,37 @@ void SetAncestorDirectionIfAuto(nsINode*
       // parent chain: none of its ancestors will have their direction set by
       // any of its descendants.
       return;
     }
     parent = parent->GetParentElement();
   }
 }
 
-void
-SetDirectionFromChangedTextNode(nsIContent* aTextNode, uint32_t aOffset,
-                                const char16_t* aBuffer, uint32_t aLength,
-                                bool aNotify)
+bool
+TextNodeWillChangeDirection(nsIContent* aTextNode, Directionality* aOldDir,
+                            uint32_t aOffset)
 {
   if (!NodeAffectsDirAutoAncestor(aTextNode)) {
     nsTextNodeDirectionalityMap::EnsureMapIsClearFor(aTextNode);
-    return;
+    return false;
   }
 
   uint32_t firstStrong;
-  Directionality oldDir = GetDirectionFromText(aTextNode->GetText(),
-                                               &firstStrong);
-  if (aOffset > firstStrong) {
-    return;
-  }
+  *aOldDir = GetDirectionFromText(aTextNode->GetText(), &firstStrong);
+  return (aOffset <= firstStrong);
+}
 
-  Directionality newDir = GetDirectionFromText(aBuffer, aLength);
+void
+TextNodeChangedDirection(nsIContent* aTextNode, Directionality aOldDir,
+                         bool aNotify)
+{
+  Directionality newDir = GetDirectionFromText(aTextNode->GetText());
   if (newDir == eDir_NotSet) {
-    if (oldDir != eDir_NotSet && aTextNode->HasTextNodeDirectionalityMap()) {
+    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
       // determined by this node.
       nsTextNodeDirectionalityMap::ResetTextNodeDirection(aTextNode);
     }
   } else {
     // This node has a strong directional character. If it has a
--- a/content/base/src/nsGenericDOMDataNode.cpp
+++ b/content/base/src/nsGenericDOMDataNode.cpp
@@ -317,19 +317,19 @@ nsGenericDOMDataNode::SetTextInternal(ui
       aOffset,
       endOffset,
       aLength,
       aDetails
     };
     nsNodeUtils::CharacterDataWillChange(this, &info);
   }
 
-  if (NodeType() == nsIDOMNode::TEXT_NODE) {
-    SetDirectionFromChangedTextNode(this, aOffset, aBuffer, aLength, aNotify);
-  }
+  Directionality oldDir = eDir_NotSet;
+  bool dirAffectsAncestor = (NodeType() == nsIDOMNode::TEXT_NODE &&
+                             TextNodeWillChangeDirection(this, &oldDir, aOffset));
 
   if (aOffset == 0 && endOffset == textLength) {
     // Replacing whole text or old text was empty.  Don't bother to check for
     // bidi in this string if the document already has bidi enabled.
     bool ok = mText.SetTo(aBuffer, aLength, !document || !document->GetBidiEnabled());
     NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
   }
   else if (aOffset == textLength) {
@@ -366,16 +366,20 @@ nsGenericDOMDataNode::SetTextInternal(ui
   UnsetFlags(NS_CACHED_TEXT_IS_ONLY_WHITESPACE);
 
   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);
+  }
+
   // Notify observers
   if (aNotify) {
     CharacterDataChangeInfo info = {
       aOffset == textLength,
       aOffset,
       endOffset,
       aLength,
       aDetails