Bug 1409520 - part 1: WSRunObject::InsertText() should update aInOutChildAtOffset after it might be modified r?m_kato draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Mon, 23 Oct 2017 21:47:56 +0900
changeset 684892 437d72cb9353831721a3da8229cce45a3d32d009
parent 684891 92f8145365566353c6dc65e01edb387fd5a5a7eb
child 684932 0aa99747bd80b1650f846be0ec4af6081c060710
push id85751
push usermasayuki@d-toybox.com
push dateMon, 23 Oct 2017 17:58:54 +0000
reviewersm_kato
bugs1409520
milestone58.0a1
Bug 1409520 - part 1: WSRunObject::InsertText() should update aInOutChildAtOffset after it might be modified r?m_kato WSRunObject::InsertText() may delete given child node at offset with calling DeleteChars() or CheckLeadingNBSP() before calling HTMLEditor::InsertTextImpl(). Therefore, even though using nsINode::GetChildAt() is slow, it needs to update aInOutChildAtOffset after calling them. MozReview-Commit-ID: AbTTfNAjMIK
editor/libeditor/WSRunObject.cpp
--- a/editor/libeditor/WSRunObject.cpp
+++ b/editor/libeditor/WSRunObject.cpp
@@ -259,48 +259,67 @@ WSRunObject::InsertText(const nsAString&
   FindRun(*aInOutParent, *aInOutOffset, &afterRun, true);
 
   {
     // Some scoping for AutoTrackDOMPoint.  This will track our insertion
     // point while we tweak any surrounding whitespace
     AutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater, aInOutParent,
                               aInOutOffset);
 
+    bool maybeModified = false;
     // Handle any changes needed to ws run after inserted text
     if (!afterRun || afterRun->mType & WSType::trailingWS) {
       // Don't need to do anything.  Just insert text.  ws won't change.
     } else if (afterRun->mType & WSType::leadingWS) {
       // Delete the leading ws that is after insertion point, because it
       // would become significant after text inserted.
       nsresult rv =
         DeleteChars(*aInOutParent, *aInOutOffset, afterRun->mEndNode,
                     afterRun->mEndOffset);
       NS_ENSURE_SUCCESS(rv, rv);
+      maybeModified = true;
     } else if (afterRun->mType == WSType::normalWS) {
       // Try to change an nbsp to a space, if possible, just to prevent nbsp
       // proliferation
       nsresult rv = CheckLeadingNBSP(afterRun, *aInOutParent, *aInOutOffset);
       NS_ENSURE_SUCCESS(rv, rv);
+      maybeModified = true;
     }
 
     // Handle any changes needed to ws run before inserted text
     if (!beforeRun || beforeRun->mType & WSType::leadingWS) {
       // Don't need to do anything.  Just insert text.  ws won't change.
     } else if (beforeRun->mType & WSType::trailingWS) {
       // Need to delete the trailing ws that is before insertion point, because
       // it would become significant after text inserted.
       nsresult rv =
         DeleteChars(beforeRun->mStartNode, beforeRun->mStartOffset,
                     *aInOutParent, *aInOutOffset);
       NS_ENSURE_SUCCESS(rv, rv);
+      maybeModified = true;
     } else if (beforeRun->mType == WSType::normalWS) {
       // Try to change an nbsp to a space, if possible, just to prevent nbsp
       // proliferation
       nsresult rv = CheckTrailingNBSP(beforeRun, *aInOutParent, *aInOutOffset);
       NS_ENSURE_SUCCESS(rv, rv);
+      maybeModified = true;
+    }
+
+    // The child node may be changed.  So, even though getting child at offset
+    // is expensive, we need to do it here.
+    if (maybeModified) {
+      if ((*aInOutParent)->HasChildren()) {
+        if (*aInOutOffset == 0) {
+          *aInOutChildAtOffset = (*aInOutParent)->GetFirstChild();
+        } else {
+          *aInOutChildAtOffset = (*aInOutParent)->GetChildAt(*aInOutOffset);
+        }
+      } else {
+        *aInOutChildAtOffset = nullptr;
+      }
     }
   }
 
   // Next up, tweak head and tail of string as needed.  First the head: there
   // are a variety of circumstances that would require us to convert a leading
   // ws char into an nbsp:
 
   if (nsCRT::IsAsciiSpace(theString[0])) {