Title: [217522] trunk
Revision
217522
Author
[email protected]
Date
2017-05-27 10:13:58 -0700 (Sat, 27 May 2017)

Log Message

getComputedStyle returns percentage values for left / right / top / bottom
https://bugs.webkit.org/show_bug.cgi?id=29084

Reviewed by Zalan Bujtas.
LayoutTests/imported/w3c:

New baselines (still failing).

* web-platform-tests/css-timing-1/frames-timing-functions-output-expected.txt:
* web-platform-tests/html/semantics/interactive-elements/the-dialog-element/centering-expected.txt:

Source/WebCore:

Fix getComputedStyle() to return pixel values for left / right / top / bottom, per spec.

This is mostly a merge of https://codereview.chromium.org/13871003/.

Behavior now matches Chrome and Firefox.

Test: fast/css/getComputedStyle/getComputedStyle-offsets.html

* css/CSSComputedStyleDeclaration.cpp:
(WebCore::getOffsetComputedLength):
(WebCore::getOffsetUsedStyleRelative):
(WebCore::getOffsetUsedStyleAbsolute):
(WebCore::positionOffsetValue):
(WebCore::positionOffsetValueIsRendererDependent):
(WebCore::isNonReplacedInline):
(WebCore::isLayoutDependent):
(WebCore::ComputedStyleExtractor::propertyValue):

LayoutTests:

Some new baselines, a new test, and an improved test.

* animations/trigger-container-scroll-boundaries-expected.txt:
* animations/trigger-container-scroll-boundaries.html:
* animations/trigger-container-scroll-empty-expected.txt:
* animations/trigger-container-scroll-empty.html:
* animations/trigger-container-scroll-simple-expected.txt:
* animations/trigger-container-scroll-simple.html:
* fast/css/getComputedStyle/computed-style-expected.txt:
* fast/css/getComputedStyle/computed-style-negative-top-expected.txt:
* fast/css/getComputedStyle/computed-style-negative-top.html: Convert to a real JS test, add more cases.
* fast/css/getComputedStyle/getComputedStyle-offsets-expected.txt: Added.
* fast/css/getComputedStyle/getComputedStyle-offsets.html: Added.
* fast/css/getComputedStyle/getComputedStyle-zoom-and-background-size-expected.txt:
* fast/css/getComputedStyle/getComputedStyle-zoom-and-background-size.html:  It doesn't make any sense to test right/bottom.
* fast/css/hover-affects-child-expected.txt:
* fast/css/hover-affects-child.html:
* platform/mac-elcapitan/fast/css/getComputedStyle/computed-style-expected.txt:
* transitions/transition-to-from-auto-expected.txt:
* transitions/transition-to-from-auto.html:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (217521 => 217522)


--- trunk/LayoutTests/ChangeLog	2017-05-27 16:23:24 UTC (rev 217521)
+++ trunk/LayoutTests/ChangeLog	2017-05-27 17:13:58 UTC (rev 217522)
@@ -1,3 +1,31 @@
+2017-05-27  Simon Fraser  <[email protected]>
+
+        getComputedStyle returns percentage values for left / right / top / bottom
+        https://bugs.webkit.org/show_bug.cgi?id=29084
+
+        Reviewed by Zalan Bujtas.
+
+        Some new baselines, a new test, and an improved test.
+
+        * animations/trigger-container-scroll-boundaries-expected.txt:
+        * animations/trigger-container-scroll-boundaries.html:
+        * animations/trigger-container-scroll-empty-expected.txt:
+        * animations/trigger-container-scroll-empty.html:
+        * animations/trigger-container-scroll-simple-expected.txt:
+        * animations/trigger-container-scroll-simple.html:
+        * fast/css/getComputedStyle/computed-style-expected.txt:
+        * fast/css/getComputedStyle/computed-style-negative-top-expected.txt:
+        * fast/css/getComputedStyle/computed-style-negative-top.html: Convert to a real JS test, add more cases.
+        * fast/css/getComputedStyle/getComputedStyle-offsets-expected.txt: Added.
+        * fast/css/getComputedStyle/getComputedStyle-offsets.html: Added.
+        * fast/css/getComputedStyle/getComputedStyle-zoom-and-background-size-expected.txt:
+        * fast/css/getComputedStyle/getComputedStyle-zoom-and-background-size.html:  It doesn't make any sense to test right/bottom.
+        * fast/css/hover-affects-child-expected.txt:
+        * fast/css/hover-affects-child.html:
+        * platform/mac-elcapitan/fast/css/getComputedStyle/computed-style-expected.txt:
+        * transitions/transition-to-from-auto-expected.txt:
+        * transitions/transition-to-from-auto.html:
+
 2017-05-26  Youenn Fablet  <[email protected]>
 
         WebRTC stats should be in milliseconds

Modified: trunk/LayoutTests/animations/trigger-container-scroll-boundaries-expected.txt (217521 => 217522)


--- trunk/LayoutTests/animations/trigger-container-scroll-boundaries-expected.txt	2017-05-27 16:23:24 UTC (rev 217521)
+++ trunk/LayoutTests/animations/trigger-container-scroll-boundaries-expected.txt	2017-05-27 17:13:58 UTC (rev 217522)
@@ -1,6 +1,6 @@
 This element should begin animating only when the page scrolls to 20px from the top. It then animates smoothly, moving 100px to the left over the next 100px of scrolling. Remember to scroll to the top of the page before reloading!
 
-PASS: Value before animation is applied is auto
+PASS: Value before animation is applied is 0px
 PASS: Value with animation but no scroll was 0px
 PASS: Value with scroll amount of 10 was 10px
 PASS: Value with scroll amount of 20 was 20px

Modified: trunk/LayoutTests/animations/trigger-container-scroll-boundaries.html (217521 => 217522)


--- trunk/LayoutTests/animations/trigger-container-scroll-boundaries.html	2017-05-27 16:23:24 UTC (rev 217521)
+++ trunk/LayoutTests/animations/trigger-container-scroll-boundaries.html	2017-05-27 17:13:58 UTC (rev 217522)
@@ -48,8 +48,8 @@
     results = document.getElementById("results");
     box = document.getElementById("box");
     var leftValue = window.getComputedStyle(box).left;
-    if (leftValue == "auto")
-        results.innerHTML = "PASS: Value before animation is applied is auto<br>";
+    if (leftValue == "0px")
+        results.innerHTML = "PASS: Value before animation is applied is 0px<br>";
     else
         results.innerHTML = "FAIL: Value before animation is applied should be auto, was " + leftValue + "<br>";
     box.className = "animating";

Modified: trunk/LayoutTests/animations/trigger-container-scroll-empty-expected.txt (217521 => 217522)


--- trunk/LayoutTests/animations/trigger-container-scroll-empty-expected.txt	2017-05-27 16:23:24 UTC (rev 217521)
+++ trunk/LayoutTests/animations/trigger-container-scroll-empty-expected.txt	2017-05-27 17:13:58 UTC (rev 217522)
@@ -1,6 +1,6 @@
 This element should begin animating only when the page scrolls to 20px from the top. It specifies an end value, but that should be ignored because it is not greater than the start. This means the animation will run to completion rather than take the scroll value as input. Remember to scroll to the top of the page before reloading!
 
-Value before animation is applied: auto (should be auto)
+Value before animation is applied: 0px (should be 0px)
 Value with animation but no scroll: 0px (should be 0px)
 PASS: Animation was not depending on scroll.
 

Modified: trunk/LayoutTests/animations/trigger-container-scroll-empty.html (217521 => 217522)


--- trunk/LayoutTests/animations/trigger-container-scroll-empty.html	2017-05-27 16:23:24 UTC (rev 217521)
+++ trunk/LayoutTests/animations/trigger-container-scroll-empty.html	2017-05-27 17:13:58 UTC (rev 217522)
@@ -44,7 +44,7 @@
 function runTest() {
     results = document.getElementById("results");
     box = document.getElementById("box");
-    results.innerHTML = "Value before animation is applied: " + window.getComputedStyle(box).left + " (should be auto)<br>";
+    results.innerHTML = "Value before animation is applied: " + window.getComputedStyle(box).left + " (should be 0px)<br>";
     box.className = "animating";
     setTimeout(checkValueWithoutScroll, 0);
 }

Modified: trunk/LayoutTests/animations/trigger-container-scroll-simple-expected.txt (217521 => 217522)


--- trunk/LayoutTests/animations/trigger-container-scroll-simple-expected.txt	2017-05-27 16:23:24 UTC (rev 217521)
+++ trunk/LayoutTests/animations/trigger-container-scroll-simple-expected.txt	2017-05-27 17:13:58 UTC (rev 217522)
@@ -1,6 +1,6 @@
 This element should begin animating only when the page scrolls to 20px from the top. The animation is almost instantaneous, so it will snap to its final position. Remember to scroll to the top of the page before reloading!
 
-Value before animation is applied: auto (should be auto)
+Value before animation is applied: 0px (should be 0px)
 Value with animation but no scroll: 0px (should be 0px)
 Value with animation after scroll: 100px (should be 100px)
 

Modified: trunk/LayoutTests/animations/trigger-container-scroll-simple.html (217521 => 217522)


--- trunk/LayoutTests/animations/trigger-container-scroll-simple.html	2017-05-27 16:23:24 UTC (rev 217521)
+++ trunk/LayoutTests/animations/trigger-container-scroll-simple.html	2017-05-27 17:13:58 UTC (rev 217522)
@@ -44,7 +44,7 @@
 function runTest() {
     results = document.getElementById("results");
     box = document.getElementById("box");
-    results.innerHTML = "Value before animation is applied: " + window.getComputedStyle(box).left + " (should be auto)<br>";
+    results.innerHTML = "Value before animation is applied: " + window.getComputedStyle(box).left + " (should be 0px)<br>";
     box.className = "animating";
     setTimeout(checkValueWithoutScroll, 0);
 }

Modified: trunk/LayoutTests/fast/css/getComputedStyle/computed-style-expected.txt (217521 => 217522)


