getComputedStyle returns percentage values for left / right / top / bottom
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 27 May 2017 17:13:58 +0000 (17:13 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 27 May 2017 17:13:58 +0000 (17:13 +0000)
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:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@217522 268f45cc-cd09-0410-ab3c-d52691b4dbfc

25 files changed:
LayoutTests/ChangeLog
LayoutTests/animations/trigger-container-scroll-boundaries-expected.txt
LayoutTests/animations/trigger-container-scroll-boundaries.html
LayoutTests/animations/trigger-container-scroll-empty-expected.txt
LayoutTests/animations/trigger-container-scroll-empty.html
LayoutTests/animations/trigger-container-scroll-simple-expected.txt
LayoutTests/animations/trigger-container-scroll-simple.html
LayoutTests/fast/css/getComputedStyle/computed-style-expected.txt
LayoutTests/fast/css/getComputedStyle/computed-style-negative-top-expected.txt
LayoutTests/fast/css/getComputedStyle/computed-style-negative-top.html
LayoutTests/fast/css/getComputedStyle/getComputedStyle-offsets-expected.txt [new file with mode: 0644]
LayoutTests/fast/css/getComputedStyle/getComputedStyle-offsets.html [new file with mode: 0644]
LayoutTests/fast/css/getComputedStyle/getComputedStyle-zoom-and-background-size-expected.txt
LayoutTests/fast/css/getComputedStyle/getComputedStyle-zoom-and-background-size.html
LayoutTests/fast/css/hover-affects-child-expected.txt
LayoutTests/fast/css/hover-affects-child.html
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/web-platform-tests/css-timing-1/frames-timing-functions-output-expected.txt
LayoutTests/imported/w3c/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/centering-expected.txt
LayoutTests/platform/ios/imported/w3c/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/centering-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac-elcapitan/fast/css/getComputedStyle/computed-style-expected.txt
LayoutTests/transitions/transition-to-from-auto-expected.txt
LayoutTests/transitions/transition-to-from-auto.html
Source/WebCore/ChangeLog
Source/WebCore/css/CSSComputedStyleDeclaration.cpp

index 0654eac..705020c 100644 (file)
@@ -1,3 +1,31 @@
+2017-05-27  Simon Fraser  <simon.fraser@apple.com>
+
+        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  <youenn@apple.com>
 
         WebRTC stats should be in milliseconds
index 2210924..552eaa6 100644 (file)
@@ -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
index a56a3d1..a2e53b4 100644 (file)
@@ -48,8 +48,8 @@ function runTest() {
     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";
index 3a6b6c8..cc8af9f 100644 (file)
@@ -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.
 
index 4ac0c35..44bcc37 100644 (file)
@@ -44,7 +44,7 @@ if (window.internals)
 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);
 }
index a3ad7e2..8a4326a 100644 (file)
@@ -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)
 
index 4594ade..fa011b0 100644 (file)
@@ -44,7 +44,7 @@ if (window.internals)
 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);
 }
index fee345f..8ad961d 100644 (file)
@@ -30,7 +30,7 @@ border-top-left-radius: 0px;
 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 @@ font-optical-sizing: auto;
 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 @@ page-break-inside: auto;
 pointer-events: auto;
 position: static;
 resize: none;
-right: auto;
+right: 8px;
 speak: normal;
 table-layout: auto;
 tab-size: 8;
@@ -100,7 +100,7 @@ text-rendering: auto;
 text-shadow: none;
 text-overflow: clip;
 text-transform: none;
-top: auto;
+top: -8px;
 transform: none;
 transform-origin: 392px 288px;
 transform-style: flat;
index 1cf6f8b..d16e42e 100644 (file)
@@ -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
+
index 582f1a0..dd29243 100644 (file)
@@ -1,16 +1,48 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../../resources/js-test-pre.js"></script>
+</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="../../../resources/js-test-post.js"></script>
 </body>
