offsetLeft and offsetParent should adjust across shadow boundaries
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 18 Dec 2018 03:52:53 +0000 (03:52 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 18 Dec 2018 03:52:53 +0000 (03:52 +0000)
commitd3728efdb49064d2de633c7fa887cdca7cdd22e9
treec7238d47cbe4ee4501d89e6765d246ef96977112
parentac0f7ee623a23ce252832384f2a036cf688934bc
offsetLeft and offsetParent should adjust across shadow boundaries
https://bugs.webkit.org/show_bug.cgi?id=157437
<rdar://problem/26154021>

Reviewed by Simon Fraser.

Source/WebCore:

Update the WebKit's treatment of shadow boundaries in offsetLeft, offsetTop, and offsetParent to match
the latest discussion in CSS WG. See https://github.com/w3c/webcomponents/issues/497
and https://github.com/w3c/webcomponents/issues/763

The latest consensus is to use the retargeting algorithm (https://dom.spec.whatwg.org/#retarget).
In practice, this would mean that we need to keep walking up the offset parent ancestors until we find
the one which is in the same tree as a shadow-inclusive ancestor of the context object.

For example, if a node (the context object of offsetTop, offsetLeft, offsetParent) was assigned to a slot
inside a shadow tree and its offset parent was in the shadow tree, we need to walk up to its offset parent,
then its offset parent, etc... until we find the offset parent in the same tree as the context object.

Note it's possible that the context object is inside a shadow tree which does not have its own offset parent.
(e.g. all elements have position: static) For this reason, we need to consider not just offset parent in
the same tree as the context object but as well as any offset parent which is in its ancestor trees.

Test: fast/shadow-dom/offsetParent-across-shadow-boundaries.html

* dom/Element.cpp:
(WebCore::adjustOffsetForZoomAndSubpixelLayout): Extracted to share code between offsetLeft and offsetTop.
(WebCore::collectAncestorTreeScopeAsHashSet): Added.
(WebCore::Element::offsetLeftForBindings): Added. Sums up offsetLeft's until it finds the first offset parent
which is a shadow-including ancestor (https://dom.spec.whatwg.org/#concept-shadow-including-ancestor).
(WebCore::Element::offsetLeft): Now uses adjustOffsetForZoomAndSubpixelLayout.
(WebCore::Element::offsetTopForBindings): Added. Like offsetLeftForBindings, this function sums up offsetTop's
until it finds the first offset parent which is a shadow-including ancestor.
(WebCore::Element::offsetTop): Now uses adjustOffsetForZoomAndSubpixelLayout.
(WebCore::Element::offsetParentForBindings): Renamed from bindingsOffsetParent to be consistent with other
functions meant to be used for bindings code.
* dom/Element.h:
* html/HTMLElement.idl:

Source/WebKit:

Use *forBindings variants of offsetLeft, offsetTop, and offsetParent.

* WebProcess/InjectedBundle/API/gtk/DOM/WebKitDOMElementGtk.cpp:
(webkit_dom_element_get_offset_left):
(webkit_dom_element_get_offset_top):
(webkit_dom_element_get_offset_parent):

Source/WebKitLegacy/mac:

Use *forBindings variants of offsetLeft, offsetTop, and offsetParent.

* DOM/DOMElement.mm:
(-[DOMElement offsetLeft]):
(-[DOMElement offsetTop]):
(-[DOMElement offsetParent]):

LayoutTests:

Added a W3C style testharness.js test.

* fast/shadow-dom/offsetParent-across-shadow-boundaries-expected.txt: Added.
* fast/shadow-dom/offsetParent-across-shadow-boundaries.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@239313 268f45cc-cd09-0410-ab3c-d52691b4dbfc
LayoutTests/ChangeLog
LayoutTests/fast/shadow-dom/offsetParent-across-shadow-boundaries-expected.txt [new file with mode: 0644]
LayoutTests/fast/shadow-dom/offsetParent-across-shadow-boundaries.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/dom/Element.cpp
Source/WebCore/dom/Element.h
Source/WebCore/html/HTMLElement.idl
Source/WebKit/ChangeLog
Source/WebKit/WebProcess/InjectedBundle/API/gtk/DOM/WebKitDOMElementGtk.cpp
Source/WebKitLegacy/mac/ChangeLog
Source/WebKitLegacy/mac/DOM/DOMElement.mm