--- trunk/LayoutTests/fast/css/getComputedStyle/computed-style-expected.txt	2017-05-27 16:23:24 UTC (rev 217521)
+++ trunk/LayoutTests/fast/css/getComputedStyle/computed-style-expected.txt	2017-05-27 17:13:58 UTC (rev 217522)
@@ -30,7 +30,7 @@
 border-top-right-radius: 0px;
 border-top-style: none;
 border-top-width: 0px;
-bottom: auto;
+bottom: 16px;
 box-shadow: none;
 box-sizing: content-box;
 caption-side: top;
@@ -54,7 +54,7 @@
 hanging-punctuation: none;
 height: 576px;
 image-rendering: auto;
-left: auto;
+left: -8px;
 letter-spacing: normal;
 line-height: 18px;
 list-style-image: none;
@@ -89,7 +89,7 @@
 pointer-events: auto;
 position: static;
 resize: none;
-right: auto;
+right: 8px;
 speak: normal;
 table-layout: auto;
 tab-size: 8;
@@ -100,7 +100,7 @@
 text-shadow: none;
 text-overflow: clip;
 text-transform: none;
-top: auto;
+top: -8px;
 transform: none;
 transform-origin: 392px 288px;
 transform-style: flat;

Modified: trunk/LayoutTests/fast/css/getComputedStyle/computed-style-negative-top-expected.txt (217521 => 217522)


--- trunk/LayoutTests/fast/css/getComputedStyle/computed-style-negative-top-expected.txt	2017-05-27 16:23:24 UTC (rev 217521)
+++ trunk/LayoutTests/fast/css/getComputedStyle/computed-style-negative-top-expected.txt	2017-05-27 17:13:58 UTC (rev 217522)
@@ -1 +1,27 @@
-Test succeeded! Top is -1px.
+Test computed offsets on elements with negative top and left.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+With no height
+PASS style.top is '-1px'
+PASS style.left is '-2px'
+PASS style.bottom is '1px'
+PASS style.right is '2px'
+
+With height:100%;
+PASS style.top is '-1px'
+PASS style.left is '-2px'
+PASS style.bottom is '1px'
+PASS style.right is '2px'
+
+With height:auto;
+PASS style.top is '-1px'
+PASS style.left is '-2px'
+PASS style.bottom is '1px'
+PASS style.right is '2px'
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Modified: trunk/LayoutTests/fast/css/getComputedStyle/computed-style-negative-top.html (217521 => 217522)


--- trunk/LayoutTests/fast/css/getComputedStyle/computed-style-negative-top.html	2017-05-27 16:23:24 UTC (rev 217521)
+++ trunk/LayoutTests/fast/css/getComputedStyle/computed-style-negative-top.html	2017-05-27 17:13:58 UTC (rev 217522)
@@ -1,16 +1,48 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<body>
+    <div id="testContainer1" style="width: 100px; height: 200px;">
+        <div id="test1" style="position:relative; top:-1px; left:-2px;"></div>
+    </div>
+
+    <div id="testContainer2" style="width: 100px; height: 200px;">
+        <div id="test2" style="position:relative; top:-1px; left:-2px; height:100%;"></div>
+    </div>
+
+    <div id="testContainer3" style="width: 100px; height: 200px;">
+        <div id="test3" style="position:relative; top:-1px; left:-2px; height:auto;"></div>
+    </div>
+
 <script>
