Title: [232530] trunk
Revision
232530
Author
wenson_hs...@apple.com
Date
2018-06-05 18:44:03 -0700 (Tue, 05 Jun 2018)

Log Message

[macOS] Spelling errors in the middle of an inserted paragraph are not displayed
https://bugs.webkit.org/show_bug.cgi?id=185584
<rdar://problem/38676081>

Reviewed by Ryosuke Niwa.

Source/WebCore:

Currently when typing, we only consider the range of adjacent words when determining where to place spelling
correction markers, even though we provide NSSpellChecker with the full context of the sentence (and get back
results encompassing the full range). In macOS Mojave, NSSpellChecker may now return spell checking results that
include correctly spelled words that are misused in the context of the sentence. This means that while typing a
sentence, a different part of the sentence may gain or lose spelling markers as a result.

To support this, WebKit needs to mark or unmark spelling corrections in the full range of the sentence whenever
a full word is typed (since the context of other words within the sentence may have changed, resulting in
different platform spellchecking results). In markMisspellingsAfterTypingToWord, we expand the spell checking
range past the adjacent words so that it encompasses the largest subrange of the full sentence that includes the
start of the typed word, and does not include any position that is under an element with `spellcheck=false`.

This guarantees that we don't erroneously place spelling document markers under elements where spellchecking is
disabled, while allowing for sentence retro corrections when spellchecking is enabled. However, this doesn't
handle the case where an element with spellchecking disabled lies between a sentence retro correction range and
the currently typed word. In the future, we could fix this by refactoring SpellCheckRequest to track a list of
non-contiguous spelling correction ranges — see the FIXME in markMisspellingsAfterTypingToWord for more detail.

Covered by 2 new layout tests, as well as an existing spell-checking test that should now be passing.

Tests: editing/spelling/retro-correction-spelling-markers.html
       editing/spelling/spelling-markers-after-pasting-sentence.html

* editing/Editor.cpp:
(WebCore::Editor::markMisspellingsAfterTypingToWord):
* testing/Internals.h:
* testing/Internals.idl:

Add an internal testing helper to determine whether retro sentence corrections are enabled.

LayoutTests:

Adds 2 new spellchecking tests, and refactors some existing tests.

* editing/spelling/grammar-expected.txt:
* editing/spelling/grammar.html:
* editing/spelling/markers-expected.txt:
* editing/spelling/markers.html:

Tweaked so that these tests pass regardless of whether sentence retro correction is enabled or disabled.

* editing/spelling/retro-correction-spelling-markers-expected.txt: Added.
* editing/spelling/retro-correction-spelling-markers.html: Added.

Tests that typing at the end of a sentence will mark other parts of the sentence as misspellings, if retro
sentence correction is enabled.

* editing/spelling/spelling-changed-text-expected.txt:
* editing/spelling/spelling-changed-text.html:

Tweaked to correctly wait for the marker range to become the expected value.

* editing/spelling/spelling-markers-after-pasting-sentence-expected.txt: Added.
* editing/spelling/spelling-markers-after-pasting-sentence.html: Added.

Tests that after pasting a sentence with misspelled words, those misspelled words will be marked as misspellings.

* platform/ios/TestExpectations:
* platform/mac-wk1/TestExpectations:
* platform/mac-wk2/TestExpectations:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (232529 => 232530)


