mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-26 12:20:56 +00:00
Bug 1739545 - part 1: Get rid of mozInlineSpellChecker::DidJoinNodes()
and mozInlineSpellChecker::DidSplitNode()
r=m_kato
Currently, they do nothing because they specify empty range to `SpellCheckBetweenNodes()`, and it makes the method does nothing. This is filed as bug 1581714. However, they are not required because `HTMLEditor` notifies `mozInlineSpellChecker` at ending handling the top level edit sub action. https://searchfox.org/mozilla-central/rev/a12c2c2e59c92d8f969d8f3f290ab16919449c9d/editor/libeditor/HTMLEditSubActionHandler.cpp#675 Therefore, these methods are not necessary anymore. Differential Revision: https://phabricator.services.mozilla.com/D130457
This commit is contained in:
parent
1759f51cd0
commit
1034b36c49
@ -688,6 +688,7 @@ class EditorDOMPointBase final {
|
||||
// We're already referring the start of the container or
|
||||
// the offset is invalid since perhaps, the offset was set before
|
||||
// the last DOM tree change.
|
||||
NS_ASSERTION(false, "Failed to rewind offset");
|
||||
return false;
|
||||
}
|
||||
mOffset = mozilla::Some(mOffset.value() - 1);
|
||||
|
@ -6370,7 +6370,9 @@ already_AddRefed<nsRange> HTMLEditor::CreateRangeIncludingAdjuscentWhiteSpaces(
|
||||
}
|
||||
}
|
||||
EditorRawDOMPoint lastRawPoint(endPoint);
|
||||
lastRawPoint.RewindOffset(); // XXX Fail if it's start of the container
|
||||
if (!lastRawPoint.IsStartOfContainer()) {
|
||||
lastRawPoint.RewindOffset();
|
||||
}
|
||||
if (!IsDescendantOfEditorRoot(lastRawPoint.GetChildOrContainerIfDataNode())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -4243,12 +4243,6 @@ already_AddRefed<nsIContent> HTMLEditor::SplitNodeWithTransaction(
|
||||
*this, *aStartOfRightNode.GetContainerAsContent(), *newLeftContent);
|
||||
}
|
||||
|
||||
if (mInlineSpellChecker) {
|
||||
RefPtr<mozInlineSpellChecker> spellChecker = mInlineSpellChecker;
|
||||
spellChecker->DidSplitNode(aStartOfRightNode.GetContainer(),
|
||||
newLeftContent);
|
||||
}
|
||||
|
||||
if (aError.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -4631,11 +4625,6 @@ nsresult HTMLEditor::JoinNodesWithTransaction(nsIContent& aLeftContent,
|
||||
TopLevelEditSubActionDataRef().DidJoinContents(
|
||||
*this, EditorRawDOMPoint(&aRightContent, oldLeftNodeLen));
|
||||
|
||||
if (mInlineSpellChecker) {
|
||||
RefPtr<mozInlineSpellChecker> spellChecker = mInlineSpellChecker;
|
||||
spellChecker->DidJoinNodes(aLeftContent, aRightContent);
|
||||
}
|
||||
|
||||
if (mTextServicesDocument && NS_SUCCEEDED(rv)) {
|
||||
RefPtr<TextServicesDocument> textServicesDocument = mTextServicesDocument;
|
||||
textServicesDocument->DidJoinNodes(aLeftContent, aRightContent);
|
||||
|
@ -40,5 +40,6 @@ skip-if = e10s
|
||||
[test_bug1418629.html]
|
||||
[test_bug1497480.html]
|
||||
[test_bug1602526.html]
|
||||
[test_spellcheck_after_edit.html]
|
||||
[test_spellcheck_after_pressing_navigation_key.html]
|
||||
[test_suggest.html]
|
||||
|
197
editor/spellchecker/tests/test_spellcheck_after_edit.html
Normal file
197
editor/spellchecker/tests/test_spellcheck_after_edit.html
Normal file
@ -0,0 +1,197 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Spellcheck result after edit</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
let {onSpellCheck} =
|
||||
SpecialPowers.Cu.import("resource://testing-common/AsyncSpellCheckTestHelper.jsm", {});
|
||||
|
||||
function waitForTick() {
|
||||
return new Promise(resolve =>
|
||||
SimpleTest.executeSoon(
|
||||
() => requestAnimationFrame(
|
||||
() => requestAnimationFrame(resolve)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
async function waitForOnSpellCheck(
|
||||
aSpellCheckSelection,
|
||||
aEditingHost,
|
||||
aWaitForNumberOfMisspelledWords,
|
||||
aWhen
|
||||
) {
|
||||
info(`Waiting for onSpellCheck (${aWhen})...`);
|
||||
for (let retry = 0; retry < 100; retry++) {
|
||||
await waitForTick();
|
||||
await new Promise(resolve => onSpellCheck(aEditingHost, resolve));
|
||||
if (aWaitForNumberOfMisspelledWords === 0) {
|
||||
if (aSpellCheckSelection.rangeCount === 0) {
|
||||
break;
|
||||
}
|
||||
} else if (aSpellCheckSelection.rangeCount >= aWaitForNumberOfMisspelledWords) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(async () => {
|
||||
/**
|
||||
* test object should have:
|
||||
* init function
|
||||
* @param normalSel The normal selection for the editing host
|
||||
* @param editingHost The editing host of the editor
|
||||
* @return Number of misspelled word in the editor
|
||||
*
|
||||
* run function
|
||||
* @param editingHost The editing host of the editor
|
||||
* @return Expected number of misspelled word in the editor
|
||||
*
|
||||
* check function
|
||||
* @param spellCheckSel The spellcheck selection for the editing host
|
||||
* @param editingHost The editing host of the editor
|
||||
*/
|
||||
for (const test of [
|
||||
{
|
||||
init: (normalSel, editingHost) => {
|
||||
info("Staring to test spellcheck of misspelled word after joining paragraphs");
|
||||
// eslint-disable-next-line no-unsanitized/property
|
||||
editingHost.innerHTML = "<p>It is</p><p>what I want</p>";
|
||||
normalSel.collapse(editingHost.querySelector("p + p").firstChild, 0);
|
||||
return 0;
|
||||
},
|
||||
run: (editingHost) => {
|
||||
document.execCommand("delete");
|
||||
return 0;
|
||||
},
|
||||
check: (spellCheckSel, editingHost) => {
|
||||
is(
|
||||
spellCheckSel.rangeCount,
|
||||
0,
|
||||
"The joined misspelled word shouldn't be marked as misspelled word because caret is in the word"
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
init: (normalSel, editingHost) => {
|
||||
info("Staring to test spellcheck of correct word after joining paragraphs");
|
||||
// eslint-disable-next-line no-unsanitized/property
|
||||
editingHost.innerHTML = "<p>It's beco</p><p>ming nicer</p>";
|
||||
normalSel.collapse(editingHost.querySelector("p + p").firstChild, 0);
|
||||
return 2;
|
||||
},
|
||||
run: (editingHost) => {
|
||||
document.execCommand("delete");
|
||||
return 0;
|
||||
},
|
||||
check: (spellCheckSel, editingHost) => {
|
||||
is(
|
||||
spellCheckSel.rangeCount,
|
||||
0,
|
||||
"There shouldn't be misspelled word after joining separated word anyway"
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
init: (normalSel, editingHost) => {
|
||||
info("Staring to test spellcheck of correct words after splitting a paragraph");
|
||||
// eslint-disable-next-line no-unsanitized/property
|
||||
editingHost.innerHTML = "<p>It iswhat I want</p>";
|
||||
normalSel.collapse(editingHost.querySelector("p").firstChild, "It is".length);
|
||||
return 1;
|
||||
},
|
||||
run: (editingHost) => {
|
||||
document.execCommand("insertParagraph");
|
||||
return 0;
|
||||
},
|
||||
check: (spellCheckSel, editingHost) => {
|
||||
is(
|
||||
spellCheckSel.rangeCount,
|
||||
0,
|
||||
"No word should be marked as misspelled after split"
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
init: (normalSel, editingHost) => {
|
||||
info("Staring to test spellcheck of misspelled words after splitting a paragraph");
|
||||
// eslint-disable-next-line no-unsanitized/property
|
||||
editingHost.innerHTML = "<p>It's becoming nicer</p>";
|
||||
normalSel.collapse(editingHost.querySelector("p").firstChild, "It's beco".length);
|
||||
return 0;
|
||||
},
|
||||
run: (editingHost) => {
|
||||
document.execCommand("insertParagraph");
|
||||
return 1;
|
||||
},
|
||||
check: (spellCheckSel, editingHost) => {
|
||||
is(
|
||||
spellCheckSel.rangeCount,
|
||||
1,
|
||||
"The split word in the first paragraph should be marked as misspelled, but the second paragraph's should be so because of caret is in it"
|
||||
);
|
||||
if (!spellCheckSel.rangeCount) {
|
||||
return;
|
||||
}
|
||||
is(
|
||||
SpecialPowers.unwrap(spellCheckSel.getRangeAt(0).startContainer),
|
||||
editingHost.querySelector("p").firstChild,
|
||||
"First misspelled word should start in the first child of the first <p>"
|
||||
);
|
||||
is(
|
||||
SpecialPowers.unwrap(spellCheckSel.getRangeAt(0).endContainer),
|
||||
editingHost.querySelector("p").firstChild,
|
||||
"First misspelled word should end in the first child of the first <p>"
|
||||
);
|
||||
is(
|
||||
spellCheckSel.getRangeAt(0).startOffset,
|
||||
"It's ".length,
|
||||
"First misspelled word should start after 'It '"
|
||||
);
|
||||
is(
|
||||
spellCheckSel.getRangeAt(0).endOffset,
|
||||
"It's beco".length,
|
||||
"First misspelled word should end by after 'bec'"
|
||||
);
|
||||
},
|
||||
},
|
||||
]) {
|
||||
const editingHost = document.createElement("div");
|
||||
editingHost.setAttribute("contenteditable", "");
|
||||
editingHost.setAttribute("spellcheck", "true");
|
||||
document.body.appendChild(editingHost);
|
||||
editingHost.focus();
|
||||
const editor =
|
||||
SpecialPowers.wrap(window).docShell.editingSession.getEditorForWindow(window);
|
||||
const nsISelectionController = SpecialPowers.Ci.nsISelectionController;
|
||||
const normalSel = editor.selectionController.getSelection(
|
||||
nsISelectionController.SELECTION_NORMAL
|
||||
);
|
||||
const spellCheckSel = editor.selectionController.getSelection(
|
||||
nsISelectionController.SELECTION_SPELLCHECK
|
||||
);
|
||||
const initialMisspelledWords = test.init(normalSel, editingHost);
|
||||
await waitForOnSpellCheck(
|
||||
spellCheckSel, editingHost, initialMisspelledWords, "before edit"
|
||||
);
|
||||
await waitForTick();
|
||||
const expectedMisspelledWords = test.run(editingHost);
|
||||
await waitForOnSpellCheck(
|
||||
spellCheckSel, editingHost, expectedMisspelledWords, "after edit"
|
||||
);
|
||||
test.check(spellCheckSel, editingHost);
|
||||
editingHost.remove();
|
||||
await waitForTick();
|
||||
}
|
||||
SimpleTest.finish();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -36,9 +36,11 @@
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/EditAction.h"
|
||||
#include "mozilla/EditorBase.h"
|
||||
#include "mozilla/EditorDOMPoint.h"
|
||||
#include "mozilla/EditorSpellCheck.h"
|
||||
#include "mozilla/EditorUtils.h"
|
||||
#include "mozilla/EventListenerManager.h"
|
||||
#include "mozilla/HTMLEditor.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/RangeUtils.h"
|
||||
#include "mozilla/Services.h"
|
||||
@ -1012,22 +1014,6 @@ mozInlineSpellChecker::IgnoreWords(const nsTArray<nsString>& aWordsToIgnore) {
|
||||
return ScheduleSpellCheck(std::move(status));
|
||||
}
|
||||
|
||||
void mozInlineSpellChecker::DidSplitNode(nsINode* aExistingRightNode,
|
||||
nsINode* aNewLeftNode) {
|
||||
if (!mIsListeningToEditSubActions) {
|
||||
return;
|
||||
}
|
||||
SpellCheckBetweenNodes(aNewLeftNode, 0, aNewLeftNode, 0);
|
||||
}
|
||||
|
||||
void mozInlineSpellChecker::DidJoinNodes(nsINode& aLeftNode,
|
||||
nsINode& aRightNode) {
|
||||
if (!mIsListeningToEditSubActions) {
|
||||
return;
|
||||
}
|
||||
SpellCheckBetweenNodes(&aRightNode, 0, &aRightNode, 0);
|
||||
}
|
||||
|
||||
// mozInlineSpellChecker::MakeSpellCheckRange
|
||||
//
|
||||
// Given begin and end positions, this function constructs a range as
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "nsIEditorSpellCheck.h"
|
||||
#include "nsIInlineSpellChecker.h"
|
||||
#include "mozInlineSpellWordUtil.h"
|
||||
#include "mozilla/EditorDOMPoint.h"
|
||||
#include "mozilla/Result.h"
|
||||
#include "nsRange.h"
|
||||
#include "nsWeakReference.h"
|
||||
@ -24,6 +25,7 @@ namespace mozilla {
|
||||
class EditorBase;
|
||||
class EditorSpellCheck;
|
||||
enum class EditSubAction : int32_t;
|
||||
enum class JoinNodesDirection;
|
||||
|
||||
namespace dom {
|
||||
class Event;
|
||||
@ -283,11 +285,6 @@ class mozInlineSpellChecker final : public nsIInlineSpellChecker,
|
||||
|
||||
nsresult ResumeCheck(mozilla::UniquePtr<mozInlineSpellStatus>&& aStatus);
|
||||
|
||||
// Those methods are called when mEditorBase splits a node or joins the
|
||||
// given nodes.
|
||||
void DidSplitNode(nsINode* aExistingRightNode, nsINode* aNewLeftNode);
|
||||
void DidJoinNodes(nsINode& aRightNode, nsINode& aLeftNode);
|
||||
|
||||
nsresult SpellCheckAfterEditorChange(mozilla::EditSubAction aEditSubAction,
|
||||
mozilla::dom::Selection& aSelection,
|
||||
nsINode* aPreviousSelectedNode,
|
||||
|
Loading…
x
Reference in New Issue
Block a user