-function test() {
-    if (window.testRunner)
-        testRunner.dumpAsText();
-    var style = document.defaultView.getComputedStyle(document.getElementById("test"), "");
-    var result = document.getElementById("result");
-    if (style.top == "-1px")
-        result.appendChild(document.createTextNode("Test succeeded! Top is " + style.top + "."));
-    else
-        result.appendChild(document.createTextNode("Test failed! Top is " + style.top + "."));
+description("Test computed offsets on elements with negative top and left.")
+
+var test = document.getElementById('test');
+var style;
+
+function testStyle(name)
+{
+    debug('');
+    debug(name);
+    shouldBe("style.top", "'-1px'");
+    shouldBe("style.left", "'-2px'");
+    shouldBe("style.bottom", "'1px'");
+    shouldBe("style.right", "'2px'");
 }
+
+style = document.defaultView.getComputedStyle(document.getElementById("test1"), "");
+testStyle("With no height");
+
+style = document.defaultView.getComputedStyle(document.getElementById("test2"), "");
+testStyle("With height:100%;");
+
+style = document.defaultView.getComputedStyle(document.getElementById("test3"), "");
+testStyle("With height:auto;");
+
 </script>
-<body _onload_="test()">
-<div id="test" style="position:relative; top:-1px"></div>
-<div id="result"></div>
+
+<script src=""
 </body>

Added: trunk/LayoutTests/fast/css/getComputedStyle/getComputedStyle-offsets-expected.txt (0 => 217522)


--- trunk/LayoutTests/fast/css/getComputedStyle/getComputedStyle-offsets-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/css/getComputedStyle/getComputedStyle-offsets-expected.txt	2017-05-27 17:13:58 UTC (rev 217522)
@@ -0,0 +1,333 @@
+Test to make sure top/bottom/left/right properly returns pixel values for any input.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+No offsets (zero width/height)
+
+PASS getComputedStyle(test).top is '0px'
+PASS getComputedStyle(test).left is '0px'
+PASS getComputedStyle(test).right is '200px'
+PASS getComputedStyle(test).bottom is '400px'
+PASS getComputedStyle(test).width is '0px'
+PASS getComputedStyle(test).height is '0px'
+
+test.setAttribute('style', 'padding: 5px;')
+PASS getComputedStyle(test).top is '0px'
+PASS getComputedStyle(test).left is '0px'
+PASS getComputedStyle(test).right is '190px'
+PASS getComputedStyle(test).bottom is '390px'
+PASS getComputedStyle(test).width is '0px'
+PASS getComputedStyle(test).height is '0px'
+
+test.setAttribute('style', 'border: solid 5px;')
+PASS getComputedStyle(test).top is '0px'
+PASS getComputedStyle(test).left is '0px'
+PASS getComputedStyle(test).right is '190px'
+PASS getComputedStyle(test).bottom is '390px'
+PASS getComputedStyle(test).width is '0px'
+PASS getComputedStyle(test).height is '0px'
+
+test.setAttribute('style', 'margin: 5px;')
+PASS getComputedStyle(test).top is '0px'
+PASS getComputedStyle(test).left is '0px'
+PASS getComputedStyle(test).right is '190px'
+PASS getComputedStyle(test).bottom is '390px'
+PASS getComputedStyle(test).width is '0px'
+PASS getComputedStyle(test).height is '0px'
+test.setAttribute('style', '')
+
+test.parentNode.setAttribute('style', 'padding: 5px;')
+PASS getComputedStyle(test).top is '5px'
+PASS getComputedStyle(test).left is '5px'
+PASS getComputedStyle(test).right is '205px'
+PASS getComputedStyle(test).bottom is '405px'
+PASS getComputedStyle(test).width is '0px'
+PASS getComputedStyle(test).height is '0px'
+
+test.parentNode.setAttribute('style', 'border: solid 5px;')
+PASS getComputedStyle(test).top is '0px'
+PASS getComputedStyle(test).left is '0px'
+PASS getComputedStyle(test).right is '200px'
+PASS getComputedStyle(test).bottom is '400px'
+PASS getComputedStyle(test).width is '0px'
+PASS getComputedStyle(test).height is '0px'
+
+test.parentNode.setAttribute('style', 'margin: 5px;')
+PASS getComputedStyle(test).top is '0px'
+PASS getComputedStyle(test).left is '0px'
+PASS getComputedStyle(test).right is '200px'
+PASS getComputedStyle(test).bottom is '400px'
+PASS getComputedStyle(test).width is '0px'
+PASS getComputedStyle(test).height is '0px'
+
+No offsets (50px width/height)
+
+test.setAttribute('style', 'width: 50px; height: 50px;')
+PASS getComputedStyle(test).top is '0px'
+PASS getComputedStyle(test).left is '0px'
+PASS getComputedStyle(test).right is '150px'
+PASS getComputedStyle(test).bottom is '350px'
+PASS getComputedStyle(test).width is '50px'
+PASS getComputedStyle(test).height is '50px'
+
+test.setAttribute('style', 'width: 50px; height: 50px; padding: 5px;')
+PASS getComputedStyle(test).top is '0px'
+PASS getComputedStyle(test).left is '0px'
+PASS getComputedStyle(test).right is '140px'
+PASS getComputedStyle(test).bottom is '340px'
+PASS getComputedStyle(test).width is '50px'
+PASS getComputedStyle(test).height is '50px'
+
+test.setAttribute('style', 'width: 50px; height: 50px; border: solid 5px;')
+PASS getComputedStyle(test).top is '0px'
+PASS getComputedStyle(test).left is '0px'
+PASS getComputedStyle(test).right is '140px'
+PASS getComputedStyle(test).bottom is '340px'
+PASS getComputedStyle(test).width is '50px'
+PASS getComputedStyle(test).height is '50px'
+
+test.setAttribute('style', 'width: 50px; height: 50px; margin: 5px;')
+PASS getComputedStyle(test).top is '0px'
+PASS getComputedStyle(test).left is '0px'
+PASS getComputedStyle(test).right is '140px'
+PASS getComputedStyle(test).bottom is '340px'
+PASS getComputedStyle(test).width is '50px'
+PASS getComputedStyle(test).height is '50px'
+test.removeAttribute('style', 'margin')
+
+test.setAttribute('style', 'width: 50px; height: 50px;')
+
+test.parentNode.setAttribute('style', 'padding: 5px;')
+PASS getComputedStyle(test).top is '5px'
+PASS getComputedStyle(test).left is '5px'
+PASS getComputedStyle(test).right is '155px'
+PASS getComputedStyle(test).bottom is '355px'
+PASS getComputedStyle(test).width is '50px'
+PASS getComputedStyle(test).height is '50px'
+
+test.parentNode.setAttribute('style', 'border: solid 5px;')
+PASS getComputedStyle(test).top is '0px'
+PASS getComputedStyle(test).left is '0px'
+PASS getComputedStyle(test).right is '150px'
+PASS getComputedStyle(test).bottom is '350px'
+PASS getComputedStyle(test).width is '50px'
+PASS getComputedStyle(test).height is '50px'
+
+test.parentNode.setAttribute('style', 'margin: 5px;')
+PASS getComputedStyle(test).top is '0px'
+PASS getComputedStyle(test).left is '0px'
+PASS getComputedStyle(test).right is '150px'
+PASS getComputedStyle(test).bottom is '350px'
+PASS getComputedStyle(test).width is '50px'
+PASS getComputedStyle(test).height is '50px'
+
+No offsets (100% width/height)
+
+test.setAttribute('style', 'width: 100%; height: 100%;')
+PASS getComputedStyle(test).top is '0px'
+PASS getComputedStyle(test).left is '0px'
+PASS getComputedStyle(test).right is '0px'
+PASS getComputedStyle(test).bottom is '0px'
+PASS getComputedStyle(test).width is '200px'
+PASS getComputedStyle(test).height is '400px'
+
+test.setAttribute('style', 'width: 100%; height: 100%; padding: 5px;')
+PASS getComputedStyle(test).top is '0px'
+PASS getComputedStyle(test).left is '0px'
+PASS getComputedStyle(test).right is '-10px'
+PASS getComputedStyle(test).bottom is '-10px'
+PASS getComputedStyle(test).width is '200px'
+PASS getComputedStyle(test).height is '400px'
+test.removeAttribute('style', 'padding')
+
+test.setAttribute('style', 'width: 100%; height: 100%; border: solid 5px;')
+PASS getComputedStyle(test).top is '0px'
+PASS getComputedStyle(test).left is '0px'
+PASS getComputedStyle(test).right is '-10px'
+PASS getComputedStyle(test).bottom is '-10px'
+PASS getComputedStyle(test).width is '200px'
+PASS getComputedStyle(test).height is '400px'
+test.removeAttribute('style', 'border')
+
+test.setAttribute('style', 'width: 100%; height: 100%; margin: 5px;')
+PASS getComputedStyle(test).top is '0px'
+PASS getComputedStyle(test).left is '0px'
+PASS getComputedStyle(test).right is '-10px'
+PASS getComputedStyle(test).bottom is '-10px'
+PASS getComputedStyle(test).width is '200px'
+PASS getComputedStyle(test).height is '400px'
+test.removeAttribute('style', 'margin')
+
+test.setAttribute('style', 'width: 100%; height: 100%;')
+
+test.parentNode.setAttribute('style', 'padding: 5px;')
+PASS getComputedStyle(test).top is '5px'
+PASS getComputedStyle(test).left is '5px'
+PASS getComputedStyle(test).right is '-5px'
+PASS getComputedStyle(test).bottom is '-5px'
+PASS getComputedStyle(test).width is '210px'
+PASS getComputedStyle(test).height is '410px'
+
+test.parentNode.setAttribute('style', 'border: solid 5px;')
+PASS getComputedStyle(test).top is '0px'
+PASS getComputedStyle(test).left is '0px'
+PASS getComputedStyle(test).right is '0px'
+PASS getComputedStyle(test).bottom is '0px'
+PASS getComputedStyle(test).width is '200px'
+PASS getComputedStyle(test).height is '400px'
+
+test.parentNode.setAttribute('style', 'margin: 5px;')
+PASS getComputedStyle(test).top is '0px'
+PASS getComputedStyle(test).left is '0px'
+PASS getComputedStyle(test).right is '0px'
+PASS getComputedStyle(test).bottom is '0px'
+PASS getComputedStyle(test).width is '200px'
+PASS getComputedStyle(test).height is '400px'
+
+% offsets (top/left)
+
+test.setAttribute('style', 'top: 10%; left: 10%; width: 50%; height: 60%;')
+PASS getComputedStyle(test).top is '40px'
+PASS getComputedStyle(test).left is '20px'
+PASS getComputedStyle(test).right is '80px'
+PASS getComputedStyle(test).bottom is '120px'
+PASS getComputedStyle(test).width is '100px'
+PASS getComputedStyle(test).height is '240px'
+
+test.parentNode.setAttribute('style', 'padding: 25px;')
+PASS getComputedStyle(test).top is '45px'
+PASS getComputedStyle(test).left is '25px'
+PASS getComputedStyle(test).right is '100px'
+PASS getComputedStyle(test).bottom is '135px'
+PASS getComputedStyle(test).width is '125px'
+PASS getComputedStyle(test).height is '270px'
+test.parentNode.removeAttribute('style', 'padding')
+
+test.parentNode.setAttribute('style', 'border: solid 25px;')
+PASS getComputedStyle(test).top is '40px'
+PASS getComputedStyle(test).left is '20px'
+PASS getComputedStyle(test).right is '80px'
+PASS getComputedStyle(test).bottom is '120px'
+PASS getComputedStyle(test).width is '100px'
+PASS getComputedStyle(test).height is '240px'
+test.parentNode.removeAttribute('style', 'border')
+
+test.parentNode.setAttribute('style', 'margin: 25px;')
+PASS getComputedStyle(test).top is '40px'
+PASS getComputedStyle(test).left is '20px'
+PASS getComputedStyle(test).right is '80px'
+PASS getComputedStyle(test).bottom is '120px'
+PASS getComputedStyle(test).width is '100px'
+PASS getComputedStyle(test).height is '240px'
+test.parentNode.removeAttribute('style', 'margin')
+
+% offsets (right/bottom)
+
+test.setAttribute('style', 'right: 10%; bottom: 10%; width: 90%; height: 80%;')
+PASS getComputedStyle(test).top is '40px'
+PASS getComputedStyle(test).left is '0px'
+PASS getComputedStyle(test).right is '20px'
+PASS getComputedStyle(test).bottom is '40px'
+PASS getComputedStyle(test).width is '180px'
+PASS getComputedStyle(test).height is '320px'
+
+test.parentNode.setAttribute('style', 'padding: 25px;')
+PASS getComputedStyle(test).top is '45px'
+PASS getComputedStyle(test).left is '0px'
+PASS getComputedStyle(test).right is '25px'
+PASS getComputedStyle(test).bottom is '45px'
+PASS getComputedStyle(test).width is '225px'
+PASS getComputedStyle(test).height is '360px'
+test.parentNode.removeAttribute('style', 'padding')
+
+test.parentNode.setAttribute('style', 'border: solid 25px;')
+PASS getComputedStyle(test).top is '40px'
+PASS getComputedStyle(test).left is '0px'
+PASS getComputedStyle(test).right is '20px'
+PASS getComputedStyle(test).bottom is '40px'
+PASS getComputedStyle(test).width is '180px'
+PASS getComputedStyle(test).height is '320px'
+test.parentNode.removeAttribute('style', 'border')
+
+test.parentNode.setAttribute('style', 'margin: 25px;')
+PASS getComputedStyle(test).top is '40px'
+PASS getComputedStyle(test).left is '0px'
+PASS getComputedStyle(test).right is '20px'
+PASS getComputedStyle(test).bottom is '40px'
+PASS getComputedStyle(test).width is '180px'
+PASS getComputedStyle(test).height is '320px'
+test.parentNode.removeAttribute('style', 'margin')
+
+em offsets
+
+test.setAttribute('style', 'top: 1em; left: 2em; width: 3em; height: 4em;')
+PASS getComputedStyle(test).top is '10px'
+PASS getComputedStyle(test).left is '20px'
+PASS getComputedStyle(test).right is '150px'
+PASS getComputedStyle(test).bottom is '350px'
+PASS getComputedStyle(test).width is '30px'
+PASS getComputedStyle(test).height is '40px'
+
+test.parentNode.setAttribute('style', 'padding: 25px;')
+PASS getComputedStyle(test).top is '10px'
+PASS getComputedStyle(test).left is '20px'
+PASS getComputedStyle(test).right is '200px'
+PASS getComputedStyle(test).bottom is '400px'
+PASS getComputedStyle(test).width is '30px'
+PASS getComputedStyle(test).height is '40px'
+
+test.parentNode.setAttribute('style', 'border: solid 25px;')
+PASS getComputedStyle(test).top is '10px'
+PASS getComputedStyle(test).left is '20px'
+PASS getComputedStyle(test).right is '150px'
+PASS getComputedStyle(test).bottom is '350px'
+PASS getComputedStyle(test).width is '30px'
+PASS getComputedStyle(test).height is '40px'
+
+test.parentNode.setAttribute('style', 'margin: 25px;')
+PASS getComputedStyle(test).top is '10px'
+PASS getComputedStyle(test).left is '20px'
+PASS getComputedStyle(test).right is '150px'
+PASS getComputedStyle(test).bottom is '350px'
+PASS getComputedStyle(test).width is '30px'
+PASS getComputedStyle(test).height is '40px'
+
+Absolute Offsets
+
+test.setAttribute('style', 'position: absolute; top: 30px; height: 300px;')
+PASS getComputedStyle(test).top is '30px'
+PASS getComputedStyle(test).left is '0px'
+PASS getComputedStyle(test).right is '200px'
+PASS getComputedStyle(test).bottom is '70px'
+PASS getComputedStyle(test).width is '0px'
+PASS getComputedStyle(test).height is '300px'
+
+test.parentNode.setAttribute('style', 'padding: 25px;')
+PASS getComputedStyle(test).top is '30px'
+PASS getComputedStyle(test).left is '25px'
+PASS getComputedStyle(test).right is '225px'
+PASS getComputedStyle(test).bottom is '120px'
+PASS getComputedStyle(test).width is '0px'
+PASS getComputedStyle(test).height is '300px'
+
+test.parentNode.setAttribute('style', 'border: solid 25px;')
+PASS getComputedStyle(test).top is '30px'
+PASS getComputedStyle(test).left is '0px'
+PASS getComputedStyle(test).right is '200px'
+PASS getComputedStyle(test).bottom is '70px'
+PASS getComputedStyle(test).width is '0px'
+PASS getComputedStyle(test).height is '300px'
+
+test.parentNode.setAttribute('style', 'margin: 25px;')
+PASS getComputedStyle(test).top is '30px'
+PASS getComputedStyle(test).left is '0px'
+PASS getComputedStyle(test).right is '200px'
+PASS getComputedStyle(test).bottom is '70px'
+PASS getComputedStyle(test).width is '0px'
+PASS getComputedStyle(test).height is '300px'
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/css/getComputedStyle/getComputedStyle-offsets.html (0 => 217522)


--- trunk/LayoutTests/fast/css/getComputedStyle/getComputedStyle-offsets.html	                        (rev 0)
+++ trunk/LayoutTests/fast/css/getComputedStyle/getComputedStyle-offsets.html	2017-05-27 17:13:58 UTC (rev 217522)
@@ -0,0 +1,419 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<script src=""
+</head>
+<body>
+<style>
+
+.relative200x400 {
+    position: relative;
+    width: 200px;
+    height: 400px;
+    font-size: 10px;
+}
+
+#test {
+    position: absolute;
+}
+
+</style>
+<div id="tests">
+<div class="relative200x400"><div id="test"></div></div>
+</div>
+<script>
+
+description("Test to make sure top/bottom/left/right properly returns pixel values for any input.")
+
+var test = document.getElementById('test');
+
+
+//-----------------------------------------------------------------------------
+debug('');
+debug('No offsets (zero width/height)');
+debug('');
+shouldBe("getComputedStyle(test).top", "'0px'");
+shouldBe("getComputedStyle(test).left", "'0px'");
+shouldBe("getComputedStyle(test).right", "'200px'");
+shouldBe("getComputedStyle(test).bottom", "'400px'");
+shouldBe("getComputedStyle(test).width", "'0px'");
+shouldBe("getComputedStyle(test).height", "'0px'");
+
+// On padding/border/margin on actual node
+debug('');
+evalAndLog("test.setAttribute('style', 'padding: 5px;')");
+shouldBe("getComputedStyle(test).top", "'0px'");
+shouldBe("getComputedStyle(test).left", "'0px'");
+shouldBe("getComputedStyle(test).right", "'190px'");
+shouldBe("getComputedStyle(test).bottom", "'390px'");
+shouldBe("getComputedStyle(test).width", "'0px'");
+shouldBe("getComputedStyle(test).height", "'0px'");
+
+debug('');
+evalAndLog("test.setAttribute('style', 'border: solid 5px;')");
+shouldBe("getComputedStyle(test).top", "'0px'");
+shouldBe("getComputedStyle(test).left", "'0px'");
+shouldBe("getComputedStyle(test).right", "'190px'");
+shouldBe("getComputedStyle(test).bottom", "'390px'");
+shouldBe("getComputedStyle(test).width", "'0px'");
+shouldBe("getComputedStyle(test).height", "'0px'");
+
+debug('');
+evalAndLog("test.setAttribute('style', 'margin: 5px;')");
+shouldBe("getComputedStyle(test).top", "'0px'");
+shouldBe("getComputedStyle(test).left", "'0px'");
+shouldBe("getComputedStyle(test).right", "'190px'");
+shouldBe("getComputedStyle(test).bottom", "'390px'");
+shouldBe("getComputedStyle(test).width", "'0px'");
+shouldBe("getComputedStyle(test).height", "'0px'");
+
+evalAndLog("test.setAttribute('style', '')");
+
+// On padding/border/margin on parent node
+debug('');
+evalAndLog("test.parentNode.setAttribute('style', 'padding: 5px;')");
+shouldBe("getComputedStyle(test).top", "'5px'");
+shouldBe("getComputedStyle(test).left", "'5px'");
+shouldBe("getComputedStyle(test).right", "'205px'");
+shouldBe("getComputedStyle(test).bottom", "'405px'");
+shouldBe("getComputedStyle(test).width", "'0px'");
+shouldBe("getComputedStyle(test).height", "'0px'");
+
+debug('');
+evalAndLog("test.parentNode.setAttribute('style', 'border: solid 5px;')");
+shouldBe("getComputedStyle(test).top", "'0px'");
+shouldBe("getComputedStyle(test).left", "'0px'");
+shouldBe("getComputedStyle(test).right", "'200px'");
+shouldBe("getComputedStyle(test).bottom", "'400px'");
+shouldBe("getComputedStyle(test).width", "'0px'");
+shouldBe("getComputedStyle(test).height", "'0px'");
+
+debug('');
+evalAndLog("test.parentNode.setAttribute('style', 'margin: 5px;')");
+shouldBe("getComputedStyle(test).top", "'0px'");
+shouldBe("getComputedStyle(test).left", "'0px'");
+shouldBe("getComputedStyle(test).right", "'200px'");
+shouldBe("getComputedStyle(test).bottom", "'400px'");
+shouldBe("getComputedStyle(test).width", "'0px'");
+shouldBe("getComputedStyle(test).height", "'0px'");
+
+//-----------------------------------------------------------------------------
+debug('');
+debug('No offsets (50px width/height)');
+debug('');
+var commonStyle = "width: 50px; height: 50px;";
+evalAndLog("test.setAttribute('style', '" + commonStyle + "')");
+shouldBe("getComputedStyle(test).top", "'0px'");
+shouldBe("getComputedStyle(test).left", "'0px'");
+shouldBe("getComputedStyle(test).right", "'150px'");
+shouldBe("getComputedStyle(test).bottom", "'350px'");
+shouldBe("getComputedStyle(test).width", "'50px'");
+shouldBe("getComputedStyle(test).height", "'50px'");
+
+// On padding/border/margin on actual node
+debug('');
+evalAndLog("test.setAttribute('style', '" + commonStyle + " padding: 5px;')");
+shouldBe("getComputedStyle(test).top", "'0px'");
+shouldBe("getComputedStyle(test).left", "'0px'");
+shouldBe("getComputedStyle(test).right", "'140px'");
+shouldBe("getComputedStyle(test).bottom", "'340px'");
+shouldBe("getComputedStyle(test).width", "'50px'");
+shouldBe("getComputedStyle(test).height", "'50px'");
+
+debug('');
+evalAndLog("test.setAttribute('style', '" + commonStyle + " border: solid 5px;')");
+shouldBe("getComputedStyle(test).top", "'0px'");
+shouldBe("getComputedStyle(test).left", "'0px'");
+shouldBe("getComputedStyle(test).right", "'140px'");
+shouldBe("getComputedStyle(test).bottom", "'340px'");
+shouldBe("getComputedStyle(test).width", "'50px'");
+shouldBe("getComputedStyle(test).height", "'50px'");
+
+debug('');
+evalAndLog("test.setAttribute('style', '" + commonStyle + " margin: 5px;')");
+shouldBe("getComputedStyle(test).top", "'0px'");
+shouldBe("getComputedStyle(test).left", "'0px'");
+shouldBe("getComputedStyle(test).right", "'140px'");
+shouldBe("getComputedStyle(test).bottom", "'340px'");
+shouldBe("getComputedStyle(test).width", "'50px'");
+shouldBe("getComputedStyle(test).height", "'50px'");
+evalAndLog("test.removeAttribute('style', 'margin')");
+
+// On padding/border/margin on parent node
+debug('');
+evalAndLog("test.setAttribute('style', '" + commonStyle + "')");
+debug('');
+evalAndLog("test.parentNode.setAttribute('style', 'padding: 5px;')");
+shouldBe("getComputedStyle(test).top", "'5px'");
+shouldBe("getComputedStyle(test).left", "'5px'");
+shouldBe("getComputedStyle(test).right", "'155px'");
+shouldBe("getComputedStyle(test).bottom", "'355px'");
+shouldBe("getComputedStyle(test).width", "'50px'");
+shouldBe("getComputedStyle(test).height", "'50px'");
+
+debug('');
+evalAndLog("test.parentNode.setAttribute('style', 'border: solid 5px;')");
+shouldBe("getComputedStyle(test).top", "'0px'");
+shouldBe("getComputedStyle(test).left", "'0px'");
+shouldBe("getComputedStyle(test).right", "'150px'");
+shouldBe("getComputedStyle(test).bottom", "'350px'");
+shouldBe("getComputedStyle(test).width", "'50px'");
+shouldBe("getComputedStyle(test).height", "'50px'");
+
+debug('');
+evalAndLog("test.parentNode.setAttribute('style', 'margin: 5px;')");
+shouldBe("getComputedStyle(test).top", "'0px'");
+shouldBe("getComputedStyle(test).left", "'0px'");
+shouldBe("getComputedStyle(test).right", "'150px'");
+shouldBe("getComputedStyle(test).bottom", "'350px'");
+shouldBe("getComputedStyle(test).width", "'50px'");
+shouldBe("getComputedStyle(test).height", "'50px'");
+
+
+//-----------------------------------------------------------------------------
+debug('');
+debug('No offsets (100% width/height)');
+debug('');
+var commonStyle = "width: 100%; height: 100%;";
+evalAndLog("test.setAttribute('style', '" + commonStyle + "')");
+shouldBe("getComputedStyle(test).top", "'0px'");
+shouldBe("getComputedStyle(test).left", "'0px'");
+shouldBe("getComputedStyle(test).right", "'0px'");
+shouldBe("getComputedStyle(test).bottom", "'0px'");
+shouldBe("getComputedStyle(test).width", "'200px'");
+shouldBe("getComputedStyle(test).height", "'400px'");
+
+// On padding/border/margin on actual node
+debug('');
+evalAndLog("test.setAttribute('style', '" + commonStyle + " padding: 5px;')");
+shouldBe("getComputedStyle(test).top", "'0px'");
+shouldBe("getComputedStyle(test).left", "'0px'");
+shouldBe("getComputedStyle(test).right", "'-10px'");
+shouldBe("getComputedStyle(test).bottom", "'-10px'");
+shouldBe("getComputedStyle(test).width", "'200px'");
+shouldBe("getComputedStyle(test).height", "'400px'");
+evalAndLog("test.removeAttribute('style', 'padding')");
+
+debug('');
+evalAndLog("test.setAttribute('style', '" + commonStyle + " border: solid 5px;')");
+shouldBe("getComputedStyle(test).top", "'0px'");
+shouldBe("getComputedStyle(test).left", "'0px'");
+shouldBe("getComputedStyle(test).right", "'-10px'");
+shouldBe("getComputedStyle(test).bottom", "'-10px'");
+shouldBe("getComputedStyle(test).width", "'200px'");
+shouldBe("getComputedStyle(test).height", "'400px'");
+evalAndLog("test.removeAttribute('style', 'border')");
+
+debug('');
+evalAndLog("test.setAttribute('style', '" + commonStyle + " margin: 5px;')");
+shouldBe("getComputedStyle(test).top", "'0px'");
+shouldBe("getComputedStyle(test).left", "'0px'");
+shouldBe("getComputedStyle(test).right", "'-10px'");
+shouldBe("getComputedStyle(test).bottom", "'-10px'");
+shouldBe("getComputedStyle(test).width", "'200px'");
+shouldBe("getComputedStyle(test).height", "'400px'");
+evalAndLog("test.removeAttribute('style', 'margin')");
+
+// On padding/border/margin on parent node
+debug('');
+evalAndLog("test.setAttribute('style', '" + commonStyle + "')");
+debug('');
+evalAndLog("test.parentNode.setAttribute('style', 'padding: 5px;')");
+shouldBe("getComputedStyle(test).top", "'5px'");
+shouldBe("getComputedStyle(test).left", "'5px'");
+shouldBe("getComputedStyle(test).right", "'-5px'");
+shouldBe("getComputedStyle(test).bottom", "'-5px'");
+shouldBe("getComputedStyle(test).width", "'210px'");
+shouldBe("getComputedStyle(test).height", "'410px'");
+
+debug('');
+evalAndLog("test.parentNode.setAttribute('style', 'border: solid 5px;')");
+shouldBe("getComputedStyle(test).top", "'0px'");
+shouldBe("getComputedStyle(test).left", "'0px'");
+shouldBe("getComputedStyle(test).right", "'0px'");
+shouldBe("getComputedStyle(test).bottom", "'0px'");
+shouldBe("getComputedStyle(test).width", "'200px'");
+shouldBe("getComputedStyle(test).height", "'400px'");
+
+debug('');
+evalAndLog("test.parentNode.setAttribute('style', 'margin: 5px;')");
+shouldBe("getComputedStyle(test).top", "'0px'");
+shouldBe("getComputedStyle(test).left", "'0px'");
+shouldBe("getComputedStyle(test).right", "'0px'");
+shouldBe("getComputedStyle(test).bottom", "'0px'");
+shouldBe("getComputedStyle(test).width", "'200px'");
+shouldBe("getComputedStyle(test).height", "'400px'");
+
+//-----------------------------------------------------------------------------
+debug('');
+debug('% offsets (top/left)');
+debug('');
+evalAndLog("test.setAttribute('style', 'top: 10%; left: 10%; width: 50%; height: 60%;')");
+shouldBe("getComputedStyle(test).top", "'40px'");
+shouldBe("getComputedStyle(test).left", "'20px'");
+shouldBe("getComputedStyle(test).right", "'80px'");
+shouldBe("getComputedStyle(test).bottom", "'120px'");
+shouldBe("getComputedStyle(test).width", "'100px'");
+shouldBe("getComputedStyle(test).height", "'240px'");
+
+debug('');
+evalAndLog("test.parentNode.setAttribute('style', 'padding: 25px;')");
+shouldBe("getComputedStyle(test).top", "'45px'");
+shouldBe("getComputedStyle(test).left", "'25px'");
+shouldBe("getComputedStyle(test).right", "'100px'");
+shouldBe("getComputedStyle(test).bottom", "'135px'");
+shouldBe("getComputedStyle(test).width", "'125px'");
+shouldBe("getComputedStyle(test).height", "'270px'");
+evalAndLog("test.parentNode.removeAttribute('style', 'padding')");
+
+debug('');
+evalAndLog("test.parentNode.setAttribute('style', 'border: solid 25px;')");
+shouldBe("getComputedStyle(test).top", "'40px'");
+shouldBe("getComputedStyle(test).left", "'20px'");
+shouldBe("getComputedStyle(test).right", "'80px'");
+shouldBe("getComputedStyle(test).bottom", "'120px'");
+shouldBe("getComputedStyle(test).width", "'100px'");
+shouldBe("getComputedStyle(test).height", "'240px'");
+evalAndLog("test.parentNode.removeAttribute('style', 'border')");
+
+debug('');
+evalAndLog("test.parentNode.setAttribute('style', 'margin: 25px;')");
+shouldBe("getComputedStyle(test).top", "'40px'");
+shouldBe("getComputedStyle(test).left", "'20px'");
+shouldBe("getComputedStyle(test).right", "'80px'");
+shouldBe("getComputedStyle(test).bottom", "'120px'");
+shouldBe("getComputedStyle(test).width", "'100px'");
+shouldBe("getComputedStyle(test).height", "'240px'");
+evalAndLog("test.parentNode.removeAttribute('style', 'margin')");
+
+
+//-----------------------------------------------------------------------------
+debug('');
+debug('% offsets (right/bottom)');
+debug('');
+evalAndLog("test.setAttribute('style', 'right: 10%; bottom: 10%; width: 90%; height: 80%;')");
+shouldBe("getComputedStyle(test).top", "'40px'");
+shouldBe("getComputedStyle(test).left", "'0px'");
+shouldBe("getComputedStyle(test).right", "'20px'");
+shouldBe("getComputedStyle(test).bottom", "'40px'");
+shouldBe("getComputedStyle(test).width", "'180px'");
+shouldBe("getComputedStyle(test).height", "'320px'");
+
+
+// On padding/border/margin on parent node
+debug('');
+evalAndLog("test.parentNode.setAttribute('style', 'padding: 25px;')");
+shouldBe("getComputedStyle(test).top", "'45px'");
+shouldBe("getComputedStyle(test).left", "'0px'");
+shouldBe("getComputedStyle(test).right", "'25px'");
+shouldBe("getComputedStyle(test).bottom", "'45px'");
+shouldBe("getComputedStyle(test).width", "'225px'");
+shouldBe("getComputedStyle(test).height", "'360px'");
+evalAndLog("test.parentNode.removeAttribute('style', 'padding')");
+
+debug('');
+evalAndLog("test.parentNode.setAttribute('style', 'border: solid 25px;')");
+shouldBe("getComputedStyle(test).top", "'40px'");
+shouldBe("getComputedStyle(test).left", "'0px'");
+shouldBe("getComputedStyle(test).right", "'20px'");
+shouldBe("getComputedStyle(test).bottom", "'40px'");
+shouldBe("getComputedStyle(test).width", "'180px'");
+shouldBe("getComputedStyle(test).height", "'320px'");
+evalAndLog("test.parentNode.removeAttribute('style', 'border')");
+
+debug('');
+evalAndLog("test.parentNode.setAttribute('style', 'margin: 25px;')");
+shouldBe("getComputedStyle(test).top", "'40px'");
+shouldBe("getComputedStyle(test).left", "'0px'");
+shouldBe("getComputedStyle(test).right", "'20px'");
+shouldBe("getComputedStyle(test).bottom", "'40px'");
+shouldBe("getComputedStyle(test).width", "'180px'");
+shouldBe("getComputedStyle(test).height", "'320px'");
+evalAndLog("test.parentNode.removeAttribute('style', 'margin')");
+
+
+
+//-----------------------------------------------------------------------------
+debug('');
+debug('em offsets');
+debug('');
+evalAndLog("test.setAttribute('style', 'top: 1em; left: 2em; width: 3em; height: 4em;')");
+shouldBe("getComputedStyle(test).top", "'10px'");
+shouldBe("getComputedStyle(test).left", "'20px'");
+shouldBe("getComputedStyle(test).right", "'150px'");
+shouldBe("getComputedStyle(test).bottom", "'350px'");
+shouldBe("getComputedStyle(test).width", "'30px'");
+shouldBe("getComputedStyle(test).height", "'40px'");
+
+// On padding/border/margin on parent node
+debug('');
+evalAndLog("test.parentNode.setAttribute('style', 'padding: 25px;')");
+shouldBe("getComputedStyle(test).top", "'10px'");
+shouldBe("getComputedStyle(test).left", "'20px'");
+shouldBe("getComputedStyle(test).right", "'200px'");
+shouldBe("getComputedStyle(test).bottom", "'400px'");
+shouldBe("getComputedStyle(test).width", "'30px'");
+shouldBe("getComputedStyle(test).height", "'40px'");
+
+debug('');
+evalAndLog("test.parentNode.setAttribute('style', 'border: solid 25px;')");
+shouldBe("getComputedStyle(test).top", "'10px'");
+shouldBe("getComputedStyle(test).left", "'20px'");
+shouldBe("getComputedStyle(test).right", "'150px'");
+shouldBe("getComputedStyle(test).bottom", "'350px'");
+shouldBe("getComputedStyle(test).width", "'30px'");
+shouldBe("getComputedStyle(test).height", "'40px'");
+
+debug('');
+evalAndLog("test.parentNode.setAttribute('style', 'margin: 25px;')");
+shouldBe("getComputedStyle(test).top", "'10px'");
+shouldBe("getComputedStyle(test).left", "'20px'");
+shouldBe("getComputedStyle(test).right", "'150px'");
+shouldBe("getComputedStyle(test).bottom", "'350px'");
+shouldBe("getComputedStyle(test).width", "'30px'");
+shouldBe("getComputedStyle(test).height", "'40px'");
+
+//-----------------------------------------------------------------------------
+debug('');
+debug('Absolute Offsets');
+debug('');
+evalAndLog("test.setAttribute('style', 'position: absolute; top: 30px; height: 300px;')");
+shouldBe("getComputedStyle(test).top", "'30px'");
+shouldBe("getComputedStyle(test).left", "'0px'");
+shouldBe("getComputedStyle(test).right", "'200px'");
+shouldBe("getComputedStyle(test).bottom", "'70px'");
+shouldBe("getComputedStyle(test).width", "'0px'");
+shouldBe("getComputedStyle(test).height", "'300px'");
+
+debug('');
+evalAndLog("test.parentNode.setAttribute('style', 'padding: 25px;')");
+shouldBe("getComputedStyle(test).top", "'30px'");
+shouldBe("getComputedStyle(test).left", "'25px'");
+shouldBe("getComputedStyle(test).right", "'225px'");
+shouldBe("getComputedStyle(test).bottom", "'120px'");
+shouldBe("getComputedStyle(test).width", "'0px'");
+shouldBe("getComputedStyle(test).height", "'300px'");
+
+debug('');
+evalAndLog("test.parentNode.setAttribute('style', 'border: solid 25px;')");
+shouldBe("getComputedStyle(test).top", "'30px'");
+shouldBe("getComputedStyle(test).left", "'0px'");
+shouldBe("getComputedStyle(test).right", "'200px'");
+shouldBe("getComputedStyle(test).bottom", "'70px'");
+shouldBe("getComputedStyle(test).width", "'0px'");
+shouldBe("getComputedStyle(test).height", "'300px'");
+
+debug('');
+evalAndLog("test.parentNode.setAttribute('style', 'margin: 25px;')");
+shouldBe("getComputedStyle(test).top", "'30px'");
+shouldBe("getComputedStyle(test).left", "'0px'");
+shouldBe("getComputedStyle(test).right", "'200px'");
+shouldBe("getComputedStyle(test).bottom", "'70px'");
+shouldBe("getComputedStyle(test).width", "'0px'");
+shouldBe("getComputedStyle(test).height", "'300px'");
+
+</script>
+<script src=""
+</body>
+</html>

