<!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>[209486] 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/209486">209486</a></dd>
<dt>Author</dt> <dd>rniwa@webkit.org</dd>
<dt>Date</dt> <dd>2016-12-07 14:51:54 -0800 (Wed, 07 Dec 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>document.caretRangeFromPoint doesn't retarget the resultant Range correctly.
https://bugs.webkit.org/show_bug.cgi?id=165146

Reviewed by Sam Weinig.

Source/WebCore:

The bug was caused by caretRangeFromPoint not retargeting the resultant Range correctly.
Namely, it's possible for RenderObject::positionForPoint to move across shadow boundary
even if node was identically equal to ancestorInThisScope(node).

Fixed the bug by directly retargeting the range's container node and its offset as done
for elementFromPoint in <a href="http://trac.webkit.org/projects/webkit/changeset/206795">r206795</a>.

Test: fast/shadow-dom/caret-range-from-point-in-shadow-tree.html

* dom/Document.cpp:
(WebCore::Document::caretRangeFromPoint):

LayoutTests:

Added a regression test for caretRangeFromPoint retargeting the result.

* fast/shadow-dom/caret-range-from-point-in-shadow-tree-expected.txt: Added.
* fast/shadow-dom/caret-range-from-point-in-shadow-tree.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoredomDocumentcpp">trunk/Source/WebCore/dom/Document.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastshadowdomcaretrangefrompointinshadowtreeexpectedtxt">trunk/LayoutTests/fast/shadow-dom/caret-range-from-point-in-shadow-tree-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastshadowdomcaretrangefrompointinshadowtreehtml">trunk/LayoutTests/fast/shadow-dom/caret-range-from-point-in-shadow-tree.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (209485 => 209486)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-12-07 22:51:21 UTC (rev 209485)
+++ trunk/LayoutTests/ChangeLog        2016-12-07 22:51:54 UTC (rev 209486)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2016-12-07  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        document.caretRangeFromPoint doesn't retarget the resultant Range correctly.
+        https://bugs.webkit.org/show_bug.cgi?id=165146
+
+        Reviewed by Sam Weinig.
+
+        Added a regression test for caretRangeFromPoint retargeting the result.
+
+        * fast/shadow-dom/caret-range-from-point-in-shadow-tree-expected.txt: Added.
+        * fast/shadow-dom/caret-range-from-point-in-shadow-tree.html: Added.
+
</ins><span class="cx"> 2016-12-07  Antoine Quint  &lt;graouts@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [Modern Media Controls] Entering fullscreen and returning to inline shows fullscreen controls
</span></span></pre></div>
<a id="trunkLayoutTestsfastshadowdomcaretrangefrompointinshadowtreeexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/shadow-dom/caret-range-from-point-in-shadow-tree-expected.txt (0 => 209486)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/shadow-dom/caret-range-from-point-in-shadow-tree-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/shadow-dom/caret-range-from-point-in-shadow-tree-expected.txt        2016-12-07 22:51:54 UTC (rev 209486)
</span><span class="lines">@@ -0,0 +1,102 @@
</span><ins>+bye
+host: &lt;i&gt;&lt;br&gt;&lt;/i&gt;, shadowRoot: &lt;b&gt;&lt;br&gt;&lt;/b&gt;
+range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 1, host.parentNode.offsetTop + 1)
+PASS range.startContainer is host
+PASS range.startOffset is 0
+PASS range.startContainer is range.endContainer
+PASS range.startOffset is range.endOffset
+
+host: &lt;i&gt;&lt;br&gt;&lt;/i&gt;, shadowRoot: &lt;b&gt;&lt;br&gt;&lt;/b&gt;
+range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 100, host.parentNode.offsetTop + 1)
+PASS range.startContainer is host
+PASS range.startOffset is 0
+PASS range.startContainer is range.endContainer
+PASS range.startOffset is range.endOffset
+
+host: &lt;i&gt;&lt;br&gt;&lt;/i&gt;, shadowRoot: hi
+range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 1, host.parentNode.offsetTop + 1)
+PASS range.startContainer is host
+PASS range.startOffset is 0
+PASS range.startContainer is range.endContainer
+PASS range.startOffset is range.endOffset
+
+range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 100, host.parentNode.offsetTop + 1)
+PASS range.startContainer is host
+PASS range.startOffset is 0
+PASS range.startContainer is range.endContainer
+PASS range.startOffset is range.endOffset
+
+host: &lt;i&gt;&lt;br&gt;&lt;/i&gt;, shadowRoot: &lt;slot&gt;&lt;/slot&gt;
+range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 1, host.parentNode.offsetTop + 1)
+PASS range.startContainer is not null
+PASS range.startContainer is host.querySelector(&quot;i&quot;)
+PASS range.startOffset is 0
+PASS range.startContainer is range.endContainer
+PASS range.startOffset is range.endOffset
+
+range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 100, host.parentNode.offsetTop + 1)
+PASS range.startContainer is not null
+PASS range.startContainer is host.querySelector(&quot;i&quot;)
+PASS range.startOffset is 0
+PASS range.startContainer is range.endContainer
+PASS range.startOffset is range.endOffset
+
+host: hi, shadowRoot: &lt;slot&gt;&lt;/slot&gt;
+range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 1, host.parentNode.offsetTop + 1)
+PASS range.startContainer is host.firstChild
+PASS range.startOffset is 0
+PASS range.startContainer is range.endContainer
+PASS range.startOffset is range.endOffset
+
+host: hi, shadowRoot: &lt;slot&gt;&lt;/slot&gt;
+range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 100, host.parentNode.offsetTop + 1)
+PASS range.startContainer is host.firstChild
+PASS range.startOffset is 2
+PASS range.startContainer is range.endContainer
+PASS range.startOffset is range.endOffset
+
+host: bye, shadowRoot: &lt;span id=&quot;inner-host&quot;&gt;&lt;/span&gt;, innerShadowRoot: hi
+range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 1, host.parentNode.offsetTop + 1)
+PASS range.startContainer is host
+PASS range.startOffset is 0
+PASS range.startContainer is range.endContainer
+PASS range.startOffset is range.endOffset
+
+host: bye, shadowRoot: &lt;span id=&quot;inner-host&quot;&gt;&lt;/span&gt;, innerShadowRoot: hi
+range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 100, host.parentNode.offsetTop + 1)
+PASS range.startContainer is host
+PASS range.startOffset is 0
+PASS range.startContainer is range.endContainer
+PASS range.startOffset is range.endOffset
+
+host: bye, shadowRoot: &lt;span id=&quot;inner-host&quot; style=&quot;margin-left: 10px; border-left: solid 1px blue;&quot;&gt;hi&lt;/span&gt;, innerShadowRoot: &lt;slot&gt;&lt;/slot&gt;
+range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 15, host.parentNode.offsetTop + 1)
+PASS range.startContainer is host
+PASS range.startOffset is 0
+PASS range.startContainer is range.endContainer
+PASS range.startOffset is range.endOffset
+
+host: bye, shadowRoot: &lt;span id=&quot;inner-host&quot; style=&quot;margin-left: 10px; border-left: solid 1px blue;&quot;&gt;hi&lt;/span&gt;, innerShadowRoot: &lt;slot&gt;&lt;/slot&gt;
+range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 100, host.parentNode.offsetTop + 1)
+PASS range.startContainer is host
+PASS range.startOffset is 0
+PASS range.startContainer is range.endContainer
+PASS range.startOffset is range.endOffset
+
+host: bye, shadowRoot: &lt;span id=&quot;inner-host&quot; style=&quot;margin-left: 10px; border-left: solid 1px blue;&quot;&gt;&lt;slot&gt;&lt;/slot&gt;&lt;/span&gt;, innerShadowRoot: &lt;slot&gt;&lt;/slot&gt;
+range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 15, host.parentNode.offsetTop + 1)
+PASS range.startContainer is host.firstChild
+PASS range.startOffset is 0
+PASS range.startContainer is range.endContainer
+PASS range.startOffset is range.endOffset
+
+host: bye, shadowRoot: &lt;span id=&quot;inner-host&quot; style=&quot;margin-left: 10px; border-left: solid 1px blue;&quot;&gt;&lt;slot&gt;&lt;/slot&gt;&lt;/span&gt;, innerShadowRoot: &lt;slot&gt;&lt;/slot&gt;
+range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 100, host.parentNode.offsetTop + 1)
+PASS range.startContainer is host.firstChild
+PASS range.startOffset is 3
+PASS range.startContainer is range.endContainer
+PASS range.startOffset is range.endOffset
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastshadowdomcaretrangefrompointinshadowtreehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/shadow-dom/caret-range-from-point-in-shadow-tree.html (0 => 209486)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/shadow-dom/caret-range-from-point-in-shadow-tree.html                                (rev 0)
+++ trunk/LayoutTests/fast/shadow-dom/caret-range-from-point-in-shadow-tree.html        2016-12-07 22:51:54 UTC (rev 209486)
</span><span class="lines">@@ -0,0 +1,149 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;body&gt;
+&lt;div id=&quot;test&quot;&gt;&lt;span&gt;&lt;i&gt;&lt;br&gt;&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;
+&lt;div id=&quot;console&quot;&gt;&lt;/div&gt;
+&lt;script src=&quot;../../resources/js-test.js&quot;&gt;&lt;/script&gt;
+&lt;style&gt;
+#test { padding-left: 10px; border: solid 1px; }
+#test &gt; span { border-left: solid 1px green; }
+&lt;/style&gt;
+&lt;script&gt;
+
+let host = document.querySelector('#test &gt; span');
+let shadowRoot = host.attachShadow({mode: 'closed'});
+shadowRoot.innerHTML = '&lt;b&gt;&lt;br&gt;&lt;/b&gt;';
+
+function markup(node) { return node.innerHTML.replace(/&lt;/g, '&amp;lt;'); }
+
+debug(`host: ${markup(host)}, shadowRoot: ${markup(shadowRoot)}`);
+evalAndLog('range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 1, host.parentNode.offsetTop + 1)');
+shouldBe('range.startContainer', 'host');
+shouldBe('range.startOffset', '0');
+shouldBe('range.startContainer', 'range.endContainer');
+shouldBe('range.startOffset', 'range.endOffset');
+
+debug('')
+debug(`host: ${markup(host)}, shadowRoot: ${markup(shadowRoot)}`);
+evalAndLog('range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 100, host.parentNode.offsetTop + 1)');
+shouldBe('range.startContainer', 'host');
+shouldBe('range.startOffset', '0');
+shouldBe('range.startContainer', 'range.endContainer');
+shouldBe('range.startOffset', 'range.endOffset');
+
+debug('');
+shadowRoot.innerHTML = 'hi';
+debug(`host: ${markup(host)}, shadowRoot: ${markup(shadowRoot)}`);
+evalAndLog('range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 1, host.parentNode.offsetTop + 1)');
+shouldBe('range.startContainer', 'host');
+shouldBe('range.startOffset', '0');
+shouldBe('range.startContainer', 'range.endContainer');
+shouldBe('range.startOffset', 'range.endOffset');
+
+debug('');
+evalAndLog('range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 100, host.parentNode.offsetTop + 1)');
+shouldBe('range.startContainer', 'host');
+shouldBe('range.startOffset', '0');
+shouldBe('range.startContainer', 'range.endContainer');
+shouldBe('range.startOffset', 'range.endOffset');
+
+debug('');
+shadowRoot.innerHTML = '&lt;slot&gt;&lt;/slot&gt;';
+debug(`host: ${markup(host)}, shadowRoot: ${markup(shadowRoot)}`);
+evalAndLog('range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 1, host.parentNode.offsetTop + 1)');
+shouldNotBe('range.startContainer', 'null');
+shouldBe('range.startContainer', 'host.querySelector(&quot;i&quot;)');
+shouldBe('range.startOffset', '0');
+shouldBe('range.startContainer', 'range.endContainer');
+shouldBe('range.startOffset', 'range.endOffset');
+
+debug('');
+evalAndLog('range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 100, host.parentNode.offsetTop + 1)');
+shouldNotBe('range.startContainer', 'null');
+shouldBe('range.startContainer', 'host.querySelector(&quot;i&quot;)');
+shouldBe('range.startOffset', '0');
+shouldBe('range.startContainer', 'range.endContainer');
+shouldBe('range.startOffset', 'range.endOffset');
+
+debug('');
+host.innerHTML = 'hi';
+shadowRoot.innerHTML = '&lt;slot&gt;&lt;/slot&gt;';
+debug(`host: ${markup(host)}, shadowRoot: ${markup(shadowRoot)}`);
+evalAndLog('range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 1, host.parentNode.offsetTop + 1)');
+shouldBe('range.startContainer', 'host.firstChild');
+shouldBe('range.startOffset', '0');
+shouldBe('range.startContainer', 'range.endContainer');
+shouldBe('range.startOffset', 'range.endOffset');
+
+debug('');
+debug(`host: ${markup(host)}, shadowRoot: ${markup(shadowRoot)}`);
+evalAndLog('range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 100, host.parentNode.offsetTop + 1)');
+shouldBe('range.startContainer', 'host.firstChild');
+shouldBe('range.startOffset', '2');
+shouldBe('range.startContainer', 'range.endContainer');
+shouldBe('range.startOffset', 'range.endOffset');
+
+debug('');
+host.innerHTML = 'bye';
+shadowRoot.innerHTML = '&lt;span id=&quot;inner-host&quot;&gt;&lt;/span&gt;';
+let innerHost = shadowRoot.getElementById('inner-host');
+let innerShadowRoot = innerHost.attachShadow({mode: 'closed'});
+innerShadowRoot.innerHTML = 'hi';
+debug(`host: ${markup(host)}, shadowRoot: ${markup(shadowRoot)}, innerShadowRoot: ${markup(innerShadowRoot)}`);
+evalAndLog('range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 1, host.parentNode.offsetTop + 1)');
+shouldBe('range.startContainer', 'host');
+shouldBe('range.startOffset', '0');
+shouldBe('range.startContainer', 'range.endContainer');
+shouldBe('range.startOffset', 'range.endOffset');
+
+debug('');
+debug(`host: ${markup(host)}, shadowRoot: ${markup(shadowRoot)}, innerShadowRoot: ${markup(innerShadowRoot)}`);
+evalAndLog('range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 100, host.parentNode.offsetTop + 1)');
+shouldBe('range.startContainer', 'host');
+shouldBe('range.startOffset', '0');
+shouldBe('range.startContainer', 'range.endContainer');
+shouldBe('range.startOffset', 'range.endOffset');
+
+debug('');
+shadowRoot.innerHTML = '&lt;span id=&quot;inner-host&quot; style=&quot;margin-left: 10px; border-left: solid 1px blue;&quot;&gt;hi&lt;/span&gt;';
+innerHost = shadowRoot.getElementById('inner-host');
+innerShadowRoot = innerHost.attachShadow({mode: 'closed'});
+innerShadowRoot.innerHTML = '&lt;slot&gt;&lt;/slot&gt;';
+debug(`host: ${markup(host)}, shadowRoot: ${markup(shadowRoot)}, innerShadowRoot: ${markup(innerShadowRoot)}`);
+evalAndLog('range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 15, host.parentNode.offsetTop + 1)');
+shouldBe('range.startContainer', 'host');
+shouldBe('range.startOffset', '0');
+shouldBe('range.startContainer', 'range.endContainer');
+shouldBe('range.startOffset', 'range.endOffset');
+
+debug('');
+debug(`host: ${markup(host)}, shadowRoot: ${markup(shadowRoot)}, innerShadowRoot: ${markup(innerShadowRoot)}`);
+evalAndLog('range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 100, host.parentNode.offsetTop + 1)');
+shouldBe('range.startContainer', 'host');
+shouldBe('range.startOffset', '0');
+shouldBe('range.startContainer', 'range.endContainer');
+shouldBe('range.startOffset', 'range.endOffset');
+
+debug('');
+shadowRoot.innerHTML = '&lt;span id=&quot;inner-host&quot; style=&quot;margin-left: 10px; border-left: solid 1px blue;&quot;&gt;&lt;slot&gt;&lt;/slot&gt;&lt;/span&gt;';
+innerHost = shadowRoot.getElementById('inner-host');
+innerShadowRoot = innerHost.attachShadow({mode: 'closed'});
+innerShadowRoot.innerHTML = '&lt;slot&gt;&lt;/slot&gt;';
+debug(`host: ${markup(host)}, shadowRoot: ${markup(shadowRoot)}, innerShadowRoot: ${markup(innerShadowRoot)}`);
+evalAndLog('range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 15, host.parentNode.offsetTop + 1)');
+shouldBe('range.startContainer', 'host.firstChild');
+shouldBe('range.startOffset', '0');
+shouldBe('range.startContainer', 'range.endContainer');
+shouldBe('range.startOffset', 'range.endOffset');
+
+debug('');
+debug(`host: ${markup(host)}, shadowRoot: ${markup(shadowRoot)}, innerShadowRoot: ${markup(innerShadowRoot)}`);
+evalAndLog('range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 100, host.parentNode.offsetTop + 1)');
+shouldBe('range.startContainer', 'host.firstChild');
+shouldBe('range.startOffset', '3');
+shouldBe('range.startContainer', 'range.endContainer');
+shouldBe('range.startOffset', 'range.endOffset');
+
+&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (209485 => 209486)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-12-07 22:51:21 UTC (rev 209485)
+++ trunk/Source/WebCore/ChangeLog        2016-12-07 22:51:54 UTC (rev 209486)
</span><span class="lines">@@ -1,3 +1,22 @@
</span><ins>+2016-12-07  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        document.caretRangeFromPoint doesn't retarget the resultant Range correctly.
+        https://bugs.webkit.org/show_bug.cgi?id=165146
+
+        Reviewed by Sam Weinig.
+
+        The bug was caused by caretRangeFromPoint not retargeting the resultant Range correctly.
+        Namely, it's possible for RenderObject::positionForPoint to move across shadow boundary
+        even if node was identically equal to ancestorInThisScope(node).
+
+        Fixed the bug by directly retargeting the range's container node and its offset as done
+        for elementFromPoint in r206795.
+
+        Test: fast/shadow-dom/caret-range-from-point-in-shadow-tree.html
+
+        * dom/Document.cpp:
+        (WebCore::Document::caretRangeFromPoint):
+
</ins><span class="cx"> 2016-12-07  Antoine Quint  &lt;graouts@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [Modern Media Controls] Entering fullscreen and returning to inline shows fullscreen controls
</span></span></pre></div>
<a id="trunkSourceWebCoredomDocumentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Document.cpp (209485 => 209486)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Document.cpp        2016-12-07 22:51:21 UTC (rev 209485)
+++ trunk/Source/WebCore/dom/Document.cpp        2016-12-07 22:51:54 UTC (rev 209486)
</span><span class="lines">@@ -1420,22 +1420,19 @@
</span><span class="cx">     if (!node)
</span><span class="cx">         return nullptr;
</span><span class="cx"> 
</span><del>-    Node* shadowAncestorNode = ancestorInThisScope(node);
-    if (shadowAncestorNode != node) {
-        unsigned offset = shadowAncestorNode-&gt;computeNodeIndex();
-        ContainerNode* container = shadowAncestorNode-&gt;parentNode();
-        return Range::create(*this, container, offset, container, offset);
-    }
-
</del><span class="cx">     RenderObject* renderer = node-&gt;renderer();
</span><span class="cx">     if (!renderer)
</span><span class="cx">         return nullptr;
</span><del>-    VisiblePosition visiblePosition = renderer-&gt;positionForPoint(localPoint, nullptr);
-    if (visiblePosition.isNull())
</del><ins>+    Position rangeCompliantPosition = renderer-&gt;positionForPoint(localPoint, nullptr).deepEquivalent().parentAnchoredEquivalent();
+    if (rangeCompliantPosition.isNull())
</ins><span class="cx">         return nullptr;
</span><span class="cx"> 
</span><del>-    Position rangeCompliantPosition = visiblePosition.deepEquivalent().parentAnchoredEquivalent();
-    return Range::create(*this, rangeCompliantPosition, rangeCompliantPosition);
</del><ins>+    unsigned offset = rangeCompliantPosition.offsetInContainerNode();
+    node = &amp;retargetToScope(*rangeCompliantPosition.containerNode());
+    if (node != rangeCompliantPosition.containerNode())
+        offset = 0;
+
+    return Range::create(*this, node, offset, node, offset);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Element* Document::scrollingElement()
</span></span></pre>
</div>
</div>

</body>
</html>