author | Olli Pettay <Olli.Pettay@helsinki.fi> |
Thu, 03 Aug 2023 09:25:44 +0000 (23 months ago) | |
changeset 674007 | 01837134e47e1685a64e399acb9ef435e1b3a65d |
parent 674006 | ebc036450b323fadbab0feb654346cf19d5720a2 |
child 674008 | 6f55c55c40c70eff3b82d3129f516257598ea115 |
push id | 41076 |
push user | imoraru@mozilla.com |
push date | Thu, 03 Aug 2023 15:59:35 +0000 (23 months ago) |
treeherder | mozilla-central@6f55c55c40c7 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | masayuki |
bugs | 1837268, 1602526 |
milestone | 118.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
|
--- a/editor/libeditor/HTMLEditor.cpp +++ b/editor/libeditor/HTMLEditor.cpp @@ -4542,16 +4542,34 @@ MOZ_CAN_RUN_SCRIPT_BOUNDARY void HTMLEdi return; } NS_WARNING_ASSERTION( NS_SUCCEEDED(rv), "HTMLEditor::OnDocumentModified() failed, but ignored"); } } +MOZ_CAN_RUN_SCRIPT_BOUNDARY void HTMLEditor::CharacterDataChanged( + nsIContent* aContent, const CharacterDataChangeInfo& aInfo) { + if (!mInlineSpellChecker || !aContent->IsEditable() || + !IsInObservedSubtree(aContent) || + GetTopLevelEditSubAction() != EditSubAction::eNone) { + return; + } + + nsIContent* parent = aContent->GetParent(); + if (!parent || !parent->InclusiveDescendantMayNeedSpellchecking(this)) { + return; + } + + RefPtr<nsRange> range = nsRange::Create(aContent); + range->SelectNodesInContainer(parent, aContent, aContent); + DebugOnly<nsresult> rvIgnored = mInlineSpellChecker->SpellCheckRange(range); +} + nsresult HTMLEditor::SelectEntireDocument() { MOZ_ASSERT(IsEditActionDataAvailable()); if (!mInitSucceeded) { return NS_ERROR_NOT_INITIALIZED; } // XXX It's odd to select all of the document body if an contenteditable
--- a/editor/libeditor/HTMLEditor.h +++ b/editor/libeditor/HTMLEditor.h @@ -97,16 +97,17 @@ class HTMLEditor final : public EditorBa NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLEditor, EditorBase) // nsStubMutationObserver overrides NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED + NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED // nsIHTMLEditor methods NS_DECL_NSIHTMLEDITOR // nsIHTMLObjectResizer methods (implemented in HTMLObjectResizer.cpp) NS_DECL_NSIHTMLOBJECTRESIZER // nsIHTMLAbsPosEditor methods (implemented in HTMLAbsPositionEditor.cpp)
--- a/editor/spellchecker/tests/mochitest.ini +++ b/editor/spellchecker/tests/mochitest.ini @@ -37,16 +37,17 @@ skip-if = true [test_bug1365383.html] [test_bug1368544.html] [test_bug1402822.html] [test_bug1418629.html] [test_bug1497480.html] [test_bug1602526.html] [test_bug1761273.html] [test_bug1773802.html] +[test_bug1837268.html] [test_bug366682.html] [test_bug432225.html] [test_bug484181.html] [test_bug596333.html] [test_bug636465.html] [test_bug678842.html] skip-if = http3
new file mode 100644 --- /dev/null +++ b/editor/spellchecker/tests/test_bug1837268.html @@ -0,0 +1,79 @@ +<!DOCTYPE html> +<html> +<head> + <title>Mozilla bug 1837268</title> + <link rel=stylesheet href="/tests/SimpleTest/test.css"> + <script src="/tests/SimpleTest/EventUtils.js"></script> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="/tests/editor/spellchecker/tests/spellcheck.js"></script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1837268">Mozilla Bug 1837268</a> +<p id="display"></p> +<div id="content" style="display: none;"> + +</div> + +<div id="contenteditable" contenteditable=true>aabbcc</div> + +<script> +const { maybeOnSpellCheck } = SpecialPowers.ChromeUtils.importESModule( + "resource://testing-common/AsyncSpellCheckTestHelper.sys.mjs" +); + +SimpleTest.waitForExplicitFinish(); + +function getEditor() { + return SpecialPowers.wrap(window).docShell.editor; +} + +SimpleTest.waitForFocus(async () => { + let contenteditable = document.getElementById("contenteditable"); + contenteditable.addEventListener("beforeinput", (ev) => { + ev.preventDefault(); + let text = contenteditable.textContent; + const sel = window.getSelection(); + let offset = sel.anchorOffset; + switch (ev.inputType) { + case "insertText": + text = text.substring(0, offset) + ev.data + text.substring(offset); + offset += 1; + break; + case "deleteContentBackward": + text = text.substring(0, offset - 1) + text.substring(offset); + offset -= 1; + break; + default: + return; + } + if (contenteditable.firstChild) { + contenteditable.firstChild.nodeValue = text; + } else { + contenteditable.textContent = text; + } + sel.collapse(contenteditable.firstChild ?? contenteditable, offset); + }); + + let misspelledWords = []; + misspelledWords.push("aabbc"); // One c removed. + + contenteditable.focus(); + window.getSelection().collapse(contenteditable.firstChild, contenteditable.firstChild.length); + + // Run spell checker + await new Promise((resolve) => { maybeOnSpellCheck(contenteditable, resolve); }); + + synthesizeKey("KEY_Backspace"); + synthesizeKey(" "); + + await new Promise((resolve) => { maybeOnSpellCheck(contenteditable, resolve); }); + let editor = getEditor(); + // isSpellingCheckOk is defined in spellcheck.js + // eslint-disable-next-line no-undef + ok(isSpellingCheckOk(editor, misspelledWords), "correct word is selected as misspelled"); + + SimpleTest.finish(); +}); +</script> +</body> +</html>