Bug 1368544 - Part 1. Use root node for mozInlineSpellChecker::SpellCheckAfterEditorChange on setText trasaction. r=masayuki
authorMakoto Kato <m_kato@ga2.so-net.ne.jp>
Wed, 31 May 2017 14:50:51 +0900
changeset 409598 0144d912dcf0bba914e62a67b5d34fe1403d06c7
parent 409597 e1d2707ee01d7ea77d580a59ce51f579f62b9bc5
child 409599 85449d8e83daf91d14ce48ca6ceda40a751db5b8
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmasayuki
bugs1368544
milestone55.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 1368544 - Part 1. Use root node for mozInlineSpellChecker::SpellCheckAfterEditorChange on setText trasaction. r=masayuki textarea element will use fallback code (using TextEditor::DeleteSelection) to set empty value for SetText. Actually, if EditorBase::HandleInlineSpellCheck returns error in AfterEdit, we might not create bogus node and trailing br node. Since SetText's fallback uses DeleteSelection, SpellCheckAfterEditorChange will return error when previous selection is invalid on SetText transaction. mozInineSpellChecker::SpellCheckAfterEditorChange creates the range between previousSelection and anchorNode. So when using setText, we should set the range of all text, and we should not use previous selection for SpellCheckAfterEditorChange. MozReview-Commit-ID: 7eDzMdRmOSz
editor/libeditor/TextEditRules.cpp
--- a/editor/libeditor/TextEditRules.cpp
+++ b/editor/libeditor/TextEditRules.cpp
@@ -181,22 +181,34 @@ TextEditRules::BeforeEdit(EditAction act
   mDidExplicitlySetInterline = false;
   if (!mActionNesting) {
     // let rules remember the top level action
     mTheAction = action;
   }
   mActionNesting++;
 
   // get the selection and cache the position before editing
-  NS_ENSURE_STATE(mTextEditor);
-  RefPtr<Selection> selection = mTextEditor->GetSelection();
+  if (NS_WARN_IF(!mTextEditor)) {
+    return NS_ERROR_FAILURE;
+  }
+  RefPtr<TextEditor> textEditor = mTextEditor;
+  RefPtr<Selection> selection = textEditor->GetSelection();
   NS_ENSURE_STATE(selection);
 
-  mCachedSelectionNode = selection->GetAnchorNode();
-  selection->GetAnchorOffset(&mCachedSelectionOffset);
+  if (action == EditAction::setText) {
+    // setText replaces all text, so mCachedSelectionNode might be invalid on
+    // AfterEdit.
+    // Since this will be used as start position of spellchecker, we should
+    // use root instead.
+    mCachedSelectionNode = textEditor->GetRoot();
+    mCachedSelectionOffset = 0;
+  } else {
+    mCachedSelectionNode = selection->GetAnchorNode();
+    selection->GetAnchorOffset(&mCachedSelectionOffset);
+  }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TextEditRules::AfterEdit(EditAction action,
                          nsIEditor::EDirection aDirection)
 {
@@ -215,16 +227,19 @@ TextEditRules::AfterEdit(EditAction acti
     NS_ENSURE_STATE(mTextEditor);
     nsresult rv =
       mTextEditor->HandleInlineSpellCheck(action, selection,
                                           GetAsDOMNode(mCachedSelectionNode),
                                           mCachedSelectionOffset,
                                           nullptr, 0, nullptr, 0);
     NS_ENSURE_SUCCESS(rv, rv);
 
+    // no longer uses mCachedSelectionNode, so release it.
+    mCachedSelectionNode = nullptr;
+
     // if only trailing <br> remaining remove it
     rv = RemoveRedundantTrailingBR();
     if (NS_FAILED(rv)) {
       return rv;
     }
 
     // detect empty doc
     rv = CreateBogusNodeIfNeeded(selection);