Modified: trunk/LayoutTests/fast/css/getComputedStyle/getComputedStyle-zoom-and-background-size-expected.txt (217521 => 217522)


--- trunk/LayoutTests/fast/css/getComputedStyle/getComputedStyle-zoom-and-background-size-expected.txt	2017-05-27 16:23:24 UTC (rev 217521)
+++ trunk/LayoutTests/fast/css/getComputedStyle/getComputedStyle-zoom-and-background-size-expected.txt	2017-05-27 17:13:58 UTC (rev 217522)
@@ -34,8 +34,6 @@
 position	PASS	absolute	absolute
 left	PASS	20px	20px
 top	PASS	20px	20px
-right	PASS	50px	50px
-bottom	PASS	50px	50px
 font-size	PASS	20px	20px
 width	PASS	400px	400px
 max-width	PASS	900px	900px
@@ -89,8 +87,6 @@
 position	PASS	absolute	absolute
 left	PASS	20px	20px
 top	PASS	20px	20px
-right	PASS	50px	50px
-bottom	PASS	50px	50px
 font-size	PASS	20px	20px
 width	PASS	400px	400px
 max-width	PASS	900px	900px

Modified: trunk/LayoutTests/fast/css/getComputedStyle/getComputedStyle-zoom-and-background-size.html (217521 => 217522)


