Title: [239313] trunk
Revision
239313
Author
rn...@webkit.org
Date
2018-12-17 19:52:53 -0800 (Mon, 17 Dec 2018)

Log Message

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.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (239312 => 239313)


--- trunk/LayoutTests/ChangeLog	2018-12-18 02:45:05 UTC (rev 239312)
+++ trunk/LayoutTests/ChangeLog	2018-12-18 03:52:53 UTC (rev 239313)
@@ -1,3 +1,16 @@
+2018-12-17  Ryosuke Niwa  <rn...@webkit.org>
+
+        offsetLeft and offsetParent should adjust across shadow boundaries
+        https://bugs.webkit.org/show_bug.cgi?id=157437
+        <rdar://problem/26154021>
+
+        Reviewed by Simon Fraser.
+
+        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.
+
 2018-12-17  Simon Fraser  <simon.fra...@apple.com>
 
         Don't use more expensive layer backing store formats when subpixel text antialiasing is not enabled

Added: trunk/LayoutTests/fast/shadow-dom/offsetParent-across-shadow-boundaries-expected.txt (0 => 239313)


--- trunk/LayoutTests/fast/shadow-dom/offsetParent-across-shadow-boundaries-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/shadow-dom/offsetParent-across-shadow-boundaries-expected.txt	2018-12-18 03:52:53 UTC (rev 239313)
@@ -0,0 +1,18 @@
+
+PASS offsetParent must return the offset parent in the same shadow tree of open mode 
+PASS offsetParent must return the offset parent in the same shadow tree of closed mode 
+PASS offsetParent must return the offset parent in the same shadow tree of open mode even when nested 
+PASS offsetParent must return the offset parent in the same shadow tree of closed mode even when nested 
+PASS offsetParent must skip offset parents of an element when the context object is assigned to a slot in a shadow tree of open mode 
+PASS offsetParent must skip offset parents of an element when the context object is assigned to a slot in a shadow tree of closed mode 
+PASS offsetParent must skip offset parents of an element when the context object is assigned to a slot in a shadow tree of open mode 
+PASS offsetParent must skip offset parents of an element when the context object is assigned to a slot in a shadow tree of closed mode 
+PASS offsetParent must skip offset parents of an element when the context object is assigned to a slot in nested shadow trees of open mode 
+PASS offsetParent must skip offset parents of an element when the context object is assigned to a slot in nested shadow trees of closed mode 
+PASS offsetParent must find the first offset parent which is a shadow-including ancestor of the context object even some shadow tree of open mode did not have any offset parent 
+PASS offsetParent must find the first offset parent which is a shadow-including ancestor of the context object even some shadow tree of closed mode did not have any offset parent 
+PASS offsetParent must return null on a child element of a shadow host for the shadow tree in open mode which is not assigned to any slot 
+PASS offsetParent must return null on a child element of a shadow host for the shadow tree in closed mode which is not assigned to any slot 
+PASS offsetParent must return null on a child element of a shadow host for the shadow tree in open mode which is not in the flat tree 
+PASS offsetParent must return null on a child element of a shadow host for the shadow tree in closed mode which is not in the flat tree 
+

Added: trunk/LayoutTests/fast/shadow-dom/offsetParent-across-shadow-boundaries.html (0 => 239313)