diff --git a/LayoutTests/fast/css/getComputedStyle/getComputedStyle-offsets-expected.txt b/LayoutTests/fast/css/getComputedStyle/getComputedStyle-offsets-expected.txt
new file mode 100644 (file)
index 0000000..f0af4e9
--- /dev/null
@@ -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
+
diff --git a/LayoutTests/fast/css/getComputedStyle/getComputedStyle-offsets.html b/LayoutTests/fast/css/getComputedStyle/getComputedStyle-offsets.html
new file mode 100644 (file)
index 0000000..e1a16e6
--- /dev/null
@@ -0,0 +1,419 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<script src="../../../resources/js-test-pre.js"></script>
+</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="../../../resources/js-test-post.js"></script>
+</body>
+</html>
index 0685069..d703b98 100644 (file)
@@ -34,8 +34,6 @@ outline-width PASS    2px     2px
 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 @@ outline-width PASS    2px     2px
 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
index ad6b23a..d3298d4 100644 (file)
       
       "left": "20px",
       "top": "20px",
-      "right": "50px",
-      "bottom": "50px",
       
       "font-size": "20px",
       "width": "400px",
index 89711dd..15f1e87 100644 (file)
@@ -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'
index b8cb8aa..7d6f41a 100644 (file)
                 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() {
index a571d8e..25b0ab3 100644 (file)
@@ -1,3 +1,15 @@
+2017-05-27  Simon Fraser  <simon.fraser@apple.com>
+
+        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  <rego@igalia.com>
 
         [css-grid] Add support for orthogonal positioned grid items
index d5f2d7e..0cc5dd0 100644 (file)
@@ -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...')
index c716542..217828e 100644 (file)
@@ -22,11 +22,11 @@ FAIL horizontal-tb: dialog bigger than viewport assert_equals: expected "0px" bu
 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"
 
diff --git a/LayoutTests/platform/ios/imported/w3c/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/centering-expected.txt b/LayoutTests/platform/ios/imported/w3c/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/centering-expected.txt
new file mode 100644 (file)
index 0000000..b12bbe8
--- /dev/null
@@ -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"
+
index 2c8e7a1..2513bf2 100644 (file)
@@ -30,7 +30,7 @@ border-top-left-radius: 0px;
 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 @@ font-weight: normal;
 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 @@ page-break-inside: auto;
 pointer-events: auto;
 position: static;
 resize: none;
-right: auto;
+right: 8px;
 speak: normal;
 table-layout: auto;
 tab-size: 8;
@@ -99,7 +99,7 @@ text-rendering: auto;
 text-shadow: none;
 text-overflow: clip;
 text-transform: none;
-top: auto;
+top: -8px;
 transform: none;
 transform-origin: 392px 288px;
 transform-style: flat;
index f749bae..529dcfa 100644 (file)
@@ -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
 
index 75e541a..8c17ae0 100644 (file)
@@ -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],
     ];
index 4ef9952..78c7ea7 100644 (file)
@@ -1,3 +1,28 @@
+2017-05-26  Simon Fraser  <simon.fraser@apple.com>
+
+        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  <zalan@apple.com>
 
         enclosingIntRect returns a rect with -1 width/height when the input FloatRect overflows integer.
index 9da202b..2b5648e 100644 (file)
@@ -708,41 +708,98 @@ static Ref<CSSValueList> createPositionListForLayer(CSSPropertyID propertyID, co
     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
@@ -2199,6 +2256,11 @@ static bool paddingOrMarginIsRendererDependent(const RenderStyle* style, RenderO
     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 @@ static CSSValueID convertToRegionBreak(BreakInside value)
     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 @@ static bool isImplicitlyInheritedGridOrFlexProperty(CSSPropertyID propertyID)
     }
 }
 
+// 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 @@ RefPtr<CSSValue> ComputedStyleExtractor::propertyValue(CSSPropertyID propertyID,
         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 @@ RefPtr<CSSValue> ComputedStyleExtractor::propertyValue(CSSPropertyID propertyID,
             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 @@ RefPtr<CSSValue> ComputedStyleExtractor::propertyValue(CSSPropertyID propertyID,
             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 @@ RefPtr<CSSValue> ComputedStyleExtractor::propertyValue(CSSPropertyID propertyID,
         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 @@ RefPtr<CSSValue> ComputedStyleExtractor::propertyValue(CSSPropertyID propertyID,
         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 @@ RefPtr<CSSValue> ComputedStyleExtractor::propertyValue(CSSPropertyID propertyID,
             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);
             }