<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[205765] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/205765">205765</a></dd>
<dt>Author</dt> <dd>timothy_horton@apple.com</dd>
<dt>Date</dt> <dd>2016-09-09 13:46:23 -0700 (Fri, 09 Sep 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Text replacement candidates don't always overwrite the entire original string
https://bugs.webkit.org/show_bug.cgi?id=161779
&lt;rdar://problem/28033492&gt;

Reviewed by Simon Fraser.

Source/WebCore:

New test: editing/mac/spelling/accept-candidate-replacing-multiple-words.html.

* editing/Editor.cpp:
(WebCore::Editor::contextRangeForCandidateRequest):
Factor contextRangeForCandidateRequest out of the WebKits, into Editor.
This just expands to paragraph boundaries from the cursor.

(WebCore::Editor::selectTextCheckingResult):
Add selectTextCheckingResult, which, given a TextCheckingResult,
selects the range represented by the result's location and length, which
indicate the portion of the context string that the result refers to.
In the case of accepting a candidate, we want to select that range
so that our insertion will overwrite it.

(WebCore::Editor::handleAcceptedCandidate):
Make use of selectTextCheckingResult instead of just assuming that we want
to replace the word to the left of the insertion point.

(WebCore::Editor::stringForCandidateRequest): Deleted.
* editing/Editor.h:

* testing/Internals.cpp:
(WebCore::Internals::handleAcceptedCandidate):
* testing/Internals.h:
* testing/Internals.idl:
Internals' handleAcceptedCandidate assumed (wrongly) that the length
of a TextCheckerResult was the length of the candidate, when really it is
the length of the text that the candidate would replace. Adjust this,
and expose the replacement range to JavaScript, so we can test this.

Source/WebKit/mac:

* WebCoreSupport/WebEditorClient.mm:
(WebEditorClient::requestCandidatesForSelection):
Make use of the shared implementation of contextRangeForCandidateRequest.

Source/WebKit2:

* WebProcess/WebPage/mac/WebPageMac.mm:
(WebKit::WebPage::platformEditorState):
Make use of the shared implementation of contextRangeForCandidateRequest.

LayoutTests:

* editing/mac/spelling/accept-candidate-without-crossing-editing-boundary.html:
* editing/mac/spelling/accept-misspelled-candidate.html:
Adjust tests to send the correct replacement range.

* editing/mac/spelling/accept-candidate-replacing-multiple-words.html:
Add a test that ensures that we will replace the entire string for a
candidate that replaces multiple words.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestseditingmacspellingacceptcandidatewithoutcrossingeditingboundaryhtml">trunk/LayoutTests/editing/mac/spelling/accept-candidate-without-crossing-editing-boundary.html</a></li>
<li><a href="#trunkLayoutTestseditingmacspellingacceptmisspelledcandidatehtml">trunk/LayoutTests/editing/mac/spelling/accept-misspelled-candidate.html</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreeditingEditorcpp">trunk/Source/WebCore/editing/Editor.cpp</a></li>
<li><a href="#trunkSourceWebCoreeditingEditorh">trunk/Source/WebCore/editing/Editor.h</a></li>
<li><a href="#trunkSourceWebCoretestingInternalscpp">trunk/Source/WebCore/testing/Internals.cpp</a></li>
<li><a href="#trunkSourceWebCoretestingInternalsh">trunk/Source/WebCore/testing/Internals.h</a></li>
<li><a href="#trunkSourceWebCoretestingInternalsidl">trunk/Source/WebCore/testing/Internals.idl</a></li>
<li><a href="#trunkSourceWebKitmacChangeLog">trunk/Source/WebKit/mac/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitmacWebCoreSupportWebEditorClientmm">trunk/Source/WebKit/mac/WebCoreSupport/WebEditorClient.mm</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPagemacWebPageMacmm">trunk/Source/WebKit2/WebProcess/WebPage/mac/WebPageMac.mm</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestseditingmacspellingacceptcandidatereplacingmultiplewordsexpectedtxt">trunk/LayoutTests/editing/mac/spelling/accept-candidate-replacing-multiple-words-expected.txt</a></li>
<li><a href="#trunkLayoutTestseditingmacspellingacceptcandidatereplacingmultiplewordshtml">trunk/LayoutTests/editing/mac/spelling/accept-candidate-replacing-multiple-words.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (205764 => 205765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-09-09 20:27:34 UTC (rev 205764)
+++ trunk/LayoutTests/ChangeLog        2016-09-09 20:46:23 UTC (rev 205765)
</span><span class="lines">@@ -1,3 +1,19 @@
</span><ins>+2016-09-09  Tim Horton  &lt;timothy_horton@apple.com&gt;
+
+        Text replacement candidates don't always overwrite the entire original string
+        https://bugs.webkit.org/show_bug.cgi?id=161779
+        &lt;rdar://problem/28033492&gt;
+
+        Reviewed by Simon Fraser.
+
+        * editing/mac/spelling/accept-candidate-without-crossing-editing-boundary.html:
+        * editing/mac/spelling/accept-misspelled-candidate.html:
+        Adjust tests to send the correct replacement range.
+
+        * editing/mac/spelling/accept-candidate-replacing-multiple-words.html:
+        Add a test that ensures that we will replace the entire string for a
+        candidate that replaces multiple words.
+
</ins><span class="cx"> 2016-09-09  Ryan Haddad  &lt;ryanhaddad@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Rebaseline js/dom/global-constructors-attributes.html for mac-wk1  after r205755.
</span></span></pre></div>
<a id="trunkLayoutTestseditingmacspellingacceptcandidatereplacingmultiplewordsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/editing/mac/spelling/accept-candidate-replacing-multiple-words-expected.txt (0 => 205765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/editing/mac/spelling/accept-candidate-replacing-multiple-words-expected.txt                                (rev 0)
+++ trunk/LayoutTests/editing/mac/spelling/accept-candidate-replacing-multiple-words-expected.txt        2016-09-09 20:46:23 UTC (rev 205765)
</span><span class="lines">@@ -0,0 +1,48 @@
</span><ins>+EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document to 0 of DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document
+EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document to 0 of DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document to 0 of DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document toDOMRange:range from 1 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document to 1 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 1 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document to 1 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document toDOMRange:range from 2 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document to 2 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 2 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document to 2 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document toDOMRange:range from 3 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document to 3 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 3 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document to 3 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document toDOMRange:range from 4 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document to 4 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 3 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document to 3 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document toDOMRange:range from 5 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document to 5 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 5 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document to 5 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document toDOMRange:range from 6 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document to 6 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 6 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document to 6 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document toDOMRange:range from 7 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document to 7 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 7 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document to 7 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document toDOMRange:range from 8 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document to 8 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 8 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document to 8 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document toDOMRange:range from 9 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document to 9 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldInsertText:good idea replacingDOMRange:range from 0 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document to 9 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document givenAction:WebViewInsertActionTyped
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document to 0 of DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document toDOMRange:range from 9 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document to 9 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: shouldInsertText:  replacingDOMRange:range from 9 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document to 9 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document givenAction:WebViewInsertActionTyped
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 9 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document to 9 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document toDOMRange:range from 10 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document to 10 of #text &gt; DIV &gt; DIV &gt; BODY &gt; HTML &gt; #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+PASS successfullyParsed is true
+
+TEST COMPLETE
+This test verifies that accepted candidates replace the entire range of the candidate source.
+
+good idea 
</ins></span></pre></div>
<a id="trunkLayoutTestseditingmacspellingacceptcandidatereplacingmultiplewordshtmlfromrev205764trunkLayoutTestseditingmacspellingacceptcandidatewithoutcrossingeditingboundaryhtml"></a>
<div class="copfile"><h4>Copied: trunk/LayoutTests/editing/mac/spelling/accept-candidate-replacing-multiple-words.html (from rev 205764, trunk/LayoutTests/editing/mac/spelling/accept-candidate-without-crossing-editing-boundary.html) (0 => 205765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/editing/mac/spelling/accept-candidate-replacing-multiple-words.html                                (rev 0)
+++ trunk/LayoutTests/editing/mac/spelling/accept-candidate-replacing-multiple-words.html        2016-09-09 20:46:23 UTC (rev 205765)
</span><span class="lines">@@ -0,0 +1,39 @@
</span><ins>+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=../../editing.js&gt;&lt;/script&gt;
+&lt;script src=&quot;../../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script&gt;
+
+function editingTest() {
+    edit = document.getElementById('edit');
+    edit.focus();
+    typeCharacterCommand('g');
+    typeCharacterCommand('o');
+    typeCharacterCommand('o');
+    typeCharacterCommand(' ');
+    typeCharacterCommand('d');
+    typeCharacterCommand('i');
+    typeCharacterCommand('d');
+    typeCharacterCommand('e');
+    typeCharacterCommand('a');
+    
+    if (window.internals)
+        internals.handleAcceptedCandidate(&quot;good idea&quot;, 0, 9);
+
+    if (window.testRunner)
+        testRunner.dumpAsText(true);
+}
+
+&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;p&gt;This test verifies that accepted candidates replace the entire range of the candidate source.&lt;/p&gt;
+&lt;div style=&quot;border:1px solid black;&quot;&gt;
+    &lt;div contenteditable=&quot;true&quot; id=&quot;edit&quot;&gt;&lt;/div&gt;
+&lt;/div&gt;
+&lt;script&gt;
+runEditingTest();
+&lt;/script&gt;
+&lt;script src=&quot;../../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestseditingmacspellingacceptcandidatewithoutcrossingeditingboundaryhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/editing/mac/spelling/accept-candidate-without-crossing-editing-boundary.html (205764 => 205765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/editing/mac/spelling/accept-candidate-without-crossing-editing-boundary.html        2016-09-09 20:27:34 UTC (rev 205764)
+++ trunk/LayoutTests/editing/mac/spelling/accept-candidate-without-crossing-editing-boundary.html        2016-09-09 20:46:23 UTC (rev 205765)
</span><span class="lines">@@ -10,7 +10,7 @@
</span><span class="cx">     typeCharacterCommand('h');
</span><span class="cx">     typeCharacterCommand('a');
</span><span class="cx">     if (window.internals)
</span><del>-        internals.handleAcceptedCandidate(&quot;happy&quot;);
</del><ins>+        internals.handleAcceptedCandidate(&quot;happy&quot;, 0, 2);
</ins><span class="cx"> 
</span><span class="cx">     if (window.testRunner)
</span><span class="cx">         testRunner.dumpAsText(true);
</span></span></pre></div>
<a id="trunkLayoutTestseditingmacspellingacceptmisspelledcandidatehtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/editing/mac/spelling/accept-misspelled-candidate.html (205764 => 205765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/editing/mac/spelling/accept-misspelled-candidate.html        2016-09-09 20:27:34 UTC (rev 205764)
+++ trunk/LayoutTests/editing/mac/spelling/accept-misspelled-candidate.html        2016-09-09 20:46:23 UTC (rev 205765)
</span><span class="lines">@@ -16,7 +16,7 @@
</span><span class="cx">     typeCharacterCommand('a');
</span><span class="cx">     typeCharacterCommand(' ');
</span><span class="cx">     if (window.internals)
</span><del>-        internals.handleAcceptedCandidate(&quot;mesage&quot;);
</del><ins>+        internals.handleAcceptedCandidate(&quot;mesage&quot;, 0, 0);
</ins><span class="cx">     typeCharacterCommand(' ');
</span><span class="cx"> 
</span><span class="cx">     if (window.testRunner)
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (205764 => 205765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-09-09 20:27:34 UTC (rev 205764)
+++ trunk/Source/WebCore/ChangeLog        2016-09-09 20:46:23 UTC (rev 205765)
</span><span class="lines">@@ -1,3 +1,41 @@
</span><ins>+2016-09-09  Tim Horton  &lt;timothy_horton@apple.com&gt;
+
+        Text replacement candidates don't always overwrite the entire original string
+        https://bugs.webkit.org/show_bug.cgi?id=161779
+        &lt;rdar://problem/28033492&gt;
+
+        Reviewed by Simon Fraser.
+
+        New test: editing/mac/spelling/accept-candidate-replacing-multiple-words.html.
+
+        * editing/Editor.cpp:
+        (WebCore::Editor::contextRangeForCandidateRequest):
+        Factor contextRangeForCandidateRequest out of the WebKits, into Editor.
+        This just expands to paragraph boundaries from the cursor.
+
+        (WebCore::Editor::selectTextCheckingResult):
+        Add selectTextCheckingResult, which, given a TextCheckingResult,
+        selects the range represented by the result's location and length, which
+        indicate the portion of the context string that the result refers to.
+        In the case of accepting a candidate, we want to select that range
+        so that our insertion will overwrite it.
+
+        (WebCore::Editor::handleAcceptedCandidate):
+        Make use of selectTextCheckingResult instead of just assuming that we want
+        to replace the word to the left of the insertion point.
+
+        (WebCore::Editor::stringForCandidateRequest): Deleted.
+        * editing/Editor.h:
+
+        * testing/Internals.cpp:
+        (WebCore::Internals::handleAcceptedCandidate):
+        * testing/Internals.h:
+        * testing/Internals.idl:
+        Internals' handleAcceptedCandidate assumed (wrongly) that the length
+        of a TextCheckerResult was the length of the candidate, when really it is
+        the length of the text that the candidate would replace. Adjust this,
+        and expose the replacement range to JavaScript, so we can test this.
+
</ins><span class="cx"> 2016-09-09  Brady Eidson  &lt;beidson@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Soft-link GameController.framework.
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingEditorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/Editor.cpp (205764 => 205765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/Editor.cpp        2016-09-09 20:27:34 UTC (rev 205764)
+++ trunk/Source/WebCore/editing/Editor.cpp        2016-09-09 20:46:23 UTC (rev 205765)
</span><span class="lines">@@ -3610,18 +3610,37 @@
</span><span class="cx"> 
</span><span class="cx">     return String();
</span><span class="cx"> }
</span><ins>+    
+RefPtr&lt;Range&gt; Editor::contextRangeForCandidateRequest() const
+{
+    const VisibleSelection&amp; selection = m_frame.selection().selection();
+    return makeRange(startOfParagraph(selection.visibleStart()), endOfParagraph(selection.visibleEnd()));
+}
+    
+void Editor::selectTextCheckingResult(const TextCheckingResult&amp; result)
+{
+    if (!result.length)
+        return;
+    
+    RefPtr&lt;Range&gt; contextRange = contextRangeForCandidateRequest();
+    if (!contextRange)
+        return;
+    
+    RefPtr&lt;Range&gt; replacementRange = TextIterator::subrange(contextRange.get(), result.location, result.length);
+    if (!replacementRange)
+        return;
+    
+    m_frame.selection().setSelectedRange(replacementRange.get(), UPSTREAM, true);
+}
</ins><span class="cx"> 
</span><span class="cx"> void Editor::handleAcceptedCandidate(TextCheckingResult acceptedCandidate)
</span><span class="cx"> {
</span><span class="cx">     const VisibleSelection&amp; selection = m_frame.selection().selection();
</span><del>-    RefPtr&lt;Range&gt; candidateRange = candidateRangeForSelection(m_frame);
</del><span class="cx">     int candidateLength = acceptedCandidate.length;
</span><span class="cx"> 
</span><span class="cx">     m_isHandlingAcceptedCandidate = true;
</span><span class="cx"> 
</span><del>-    if (candidateWouldReplaceText(selection))
-        m_frame.selection().setSelectedRange(candidateRange.get(), UPSTREAM, true);
-
</del><ins>+    selectTextCheckingResult(acceptedCandidate);
</ins><span class="cx">     insertText(acceptedCandidate.replacement, 0);
</span><span class="cx"> 
</span><span class="cx">     // Some candidates come with a space built in, and we do not need to add another space in that case.
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingEditorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/Editor.h (205764 => 205765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/Editor.h        2016-09-09 20:27:34 UTC (rev 205764)
+++ trunk/Source/WebCore/editing/Editor.h        2016-09-09 20:46:23 UTC (rev 205765)
</span><span class="lines">@@ -466,6 +466,8 @@
</span><span class="cx"> 
</span><span class="cx">     WEBCORE_EXPORT String stringForCandidateRequest() const;
</span><span class="cx">     WEBCORE_EXPORT void handleAcceptedCandidate(TextCheckingResult);
</span><ins>+    WEBCORE_EXPORT RefPtr&lt;Range&gt; contextRangeForCandidateRequest() const;
+    void selectTextCheckingResult(const TextCheckingResult&amp;);
</ins><span class="cx">     bool isHandlingAcceptedCandidate() const { return m_isHandlingAcceptedCandidate; }
</span><span class="cx"> 
</span><span class="cx"> private:
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.cpp (205764 => 205765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.cpp        2016-09-09 20:27:34 UTC (rev 205764)
+++ trunk/Source/WebCore/testing/Internals.cpp        2016-09-09 20:46:23 UTC (rev 205765)
</span><span class="lines">@@ -1684,7 +1684,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Internals::handleAcceptedCandidate(const String&amp; candidate, ExceptionCode&amp;)
</del><ins>+void Internals::handleAcceptedCandidate(const String&amp; candidate, unsigned location, unsigned length, ExceptionCode&amp;)
</ins><span class="cx"> {
</span><span class="cx">     if (!contextDocument() || !contextDocument()-&gt;frame())
</span><span class="cx">         return;
</span><span class="lines">@@ -1691,7 +1691,8 @@
</span><span class="cx"> 
</span><span class="cx">     TextCheckingResult result;
</span><span class="cx">     result.type = TextCheckingTypeNone;
</span><del>-    result.length = candidate.length();
</del><ins>+    result.location = location;
+    result.length = length;
</ins><span class="cx">     result.replacement = candidate;
</span><span class="cx">     contextDocument()-&gt;frame()-&gt;editor().handleAcceptedCandidate(result);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.h (205764 => 205765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.h        2016-09-09 20:27:34 UTC (rev 205764)
+++ trunk/Source/WebCore/testing/Internals.h        2016-09-09 20:46:23 UTC (rev 205765)
</span><span class="lines">@@ -218,7 +218,7 @@
</span><span class="cx">     void setAutomaticTextReplacementEnabled(bool enabled, ExceptionCode&amp;);
</span><span class="cx">     void setAutomaticSpellingCorrectionEnabled(bool enabled, ExceptionCode&amp;);
</span><span class="cx"> 
</span><del>-    void handleAcceptedCandidate(const String&amp; candidate, ExceptionCode&amp;);
</del><ins>+    void handleAcceptedCandidate(const String&amp; candidate, unsigned location, unsigned length, ExceptionCode&amp;);
</ins><span class="cx"> 
</span><span class="cx">     bool isOverwriteModeEnabled(ExceptionCode&amp;);
</span><span class="cx">     void toggleOverwriteModeEnabled(ExceptionCode&amp;);
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalsidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.idl (205764 => 205765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.idl        2016-09-09 20:27:34 UTC (rev 205764)
+++ trunk/Source/WebCore/testing/Internals.idl        2016-09-09 20:46:23 UTC (rev 205765)
</span><span class="lines">@@ -214,7 +214,7 @@
</span><span class="cx">     [RaisesException] void setAutomaticTextReplacementEnabled(boolean enabled);
</span><span class="cx">     [RaisesException] void setAutomaticSpellingCorrectionEnabled(boolean enabled);
</span><span class="cx"> 
</span><del>-    [RaisesException] void handleAcceptedCandidate(DOMString candidate);
</del><ins>+    [RaisesException] void handleAcceptedCandidate(DOMString candidate, unsigned long location, unsigned long length);
</ins><span class="cx"> 
</span><span class="cx">     [RaisesException] boolean isOverwriteModeEnabled();
</span><span class="cx">     [RaisesException] void toggleOverwriteModeEnabled();
</span></span></pre></div>
<a id="trunkSourceWebKitmacChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/mac/ChangeLog (205764 => 205765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/mac/ChangeLog        2016-09-09 20:27:34 UTC (rev 205764)
+++ trunk/Source/WebKit/mac/ChangeLog        2016-09-09 20:46:23 UTC (rev 205765)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2016-09-09  Tim Horton  &lt;timothy_horton@apple.com&gt;
+
+        Text replacement candidates don't always overwrite the entire original string
+        https://bugs.webkit.org/show_bug.cgi?id=161779
+        &lt;rdar://problem/28033492&gt;
+
+        Reviewed by Simon Fraser.
+
+        * WebCoreSupport/WebEditorClient.mm:
+        (WebEditorClient::requestCandidatesForSelection):
+        Make use of the shared implementation of contextRangeForCandidateRequest.
+
</ins><span class="cx"> 2016-09-08  Said Abou-Hallawa  &lt;sabouhallawa@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Move the BitmapImage platform dependent code to a new file named NativeImage[CG|Cairo].cpp
</span></span></pre></div>
<a id="trunkSourceWebKitmacWebCoreSupportWebEditorClientmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/mac/WebCoreSupport/WebEditorClient.mm (205764 => 205765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/mac/WebCoreSupport/WebEditorClient.mm        2016-09-09 20:27:34 UTC (rev 205764)
+++ trunk/Source/WebKit/mac/WebCoreSupport/WebEditorClient.mm        2016-09-09 20:46:23 UTC (rev 205765)
</span><span class="lines">@@ -1163,6 +1163,10 @@
</span><span class="cx">     RefPtr&lt;Range&gt; selectedRange = selection.toNormalizedRange();
</span><span class="cx">     if (!selectedRange)
</span><span class="cx">         return;
</span><ins>+    
+    Frame* frame = core([m_webView _selectedOrMainFrame]);
+    if (!frame)
+        return;
</ins><span class="cx"> 
</span><span class="cx">     m_lastSelectionForRequestedCandidates = selection;
</span><span class="cx"> 
</span><span class="lines">@@ -1175,7 +1179,7 @@
</span><span class="cx">     int lengthToSelectionStart = TextIterator::rangeLength(makeRange(paragraphStart, selectionStart).get());
</span><span class="cx">     int lengthToSelectionEnd = TextIterator::rangeLength(makeRange(paragraphStart, selectionEnd).get());
</span><span class="cx">     m_rangeForCandidates = NSMakeRange(lengthToSelectionStart, lengthToSelectionEnd - lengthToSelectionStart);
</span><del>-    m_paragraphContextForCandidateRequest = plainText(makeRange(paragraphStart, paragraphEnd).get());
</del><ins>+    m_paragraphContextForCandidateRequest = plainText(frame-&gt;editor().contextRangeForCandidateRequest().get());
</ins><span class="cx"> 
</span><span class="cx">     NSTextCheckingTypes checkingTypes = NSTextCheckingTypeSpelling | NSTextCheckingTypeReplacement | NSTextCheckingTypeCorrection;
</span><span class="cx">     auto weakEditor = m_weakPtrFactory.createWeakPtr();
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (205764 => 205765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2016-09-09 20:27:34 UTC (rev 205764)
+++ trunk/Source/WebKit2/ChangeLog        2016-09-09 20:46:23 UTC (rev 205765)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2016-09-09  Tim Horton  &lt;timothy_horton@apple.com&gt;
+
+        Text replacement candidates don't always overwrite the entire original string
+        https://bugs.webkit.org/show_bug.cgi?id=161779
+        &lt;rdar://problem/28033492&gt;
+
+        Reviewed by Simon Fraser.
+
+        * WebProcess/WebPage/mac/WebPageMac.mm:
+        (WebKit::WebPage::platformEditorState):
+        Make use of the shared implementation of contextRangeForCandidateRequest.
+
</ins><span class="cx"> 2016-09-08  Carlos Garcia Campos  &lt;cgarcia@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed. Fix GTK+ build after r205689.
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPagemacWebPageMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/mac/WebPageMac.mm (205764 => 205765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/mac/WebPageMac.mm        2016-09-09 20:27:34 UTC (rev 205764)
+++ trunk/Source/WebKit2/WebProcess/WebPage/mac/WebPageMac.mm        2016-09-09 20:46:23 UTC (rev 205765)
</span><span class="lines">@@ -139,7 +139,7 @@
</span><span class="cx"> 
</span><span class="cx">     postLayoutData.candidateRequestStartPosition = TextIterator::rangeLength(makeRange(paragraphStart, selectionStart).get());
</span><span class="cx">     postLayoutData.selectedTextLength = TextIterator::rangeLength(makeRange(paragraphStart, selectionEnd).get()) - postLayoutData.candidateRequestStartPosition;
</span><del>-    postLayoutData.paragraphContextForCandidateRequest = plainText(makeRange(paragraphStart, paragraphEnd).get());
</del><ins>+    postLayoutData.paragraphContextForCandidateRequest = plainText(frame.editor().contextRangeForCandidateRequest().get());
</ins><span class="cx">     postLayoutData.stringForCandidateRequest = frame.editor().stringForCandidateRequest();
</span><span class="cx"> 
</span><span class="cx">     IntRect rectForSelectionCandidates;
</span></span></pre>
</div>
</div>

</body>
</html>