--- trunk/LayoutTests/fast/shadow-dom/offsetParent-across-shadow-boundaries.html	                        (rev 0)
+++ trunk/LayoutTests/fast/shadow-dom/offsetParent-across-shadow-boundaries.html	2018-12-18 03:52:53 UTC (rev 239313)
@@ -0,0 +1,190 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta name="author" title="Ryosuke Niwa" href=""
+<meta name="assert" content="offsetParent should only return nodes that are shadow including ancestor">
+<link rel="help" href=""
+<link rel="help" href=""
+<script src=""
+<script src=""
+<script src=""
+</head>
+<body>
+<div id="log"></div>
+<div id="container" style="position: relative"></div>
+<script>
+
+const container = document.getElementById('container');
+
+function testOffsetParentInShadowTree(mode) {
+    test(function () {
+        const host = document.createElement('div');
+        container.appendChild(host);
+        this.add_cleanup(() => host.remove());
+        const shadowRoot = host.attachShadow({mode});
+        shadowRoot.innerHTML = '<div id="relativeParent" style="position: relative; padding-left: 100px; padding-top: 70px;"><div id="target"></div></div>';
+        const relativeParent = shadowRoot.getElementById('relativeParent');
+
+        assert_true(relativeParent instanceof HTMLDivElement);
+        const target = shadowRoot.getElementById('target');
+        assert_equals(target.offsetParent, relativeParent);
+        assert_equals(target.offsetLeft, 100);
+        assert_equals(target.offsetTop, 70);
+    }, `offsetParent must return the offset parent in the same shadow tree of ${mode} mode`);
+}
+
+testOffsetParentInShadowTree('open');
+testOffsetParentInShadowTree('closed');
+
+function testOffsetParentInNestedShadowTrees(mode) {
+    test(function () {
+        const outerHost = document.createElement('section');
+        container.appendChild(outerHost);
+        this.add_cleanup(() => outerHost.remove());
+        const outerShadow = outerHost.attachShadow({mode});
+        outerShadow.innerHTML = '<section id="outerParent" style="position: absolute; top: 50px; left: 50px;"></section>';
+
+        const innerHost = document.createElement('div');
+        outerShadow.firstChild.appendChild(innerHost);
+        const innerShadow = innerHost.attachShadow({mode});
+        innerShadow.innerHTML = '<div id="innerParent" style="position: relative; padding-left: 60px; padding-top: 40px;"><div id="target"></div></div>';
+        const innerParent = innerShadow.getElementById('innerParent');
+
+        const target = innerShadow.getElementById('target');
+        assert_true(innerParent instanceof HTMLDivElement);
+        assert_equals(target.offsetParent, innerParent);
+        assert_equals(target.offsetLeft, 60);
+        assert_equals(target.offsetTop, 40);
+
+        outerHost.remove();
+    }, `offsetParent must return the offset parent in the same shadow tree of ${mode} mode even when nested`);
+}
+
+testOffsetParentInNestedShadowTrees('open');
+testOffsetParentInNestedShadowTrees('closed');
+
+function testOffsetParentOnElementAssignedToSlotInsideOffsetParent(mode) {
+    test(function () {
+        const host = document.createElement('div');
+        host.innerHTML = '<div id="target"></div>'
+        container.appendChild(host);
+        this.add_cleanup(() => host.remove());
+        const shadowRoot = host.attachShadow({mode});
+        shadowRoot.innerHTML = '<div style="position: relative; padding-left: 85px; padding-top: 45px;"><slot></slot></div>';
+        const target = host.querySelector('#target');
+        assert_equals(target.offsetParent, container);
+        assert_equals(target.offsetLeft, 85);
+        assert_equals(target.offsetTop, 45);
+    }, `offsetParent must skip offset parents of an element when the context object is assigned to a slot in a shadow tree of ${mode} mode`);
+}
+
+testOffsetParentOnElementAssignedToSlotInsideOffsetParent('open');
+testOffsetParentOnElementAssignedToSlotInsideOffsetParent('closed');
+
+function testOffsetParentOnElementAssignedToSlotInsideNestedOffsetParents(mode) {
+    test(function () {
+        const host = document.createElement('div');
+        host.innerHTML = '<div id="target" style="border:solid 1px blue;">hi</div>';
+        const previousBlock = document.createElement('div');
+        previousBlock.style.height = '12px';
+        container.append(previousBlock, host);
+        this.add_cleanup(() => container.innerHTML = '');
+        const shadowRoot = host.attachShadow({mode});
+        shadowRoot.innerHTML = '<section style="position: relative; margin-left: 20px; margin-top: 100px; background: #ccc"><div style="position: absolute; top: 10px; left: 10px;"><slot></slot></div></section>';
+        const target = host.querySelector('#target');
+        assert_equals(target.offsetParent, container);
+        assert_equals(target.offsetLeft, 30);
+        assert_equals(target.offsetTop, 122);
+    }, `offsetParent must skip offset parents of an element when the context object is assigned to a slot in a shadow tree of ${mode} mode`);
+}
+
+testOffsetParentOnElementAssignedToSlotInsideNestedOffsetParents('open');
+testOffsetParentOnElementAssignedToSlotInsideNestedOffsetParents('closed');
+
+function testOffsetParentOnElementAssignedToSlotInsideNestedShadowTrees(mode) {
+    test(function () {
+        const outerHost = document.createElement('section');
+        outerHost.innerHTML = '<div id="target"></div>';
+        container.appendChild(outerHost);
+        this.add_cleanup(() => outerHost.remove());
+        const outerShadow = outerHost.attachShadow({mode});
+        outerShadow.innerHTML = '<section style="position: absolute; top: 40px; left: 50px;"><div id="innerHost"><slot></slot></div></section>';
+
+        const innerShadow = outerShadow.getElementById('innerHost').attachShadow({mode});
+        innerShadow.innerHTML = '<div style="position: absolute; top: 200px; margin-left: 100px;"><slot></slot></div>';
+
+        const target = outerHost.querySelector('#target');
+        assert_equals(target.offsetParent, container);
+        assert_equals(target.offsetLeft, 150);
+        assert_equals(target.offsetTop, 240);
+        outerHost.remove();
+    }, `offsetParent must skip offset parents of an element when the context object is assigned to a slot in nested shadow trees of ${mode} mode`);
+}
+
+testOffsetParentOnElementAssignedToSlotInsideNestedShadowTrees('open');
+testOffsetParentOnElementAssignedToSlotInsideNestedShadowTrees('closed');
+
+function testOffsetParentOnElementInsideShadowTreeWithoutOffsetParent(mode) {
+    test(function () {
+        const outerHost = document.createElement('section');
+        container.appendChild(outerHost);
+        this.add_cleanup(() => outerHost.remove());
+        const outerShadow = outerHost.attachShadow({mode});
+        outerShadow.innerHTML = '<div id="innerHost"><div id="target"></div></div>';
+
+        const innerShadow = outerShadow.getElementById('innerHost').attachShadow({mode});
+        innerShadow.innerHTML = '<div style="position: absolute; top: 23px; left: 24px;"><slot></slot></div>';
+
+        const target = outerShadow.querySelector('#target');
+        assert_equals(target.offsetParent, container);
+        assert_equals(target.offsetLeft, 24);
+        assert_equals(target.offsetTop, 23);
+    }, `offsetParent must find the first offset parent which is a shadow-including ancestor of the context object even some shadow tree of ${mode} mode did not have any offset parent`);
+}
+
+testOffsetParentOnElementInsideShadowTreeWithoutOffsetParent('open');
+testOffsetParentOnElementInsideShadowTreeWithoutOffsetParent('closed');
+
+function testOffsetParentOnUnassignedChild(mode) {
+    test(function () {
+        const host = document.createElement('section');
+        host.innerHTML = '<div id="target"></div>';
+        this.add_cleanup(() => host.remove());
+        container.appendChild(host);
+        const shadowRoot = host.attachShadow({mode});
+        shadowRoot.innerHTML = '<section style="position: absolute; top: 50px; left: 50px;">content</section>';
+        const target = host.querySelector('#target');
+        assert_equals(target.offsetParent, null);
+        assert_equals(target.offsetLeft, 0);
+        assert_equals(target.offsetTop, 0);
+    }, `offsetParent must return null on a child element of a shadow host for the shadow tree in ${mode} mode which is not assigned to any slot`);
+}
+
+testOffsetParentOnUnassignedChild('open');
+testOffsetParentOnUnassignedChild('closed');
+
+function testOffsetParentOnAssignedChildNotInFlatTree(mode) {
+    test(function () {
+        const outerHost = document.createElement('section');
+        outerHost.innerHTML = '<div id="target"></div>';
+        container.appendChild(outerHost);
+        this.add_cleanup(() => outerHost.remove());
+        const outerShadow = outerHost.attachShadow({mode});
+        outerShadow.innerHTML = '<div id="innerHost"><div style="position: absolute; top: 50px; left: 50px;"><slot></slot></div></div>';
+
+        const innerShadow = outerShadow.getElementById('innerHost').attachShadow({mode});
+        innerShadow.innerHTML = '<div>content</div>';
+
+        const target = outerHost.querySelector('#target');
+        assert_equals(target.offsetParent, null);
+        assert_equals(target.offsetLeft, 0);
+        assert_equals(target.offsetTop, 0);
+    }, `offsetParent must return null on a child element of a shadow host for the shadow tree in ${mode} mode which is not in the flat tree`);
+}
+
+testOffsetParentOnAssignedChildNotInFlatTree('open');
+testOffsetParentOnAssignedChildNotInFlatTree('closed');
+
+</script>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (239312 => 239313)