--- trunk/LayoutTests/ChangeLog	2018-06-06 00:50:54 UTC (rev 232529)
+++ trunk/LayoutTests/ChangeLog	2018-06-06 01:44:03 UTC (rev 232530)
@@ -1,3 +1,40 @@
+2018-06-05  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [macOS] Spelling errors in the middle of an inserted paragraph are not displayed
+        https://bugs.webkit.org/show_bug.cgi?id=185584
+        <rdar://problem/38676081>
+
+        Reviewed by Ryosuke Niwa.
+
+        Adds 2 new spellchecking tests, and refactors some existing tests.
+
+        * editing/spelling/grammar-expected.txt:
+        * editing/spelling/grammar.html:
+        * editing/spelling/markers-expected.txt:
+        * editing/spelling/markers.html:
+
+        Tweaked so that these tests pass regardless of whether sentence retro correction is enabled or disabled.
+
+        * editing/spelling/retro-correction-spelling-markers-expected.txt: Added.
+        * editing/spelling/retro-correction-spelling-markers.html: Added.
+
+        Tests that typing at the end of a sentence will mark other parts of the sentence as misspellings, if retro
+        sentence correction is enabled.
+
+        * editing/spelling/spelling-changed-text-expected.txt:
+        * editing/spelling/spelling-changed-text.html:
+
+        Tweaked to correctly wait for the marker range to become the expected value.
+
+        * editing/spelling/spelling-markers-after-pasting-sentence-expected.txt: Added.
+        * editing/spelling/spelling-markers-after-pasting-sentence.html: Added.
+
+        Tests that after pasting a sentence with misspelled words, those misspelled words will be marked as misspellings.
+
+        * platform/ios/TestExpectations:
+        * platform/mac-wk1/TestExpectations:
+        * platform/mac-wk2/TestExpectations:
+
 2018-06-05  Brent Fulgham  <bfulg...@apple.com>
 
         Adjust compile and runtime flags to match shippable state of features

Modified: trunk/LayoutTests/editing/spelling/grammar-expected.txt (232529 => 232530)


--- trunk/LayoutTests/editing/spelling/grammar-expected.txt	2018-06-06 00:50:54 UTC (rev 232529)
+++ trunk/LayoutTests/editing/spelling/grammar-expected.txt	2018-06-06 01:44:03 UTC (rev 232530)
@@ -3,7 +3,7 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS internals.hasGrammarMarker(7, 1) became true
+PASS hasExpectedSpellingOrGrammarMarkerInRange(7, 1) became true
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/editing/spelling/grammar.html (232529 => 232530)


--- trunk/LayoutTests/editing/spelling/grammar.html	2018-06-06 00:50:54 UTC (rev 232529)
+++ trunk/LayoutTests/editing/spelling/grammar.html	2018-06-06 01:44:03 UTC (rev 232530)
@@ -11,12 +11,18 @@
 <script src="" language="_javascript_" type="text/_javascript_" ></script>
 
 <script>
+function hasExpectedSpellingOrGrammarMarkerInRange(from, length) {
+    if (internals.sentenceRetroCorrectionEnabled)
+        return internals.hasSpellingMarker(from, length);
+    return internals.hasGrammarMarker(from, length);
+}
+
 function editingTest() {
     document.getElementById("root").focus();
     document.execCommand("InsertText", false, "I have a issue.");
 
     if (window.internals) {
-        shouldBecomeEqual('internals.hasGrammarMarker(7, 1)', 'true', function() {
+        shouldBecomeEqual('hasExpectedSpellingOrGrammarMarkerInRange(7, 1)', 'true', function() {
             document.getElementById("root").style.display = "none";
             finishJSTest();
         });

Modified: trunk/LayoutTests/editing/spelling/markers-expected.txt (232529 => 232530)


--- trunk/LayoutTests/editing/spelling/markers-expected.txt	2018-06-06 00:50:54 UTC (rev 232529)
+++ trunk/LayoutTests/editing/spelling/markers-expected.txt	2018-06-06 01:44:03 UTC (rev 232530)
@@ -3,26 +3,26 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-Checking grammar issue on 'I have a issue.'
+Checking for issue on 'I have a issue.'
 PASS internals.markerRangeForNode(element.firstChild, nextMisspellingData.marker, 0) became different from null
 PASS range.toString() is "a"
 
-Checking spelling issue on 'zz.'
+Checking for issue on 'zz.'
 PASS internals.markerRangeForNode(element.firstChild, nextMisspellingData.marker, 0) became different from null
 PASS range.toString() is "zz"
 
-Checking spelling issue on 'orange,zz,apple.'
+Checking for issue on 'orange,zz,apple.'
 PASS internals.markerRangeForNode(element.firstChild, nextMisspellingData.marker, 0) became different from null
-PASS range.toString() is "zz"
+PASS range.toString() is "orange,zz,apple."
 
-Checking grammar issue on 'orange,zz,apple.'
+Checking for issue on 'orange,zz,apple.'
 PASS internals.markerRangeForNode(element.firstChild, nextMisspellingData.marker, 0) became different from null
-PASS range.toString() is "orange,zz,apple."
+PASS range.toString() is "orange,zz,apple"
 
-Checking spelling issue on 'I have a issue.'
+Checking for no other issues on 'I have a issue.'
 PASS internals.markerCountForNode(element.firstChild, oppositeMarker) became 0
 
-Checking grammar issue on 'zz.'
+Checking for no other issues on 'zz.'
 PASS internals.markerCountForNode(element.firstChild, oppositeMarker) became 0
 
 PASS successfullyParsed is true

Modified: trunk/LayoutTests/editing/spelling/markers.html (232529 => 232530)


--- trunk/LayoutTests/editing/spelling/markers.html	2018-06-06 00:50:54 UTC (rev 232529)
+++ trunk/LayoutTests/editing/spelling/markers.html	2018-06-06 01:44:03 UTC (rev 232530)
@@ -52,15 +52,16 @@
 typeText(elementWithGrammarAndSpellingIssue, 'orange,zz,apple.');
 
 var misspellings = [
-    { marker:'grammar',  issue:'a' },
-    { marker:'spelling', issue:'zz' },
-    { marker:'grammar',  issue:'orange,zz,apple.' }
+    { marker: internals.sentenceRetroCorrectionEnabled ? 'spelling' : 'grammar',  issue: 'a' },
+    { marker: 'spelling', issue: 'zz' },
+    { marker: 'grammar',  issue: 'orange,zz,apple.' },
+    { marker: 'spelling',  issue: 'orange,zz,apple' },
 ];
 
 var tests = [
     function() { verifyDesiredMarkers(elementWithGrammarIssue, misspellings.slice(0, 1)) },
     function() { verifyDesiredMarkers(elementWithSpellingIssue, misspellings.slice(1, 2)) },
-    function() { verifyDesiredMarkers(elementWithGrammarAndSpellingIssue, misspellings.slice(1, 3)) },
+    function() { verifyDesiredMarkers(elementWithGrammarAndSpellingIssue, misspellings.slice(2, 4)) },
 
     // Those expect to have only one kind of markers either spelling or grammar.
     function() { verifyUnexpectedMarkers(elementWithGrammarIssue, misspellings.slice(0, 1)) },
@@ -80,7 +81,7 @@
     if (!nextMisspellingData)
         return done();
 
-    debug("Checking " + nextMisspellingData.marker + " issue on '" + element.firstChild.nodeValue + "'");
+    debug("Checking for issue on '" + element.firstChild.nodeValue + "'");
 
     shouldBecomeDifferent('internals.markerRangeForNode(element.firstChild, nextMisspellingData.marker, 0)', "null", function() {
         range = internals.markerRangeForNode(element.firstChild, nextMisspellingData.marker, 0);
@@ -101,7 +102,7 @@
     else if (nextMisspellingData.marker == 'spelling')
         oppositeMarker = 'grammar';
 
-    debug("Checking " + oppositeMarker + " issue on '" + element.firstChild.nodeValue + "'");
+    debug("Checking for no other issues on '" + element.firstChild.nodeValue + "'");
 
     shouldBecomeEqual('internals.markerCountForNode(element.firstChild, oppositeMarker)', '0', function() {
         debug("");

Added: trunk/LayoutTests/editing/spelling/retro-correction-spelling-markers-expected.txt (0 => 232530)


--- trunk/LayoutTests/editing/spelling/retro-correction-spelling-markers-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/editing/spelling/retro-correction-spelling-markers-expected.txt	2018-06-06 01:44:03 UTC (rev 232530)
@@ -0,0 +1,7 @@
+PASS internals.hasSpellingMarker(5, 4) became true
+PASS !internals.sentenceRetroCorrectionEnabled || internals.hasSpellingMarker(10, 2) is true
+PASS !internals.sentenceRetroCorrectionEnabled || internals.hasSpellingMarker(18, 3) is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+It's muhc to late too finish this.

Added: trunk/LayoutTests/editing/spelling/retro-correction-spelling-markers.html (0 => 232530)


--- trunk/LayoutTests/editing/spelling/retro-correction-spelling-markers.html	                        (rev 0)
+++ trunk/LayoutTests/editing/spelling/retro-correction-spelling-markers.html	2018-06-06 01:44:03 UTC (rev 232530)
@@ -0,0 +1,44 @@
+<html>
+<head>
+<script src=""
+<script src=""
+
+<script>
+function runTest() {
+    jsTestIsAsync = true;
+
+    if (window.internals) {
+        internals.settings.setUnifiedTextCheckerEnabled(true);
+        internals.settings.setAsynchronousSpellCheckingEnabled(true);
+        internals.setAutomaticTextReplacementEnabled(false);
+        internals.setAutomaticSpellingCorrectionEnabled(false);
+    }
+
+    document.getElementById("editor").focus();
+    for (const character of "It's muhc to late too finish this.")
+        typeCharacterCommand(character);
+
+    if (!window.testRunner) {
+        document.getElementById("description").innerHTML = `To manually test, verify that there are correction markers
+            below <strong>muhc</strong> as well as <strong>to</strong> and <strong>too</strong> on macOS Mojave.`;
+        return;
+    }
+
+    shouldBecomeEqual("internals.hasSpellingMarker(5, 4)", "true", () => {
+        shouldBeTrue("!internals.sentenceRetroCorrectionEnabled || internals.hasSpellingMarker(10, 2)", "true");
+        shouldBeTrue("!internals.sentenceRetroCorrectionEnabled || internals.hasSpellingMarker(18, 3)", "true");
+        finishJSTest();
+    });
+}
+</script>
+</head>
+
+<body>
+    <div id="description"></div>
+    <div contenteditable style="margin-bottom: 1em; border: 1px orange dashed;" id="editor"></div>
+    <script>
+        runTest();
+    </script>
+    <script src=""
+</body>
+</html>

Modified: trunk/LayoutTests/editing/spelling/spelling-changed-text-expected.txt (232529 => 232530)


--- trunk/LayoutTests/editing/spelling/spelling-changed-text-expected.txt	2018-06-06 00:50:54 UTC (rev 232529)
+++ trunk/LayoutTests/editing/spelling/spelling-changed-text-expected.txt	2018-06-06 01:44:03 UTC (rev 232530)
@@ -5,7 +5,7 @@
 
 PASS internals.markerCountForNode(destination.childNodes[0], "spelling") became different from 0
 PASS window.getSelection().toString() is " Is it broken?"
-PASS spellingMarkerRange.toString() became "wellcome"
+PASS misspellingString() became "wellcome"
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/editing/spelling/spelling-changed-text.html (232529 => 232530)


--- trunk/LayoutTests/editing/spelling/spelling-changed-text.html	2018-06-06 00:50:54 UTC (rev 232529)
+++ trunk/LayoutTests/editing/spelling/spelling-changed-text.html	2018-06-06 01:44:03 UTC (rev 232530)
@@ -16,6 +16,10 @@
     + " The test succeeds when WebKit does not crash and 'wellcome' has spelling marker.");
 
 initSpellTest("destination", "Spell wellcome. Is it broken?", function(textNode) {
+    misspellingString = () => {
+        const range = internals.markerRangeForNode(textNode, "spelling", 0);
+        return range ? range.toString() : null;
+    };
     // Select the text "Is it broken?".
     var deleteRange = document.createRange();
     deleteRange.setStart(textNode, 15);
@@ -25,9 +29,7 @@
     shouldBeEqualToString("window.getSelection().toString()", " Is it broken?");
     // Del key to delete the text "Is it broken?".
     eventSender.keyDown(String.fromCharCode(0x007F), null);
-
-    spellingMarkerRange = internals.markerRangeForNode(textNode, "spelling", 0);
-    shouldBecomeEqualToString("spellingMarkerRange.toString()", "wellcome", function() {
+    shouldBecomeEqualToString("misspellingString()", "wellcome", function() {
         document.getElementById("destination").innerHTML = "";
         finishJSTest();
     });

Added: trunk/LayoutTests/editing/spelling/spelling-markers-after-pasting-sentence-expected.txt (0 => 232530)


--- trunk/LayoutTests/editing/spelling/spelling-markers-after-pasting-sentence-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/editing/spelling/spelling-markers-after-pasting-sentence-expected.txt	2018-06-06 01:44:03 UTC (rev 232530)
@@ -0,0 +1,7 @@
+PASS internals.hasSpellingMarker(0, 5) became true
+PASS internals.hasSpellingMarker(6, 5) is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+Helol wordl this is a test
+Helol wordl this is a test

Added: trunk/LayoutTests/editing/spelling/spelling-markers-after-pasting-sentence.html (0 => 232530)


--- trunk/LayoutTests/editing/spelling/spelling-markers-after-pasting-sentence.html	                        (rev 0)
+++ trunk/LayoutTests/editing/spelling/spelling-markers-after-pasting-sentence.html	2018-06-06 01:44:03 UTC (rev 232530)
@@ -0,0 +1,42 @@
+<html>
+<head>
+<script src=""
+<script src=""
+
+<script>
+function runTest() {
+    jsTestIsAsync = true;
+    getSelection().setBaseAndExtent(source, 0, source, 1);
+
+    if (!window.testRunner) {
+        document.getElementById("description").innerHTML = `To manually test, select the text below and paste into the
+            editable area. There should be misspelling markers below both words.`;
+        return;
+    }
+
+    internals.settings.setUnifiedTextCheckerEnabled(true);
+    internals.settings.setAsynchronousSpellCheckingEnabled(true);
+    internals.setAutomaticTextReplacementEnabled(false);
+    internals.setAutomaticSpellingCorrectionEnabled(false);
+
+    copyCommand();
+    document.getElementById("editor").focus();
+    pasteCommand();
+    shouldBecomeEqual("internals.hasSpellingMarker(0, 5)", "true", () => {
+        shouldBeTrue("internals.hasSpellingMarker(6, 5)", "true");
+        finishJSTest();
+    });
+}
+</script>
+</head>
+
+<body>
+    <div id="description"></div>
+    <div id="source">Helol wordl this is a test</div>
+    <div contenteditable style="margin-bottom: 1em; border: 1px orange dashed;" id="editor"></div>
+    <script>
+        runTest();
+    </script>
+    <script src=""
+</body>
+</html>
\ No newline at end of file

Modified: trunk/LayoutTests/platform/ios/TestExpectations (232529 => 232530)


--- trunk/LayoutTests/platform/ios/TestExpectations	2018-06-06 00:50:54 UTC (rev 232529)
+++ trunk/LayoutTests/platform/ios/TestExpectations	2018-06-06 01:44:03 UTC (rev 232530)
@@ -99,7 +99,9 @@
 fast/css/draggable-region-parser.html
 
 # Spelling and grammar markers are not supported
+editing/spelling/retro-correction-spelling-markers.html [ WontFix ]
 editing/spelling/spelling-marker-includes-hyphen.html [ WontFix ]
+editing/spelling/spelling-markers-after-pasting-sentence.html [ WontFix ]
 editing/spelling/spelling-markers-in-overlapping-lines.html [ WontFix ]
 editing/spelling/spelling-markers-in-overlapping-lines-large-font.html [ WontFix ]
 fast/writing-mode/english-bt-text-with-spelling-marker.html [ WontFix ]

Modified: trunk/LayoutTests/platform/mac-wk1/TestExpectations (232529 => 232530)


--- trunk/LayoutTests/platform/mac-wk1/TestExpectations	2018-06-06 00:50:54 UTC (rev 232529)
+++ trunk/LayoutTests/platform/mac-wk1/TestExpectations	2018-06-06 01:44:03 UTC (rev 232530)
@@ -348,7 +348,6 @@
 
 # <rdar://problem/26399598>
 [ Sierra+ ] editing/spelling/spellcheck-async.html [ Failure ]
-[ Sierra+ ] editing/spelling/markers.html [ Failure ]
 [ Sierra+ ] editing/spelling/spelling-unified-emulation.html [ Failure ]
 
 # <rdar://problem/26050923> The result is probably still a pass, but we don't have a way

Modified: trunk/LayoutTests/platform/mac-wk2/TestExpectations (232529 => 232530)


--- trunk/LayoutTests/platform/mac-wk2/TestExpectations	2018-06-06 00:50:54 UTC (rev 232529)
+++ trunk/LayoutTests/platform/mac-wk2/TestExpectations	2018-06-06 01:44:03 UTC (rev 232530)
@@ -177,6 +177,8 @@
 webkit.org/b/105616 editing/spelling/spelling-with-whitespace-selection.html
 webkit.org/b/105616 editing/spelling/grammar.html
 webkit.org/b/105616 editing/spelling/markers.html
+webkit.org/b/105616 editing/spelling/retro-correction-spelling-markers.html
+webkit.org/b/105616 editing/spelling/spelling-markers-after-pasting-sentence.html
 webkit.org/b/105616 editing/mac/spelling/autocorrection-delete.html [ Failure ]
 webkit.org/b/105616 editing/mac/spelling/autocorrection-removing-underline-after-paste.html [ Failure ]
 webkit.org/b/105616 editing/mac/spelling/autocorrection-removing-underline.html [ Failure ]

Modified: trunk/Source/WebCore/ChangeLog (232529 => 232530)


--- trunk/Source/WebCore/ChangeLog	2018-06-06 00:50:54 UTC (rev 232529)
+++ trunk/Source/WebCore/ChangeLog	2018-06-06 01:44:03 UTC (rev 232530)
@@ -1,3 +1,41 @@
+2018-06-05  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [macOS] Spelling errors in the middle of an inserted paragraph are not displayed
+        https://bugs.webkit.org/show_bug.cgi?id=185584
+        <rdar://problem/38676081>
+
+        Reviewed by Ryosuke Niwa.
+
+        Currently when typing, we only consider the range of adjacent words when determining where to place spelling
+        correction markers, even though we provide NSSpellChecker with the full context of the sentence (and get back
+        results encompassing the full range). In macOS Mojave, NSSpellChecker may now return spell checking results that
+        include correctly spelled words that are misused in the context of the sentence. This means that while typing a
+        sentence, a different part of the sentence may gain or lose spelling markers as a result.
+
+        To support this, WebKit needs to mark or unmark spelling corrections in the full range of the sentence whenever
+        a full word is typed (since the context of other words within the sentence may have changed, resulting in
+        different platform spellchecking results). In markMisspellingsAfterTypingToWord, we expand the spell checking
+        range past the adjacent words so that it encompasses the largest subrange of the full sentence that includes the
+        start of the typed word, and does not include any position that is under an element with `spellcheck=false`.
+
+        This guarantees that we don't erroneously place spelling document markers under elements where spellchecking is
+        disabled, while allowing for sentence retro corrections when spellchecking is enabled. However, this doesn't
+        handle the case where an element with spellchecking disabled lies between a sentence retro correction range and
+        the currently typed word. In the future, we could fix this by refactoring SpellCheckRequest to track a list of
+        non-contiguous spelling correction ranges — see the FIXME in markMisspellingsAfterTypingToWord for more detail.
+
+        Covered by 2 new layout tests, as well as an existing spell-checking test that should now be passing.
+
+        Tests: editing/spelling/retro-correction-spelling-markers.html
+               editing/spelling/spelling-markers-after-pasting-sentence.html
+
+        * editing/Editor.cpp:
+        (WebCore::Editor::markMisspellingsAfterTypingToWord):
+        * testing/Internals.h:
+        * testing/Internals.idl:
+
+        Add an internal testing helper to determine whether retro sentence corrections are enabled.
+
 2018-06-05  Darin Adler  <da...@apple.com>
 
         [Cocoa] Retire DispatchPtr, and add more move semantics and simpler #ifs to other smart pointers

Modified: trunk/Source/WebCore/editing/Editor.cpp (232529 => 232530)


--- trunk/Source/WebCore/editing/Editor.cpp	2018-06-06 00:50:54 UTC (rev 232529)
+++ trunk/Source/WebCore/editing/Editor.cpp	2018-06-06 01:44:03 UTC (rev 232530)
@@ -2371,12 +2371,59 @@
         if (isGrammarCheckingEnabled())
             textCheckingOptions |= TextCheckingTypeGrammar;
 
-        VisibleSelection adjacentWords = VisibleSelection(startOfWord(wordStart, LeftWordIfOnBoundary), endOfWord(wordStart, RightWordIfOnBoundary));
-        if (textCheckingOptions & TextCheckingTypeGrammar) {
-            VisibleSelection selectedSentence = VisibleSelection(startOfSentence(wordStart), endOfSentence(wordStart));
-            markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, adjacentWords.toNormalizedRange().get(), selectedSentence.toNormalizedRange().get());
-        } else
-            markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, adjacentWords.toNormalizedRange().get(), adjacentWords.toNormalizedRange().get());
+        auto sentenceStart = startOfSentence(wordStart);
+        auto sentenceEnd = endOfSentence(wordStart);
+        VisibleSelection fullSentence(sentenceStart, sentenceEnd);
+        auto fullSentenceRange = fullSentence.toNormalizedRange();
+        if (!fullSentenceRange)
+            return;
+
+        auto spellCheckingStart = wordStart;
+        auto spellCheckingEnd = wordStart;
+
+        // FIXME: The following logic doesn't handle adding spelling markers due to retro sentence corrections when an
+        // incorrectly spelled range is separated from the start of the current word by a text node inside an element
+        // with spellcheck disabled. To fix this, we need to refactor markAllMisspellingsAndBadGrammarInRanges so that
+        // it can handle a list of spelling ranges, alongside the grammar range.
+        while (sentenceStart < spellCheckingStart) {
+            auto previousPosition = spellCheckingStart.previous(CannotCrossEditingBoundary);
+            if (previousPosition.isNull() || previousPosition == spellCheckingStart)
+                break;
+
+            auto* container = previousPosition.deepEquivalent().downstream().containerNode();
+            if (auto* containerElement = is<Element>(container) ? downcast<Element>(container) : container->parentElement()) {
+                if (!containerElement->isSpellCheckingEnabled())
+                    break;
+            }
+
+            spellCheckingStart = previousPosition;
+        }
+
+        while (spellCheckingEnd < sentenceEnd) {
+            auto nextPosition = spellCheckingEnd.next(CannotCrossEditingBoundary);
+            if (nextPosition.isNull() || nextPosition == spellCheckingEnd)
+                break;
+
+            auto* container = nextPosition.deepEquivalent().upstream().containerNode();
+            if (auto* containerElement = is<Element>(container) ? downcast<Element>(container) : container->parentElement()) {
+                if (!containerElement->isSpellCheckingEnabled())
+                    break;
+            }
+
+            spellCheckingEnd = nextPosition;
+        }
+
+        auto spellCheckingRange = VisibleSelection(spellCheckingStart, spellCheckingEnd).toNormalizedRange();
+        if (!spellCheckingRange)
+            return;
+
+        // The spelling and grammar markers in these ranges are recomputed. This is because typing a word may
+        // cause any other part of the current sentence to lose or gain spelling correction markers, due to
+        // sentence retro correction. As such, we expand the spell checking range to encompass as much of the
+        // full sentence as we can, respecting boundaries where spellchecking is disabled.
+        fullSentenceRange->ownerDocument().markers().removeMarkers(fullSentenceRange.get(), DocumentMarker::Grammar);
+        spellCheckingRange->ownerDocument().markers().removeMarkers(spellCheckingRange.get(), DocumentMarker::Spelling);
+        markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, spellCheckingRange.get(), fullSentenceRange.get());
         return;
     }
 

Modified: trunk/Source/WebCore/testing/Internals.h (232529 => 232530)


--- trunk/Source/WebCore/testing/Internals.h	2018-06-06 00:50:54 UTC (rev 232529)
+++ trunk/Source/WebCore/testing/Internals.h	2018-06-06 01:44:03 UTC (rev 232530)
@@ -286,6 +286,14 @@
 
     void updateEditorUINowIfScheduled();
 
+    bool sentenceRetroCorrectionEnabled() const
+    {
+#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+        return true;
+#else
+        return false;
+#endif
+    }
     bool hasSpellingMarker(int from, int length);
     bool hasGrammarMarker(int from, int length);
     bool hasAutocorrectedMarker(int from, int length);

Modified: trunk/Source/WebCore/testing/Internals.idl (232529 => 232530)


--- trunk/Source/WebCore/testing/Internals.idl	2018-06-06 00:50:54 UTC (rev 232529)
+++ trunk/Source/WebCore/testing/Internals.idl	2018-06-06 01:44:03 UTC (rev 232530)
@@ -258,6 +258,7 @@
 
     void updateEditorUINowIfScheduled();
 
+    readonly attribute boolean sentenceRetroCorrectionEnabled;
     boolean hasSpellingMarker(long from, long length);
     boolean hasGrammarMarker(long from, long length);
     boolean hasAutocorrectedMarker(long from, long length);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to