--- trunk/LayoutTests/fast/css/getComputedStyle/getComputedStyle-zoom-and-background-size.html	2017-05-27 16:23:24 UTC (rev 217521)
+++ trunk/LayoutTests/fast/css/getComputedStyle/getComputedStyle-zoom-and-background-size.html	2017-05-27 17:13:58 UTC (rev 217522)
@@ -137,8 +137,6 @@
       
       "left": "20px",
       "top": "20px",
-      "right": "50px",
-      "bottom": "50px",
       
       "font-size": "20px",
       "width": "400px",

Modified: trunk/LayoutTests/fast/css/hover-affects-child-expected.txt (217521 => 217522)


--- trunk/LayoutTests/fast/css/hover-affects-child-expected.txt	2017-05-27 16:23:24 UTC (rev 217521)
+++ trunk/LayoutTests/fast/css/hover-affects-child-expected.txt	2017-05-27 17:13:58 UTC (rev 217522)
@@ -1,2 +1,2 @@
 This tests that a style that affects child elements when hovering over a parent element correctly recalculates the child style. To test manually move the mouse over the red square, it should become green.
-PASSED: Calculated style of inner element is correct
+FAILED: Calculated style of inner element is wrong, should be 'left: 0px'

Modified: trunk/LayoutTests/fast/css/hover-affects-child.html (217521 => 217522)


--- trunk/LayoutTests/fast/css/hover-affects-child.html	2017-05-27 16:23:24 UTC (rev 217521)
+++ trunk/LayoutTests/fast/css/hover-affects-child.html	2017-05-27 17:13:58 UTC (rev 217522)
@@ -32,10 +32,10 @@
                 var innerElem = document.getElementById('innerElem');
                 var calculatedStyle = window.getComputedStyle(innerElem);
     
-                if (calculatedStyle.getPropertyValue('left') == "auto")
+                if (calculatedStyle.getPropertyValue('left') == "0px")
                     log("PASSED: Calculated style of inner element is correct");
                 else
-                    log("FAILED: Calculated style of inner element is wrong, should be 'left: auto'");
+                    log("FAILED: Calculated style of inner element is wrong, should be 'left: 0px'");
             }
         
             function runTest() {

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (217521 => 217522)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2017-05-27 16:23:24 UTC (rev 217521)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2017-05-27 17:13:58 UTC (rev 217522)
@@ -1,3 +1,15 @@
+2017-05-27  Simon Fraser  <[email protected]>
+
+        getComputedStyle returns percentage values for left / right / top / bottom
+        https://bugs.webkit.org/show_bug.cgi?id=29084
+
+        Reviewed by Zalan Bujtas.
+        
+        New baselines (still failing).
+
+        * web-platform-tests/css-timing-1/frames-timing-functions-output-expected.txt:
+        * web-platform-tests/html/semantics/interactive-elements/the-dialog-element/centering-expected.txt:
+
 2017-05-26  Manuel Rego Casasnovas  <[email protected]>
 
         [css-grid] Add support for orthogonal positioned grid items

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css-timing-1/frames-timing-functions-output-expected.txt (217521 => 217522)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css-timing-1/frames-timing-functions-output-expected.txt	2017-05-27 16:23:24 UTC (rev 217521)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css-timing-1/frames-timing-functions-output-expected.txt	2017-05-27 17:13:58 UTC (rev 217522)
@@ -1,9 +1,9 @@
 
-FAIL For an input progress of 0.0, the output of a frames timing function is the first frame assert_equals: expected "0px" but got "auto"
-FAIL At a frame boundary, the output of a frames timing function is the next frame assert_equals: expected "0px" but got "auto"
-FAIL For an input progress of 1.0, the output of a frames timing function is the final frame assert_equals: expected "100px" but got "auto"
-FAIL The number of frames is correctly reflected in the frames timing function output assert_equals: expected "0px" but got "auto"
-FAIL The number of frames is correctly reflected in the frames timing function output on CSS Transitions assert_equals: expected "0px" but got "auto"
+FAIL For an input progress of 0.0, the output of a frames timing function is the first frame assert_equals: expected "0px" but got "8px"
+FAIL At a frame boundary, the output of a frames timing function is the next frame assert_equals: expected "0px" but got "8px"
+FAIL For an input progress of 1.0, the output of a frames timing function is the final frame assert_equals: expected "100px" but got "8px"
+FAIL The number of frames is correctly reflected in the frames timing function output assert_equals: expected "0px" but got "8px"
+FAIL The number of frames is correctly reflected in the frames timing function output on CSS Transitions assert_equals: expected "0px" but got "8px"
 FAIL frames easing with input progress greater than 1 undefined is not a function (near '...target.animate...')
 FAIL frames easing with input progress greater than 1.5 undefined is not a function (near '...target.animate...')
 FAIL frames easing with input progress less than 0 undefined is not a function (near '...target.animate...')

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/centering-expected.txt (217521 => 217522)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/centering-expected.txt	2017-05-27 16:23:24 UTC (rev 217521)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/centering-expected.txt	2017-05-27 17:13:58 UTC (rev 217522)
@@ -22,11 +22,11 @@
 FAIL vertical-rl: tall viewport assert_equals: expected "10px" but got "auto"
 FAIL vertical-lr: tall viewport assert_equals: expected "10px" but got "auto"
 FAIL vertical-lr: dialog bigger than viewport assert_equals: expected "0px" but got "auto"
-FAIL vertical-rl (dialog horizontal-tb): tall viewport assert_equals: expected "10px" but got "auto"
-FAIL vertical-lr (dialog horizontal-tb): tall viewport assert_equals: expected "10px" but got "auto"
-FAIL vertical-lr (dialog horizontal-tb): dialog bigger than viewport assert_equals: expected "0px" but got "auto"
+FAIL vertical-rl (dialog horizontal-tb): tall viewport assert_equals: expected "10px" but got "12px"
+FAIL vertical-lr (dialog horizontal-tb): tall viewport assert_equals: expected "10px" but got "-8px"
+FAIL vertical-lr (dialog horizontal-tb): dialog bigger than viewport assert_equals: expected "0px" but got "-8px"
 FAIL horizontal-tb (container vertical-rl): tall viewport assert_equals: expected "10px" but got "auto"
 FAIL vertical-rl (container horizontal-tb): tall viewport assert_equals: expected "45px" but got "auto"
-FAIL horizontal-tb (container vertical-rl) (dialog horizontal-tb): tall viewport assert_equals: expected "10px" but got "auto"
-FAIL vertical-rl (container horizontal-tb) (dialog vertical-rl): tall viewport assert_equals: expected "45px" but got "auto"
+FAIL horizontal-tb (container vertical-rl) (dialog horizontal-tb): tall viewport assert_equals: expected "10px" but got "-8px"
+FAIL vertical-rl (container horizontal-tb) (dialog vertical-rl): tall viewport assert_equals: expected "45px" but got "12px"
 

Copied: trunk/LayoutTests/platform/ios/imported/w3c/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/centering-expected.txt (from rev 217521, trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/centering-expected.txt) (0 => 217522)


--- trunk/LayoutTests/platform/ios/imported/w3c/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/centering-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/platform/ios/imported/w3c/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/centering-expected.txt	2017-05-27 17:13:58 UTC (rev 217522)
@@ -0,0 +1,32 @@
+CONSOLE MESSAGE: line 27: TypeError: document.querySelector("dialog").showModal is not a function. (In 'document.querySelector("dialog").showModal()', 'document.querySelector("dialog").showModal' is undefined)
+CONSOLE MESSAGE: line 27: TypeError: document.querySelector("dialog").showModal is not a function. (In 'document.querySelector("dialog").showModal()', 'document.querySelector("dialog").showModal' is undefined)
+CONSOLE MESSAGE: line 27: TypeError: document.querySelector("dialog").showModal is not a function. (In 'document.querySelector("dialog").showModal()', 'document.querySelector("dialog").showModal' is undefined)
+CONSOLE MESSAGE: line 27: TypeError: document.querySelector("dialog").showModal is not a function. (In 'document.querySelector("dialog").showModal()', 'document.querySelector("dialog").showModal' is undefined)
+CONSOLE MESSAGE: line 27: TypeError: document.querySelector("dialog").showModal is not a function. (In 'document.querySelector("dialog").showModal()', 'document.querySelector("dialog").showModal' is undefined)
+CONSOLE MESSAGE: line 27: TypeError: document.querySelector("dialog").showModal is not a function. (In 'document.querySelector("dialog").showModal()', 'document.querySelector("dialog").showModal' is undefined)
+CONSOLE MESSAGE: line 27: TypeError: document.querySelector("dialog").showModal is not a function. (In 'document.querySelector("dialog").showModal()', 'document.querySelector("dialog").showModal' is undefined)
+CONSOLE MESSAGE: line 27: TypeError: document.querySelector("dialog").showModal is not a function. (In 'document.querySelector("dialog").showModal()', 'document.querySelector("dialog").showModal' is undefined)
+CONSOLE MESSAGE: line 27: TypeError: document.querySelector("dialog").showModal is not a function. (In 'document.querySelector("dialog").showModal()', 'document.querySelector("dialog").showModal' is undefined)
+CONSOLE MESSAGE: line 27: TypeError: document.querySelector("dialog").showModal is not a function. (In 'document.querySelector("dialog").showModal()', 'document.querySelector("dialog").showModal' is undefined)
+CONSOLE MESSAGE: line 27: TypeError: document.querySelector("dialog").showModal is not a function. (In 'document.querySelector("dialog").showModal()', 'document.querySelector("dialog").showModal' is undefined)
+CONSOLE MESSAGE: line 27: TypeError: document.querySelector("dialog").showModal is not a function. (In 'document.querySelector("dialog").showModal()', 'document.querySelector("dialog").showModal' is undefined)
+CONSOLE MESSAGE: line 27: TypeError: document.querySelector("dialog").showModal is not a function. (In 'document.querySelector("dialog").showModal()', 'document.querySelector("dialog").showModal' is undefined)
+CONSOLE MESSAGE: line 27: TypeError: document.querySelector("dialog").showModal is not a function. (In 'document.querySelector("dialog").showModal()', 'document.querySelector("dialog").showModal' is undefined)
+CONSOLE MESSAGE: line 27: TypeError: document.querySelector("dialog").showModal is not a function. (In 'document.querySelector("dialog").showModal()', 'document.querySelector("dialog").showModal' is undefined)
+
+FAIL horizontal-tb: tall viewport assert_equals: expected "45px" but got "auto"
+FAIL horizontal-tb: wide viewport assert_equals: expected "15px" but got "auto"
+FAIL horizontal-tb: square viewport assert_equals: expected "45px" but got "auto"
+FAIL horizontal-tb: dialog and viewport match assert_equals: expected "0px" but got "auto"
+FAIL horizontal-tb: dialog bigger than viewport assert_equals: expected "0px" but got "auto"
+FAIL vertical-rl: tall viewport assert_equals: expected "10px" but got "auto"
+FAIL vertical-lr: tall viewport assert_equals: expected "10px" but got "auto"
+FAIL vertical-lr: dialog bigger than viewport assert_equals: expected "0px" but got "auto"
+FAIL vertical-rl (dialog horizontal-tb): tall viewport assert_equals: expected "10px" but got "13px"
+FAIL vertical-lr (dialog horizontal-tb): tall viewport assert_equals: expected "10px" but got "-7px"
+FAIL vertical-lr (dialog horizontal-tb): dialog bigger than viewport assert_equals: expected "0px" but got "-7px"
+FAIL horizontal-tb (container vertical-rl): tall viewport assert_equals: expected "10px" but got "auto"
+FAIL vertical-rl (container horizontal-tb): tall viewport assert_equals: expected "45px" but got "auto"
+FAIL horizontal-tb (container vertical-rl) (dialog horizontal-tb): tall viewport assert_equals: expected "10px" but got "-8px"
+FAIL vertical-rl (container horizontal-tb) (dialog vertical-rl): tall viewport assert_equals: expected "45px" but got "13px"
+

Modified: trunk/LayoutTests/platform/mac-elcapitan/fast/css/getComputedStyle/computed-style-expected.txt (217521 => 217522)


--- trunk/LayoutTests/platform/mac-elcapitan/fast/css/getComputedStyle/computed-style-expected.txt	2017-05-27 16:23:24 UTC (rev 217521)
+++ trunk/LayoutTests/platform/mac-elcapitan/fast/css/getComputedStyle/computed-style-expected.txt	2017-05-27 17:13:58 UTC (rev 217522)
@@ -30,7 +30,7 @@
 border-top-right-radius: 0px;
 border-top-style: none;
 border-top-width: 0px;
-bottom: auto;
+bottom: 16px;
 box-shadow: none;
 box-sizing: content-box;
 caption-side: top;
@@ -53,7 +53,7 @@
 hanging-punctuation: none;
 height: 576px;
 image-rendering: auto;
-left: auto;
+left: -8px;
 letter-spacing: normal;
 line-height: 18px;
 list-style-image: none;
@@ -88,7 +88,7 @@
 pointer-events: auto;
 position: static;
 resize: none;
-right: auto;
+right: 8px;
 speak: normal;
 table-layout: auto;
 tab-size: 8;
@@ -99,7 +99,7 @@
 text-shadow: none;
 text-overflow: clip;
 text-transform: none;
-top: auto;
+top: -8px;
 transform: none;
 transform-origin: 392px 288px;
 transform-style: flat;

Modified: trunk/LayoutTests/transitions/transition-to-from-auto-expected.txt (217521 => 217522)


--- trunk/LayoutTests/transitions/transition-to-from-auto-expected.txt	2017-05-27 16:23:24 UTC (rev 217521)
+++ trunk/LayoutTests/transitions/transition-to-from-auto-expected.txt	2017-05-27 17:13:58 UTC (rev 217522)
@@ -1,4 +1,4 @@
-PASS - "left" property for "test1" element at 1s saw something close to: auto
+PASS - "left" property for "test1" element at 1s saw something close to: 0
 PASS - "left" property for "test2" element at 1s saw something close to: 100
 PASS - "left" property for "test3" element at 1s saw something close to: 50
 

Modified: trunk/LayoutTests/transitions/transition-to-from-auto.html (217521 => 217522)


--- trunk/LayoutTests/transitions/transition-to-from-auto.html	2017-05-27 16:23:24 UTC (rev 217521)
+++ trunk/LayoutTests/transitions/transition-to-from-auto.html	2017-05-27 17:13:58 UTC (rev 217522)
@@ -41,7 +41,7 @@
 
     const expectedValues = [
       // [time, element-id, property, expected-value, tolerance]
-      [1, 'test1', 'left', 'auto', 2],
+      [1, 'test1', 'left', '0', 2],
       [1, 'test2', 'left', '100', 2],
       [1, 'test3', 'left', '50', 2],
     ];

Modified: trunk/Source/WebCore/ChangeLog (217521 => 217522)


--- trunk/Source/WebCore/ChangeLog	2017-05-27 16:23:24 UTC (rev 217521)
+++ trunk/Source/WebCore/ChangeLog	2017-05-27 17:13:58 UTC (rev 217522)
@@ -1,3 +1,28 @@
+2017-05-26  Simon Fraser  <[email protected]>
+
+        getComputedStyle returns percentage values for left / right / top / bottom
+        https://bugs.webkit.org/show_bug.cgi?id=29084
+
+        Reviewed by Zalan Bujtas.
+        
+        Fix getComputedStyle() to return pixel values for left / right / top / bottom, per spec.
+
+        This is mostly a merge of https://codereview.chromium.org/13871003/.
+
+        Behavior now matches Chrome and Firefox.
+
+        Test: fast/css/getComputedStyle/getComputedStyle-offsets.html
+
+        * css/CSSComputedStyleDeclaration.cpp:
+        (WebCore::getOffsetComputedLength):
+        (WebCore::getOffsetUsedStyleRelative):
+        (WebCore::getOffsetUsedStyleAbsolute):
+        (WebCore::positionOffsetValue):
+        (WebCore::positionOffsetValueIsRendererDependent):
+        (WebCore::isNonReplacedInline):
+        (WebCore::isLayoutDependent):
+        (WebCore::ComputedStyleExtractor::propertyValue):
+
 2017-05-27  Zalan Bujtas  <[email protected]>
 
         enclosingIntRect returns a rect with -1 width/height when the input FloatRect overflows integer.

Modified: trunk/Source/WebCore/css/CSSComputedStyleDeclaration.cpp (217521 => 217522)


--- trunk/Source/WebCore/css/CSSComputedStyleDeclaration.cpp	2017-05-27 16:23:24 UTC (rev 217521)
+++ trunk/Source/WebCore/css/CSSComputedStyleDeclaration.cpp	2017-05-27 17:13:58 UTC (rev 217522)
@@ -708,43 +708,100 @@
     return list;
 }
 
-static RefPtr<CSSValue> positionOffsetValue(const RenderStyle& style, CSSPropertyID propertyID)
+static Length getOffsetComputedLength(const RenderStyle& style, CSSPropertyID propertyID)
 {
-    Length length;
+    // If specified as a length, the corresponding absolute length; if specified as
+    // a percentage, the specified value; otherwise, 'auto'. Hence, we can just
+    // return the value in the style.
+    //
+    // See http://www.w3.org/TR/CSS21/cascade.html#computed-value
     switch (propertyID) {
-        case CSSPropertyLeft:
-            length = style.left();
-            break;
-        case CSSPropertyRight:
-            length = style.right();
-            break;
-        case CSSPropertyTop:
-            length = style.top();
-            break;
-        case CSSPropertyBottom:
-            length = style.bottom();
-            break;
-        default:
-            return nullptr;
+    case CSSPropertyLeft:
+        return style.left();
+    case CSSPropertyRight:
+        return style.right();
+    case CSSPropertyTop:
+        return style.top();
+    case CSSPropertyBottom:
+        return style.bottom();
+    default:
+        ASSERT_NOT_REACHED();
     }
 
-    if (style.hasOutOfFlowPosition()) {
-        if (length.isFixed())
-            return zoomAdjustedPixelValue(length.value(), style);
+    return { };
+}
 
-        return CSSValuePool::singleton().createValue(length);
+static LayoutUnit getOffsetUsedStyleRelative(RenderBox& box, CSSPropertyID propertyID)
+{
+    // For relatively positioned boxes, the offset is with respect to the top edges
+    // of the box itself. This ties together top/bottom and left/right to be
+    // opposites of each other.
+    //
+    // See http://www.w3.org/TR/CSS2/visuren.html#relative-positioning
+    //
+    // Specifically;
+    //   Since boxes are not split or stretched as a result of 'left' or
+    //   'right', the used values are always: left = -right.
+    // and
+    //   Since boxes are not split or stretched as a result of 'top' or
+    //   'bottom', the used values are always: top = -bottom.
+    switch (propertyID) {
+    case CSSPropertyTop:
+        return box.relativePositionOffset().height();
+    case CSSPropertyBottom:
+        return -(box.relativePositionOffset().height());
+    case CSSPropertyLeft:
+        return box.relativePositionOffset().width();
+    case CSSPropertyRight:
+        return -(box.relativePositionOffset().width());
+    default:
+        ASSERT_NOT_REACHED();
     }
 
-    if (style.hasInFlowPosition()) {
-        // FIXME: It's not enough to simply return "auto" values for one offset if the other side is defined.
-        // In other words if left is auto and right is not auto, then left's computed value is negative right().
-        // So we should get the opposite length unit and see if it is auto.
-        return CSSValuePool::singleton().createValue(length);
+    return 0;
+}
+
+static LayoutUnit getOffsetUsedStyleAbsolute(RenderBlock& container, RenderBox& box, CSSPropertyID propertyID)
+{
+    // For absoultely positioned boxes, the offset is how far an box's margin
+    // edge is offset below the edge of the box's containing block.
+    // See http://www.w3.org/TR/CSS2/visuren.html#position-props
+
+    // Margins are included in offsetTop/offsetLeft so we need to remove them here.
+    switch (propertyID) {
+    case CSSPropertyTop:
+        return box.offsetTop() - box.marginTop();
+    case CSSPropertyBottom:
+        return container.clientHeight() - (box.offsetTop() + box.offsetHeight()) - box.marginBottom();
+    case CSSPropertyLeft:
+        return box.offsetLeft() - box.marginLeft();
+    case CSSPropertyRight:
+        return container.clientWidth() - (box.offsetLeft() + box.offsetWidth()) - box.marginRight();
+    default:
+        ASSERT_NOT_REACHED();
     }
 
-    return CSSValuePool::singleton().createIdentifierValue(CSSValueAuto);
+    return 0;
 }
 
+static RefPtr<CSSValue> positionOffsetValue(const RenderStyle& style, CSSPropertyID propertyID, RenderObject* renderer)
+{
+    // If the element is not displayed; return the "computed value".
+    if (!renderer || !renderer->isBox())
+        return zoomAdjustedPixelValueForLength(getOffsetComputedLength(style, propertyID), style);
+
+    // We should return the "used value".
+    LayoutUnit length = 0;
+    auto& box = downcast<RenderBox>(*renderer);
+    RenderBlock* containingBlock = box.containingBlock();
+    if (box.isRelPositioned() || !containingBlock)
+        length = getOffsetUsedStyleRelative(box, propertyID);
+    else
+        length = getOffsetUsedStyleAbsolute(*containingBlock, box, propertyID);
+        
+    return zoomAdjustedPixelValue(length, style);
+}
+
 RefPtr<CSSPrimitiveValue> ComputedStyleExtractor::currentColorOrValidColor(const RenderStyle* style, const Color& color) const
 {
     // This function does NOT look at visited information, so that computed style doesn't expose that.
@@ -2199,6 +2256,11 @@
     return renderer && style && renderer->isBox() && !(style->*lengthGetter)().isFixed();
 }
 
+static bool positionOffsetValueIsRendererDependent(const RenderStyle* style, RenderObject* renderer)
+{
+    return renderer && style && renderer->isBox();
+}
+
 static CSSValueID convertToPageBreak(BreakBetween value)
 {
     if (value == PageBreakBetween || value == LeftPageBreakBetween || value == RightPageBreakBetween
@@ -2249,18 +2311,29 @@
     return CSSValueAuto;
 }
 #endif
-    
+
+static inline bool isNonReplacedInline(RenderObject& renderer)
+{
+    return renderer.isInline() && !renderer.isReplaced();
+}
+
 static bool isLayoutDependent(CSSPropertyID propertyID, const RenderStyle* style, RenderObject* renderer)
 {
     switch (propertyID) {
+    case CSSPropertyTop:
+    case CSSPropertyBottom:
+    case CSSPropertyLeft:
+    case CSSPropertyRight:
+        return positionOffsetValueIsRendererDependent(style, renderer);
     case CSSPropertyWidth:
     case CSSPropertyHeight:
+        return renderer && !renderer->isRenderSVGModelObject() && !isNonReplacedInline(*renderer);
     case CSSPropertyPerspectiveOrigin:
     case CSSPropertyTransformOrigin:
     case CSSPropertyTransform:
-    case CSSPropertyFilter:
+    case CSSPropertyFilter: // Why are filters layout-dependent?
 #if ENABLE(FILTERS_LEVEL_2)
-    case CSSPropertyWebkitBackdropFilter:
+    case CSSPropertyWebkitBackdropFilter: // Ditto for backdrop-filter.
 #endif
         return true;
     case CSSPropertyMargin: {
@@ -2371,6 +2444,13 @@
     }
 }
 
+// In CSS 2.1 the returned object should actually contain the "used values"
+// rather then the "computed values" (despite the name saying otherwise).
+//
+// See;
+// http://www.w3.org/TR/CSS21/cascade.html#used-value
+// http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration
+// https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle#Notes
 RefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropertyID propertyID, EUpdateLayout updateLayout) const
 {
     return ComputedStyleExtractor(m_element.ptr(), m_allowVisitedStyle, m_pseudoElementSpecifier).propertyValue(propertyID, updateLayout);
@@ -2829,7 +2909,7 @@
         case CSSPropertyBorderLeftWidth:
             return zoomAdjustedPixelValue(style->borderLeftWidth(), *style);
         case CSSPropertyBottom:
-            return positionOffsetValue(*style, CSSPropertyBottom);
+            return positionOffsetValue(*style, CSSPropertyBottom, renderer);
         case CSSPropertyWebkitBoxAlign:
             return cssValuePool.createValue(style->boxAlign());
 #if ENABLE(CSS_BOX_DECORATION_BREAK)
@@ -3077,7 +3157,7 @@
             if (renderer && !renderer->isRenderSVGModelObject()) {
                 // According to http://www.w3.org/TR/CSS2/visudet.html#the-height-property,
                 // the "height" property does not apply for non-replaced inline elements.
-                if (!renderer->isReplaced() && renderer->isInline())
+                if (isNonReplacedInline(*renderer))
                     return cssValuePool.createIdentifierValue(CSSValueAuto);
                 return zoomAdjustedPixelValue(sizingBox(*renderer).height(), *style);
             }
@@ -3115,7 +3195,7 @@
             return cssValuePool.createValue(style->imageResolution(), CSSPrimitiveValue::CSS_DPPX);
 #endif
         case CSSPropertyLeft:
-            return positionOffsetValue(*style, CSSPropertyLeft);
+            return positionOffsetValue(*style, CSSPropertyLeft, renderer);
         case CSSPropertyLetterSpacing:
             if (!style->letterSpacing())
                 return cssValuePool.createIdentifierValue(CSSValueNormal);
@@ -3253,7 +3333,7 @@
         case CSSPropertyPosition:
             return cssValuePool.createValue(style->position());
         case CSSPropertyRight:
-            return positionOffsetValue(*style, CSSPropertyRight);
+            return positionOffsetValue(*style, CSSPropertyRight, renderer);
         case CSSPropertyWebkitRubyPosition:
             return cssValuePool.createValue(style->rubyPosition());
         case CSSPropertyTableLayout:
@@ -3353,7 +3433,7 @@
         case CSSPropertyTextTransform:
             return cssValuePool.createValue(style->textTransform());
         case CSSPropertyTop:
-            return positionOffsetValue(*style, CSSPropertyTop);
+            return positionOffsetValue(*style, CSSPropertyTop, renderer);
         case CSSPropertyUnicodeBidi:
             return cssValuePool.createValue(style->unicodeBidi());
         case CSSPropertyVerticalAlign:
@@ -3393,7 +3473,7 @@
             if (renderer && !renderer->isRenderSVGModelObject()) {
                 // According to http://www.w3.org/TR/CSS2/visudet.html#the-width-property,
                 // the "width" property does not apply for non-replaced inline elements.
-                if (!renderer->isReplaced() && renderer->isInline())
+                if (isNonReplacedInline(*renderer))
                     return cssValuePool.createIdentifierValue(CSSValueAuto);
                 return zoomAdjustedPixelValue(sizingBox(*renderer).width(), *style);
             }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to