--- trunk/Source/WebCore/ChangeLog	2018-12-18 02:45:05 UTC (rev 239312)
+++ trunk/Source/WebCore/ChangeLog	2018-12-18 03:52:53 UTC (rev 239313)
@@ -1,3 +1,43 @@
+2018-12-17  Ryosuke Niwa  <rn...@webkit.org>
+
+        offsetLeft and offsetParent should adjust across shadow boundaries
+        https://bugs.webkit.org/show_bug.cgi?id=157437
+        <rdar://problem/26154021>
+
+        Reviewed by Simon Fraser.
+
+        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:
+
 2018-12-17  Simon Fraser  <simon.fra...@apple.com>
 
         Don't use more expensive layer backing store formats when subpixel text antialiasing is not enabled

Modified: trunk/Source/WebCore/dom/Element.cpp (239312 => 239313)


--- trunk/Source/WebCore/dom/Element.cpp	2018-12-18 02:45:05 UTC (rev 239312)
+++ trunk/Source/WebCore/dom/Element.cpp	2018-12-18 03:52:53 UTC (rev 239313)
@@ -883,27 +883,77 @@
     return subpixelMetricsEnabled(document) ? value : roundStrategy == Round ? round(value) : floor(value);
 }
 
+static double adjustOffsetForZoomAndSubpixelLayout(RenderBoxModelObject* renderer, const LayoutUnit& offset)
+{
+    LayoutUnit offsetLeft = subpixelMetricsEnabled(renderer->document()) ? offset : LayoutUnit(roundToInt(offset));
+    double zoomFactor = 1;
+    double offsetLeftAdjustedWithZoom = adjustForLocalZoom(offsetLeft, *renderer, zoomFactor);
+    return convertToNonSubpixelValueIfNeeded(offsetLeftAdjustedWithZoom, renderer->document(), zoomFactor == 1 ? Floor : Round);
+}
+
+static HashSet<TreeScope*> collectAncestorTreeScopeAsHashSet(Node& node)
+{
+    HashSet<TreeScope*> ancestors;
+    for (auto* currentScope = &node.treeScope(); currentScope; currentScope = currentScope->parentTreeScope())
+        ancestors.add(currentScope);
+    return ancestors;
+}
+
+double Element::offsetLeftForBindings()
+{
+    auto offset = offsetLeft();
+
+    auto parent = makeRefPtr(offsetParent());
+    if (!parent || !parent->isInShadowTree())
+        return offset;
+
+    ASSERT(&parent->document() == &document());
+    if (&parent->treeScope() == &treeScope())
+        return offset;
+
+    auto ancestorTreeScopes = collectAncestorTreeScopeAsHashSet(*this);
+    while (parent && !ancestorTreeScopes.contains(&parent->treeScope())) {
+        offset += parent->offsetLeft();
+        parent = parent->offsetParent();
+    }
+
+    return offset;
+}
+
 double Element::offsetLeft()
 {
     document().updateLayoutIgnorePendingStylesheets();
-    if (RenderBoxModelObject* renderer = renderBoxModelObject()) {
-        LayoutUnit offsetLeft = subpixelMetricsEnabled(renderer->document()) ? renderer->offsetLeft() : LayoutUnit(roundToInt(renderer->offsetLeft()));
-        double zoomFactor = 1;
-        double offsetLeftAdjustedWithZoom = adjustForLocalZoom(offsetLeft, *renderer, zoomFactor);
-        return convertToNonSubpixelValueIfNeeded(offsetLeftAdjustedWithZoom, renderer->document(), zoomFactor == 1 ? Floor : Round);
-    }
+    if (RenderBoxModelObject* renderer = renderBoxModelObject())
+        return adjustOffsetForZoomAndSubpixelLayout(renderer, renderer->offsetLeft());
     return 0;
 }
 
+double Element::offsetTopForBindings()
+{
+    auto offset = offsetTop();
+
+    auto parent = makeRefPtr(offsetParent());
+    if (!parent || !parent->isInShadowTree())
+        return offset;
+
+    ASSERT(&parent->document() == &document());
+    if (&parent->treeScope() == &treeScope())
+        return offset;
+
+    auto ancestorTreeScopes = collectAncestorTreeScopeAsHashSet(*this);
+    while (parent && !ancestorTreeScopes.contains(&parent->treeScope())) {
+        offset += parent->offsetTop();
+        parent = parent->offsetParent();
+    }
+
+    return offset;
+}
+
 double Element::offsetTop()
 {
     document().updateLayoutIgnorePendingStylesheets();
-    if (RenderBoxModelObject* renderer = renderBoxModelObject()) {
-        LayoutUnit offsetTop = subpixelMetricsEnabled(renderer->document()) ? renderer->offsetTop() : LayoutUnit(roundToInt(renderer->offsetTop()));
-        double zoomFactor = 1;
-        double offsetTopAdjustedWithZoom = adjustForLocalZoom(offsetTop, *renderer, zoomFactor);
-        return convertToNonSubpixelValueIfNeeded(offsetTopAdjustedWithZoom, renderer->document(), zoomFactor == 1 ? Floor : Round);
-    }
+    if (RenderBoxModelObject* renderer = renderBoxModelObject())
+        return adjustOffsetForZoomAndSubpixelLayout(renderer, renderer->offsetTop());
     return 0;
 }
 
@@ -927,12 +977,14 @@
     return 0;
 }
 
-Element* Element::bindingsOffsetParent()
+Element* Element::offsetParentForBindings()
 {
     Element* element = offsetParent();
     if (!element || !element->isInShadowTree())
         return element;
-    return element->containingShadowRoot()->mode() == ShadowRootMode::UserAgent ? nullptr : element;
+    while (element && !isDescendantOrShadowDescendantOf(&element->rootNode()))
+        element = element->offsetParent();
+    return element;
 }
 
 Element* Element::offsetParent()

Modified: trunk/Source/WebCore/dom/Element.h (239312 => 239313)


--- trunk/Source/WebCore/dom/Element.h	2018-12-18 02:45:05 UTC (rev 239312)
+++ trunk/Source/WebCore/dom/Element.h	2018-12-18 03:52:53 UTC (rev 239313)
@@ -156,7 +156,9 @@
     WEBCORE_EXPORT void scrollByLines(int lines);
     WEBCORE_EXPORT void scrollByPages(int pages);
 
+    WEBCORE_EXPORT double offsetLeftForBindings();
     WEBCORE_EXPORT double offsetLeft();
+    WEBCORE_EXPORT double offsetTopForBindings();
     WEBCORE_EXPORT double offsetTop();
     WEBCORE_EXPORT double offsetWidth();
     WEBCORE_EXPORT double offsetHeight();
@@ -165,7 +167,7 @@
 
     // FIXME: Replace uses of offsetParent in the platform with calls
     // to the render layer and merge bindingsOffsetParent and offsetParent.
-    WEBCORE_EXPORT Element* bindingsOffsetParent();
+    WEBCORE_EXPORT Element* offsetParentForBindings();
 
     const Element* rootElement() const;
 

Modified: trunk/Source/WebCore/html/HTMLElement.idl (239312 => 239313)


--- trunk/Source/WebCore/html/HTMLElement.idl	2018-12-18 02:45:05 UTC (rev 239312)
+++ trunk/Source/WebCore/html/HTMLElement.idl	2018-12-18 03:52:53 UTC (rev 239313)
@@ -52,9 +52,9 @@
     readonly attribute boolean isContentEditable;
 
     // Extensions from CSSOM-view specification (https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface).
-    [ImplementedAs=bindingsOffsetParent] readonly attribute Element? offsetParent;
-    readonly attribute double offsetTop; // FIXME: Should be of type long.
-    readonly attribute double offsetLeft; // FIXME: Should be of type long.
+    [ImplementedAs=offsetParentForBindings] readonly attribute Element? offsetParent;
+    [ImplementedAs=offsetTopForBindings] readonly attribute double offsetTop; // FIXME: Should be of type long.
+    [ImplementedAs=offsetLeftForBindings] readonly attribute double offsetLeft; // FIXME: Should be of type long.
     readonly attribute double offsetWidth; // FIXME: Should be of type long.
     readonly attribute double offsetHeight; // FIXME: Should be of type long.
 

Modified: trunk/Source/WebKit/ChangeLog (239312 => 239313)


--- trunk/Source/WebKit/ChangeLog	2018-12-18 02:45:05 UTC (rev 239312)
+++ trunk/Source/WebKit/ChangeLog	2018-12-18 03:52:53 UTC (rev 239313)
@@ -1,3 +1,18 @@
+2018-12-17  Ryosuke Niwa  <rn...@webkit.org>
+
+        offsetLeft and offsetParent should adjust across shadow boundaries
+        https://bugs.webkit.org/show_bug.cgi?id=157437
+        <rdar://problem/26154021>
+
+        Reviewed by Simon Fraser.
+
+        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):
+
 2018-12-17  Chris Fleizach  <cfleiz...@apple.com>
 
         Some builds are broken after r239262

Modified: trunk/Source/WebKit/WebProcess/InjectedBundle/API/gtk/DOM/WebKitDOMElementGtk.cpp (239312 => 239313)


--- trunk/Source/WebKit/WebProcess/InjectedBundle/API/gtk/DOM/WebKitDOMElementGtk.cpp	2018-12-18 02:45:05 UTC (rev 239312)
+++ trunk/Source/WebKit/WebProcess/InjectedBundle/API/gtk/DOM/WebKitDOMElementGtk.cpp	2018-12-18 03:52:53 UTC (rev 239313)
@@ -1088,7 +1088,7 @@
     WebCore::JSMainThreadNullState state;
     g_return_val_if_fail(WEBKIT_DOM_IS_ELEMENT(self), 0);
     WebCore::Element* item = WebKit::core(self);
-    gdouble result = item->offsetLeft();
+    gdouble result = item->offsetLeftForBindings();
     return result;
 }
 
@@ -1097,7 +1097,7 @@
     WebCore::JSMainThreadNullState state;
     g_return_val_if_fail(WEBKIT_DOM_IS_ELEMENT(self), 0);
     WebCore::Element* item = WebKit::core(self);
-    gdouble result = item->offsetTop();
+    gdouble result = item->offsetTopForBindings();
     return result;
 }
 
@@ -1228,7 +1228,7 @@
     WebCore::JSMainThreadNullState state;
     g_return_val_if_fail(WEBKIT_DOM_IS_ELEMENT(self), 0);
     WebCore::Element* item = WebKit::core(self);
-    RefPtr<WebCore::Element> gobjectResult = WTF::getPtr(item->bindingsOffsetParent());
+    RefPtr<WebCore::Element> gobjectResult = WTF::getPtr(item->offsetParentForBindings());
     return WebKit::kit(gobjectResult.get());
 }
 

Modified: trunk/Source/WebKitLegacy/mac/ChangeLog (239312 => 239313)


--- trunk/Source/WebKitLegacy/mac/ChangeLog	2018-12-18 02:45:05 UTC (rev 239312)
+++ trunk/Source/WebKitLegacy/mac/ChangeLog	2018-12-18 03:52:53 UTC (rev 239313)
@@ -1,3 +1,18 @@
+2018-12-17  Ryosuke Niwa  <rn...@webkit.org>
+
+        offsetLeft and offsetParent should adjust across shadow boundaries
+        https://bugs.webkit.org/show_bug.cgi?id=157437
+        <rdar://problem/26154021>
+
+        Reviewed by Simon Fraser.
+
+        Use *forBindings variants of offsetLeft, offsetTop, and offsetParent.
+
+        * DOM/DOMElement.mm:
+        (-[DOMElement offsetLeft]):
+        (-[DOMElement offsetTop]):
+        (-[DOMElement offsetParent]):
+
 2018-12-17  Zalan Bujtas  <za...@apple.com>
 
         Unreviewed build fix.

Modified: trunk/Source/WebKitLegacy/mac/DOM/DOMElement.mm (239312 => 239313)


--- trunk/Source/WebKitLegacy/mac/DOM/DOMElement.mm	2018-12-18 02:45:05 UTC (rev 239312)
+++ trunk/Source/WebKitLegacy/mac/DOM/DOMElement.mm	2018-12-18 03:52:53 UTC (rev 239313)
@@ -81,13 +81,13 @@
 - (int)offsetLeft
 {
     WebCore::JSMainThreadNullState state;
-    return unwrap(*self).offsetLeft();
+    return unwrap(*self).offsetLeftForBindings();
 }
 
 - (int)offsetTop
 {
     WebCore::JSMainThreadNullState state;
-    return unwrap(*self).offsetTop();
+    return unwrap(*self).offsetTopForBindings();
 }
 
 - (int)offsetWidth
@@ -165,7 +165,7 @@
 - (DOMElement *)offsetParent
 {
     WebCore::JSMainThreadNullState state;
-    return kit(unwrap(*self).bindingsOffsetParent());
+    return kit(unwrap(*self).offsetParentForBindings());
 }
 
 - (NSString *)innerHTML
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to