forked from WebKit/WebKit-http
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ShadowRoot interface should have elementFromPoint
https://bugs.webkit.org/show_bug.cgi?id=162882 Reviewed by Chris Dumez. Source/WebCore: Add elementFromPoint to ShadowRoot's prototype as specified at: https://www.w3.org/TR/shadow-dom/#extensions-to-the-documentorshadowroot-mixin with changes proposed at w3c/csswg-drafts#556 Added TreeScope::retargetToScope which implements This patch also factors DocumentOrShadowRoot.idl out of Document and ShadowRoot interfaces to better match the latest DOM specification: https://dom.spec.whatwg.org/#mixin-documentorshadowroot Test: fast/shadow-dom/Document-prototype-elementFromPoint.html * CMakeLists.txt: * DerivedSources.make: * WebCore.xcodeproj/project.pbxproj: * dom/Document.cpp: (WebCore::Document::nodeFromPoint): Moved to TreeScope. (WebCore::Document::elementFromPoint): Moved to TreeScope. * dom/Document.h: * dom/Document.idl: Moved elementFromPoint and activeElement to DocumentOrShadowRoot.idl. * dom/DocumentOrShadowRoot.idl: Added. * dom/EventPath.cpp: (WebCore::RelatedNodeRetargeter::checkConsistency): Use newly added TreeScope::retargetToScope. * dom/ShadowRoot.idl: Moved activeElement to DocumentOrShadowRoot.idl. * dom/TreeScope.cpp: (WebCore::TreeScope::retargetToScope): Added. Implements https://dom.spec.whatwg.org/#retarget efficiently. Instead of checking whether A (node) is a shadow-including inclusive ancestor of B (this scope) at each parent, find the lowest ancestor which contains both A and B, and return the self-inclusive ancestor of B in that tree. To find the lowest common ancestor in O(n), traverse all ancestors of A and B separately and do a top-down traversal. The last tree scope in which A's ancestor and B's ancestor match is the lowest common ancestor. (WebCore::TreeScope::nodeFromPoint): Moved from Document. (WebCore::TreeScope::elementFromPoint): Moved from Document. Use retargetToScope and parentInComposedTree instead of parentNode and ancestorInThisScope to match the semantics proposed in w3c/csswg-drafts#556 * dom/TreeScope.h: LayoutTests: Add a W3C style testharness.js test for elementFromPoint on ShadowRoot. * fast/shadow-dom/DocumentOrShadowRoot-prototype-elementFromPoint-expected.txt: Added. * fast/shadow-dom/DocumentOrShadowRoot-prototype-elementFromPoint.html: Added. git-svn-id: http://svn.webkit.org/repository/webkit/trunk@206795 268f45cc-cd09-0410-ab3c-d52691b4dbfc
- Loading branch information
rniwa@webkit.org
committed
Oct 4, 2016
1 parent
ade1810
commit 42a0769
Showing
16 changed files
with
433 additions
and
66 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
35 changes: 35 additions & 0 deletions
35
LayoutTests/fast/shadow-dom/DocumentOrShadowRoot-prototype-elementFromPoint-expected.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
|
||
PASS document.elementFromPoint must return the shadow host of the hit-tested text node when the host has display: inline | ||
PASS document.elementFromPoint must return the shadow host of the hit-tested text node when the host has display: block | ||
PASS document.elementFromPoint must return the shadow host of the hit-tested text node when the host has display: inline-block | ||
PASS document.elementFromPoint must return the shadow host of the hit-tested text node assigned to a slot when the host has display: inline | ||
PASS document.elementFromPoint must return the shadow host of the hit-tested text node assigned to a slot when the host has display: block | ||
PASS document.elementFromPoint must return the shadow host of the hit-tested text node assigned to a slot when the host has display: inline-block | ||
PASS document.elementFromPoint must return the element assigned to a slot when the shadow host of the slot has display: inline | ||
PASS document.elementFromPoint must return the element assigned to a slot when the shadow host of the slot has display: block | ||
PASS document.elementFromPoint must return the element assigned to a slot when the shadow host of the slot has display: inline-block | ||
PASS shadowRoot.elementFromPoint must return the element parent of the hit-tested text node under the point when the shadow host has display: inline | ||
PASS shadowRoot.elementFromPoint must return the element parent of the hit-tested text node under the point when the shadow host has display: block | ||
PASS shadowRoot.elementFromPoint must return the element parent of the hit-tested text node under the point when the shadow host has display: inline-block | ||
PASS shadowRoot.elementFromPoint must return the shadow host when the hit-tested text node is a direct child of the root and the host has display: inline | ||
PASS shadowRoot.elementFromPoint must return the shadow host when the hit-tested text node is a direct child of the root and the host has display: block | ||
PASS shadowRoot.elementFromPoint must return the shadow host when the hit-tested text node is a direct child of the root and the host has display: inline-block | ||
PASS shadowRoot.elementFromPoint must return the slot to which the hit-tested text node is assigned when its host has display: inline | ||
PASS shadowRoot.elementFromPoint must return the slot to which the hit-tested text node is assigned when its host has display: block | ||
PASS shadowRoot.elementFromPoint must return the slot to which the hit-tested text node is assigned when its host has display: inline-block | ||
PASS shadowRoot.elementFromPoint must return the element parent of the hit-tested text node assigned to a slot in the shadow tree when its host has display: inline | ||
PASS shadowRoot.elementFromPoint must return the element parent of the hit-tested text node assigned to a slot in the shadow tree when its host has display: block | ||
PASS shadowRoot.elementFromPoint must return the element parent of the hit-tested text node assigned to a slot in the shadow tree when its host has display: inline-block | ||
PASS shadowRoot.elementFromPoint must return a child element assigned to a slot when the hit-tested text node is assigned to the shadow tree of the child element and the outer shadow host has display: inline | ||
PASS shadowRoot.elementFromPoint must return a child element assigned to a slot when the hit-tested text node is assigned to the shadow tree of the child element and the outer shadow host has display: block | ||
PASS shadowRoot.elementFromPoint must return a child element assigned to a slot when the hit-tested text node is assigned to the shadow tree of the child element and the outer shadow host has display: inline-block | ||
PASS shadowRoot.elementFromPoint must return a child element assigned to a slot when the hit-tested text node is assigned to a slot in the shadow tree of the child element and the outer shadow host has display: inline | ||
PASS shadowRoot.elementFromPoint must return a child element assigned to a slot when the hit-tested text node is assigned to a slot in the shadow tree of the child element and the outer shadow host has display: block | ||
PASS shadowRoot.elementFromPoint must return a child element assigned to a slot when the hit-tested text node is assigned to a slot in the shadow tree of the child element and the outer shadow host has display: inline-block | ||
PASS shadowRoot.elementFromPoint must return a child element with its own shadow tree assigned to a slot when the hit-tested text node is its direct child and the outer shadow host has display: inline | ||
PASS shadowRoot.elementFromPoint must return a child element with its own shadow tree assigned to a slot when the hit-tested text node is its direct child and the outer shadow host has display: block | ||
PASS shadowRoot.elementFromPoint must return a child element with its own shadow tree assigned to a slot when the hit-tested text node is its direct child and the outer shadow host has display: inline-block | ||
PASS shadowRoot.elementFromPoint must return a child element with its own shadow tree assigned to a slot when the hit-tested text node is a child of another element and the outer shadow host has display: inline | ||
PASS shadowRoot.elementFromPoint must return a child element with its own shadow tree assigned to a slot when the hit-tested text node is a child of another element and the outer shadow host has display: block | ||
PASS shadowRoot.elementFromPoint must return a child element with its own shadow tree assigned to a slot when the hit-tested text node is a child of another element and the outer shadow host has display: inline-block | ||
|
204 changes: 204 additions & 0 deletions
204
LayoutTests/fast/shadow-dom/DocumentOrShadowRoot-prototype-elementFromPoint.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<title>Shadow DOM and CSSOM View: Document.prototype.elementFromPoint</title> | ||
<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"> | ||
<meta name="assert" content="DocumentOrShadowRoot must have elementFromPoint and must return retarget the result against the context object."> | ||
<link rel="help" href="https://www.w3.org/TR/cssom-view-1/#dom-document-elementfrompoint"> | ||
<link rel="help" href="https://www.w3.org/TR/shadow-dom/#extensions-to-the-documentorshadowroot-mixin"> | ||
<script src="../../resources/testharness.js"></script> | ||
<script src="../../resources/testharnessreport.js"></script> | ||
</head> | ||
<body> | ||
<div id="container"></div> | ||
<style> | ||
|
||
container { position: relative; } | ||
test-element { display: block; width: 100px; height: 100px; } | ||
|
||
</style> | ||
<script> | ||
|
||
function pointInElement(node) { | ||
let x = 5; | ||
let y = 5; | ||
do { | ||
x += node.offsetLeft; | ||
y += node.offsetTop; | ||
node = node.offsetParent; | ||
} while (node); | ||
return [x, y]; | ||
} | ||
|
||
const displayValues = ['inline', 'block', 'inline-block']; | ||
var container = document.getElementById('container'); | ||
|
||
displayValues.forEach(function (displayValue) { | ||
test(function () { | ||
container.innerHTML = ''; | ||
let host = document.createElement('test-element'); | ||
host.style.display = displayValue; | ||
let shadow = host.attachShadow({mode: 'closed'}); | ||
shadow.innerHTML = 'hello'; | ||
container.appendChild(host); | ||
assert_equals(document.elementFromPoint(...pointInElement(host)), host); | ||
}, 'document.elementFromPoint must return the shadow host of the hit-tested text node when the host has display: ' + displayValue); | ||
}); | ||
|
||
displayValues.forEach(function (displayValue) { | ||
test(function () { | ||
container.innerHTML = ''; | ||
let host = document.createElement('test-element'); | ||
host.style.display = displayValue; | ||
let shadow = host.attachShadow({mode: 'closed'}); | ||
shadow.innerHTML = '<slot></slot>'; | ||
host.innerHTML = 'text'; | ||
container.appendChild(host); | ||
assert_equals(document.elementFromPoint(...pointInElement(host)), host); | ||
}, 'document.elementFromPoint must return the shadow host of the hit-tested text node assigned to a slot when the host has display: ' + displayValue); | ||
}); | ||
|
||
displayValues.forEach(function (displayValue) { | ||
test(function () { | ||
container.innerHTML = ''; | ||
let host = document.createElement('test-element'); | ||
host.style.display = displayValue; | ||
let shadow = host.attachShadow({mode: 'closed'}); | ||
shadow.innerHTML = '<slot></slot>'; | ||
host.innerHTML = '<span>text</span>'; | ||
container.appendChild(host); | ||
assert_equals(document.elementFromPoint(...pointInElement(host)), host.querySelector('span')); | ||
}, 'document.elementFromPoint must return the element assigned to a slot when the shadow host of the slot has display: ' + displayValue); | ||
}); | ||
|
||
displayValues.forEach(function (displayValue) { | ||
test(function () { | ||
container.innerHTML = ''; | ||
let host = document.createElement('test-element'); | ||
host.style.display = displayValue; | ||
let shadow = host.attachShadow({mode: 'closed'}); | ||
shadow.innerHTML = '<span>text</span>'; | ||
container.appendChild(host); | ||
assert_equals(shadow.elementFromPoint(...pointInElement(shadow.querySelector('span'))), shadow.querySelector('span')); | ||
}, 'shadowRoot.elementFromPoint must return the element parent of the hit-tested text node under the point when the shadow host has display: ' + displayValue); | ||
}); | ||
|
||
displayValues.forEach(function (displayValue) { | ||
test(function () { | ||
container.innerHTML = ''; | ||
let host = document.createElement('test-element'); | ||
host.style.display = displayValue; | ||
let shadow = host.attachShadow({mode: 'closed'}); | ||
shadow.innerHTML = 'text'; | ||
container.appendChild(host); | ||
assert_equals(shadow.elementFromPoint(...pointInElement(host)), host); | ||
}, 'shadowRoot.elementFromPoint must return the shadow host when the hit-tested text node is a direct child of the root and the host has display: ' + displayValue); | ||
}); | ||
|
||
displayValues.forEach(function (displayValue) { | ||
test(function () { | ||
container.innerHTML = ''; | ||
let host = document.createElement('test-element'); | ||
host.style.display = displayValue; | ||
let shadow = host.attachShadow({mode: 'closed'}); | ||
shadow.innerHTML = '<slot></slot>'; | ||
host.innerHTML = 'hello'; | ||
container.appendChild(host); | ||
assert_equals(shadow.elementFromPoint(...pointInElement(host)), shadow.querySelector('slot')); | ||
}, 'shadowRoot.elementFromPoint must return the slot to which the hit-tested text node is assigned when its host has display: ' + displayValue); | ||
}); | ||
|
||
displayValues.forEach(function (displayValue) { | ||
test(function () { | ||
container.innerHTML = ''; | ||
let host = document.createElement('test-element'); | ||
host.style.display = displayValue; | ||
let shadow = host.attachShadow({mode: 'closed'}); | ||
shadow.innerHTML = '<slot></slot>'; | ||
host.innerHTML = '<span>hello</span>'; | ||
container.appendChild(host); | ||
assert_equals(shadow.elementFromPoint(...pointInElement(host)), host.querySelector('span')); | ||
}, 'shadowRoot.elementFromPoint must return the element parent of the hit-tested text node assigned to a slot in the shadow tree when its host has display: ' + displayValue); | ||
}); | ||
|
||
displayValues.forEach(function (displayValue) { | ||
test(function () { | ||
container.innerHTML = ''; | ||
let host = document.createElement('test-element'); | ||
host.style.display = displayValue; | ||
let shadow = host.attachShadow({mode: 'closed'}); | ||
shadow.innerHTML = '<slot></slot>'; | ||
host.innerHTML = '<inner-host>hello</inner-host>'; | ||
container.appendChild(host); | ||
|
||
let innerHost = host.querySelector('inner-host'); | ||
let innerShadow = innerHost.attachShadow({mode: 'closed'}); | ||
innerShadow.innerHTML = '<slot></slot>'; | ||
|
||
assert_equals(shadow.elementFromPoint(...pointInElement(host)), innerHost); | ||
}, 'shadowRoot.elementFromPoint must return a child element assigned to a slot' | ||
+ ' when the hit-tested text node is assigned to the shadow tree of the child element and the outer shadow host has display: ' + displayValue); | ||
}); | ||
|
||
displayValues.forEach(function (displayValue) { | ||
test(function () { | ||
container.innerHTML = ''; | ||
let host = document.createElement('test-element'); | ||
host.style.display = displayValue; | ||
let shadow = host.attachShadow({mode: 'closed'}); | ||
shadow.innerHTML = '<slot></slot>'; | ||
host.innerHTML = '<inner-host>hello</inner-host>'; | ||
container.appendChild(host); | ||
|
||
let innerHost = host.querySelector('inner-host'); | ||
let innerShadow = innerHost.attachShadow({mode: 'closed'}); | ||
innerShadow.innerHTML = '<slot></slot>'; | ||
|
||
assert_equals(shadow.elementFromPoint(...pointInElement(host)), innerHost); | ||
}, 'shadowRoot.elementFromPoint must return a child element assigned to a slot' | ||
+ ' when the hit-tested text node is assigned to a slot in the shadow tree of the child element and the outer shadow host has display: ' + displayValue); | ||
}); | ||
|
||
displayValues.forEach(function (displayValue) { | ||
test(function () { | ||
container.innerHTML = ''; | ||
let host = document.createElement('test-element'); | ||
host.style.display = displayValue; | ||
let shadow = host.attachShadow({mode: 'closed'}); | ||
shadow.innerHTML = '<slot></slot>'; | ||
host.innerHTML = '<inner-host></inner-host>'; | ||
container.appendChild(host); | ||
|
||
let innerHost = host.querySelector('inner-host'); | ||
let innerShadow = innerHost.attachShadow({mode: 'closed'}); | ||
innerShadow.innerHTML = 'hello'; | ||
|
||
assert_equals(shadow.elementFromPoint(...pointInElement(host)), innerHost); | ||
}, 'shadowRoot.elementFromPoint must return a child element with its own shadow tree assigned to a slot' | ||
+ ' when the hit-tested text node is its direct child and the outer shadow host has display: ' + displayValue); | ||
}); | ||
|
||
displayValues.forEach(function (displayValue) { | ||
test(function () { | ||
container.innerHTML = ''; | ||
let host = document.createElement('test-element'); | ||
host.style.display = displayValue; | ||
let shadow = host.attachShadow({mode: 'closed'}); | ||
shadow.innerHTML = '<slot></slot>'; | ||
host.innerHTML = '<inner-host></inner-host>'; | ||
container.appendChild(host); | ||
|
||
let innerHost = host.querySelector('inner-host'); | ||
let innerShadow = innerHost.attachShadow({mode: 'closed'}); | ||
innerShadow.innerHTML = '<span>hello</span>'; | ||
|
||
assert_equals(shadow.elementFromPoint(...pointInElement(host)), innerHost); | ||
}, 'shadowRoot.elementFromPoint must return a child element with its own shadow tree assigned to a slot' | ||
+ ' when the hit-tested text node is a child of another element and the outer shadow host has display: ' + displayValue); | ||
}); | ||
|
||
container.innerHTML = ''; | ||
|
||
</script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.