Commit 7809be6a authored by Rakina Zata Amni's avatar Rakina Zata Amni Committed by Commit Bot

Make ShadowRoot.elementsFromPoint always return document element

Currently in some cases, ShadowRoot.elementsFromPoint may not return
the document element even when Document.elementsFromPoint returns the
document element such as when the document element height is shorter than
the hit-tested element's position. This CL fixes it by removing a check
in TreeScope::ElementsFromHitTestResult.

See example live case detailed in this comment:
https://bugs.chromium.org/p/chromium/issues/detail?id=843215#c16

Bug: 843215
Change-Id: I5b774d1a091f3c3f72345c55bca188fad309ba58
Reviewed-on: https://chromium-review.googlesource.com/1131023
Commit-Queue: Rakina Zata Amni <rakina@chromium.org>
Reviewed-by: default avatarHayato Ito <hayato@chromium.org>
Cr-Commit-Position: refs/heads/master@{#574104}
parent 0e26719b
...@@ -29,6 +29,11 @@ function pointInElement(node) { ...@@ -29,6 +29,11 @@ function pointInElement(node) {
const displayValues = ['inline', 'block', 'inline-block']; const displayValues = ['inline', 'block', 'inline-block'];
var container = document.getElementById('container'); var container = document.getElementById('container');
customElements.define('test-element', class extends HTMLElement {
constructor() {
super();
}
});
displayValues.forEach(function (displayValue) { displayValues.forEach(function (displayValue) {
test(function () { test(function () {
...@@ -228,6 +233,21 @@ displayValues.forEach(function (displayValue) { ...@@ -228,6 +233,21 @@ displayValues.forEach(function (displayValue) {
}, 'document.elementsFromPoint must return the shadow host and its ancestors and shadowRoot.elementsFromPoint must return the slot parent of the fallback text and its non-shadow ancestors when the hit-tested text node is a fallback content and the host has display: ' + displayValue); }, 'document.elementsFromPoint must return the shadow host and its ancestors and shadowRoot.elementsFromPoint must return the slot parent of the fallback text and its non-shadow ancestors when the hit-tested text node is a fallback content and the host has display: ' + displayValue);
}); });
test(function () {
container.innerHTML = '';
let host = document.createElement('test-element');
host.style.display = 'block';
let shadow = host.attachShadow({mode: 'closed'});
shadow.innerHTML = '<div style="margin: 2px;">not hit</div>';
let aboveHost = document.createElement("div");
aboveHost.appendChild(host);
container.appendChild(aboveHost);
document.documentElement.style = 'background-attachment: scroll; height: 2px;';
let boundingRect = host.getBoundingClientRect();
assert_array_equals(document.elementsFromPoint(boundingRect.x, boundingRect.y), [host, aboveHost, container, document.body, document.documentElement]);
assert_array_equals(shadow.elementsFromPoint(boundingRect.x, boundingRect.y), [host, aboveHost, container, document.body, document.documentElement]);
}, 'shadowRoot.elementsFromPoint must behave the same with document.elementsFromPoint regarding HTML element');
container.innerHTML = ''; container.innerHTML = '';
</script> </script>
......
...@@ -279,8 +279,8 @@ static bool ShouldAcceptNonElementNode(const Node& node) { ...@@ -279,8 +279,8 @@ static bool ShouldAcceptNonElementNode(const Node& node) {
HeapVector<Member<Element>> TreeScope::ElementsFromHitTestResult( HeapVector<Member<Element>> TreeScope::ElementsFromHitTestResult(
HitTestResult& result) const { HitTestResult& result) const {
DCHECK(RootNode().isConnected());
HeapVector<Member<Element>> elements; HeapVector<Member<Element>> elements;
Node* last_node = nullptr; Node* last_node = nullptr;
for (const auto rect_based_node : result.ListBasedTestResult()) { for (const auto rect_based_node : result.ListBasedTestResult()) {
Node* node = rect_based_node.Get(); Node* node = rect_based_node.Get();
...@@ -297,14 +297,10 @@ HeapVector<Member<Element>> TreeScope::ElementsFromHitTestResult( ...@@ -297,14 +297,10 @@ HeapVector<Member<Element>> TreeScope::ElementsFromHitTestResult(
last_node = node; last_node = node;
} }
} }
if (Element* document_element = GetDocument().documentElement()) {
if (RootNode().IsDocumentNode()) { if (elements.IsEmpty() || elements.back() != document_element)
if (Element* root_element = ToDocument(RootNode()).documentElement()) { elements.push_back(document_element);
if (elements.IsEmpty() || elements.back() != root_element)
elements.push_back(root_element);
}
} }
return elements; return elements;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment