Bug 1368544 - Part 1. Use root node for mozInlineSpellChecker::SpellCheckAfterEditorChange on setText trasaction. r?masayuki draft
authorMakoto Kato <m_kato@ga2.so-net.ne.jp>
Wed, 31 May 2017 14:50:51 +0900
changeset 586906 c6f657259ec5283d224e787263565b18b6c87cce
parent 586049 34ac1a5d6576d6775491c8a882710a1520551da6
child 586907 dfbf4c652b818eb5329c1700558e019b81a66269
push id61576
push userm_kato@ga2.so-net.ne.jp
push dateWed, 31 May 2017 09:00:52 +0000
reviewersmasayuki
bugs1368544
milestone55.0a1
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
@@ -182,22 +182,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)
 {
@@ -216,16 +228,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);