Added: trunk/LayoutTests/fast/shadow-dom/caret-range-from-point-in-shadow-tree-expected.txt (0 => 209486)
--- 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)
@@ -0,0 +1,102 @@
+bye
+host: <i><br></i>, shadowRoot: <b><br></b>
+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: <i><br></i>, shadowRoot: <b><br></b>
+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: <i><br></i>, 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: <i><br></i>, shadowRoot: <slot></slot>
+range = document.caretRangeFromPoint(host.parentNode.offsetLeft + 1, host.parentNode.offsetTop + 1)
+PASS range.startContainer is not null
+PASS range.startContainer is host.querySelector("i")
+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("i")
+PASS range.startOffset is 0
+PASS range.startContainer is range.endContainer
+PASS range.startOffset is range.endOffset
+
+host: hi, shadowRoot: <slot></slot>
+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: <slot></slot>
+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: <span id="inner-host"></span>, 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: <span id="inner-host"></span>, 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: <span id="inner-host" style="margin-left: 10px; border-left: solid 1px blue;">hi</span>, innerShadowRoot: <slot></slot>
+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: <span id="inner-host" style="margin-left: 10px; border-left: solid 1px blue;">hi</span>, innerShadowRoot: <slot></slot>
+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: <span id="inner-host" style="margin-left: 10px; border-left: solid 1px blue;"><slot></slot></span>, innerShadowRoot: <slot></slot>
+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: <span id="inner-host" style="margin-left: 10px; border-left: solid 1px blue;"><slot></slot></span>, innerShadowRoot: <slot></slot>
+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
+
Added: trunk/LayoutTests/fast/shadow-dom/caret-range-from-point-in-shadow-tree.html (0 => 209486)
--- 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)
@@ -0,0 +1,149 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div id="test"><span><i><br></i></span></div>
+<div id="console"></div>
+<script src=""
+<style>
+#test { padding-left: 10px; border: solid 1px; }
+#test > span { border-left: solid 1px green; }
+</style>
+<script>
+
+let host = document.querySelector('#test > span');
+let shadowRoot = host.attachShadow({mode: 'closed'});
+shadowRoot.innerHTML = '<b><br></b>';
+
+function markup(node) { return node.innerHTML.replace(/</g, '<'); }
+
+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 = '<slot></slot>';
+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("i")');
+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("i")');
+shouldBe('range.startOffset', '0');
+shouldBe('range.startContainer', 'range.endContainer');
+shouldBe('range.startOffset', 'range.endOffset');
+
+debug('');
+host.innerHTML = 'hi';
+shadowRoot.innerHTML = '<slot></slot>';
+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 = '<span id="inner-host"></span>';
+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 = '<span id="inner-host" style="margin-left: 10px; border-left: solid 1px blue;">hi</span>';
+innerHost = shadowRoot.getElementById('inner-host');
+innerShadowRoot = innerHost.attachShadow({mode: 'closed'});
+innerShadowRoot.innerHTML = '<slot></slot>';
+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 = '<span id="inner-host" style="margin-left: 10px; border-left: solid 1px blue;"><slot></slot></span>';
+innerHost = shadowRoot.getElementById('inner-host');
+innerShadowRoot = innerHost.attachShadow({mode: 'closed'});
+innerShadowRoot.innerHTML = '<slot></slot>';
+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');
+
+</script>
+</body>
+</html>
Modified: trunk/Source/WebCore/dom/Document.cpp (209485 => 209486)
--- 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)
@@ -1420,22 +1420,19 @@
if (!node)
return nullptr;
- Node* shadowAncestorNode = ancestorInThisScope(node);
- if (shadowAncestorNode != node) {
- unsigned offset = shadowAncestorNode->computeNodeIndex();
- ContainerNode* container = shadowAncestorNode->parentNode();
- return Range::create(*this, container, offset, container, offset);
- }
-
RenderObject* renderer = node->renderer();
if (!renderer)
return nullptr;
- VisiblePosition visiblePosition = renderer->positionForPoint(localPoint, nullptr);
- if (visiblePosition.isNull())
+ Position rangeCompliantPosition = renderer->positionForPoint(localPoint, nullptr).deepEquivalent().parentAnchoredEquivalent();
+ if (rangeCompliantPosition.isNull())
return nullptr;
- Position rangeCompliantPosition = visiblePosition.deepEquivalent().parentAnchoredEquivalent();
- return Range::create(*this, rangeCompliantPosition, rangeCompliantPosition);
+ unsigned offset = rangeCompliantPosition.offsetInContainerNode();
+ node = &retargetToScope(*rangeCompliantPosition.containerNode());
+ if (node != rangeCompliantPosition.containerNode())
+ offset = 0;
+
+ return Range::create(*this, node, offset, node, offset);
}
Element* Document::scrollingElement()