Legacy scroll behavior on HTMLBodyElement should only apply to the first body element...
authorbenjamin@webkit.org <benjamin@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 13 Apr 2015 04:42:53 +0000 (04:42 +0000)
committerbenjamin@webkit.org <benjamin@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 13 Apr 2015 04:42:53 +0000 (04:42 +0000)
https://bugs.webkit.org/show_bug.cgi?id=143651

Source/WebCore:

Reviewed by Sam Weinig.

WebKit has some very weird behaviors for the scroll methods on body. This patch
address the first bug: only the first body element should have the legacy behavior.

The relevant text in spec:
-http://dev.w3.org/csswg/cssom-view/#dom-element-scrollleft
-http://dev.w3.org/csswg/cssom-view/#dom-element-scrolltop
-http://dev.w3.org/csswg/cssom-view/#dom-element-scrollwidth
-http://dev.w3.org/csswg/cssom-view/#dom-element-scrollheight

Tests: fast/dom/Element/body-scrollHeight-basics-quirks.html
       fast/dom/Element/body-scrollLeft-basics-quirks.html
       fast/dom/Element/body-scrollTop-basics-quirks.html
       fast/dom/Element/body-scrollWidth-basics-quirks.html
       fast/dom/Element/detached-body-element-does-not-scroll-main-frame-with-scrollLeft.html
       fast/dom/Element/detached-body-element-does-not-scroll-main-frame-with-scrollTop.html

* html/HTMLBodyElement.cpp:
(WebCore::HTMLBodyElement::isFirstBodyElementOfDocument):
(WebCore::HTMLBodyElement::scrollLeft):
(WebCore::HTMLBodyElement::setScrollLeft):
(WebCore::HTMLBodyElement::scrollTop):
(WebCore::HTMLBodyElement::setScrollTop):
(WebCore::HTMLBodyElement::scrollHeight):
(WebCore::HTMLBodyElement::scrollWidth):
* html/HTMLBodyElement.h:

LayoutTests:

Patch by Benjamin Poulain  <benjamin@webkit.org> and Diego Perini <diego.perini@gmail.com> on 2015-04-12
Reviewed by Sam Weinig.

* fast/dom/Element/body-scrollHeight-basics-quirks-expected.txt: Added.
* fast/dom/Element/body-scrollHeight-basics-quirks.html: Added.
* fast/dom/Element/body-scrollLeft-basics-quirks-expected.txt: Added.
* fast/dom/Element/body-scrollLeft-basics-quirks.html: Added.
* fast/dom/Element/body-scrollTop-basics-quirks-expected.txt: Added.
* fast/dom/Element/body-scrollTop-basics-quirks.html: Added.
* fast/dom/Element/body-scrollWidth-basics-quirks-expected.txt: Added.
* fast/dom/Element/body-scrollWidth-basics-quirks.html: Added.
Test the various behaviors.

* fast/dom/Element/detached-body-element-does-not-scroll-main-frame-with-scrollLeft-expected.txt: Added.
* fast/dom/Element/detached-body-element-does-not-scroll-main-frame-with-scrollLeft.html: Added.
* fast/dom/Element/detached-body-element-does-not-scroll-main-frame-with-scrollTop-expected.txt: Added.
* fast/dom/Element/detached-body-element-does-not-scroll-main-frame-with-scrollTop.html: Added.
Those tests target specifically the bug.

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

16 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/dom/Element/body-scrollHeight-basics-quirks-expected.txt [new file with mode: 0644]
LayoutTests/fast/dom/Element/body-scrollHeight-basics-quirks.html [new file with mode: 0644]
LayoutTests/fast/dom/Element/body-scrollLeft-basics-quirks-expected.txt [new file with mode: 0644]
LayoutTests/fast/dom/Element/body-scrollLeft-basics-quirks.html [new file with mode: 0644]
LayoutTests/fast/dom/Element/body-scrollTop-basics-quirks-expected.txt [new file with mode: 0644]
LayoutTests/fast/dom/Element/body-scrollTop-basics-quirks.html [new file with mode: 0644]
LayoutTests/fast/dom/Element/body-scrollWidth-basics-quirks-expected.txt [new file with mode: 0644]
LayoutTests/fast/dom/Element/body-scrollWidth-basics-quirks.html [new file with mode: 0644]
LayoutTests/fast/dom/Element/detached-body-element-does-not-scroll-main-frame-with-scrollLeft-expected.txt [new file with mode: 0644]
LayoutTests/fast/dom/Element/detached-body-element-does-not-scroll-main-frame-with-scrollLeft.html [new file with mode: 0644]
LayoutTests/fast/dom/Element/detached-body-element-does-not-scroll-main-frame-with-scrollTop-expected.txt [new file with mode: 0644]
LayoutTests/fast/dom/Element/detached-body-element-does-not-scroll-main-frame-with-scrollTop.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/html/HTMLBodyElement.cpp
Source/WebCore/html/HTMLBodyElement.h

index 6b08d8a..49d3bac 100644 (file)
@@ -1,3 +1,26 @@
+2015-04-12  Benjamin Poulain  <benjamin@webkit.org> and Diego Perini  <diego.perini@gmail.com>
+
+        Legacy scroll behavior on HTMLBodyElement should only apply to the first body element of a document
+        https://bugs.webkit.org/show_bug.cgi?id=143651
+
+        Reviewed by Sam Weinig.
+
+        * fast/dom/Element/body-scrollHeight-basics-quirks-expected.txt: Added.
+        * fast/dom/Element/body-scrollHeight-basics-quirks.html: Added.
+        * fast/dom/Element/body-scrollLeft-basics-quirks-expected.txt: Added.
+        * fast/dom/Element/body-scrollLeft-basics-quirks.html: Added.
+        * fast/dom/Element/body-scrollTop-basics-quirks-expected.txt: Added.
+        * fast/dom/Element/body-scrollTop-basics-quirks.html: Added.
+        * fast/dom/Element/body-scrollWidth-basics-quirks-expected.txt: Added.
+        * fast/dom/Element/body-scrollWidth-basics-quirks.html: Added.
+        Test the various behaviors.
+
+        * fast/dom/Element/detached-body-element-does-not-scroll-main-frame-with-scrollLeft-expected.txt: Added.
+        * fast/dom/Element/detached-body-element-does-not-scroll-main-frame-with-scrollLeft.html: Added.
+        * fast/dom/Element/detached-body-element-does-not-scroll-main-frame-with-scrollTop-expected.txt: Added.
+        * fast/dom/Element/detached-body-element-does-not-scroll-main-frame-with-scrollTop.html: Added.
+        Those tests target specifically the bug.
+
 2015-04-12  Gyuyoung Kim  <gyuyoung.kim@webkit.org>
 
         [EFL] Enable Media Source
diff --git a/LayoutTests/fast/dom/Element/body-scrollHeight-basics-quirks-expected.txt b/LayoutTests/fast/dom/Element/body-scrollHeight-basics-quirks-expected.txt
new file mode 100644 (file)
index 0000000..6bb304e
--- /dev/null
@@ -0,0 +1,29 @@
+Test the "scrollHeight" properties on the body element in quirks mode.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Initial values
+PASS document.body.scrollHeight is document.documentElement.scrollHeight
+
+Now we create a body element, it should not have a scrollHeight since it is not the first body element of the document.
+PASS document.body.scrollHeight is document.documentElement.scrollHeight
+PASS floatingBody.scrollHeight is 0
+
+We add a new body element after the first body element, this should have no impact on the state.
+PASS document.body.scrollHeight is document.documentElement.scrollHeight
+PASS secondSiblingBody.scrollHeight is secondSiblingBody.clientHeight
+PASS document.body.scrollHeight is not secondSiblingBody.scrollHeight
+
+We add a new body element inside the first body element, this should have no impact on the state.
+PASS document.body.scrollHeight is document.documentElement.scrollHeight
+PASS bodyChildOfMainBody.scrollHeight is bodyChildOfMainBody.clientHeight
+PASS document.body.scrollHeight is not bodyChildOfMainBody.scrollHeight
+
+Getting the scrollHeight should not require a renderer.
+PASS document.body.style.display = 'none' is 'none'
+PASS document.body.scrollHeight is document.documentElement.scrollHeight
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/dom/Element/body-scrollHeight-basics-quirks.html b/LayoutTests/fast/dom/Element/body-scrollHeight-basics-quirks.html
new file mode 100644 (file)
index 0000000..eba3502
--- /dev/null
@@ -0,0 +1,58 @@
+<html>
+    <head>
+        <style>
+            div {
+                height: 9999px;
+                width: 9999px;
+            }
+        </style>
+        <script src="../../../resources/js-test-pre.js"></script>
+        <script>
+            jsTestIsAsync = true;
+
+            function runTest() {
+                description('Test the "scrollHeight" properties on the body element in quirks mode.');
+
+                debug("Initial values");
+                shouldBe("document.body.scrollHeight", "document.documentElement.scrollHeight");
+
+                debug("");
+                debug("Now we create a body element, it should not have a scrollHeight since it is not the first body element of the document.");
+                floatingBody = document.createElement('body');
+                shouldBe("document.body.scrollHeight", "document.documentElement.scrollHeight");
+                shouldBe("floatingBody.scrollHeight", "0");
+
+                secondSiblingBody = document.createElement('body');
+                document.documentElement.appendChild(secondSiblingBody);
+                debug("");
+                debug("We add a new body element after the first body element, this should have no impact on the state.");
+                shouldBe("document.body.scrollHeight", "document.documentElement.scrollHeight");
+                shouldBe("secondSiblingBody.scrollHeight", "secondSiblingBody.clientHeight");
+                shouldNotBe("document.body.scrollHeight", "secondSiblingBody.scrollHeight");
+
+                bodyChildOfMainBody = document.createElement('body');
+                document.body.appendChild(bodyChildOfMainBody);
+                debug("");
+                debug("We add a new body element inside the first body element, this should have no impact on the state.");
+                shouldBe("document.body.scrollHeight", "document.documentElement.scrollHeight");
+                shouldBe("bodyChildOfMainBody.scrollHeight", "bodyChildOfMainBody.clientHeight");
+                shouldNotBe("document.body.scrollHeight", "bodyChildOfMainBody.scrollHeight");
+
+                debug("");
+                debug("Getting the scrollHeight should not require a renderer.");
+                shouldBe("document.body.style.display = 'none'", "'none'");
+                shouldBe("document.body.scrollHeight", "document.documentElement.scrollHeight");
+
+                // Finally, let's clear the state to make this simpler for manual testing.
+                document.body.style.display = "block";
+                window.scrollTo(0, 0);
+
+                finishJSTest();
+            }
+        </script>
+    </head>
+    <body onload="runTest()">
+        <div></div>
+        <script src="../../../resources/js-test-post.js"></script>
+    </body>
+</html>
diff --git a/LayoutTests/fast/dom/Element/body-scrollLeft-basics-quirks-expected.txt b/LayoutTests/fast/dom/Element/body-scrollLeft-basics-quirks-expected.txt
new file mode 100644 (file)
index 0000000..d4d63e2
--- /dev/null
@@ -0,0 +1,134 @@
+Test the "scrollLeft" properties on the body element in quirks mode.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Initial values
+PASS document.body.scrollLeft is 0
+PASS document.body.scrollTop is 0
+PASS document.documentElement.scrollLeft is 0
+PASS document.documentElement.scrollTop is 0
+PASS window.scrollX is 0
+PASS window.scrollY is 0
+
+Let set the scrollLeft value on the main body element (document.body), in quirks mode, this should change the main frame's scroll position.
+PASS document.body.scrollLeft = 42 is 42
+PASS document.body.scrollLeft is 42
+PASS document.body.scrollTop is 0
+PASS document.documentElement.scrollLeft is 0
+PASS document.documentElement.scrollTop is 0
+PASS window.scrollX is 42
+PASS window.scrollY is 0
+
+Change scrollX, this should have no effect on the horizontal scrolling
+PASS window.scrollBy(0, 21) is undefined
+PASS document.body.scrollLeft is 42
+PASS document.body.scrollTop is 21
+PASS document.documentElement.scrollLeft is 0
+PASS document.documentElement.scrollTop is 0
+PASS window.scrollX is 42
+PASS window.scrollY is 21
+
+Now we create a body element, completely detached from the DOM tree. This should not change the scroll position in any way.
+PASS floatingBody.scrollLeft is 0
+PASS floatingBody.scrollTop is 0
+PASS document.body.scrollLeft is 42
+PASS document.body.scrollTop is 21
+PASS document.documentElement.scrollLeft is 0
+PASS document.documentElement.scrollTop is 0
+PASS window.scrollX is 42
+PASS window.scrollY is 21
+
+Setting the scroll position on that detached body element should not affect the main frame since it is not the first body element of the document.
+PASS floatingBody.scrollLeft = 654 is 654
+PASS floatingBody.scrollLeft is 0
+PASS floatingBody.scrollTop is 0
+PASS document.body.scrollLeft is 42
+PASS document.body.scrollTop is 21
+PASS document.documentElement.scrollLeft is 0
+PASS document.documentElement.scrollTop is 0
+PASS window.scrollX is 42
+PASS window.scrollY is 21
+
+We add a new body element after the first body element, this should have no impact on the state.
+PASS secondSiblingBody.scrollLeft is 0
+PASS secondSiblingBody.scrollTop is 0
+PASS document.body.scrollLeft is 42
+PASS document.body.scrollTop is 21
+PASS document.documentElement.scrollLeft is 0
+PASS document.documentElement.scrollTop is 0
+PASS window.scrollX is 42
+PASS window.scrollY is 21
+
+Setting a "scrollTop" on secondSiblingBody should not affect the main frame.
+PASS secondSiblingBody.scrollLeft = 987 is 987
+PASS secondSiblingBody.scrollLeft is 0
+PASS secondSiblingBody.scrollTop is 0
+PASS document.body.scrollLeft is 42
+PASS document.body.scrollTop is 21
+PASS document.documentElement.scrollLeft is 0
+PASS document.documentElement.scrollTop is 0
+PASS window.scrollX is 42
+PASS window.scrollY is 21
+
+We add a new body element inside the first body element, this should have no impact on the state.
+PASS bodyChildOfMainBody.scrollLeft is 0
+PASS bodyChildOfMainBody.scrollTop is 0
+PASS document.body.scrollLeft is 42
+PASS document.body.scrollTop is 21
+PASS document.documentElement.scrollLeft is 0
+PASS document.documentElement.scrollTop is 0
+PASS window.scrollX is 42
+PASS window.scrollY is 21
+
+Setting a "scrollTop" on bodyChildOfMainBody should not affect the main frame.
+PASS bodyChildOfMainBody.scrollLeft = 57 is 57
+PASS bodyChildOfMainBody.scrollLeft is 0
+PASS bodyChildOfMainBody.scrollTop is 0
+PASS document.body.scrollLeft is 42
+PASS document.body.scrollTop is 21
+PASS document.documentElement.scrollLeft is 0
+PASS document.documentElement.scrollTop is 0
+PASS window.scrollX is 42
+PASS window.scrollY is 21
+
+Now we insert a new body element *before* the existing one. It will replace the existing element as the first body element of the document.
+PASS document.body === newMainBody is true
+PASS document.body !== oldBodyElement is true
+Since we are in quirks mode, the new body element gets the scroll position from the frame, and the old one lose its scroll position.
+PASS oldBodyElement.scrollLeft is 0
+PASS oldBodyElement.scrollTop is 0
+PASS document.body.scrollLeft is 42
+PASS document.body.scrollTop is 21
+PASS document.documentElement.scrollLeft is 0
+PASS document.documentElement.scrollTop is 0
+PASS window.scrollX is 42
+PASS window.scrollY is 21
+
+Scrolling that new body should work as expected.
+PASS document.body.scrollLeft = 68 is 68
+PASS oldBodyElement.scrollLeft = 894 is 894
+PASS oldBodyElement.scrollLeft is 0
+PASS oldBodyElement.scrollTop is 0
+PASS document.body.scrollLeft is 68
+PASS document.body.scrollTop is 21
+PASS document.documentElement.scrollLeft is 0
+PASS document.documentElement.scrollTop is 0
+PASS window.scrollX is 68
+PASS window.scrollY is 21
+
+Scrolling the main frame should not require a renderer.
+PASS document.body.style.display = 'none' is 'none'
+PASS document.body.scrollLeft = 54 is 54
+PASS oldBodyElement.scrollLeft is 0
+PASS oldBodyElement.scrollTop is 0
+PASS document.body.scrollLeft is 54
+PASS document.body.scrollTop is 21
+PASS document.documentElement.scrollLeft is 0
+PASS document.documentElement.scrollTop is 0
+PASS window.scrollX is 54
+PASS window.scrollY is 21
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/dom/Element/body-scrollLeft-basics-quirks.html b/LayoutTests/fast/dom/Element/body-scrollLeft-basics-quirks.html
new file mode 100644 (file)
index 0000000..bf9fc57
--- /dev/null
@@ -0,0 +1,175 @@
+<html>
+    <head>
+        <style>
+            div {
+                height: 9999px;
+                width: 9999px;
+            }
+        </style>
+        <script src="../../../resources/js-test-pre.js"></script>
+        <script>
+            jsTestIsAsync = true;
+
+            function runTest() {
+                description('Test the "scrollLeft" properties on the body element in quirks mode.');
+
+                debug("Initial values");
+                shouldBe("document.body.scrollLeft", "0");
+                shouldBe("document.body.scrollTop", "0");
+                shouldBe("document.documentElement.scrollLeft", "0");
+                shouldBe("document.documentElement.scrollTop", "0");
+                shouldBe("window.scrollX", "0");
+                shouldBe("window.scrollY", "0");
+
+                debug("");
+                debug("Let set the scrollLeft value on the main body element (document.body), in quirks mode, this should change the main frame's scroll position.");
+                shouldBe("document.body.scrollLeft = 42", "42");
+                shouldBe("document.body.scrollLeft", "42");
+                shouldBe("document.body.scrollTop", "0");
+                shouldBe("document.documentElement.scrollLeft", "0");
+                shouldBe("document.documentElement.scrollTop", "0");
+                shouldBe("window.scrollX", "42");
+                shouldBe("window.scrollY", "0");
+
+                debug("");
+                debug("Change scrollX, this should have no effect on the horizontal scrolling");
+                shouldBe("window.scrollBy(0, 21)", "undefined");
+                shouldBe("document.body.scrollLeft", "42");
+                shouldBe("document.body.scrollTop", "21");
+                shouldBe("document.documentElement.scrollLeft", "0");
+                shouldBe("document.documentElement.scrollTop", "0");
+                shouldBe("window.scrollX", "42");
+                shouldBe("window.scrollY", "21");
+
+                debug("");
+                debug("Now we create a body element, completely detached from the DOM tree. This should not change the scroll position in any way.");
+                floatingBody = document.createElement('body');
+                shouldBe("floatingBody.scrollLeft", "0");
+                shouldBe("floatingBody.scrollTop", "0");
+                shouldBe("document.body.scrollLeft", "42");
+                shouldBe("document.body.scrollTop", "21");
+                shouldBe("document.documentElement.scrollLeft", "0");
+                shouldBe("document.documentElement.scrollTop", "0");
+                shouldBe("window.scrollX", "42");
+                shouldBe("window.scrollY", "21");
+
+                debug("");
+                debug("Setting the scroll position on that detached body element should not affect the main frame since it is not the first body element of the document.");
+                shouldBe("floatingBody.scrollLeft = 654", "654");
+                shouldBe("floatingBody.scrollLeft", "0");
+                shouldBe("floatingBody.scrollTop", "0");
+                shouldBe("document.body.scrollLeft", "42");
+                shouldBe("document.body.scrollTop", "21");
+                shouldBe("document.documentElement.scrollLeft", "0");
+                shouldBe("document.documentElement.scrollTop", "0");
+                shouldBe("window.scrollX", "42");
+                shouldBe("window.scrollY", "21");
+
+                secondSiblingBody = document.createElement('body');
+                document.documentElement.appendChild(secondSiblingBody);
+                debug("");
+                debug("We add a new body element after the first body element, this should have no impact on the state.");
+                shouldBe("secondSiblingBody.scrollLeft", "0");
+                shouldBe("secondSiblingBody.scrollTop", "0");
+                shouldBe("document.body.scrollLeft", "42");
+                shouldBe("document.body.scrollTop", "21");
+                shouldBe("document.documentElement.scrollLeft", "0");
+                shouldBe("document.documentElement.scrollTop", "0");
+                shouldBe("window.scrollX", "42");
+                shouldBe("window.scrollY", "21");
+
+                debug("");
+                debug("Setting a \"scrollTop\" on secondSiblingBody should not affect the main frame.");
+                shouldBe("secondSiblingBody.scrollLeft = 987", "987");
+                shouldBe("secondSiblingBody.scrollLeft", "0");
+                shouldBe("secondSiblingBody.scrollTop", "0");
+                shouldBe("document.body.scrollLeft", "42");
+                shouldBe("document.body.scrollTop", "21");
+                shouldBe("document.documentElement.scrollLeft", "0");
+                shouldBe("document.documentElement.scrollTop", "0");
+                shouldBe("window.scrollX", "42");
+                shouldBe("window.scrollY", "21");
+
+                bodyChildOfMainBody = document.createElement('body');
+                document.body.appendChild(bodyChildOfMainBody);
+                debug("");
+                debug("We add a new body element inside the first body element, this should have no impact on the state.");
+                shouldBe("bodyChildOfMainBody.scrollLeft", "0");
+                shouldBe("bodyChildOfMainBody.scrollTop", "0");
+                shouldBe("document.body.scrollLeft", "42");
+                shouldBe("document.body.scrollTop", "21");
+                shouldBe("document.documentElement.scrollLeft", "0");
+                shouldBe("document.documentElement.scrollTop", "0");
+                shouldBe("window.scrollX", "42");
+                shouldBe("window.scrollY", "21");
+
+                debug("");
+                debug("Setting a \"scrollTop\" on bodyChildOfMainBody should not affect the main frame.");
+                shouldBe("bodyChildOfMainBody.scrollLeft = 57", "57");
+                shouldBe("bodyChildOfMainBody.scrollLeft", "0");
+                shouldBe("bodyChildOfMainBody.scrollTop", "0");
+                shouldBe("document.body.scrollLeft", "42");
+                shouldBe("document.body.scrollTop", "21");
+                shouldBe("document.documentElement.scrollLeft", "0");
+                shouldBe("document.documentElement.scrollTop", "0");
+                shouldBe("window.scrollX", "42");
+                shouldBe("window.scrollY", "21");
+
+                debug("");
+                debug("Now we insert a new body element *before* the existing one. It will replace the existing element as the first body element of the document.");
+                oldBodyElement = document.body;
+                newMainBody = document.createElement('body');
+                document.documentElement.insertBefore(newMainBody, oldBodyElement);
+                shouldBeTrue("document.body === newMainBody");
+                shouldBeTrue("document.body !== oldBodyElement");
+
+                debug("Since we are in quirks mode, the new body element gets the scroll position from the frame, and the old one lose its scroll position.");
+                shouldBe("oldBodyElement.scrollLeft", "0");
+                shouldBe("oldBodyElement.scrollTop", "0");
+                shouldBe("document.body.scrollLeft", "42");
+                shouldBe("document.body.scrollTop", "21");
+                shouldBe("document.documentElement.scrollLeft", "0");
+                shouldBe("document.documentElement.scrollTop", "0");
+                shouldBe("window.scrollX", "42");
+                shouldBe("window.scrollY", "21");
+
+                debug("");
+                debug("Scrolling that new body should work as expected.");
+                shouldBe("document.body.scrollLeft = 68", "68");
+                shouldBe("oldBodyElement.scrollLeft = 894", "894");
+
+                shouldBe("oldBodyElement.scrollLeft", "0");
+                shouldBe("oldBodyElement.scrollTop", "0");
+                shouldBe("document.body.scrollLeft", "68");
+                shouldBe("document.body.scrollTop", "21");
+                shouldBe("document.documentElement.scrollLeft", "0");
+                shouldBe("document.documentElement.scrollTop", "0");
+                shouldBe("window.scrollX", "68");
+                shouldBe("window.scrollY", "21");
+
+                debug("");
+                debug("Scrolling the main frame should not require a renderer.");
+                shouldBe("document.body.style.display = 'none'", "'none'");
+                shouldBe("document.body.scrollLeft = 54", "54");
+                shouldBe("oldBodyElement.scrollLeft", "0");
+                shouldBe("oldBodyElement.scrollTop", "0");
+                shouldBe("document.body.scrollLeft", "54");
+                shouldBe("document.body.scrollTop", "21");
+                shouldBe("document.documentElement.scrollLeft", "0");
+                shouldBe("document.documentElement.scrollTop", "0");
+                shouldBe("window.scrollX", "54");
+                shouldBe("window.scrollY", "21");
+
+                // Finally, let's clear the state to make this simpler for manual testing.
+                newMainBody.parentNode.removeChild(newMainBody);
+                window.scrollTo(0, 0);
+
+                finishJSTest();
+            }
+        </script>
+    </head>
+    <body onload="runTest()">
+        <div></div>
+        <script src="../../../resources/js-test-post.js"></script>
+    </body>
+</html>
diff --git a/LayoutTests/fast/dom/Element/body-scrollTop-basics-quirks-expected.txt b/LayoutTests/fast/dom/Element/body-scrollTop-basics-quirks-expected.txt
new file mode 100644 (file)
index 0000000..8e0a345
--- /dev/null
@@ -0,0 +1,134 @@
+Test the "scrollTop" properties on the body element in quirks mode.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Initial values
+PASS document.body.scrollLeft is 0
+PASS document.body.scrollTop is 0
+PASS document.documentElement.scrollLeft is 0
+PASS document.documentElement.scrollTop is 0
+PASS window.scrollX is 0
+PASS window.scrollY is 0
+
+Let set the scrollTop value on the main body element (document.body), in quirks mode, this should change the main frame's scroll position.
+PASS document.body.scrollTop = 42 is 42
+PASS document.body.scrollLeft is 0
+PASS document.body.scrollTop is 42
+PASS document.documentElement.scrollLeft is 0
+PASS document.documentElement.scrollTop is 0
+PASS window.scrollX is 0
+PASS window.scrollY is 42
+
+Change scrollX, this should have no effect on the vertical scrolling
+PASS window.scrollBy(21, 0) is undefined
+PASS document.body.scrollLeft is 21
+PASS document.body.scrollTop is 42
+PASS document.documentElement.scrollLeft is 0
+PASS document.documentElement.scrollTop is 0
+PASS window.scrollX is 21
+PASS window.scrollY is 42
+
+Now we create a body element, completely detached from the DOM tree. This should not change the scroll position in any way.
+PASS floatingBody.scrollLeft is 0
+PASS floatingBody.scrollTop is 0
+PASS document.body.scrollLeft is 21
+PASS document.body.scrollTop is 42
+PASS document.documentElement.scrollLeft is 0
+PASS document.documentElement.scrollTop is 0
+PASS window.scrollX is 21
+PASS window.scrollY is 42
+
+Setting the scroll position on that detached body element should not affect the main frame since it is not the first body element of the document.
+PASS floatingBody.scrollTop = 500 is 500
+PASS floatingBody.scrollLeft is 0
+PASS floatingBody.scrollTop is 0
+PASS document.body.scrollLeft is 21
+PASS document.body.scrollTop is 42
+PASS document.documentElement.scrollLeft is 0
+PASS document.documentElement.scrollTop is 0
+PASS window.scrollX is 21
+PASS window.scrollY is 42
+
+We add a new body element after the first body element, this should have no impact on the state.
+PASS secondSiblingBody.scrollLeft is 0
+PASS secondSiblingBody.scrollTop is 0
+PASS document.body.scrollLeft is 21
+PASS document.body.scrollTop is 42
+PASS document.documentElement.scrollLeft is 0
+PASS document.documentElement.scrollTop is 0
+PASS window.scrollX is 21
+PASS window.scrollY is 42
+
+Setting a "scrollTop" on secondSiblingBody should not affect the main frame.
+PASS secondSiblingBody.scrollTop = 321 is 321
+PASS secondSiblingBody.scrollLeft is 0
+PASS secondSiblingBody.scrollTop is 0
+PASS document.body.scrollLeft is 21
+PASS document.body.scrollTop is 42
+PASS document.documentElement.scrollLeft is 0
+PASS document.documentElement.scrollTop is 0
+PASS window.scrollX is 21
+PASS window.scrollY is 42
+
+We add a new body element inside the first body element, this should have no impact on the state.
+PASS bodyChildOfMainBody.scrollLeft is 0
+PASS bodyChildOfMainBody.scrollTop is 0
+PASS document.body.scrollLeft is 21
+PASS document.body.scrollTop is 42
+PASS document.documentElement.scrollLeft is 0
+PASS document.documentElement.scrollTop is 0
+PASS window.scrollX is 21
+PASS window.scrollY is 42
+
+Setting a "scrollTop" on bodyChildOfMainBody should not affect the main frame.
+PASS bodyChildOfMainBody.scrollTop = 57 is 57
+PASS bodyChildOfMainBody.scrollLeft is 0
+PASS bodyChildOfMainBody.scrollTop is 0
+PASS document.body.scrollLeft is 21
+PASS document.body.scrollTop is 42
+PASS document.documentElement.scrollLeft is 0
+PASS document.documentElement.scrollTop is 0
+PASS window.scrollX is 21
+PASS window.scrollY is 42
+
+Now we insert a new body element *before* the existing one. It will replace the existing element as the first body element of the document.
+PASS document.body === newMainBody is true
+PASS document.body !== oldBodyElement is true
+Since we are in quirks mode, the new body element gets the scroll position from the frame, and the old one lose its scroll position.
+PASS oldBodyElement.scrollLeft is 0
+PASS oldBodyElement.scrollTop is 0
+PASS document.body.scrollLeft is 21
+PASS document.body.scrollTop is 42
+PASS document.documentElement.scrollLeft is 0
+PASS document.documentElement.scrollTop is 0
+PASS window.scrollX is 21
+PASS window.scrollY is 42
+
+Scrolling that new body should work as expected.
+PASS document.body.scrollTop = 68 is 68
+PASS oldBodyElement.scrollTop = 894 is 894
+PASS oldBodyElement.scrollLeft is 0
+PASS oldBodyElement.scrollTop is 0
+PASS document.body.scrollLeft is 21
+PASS document.body.scrollTop is 68
+PASS document.documentElement.scrollLeft is 0
+PASS document.documentElement.scrollTop is 0
+PASS window.scrollX is 21
+PASS window.scrollY is 68
+
+Scrolling the main frame should not require a renderer.
+PASS document.body.style.display = 'none' is 'none'
+PASS document.body.scrollTop = 54 is 54
+PASS oldBodyElement.scrollLeft is 0
+PASS oldBodyElement.scrollTop is 0
+PASS document.body.scrollLeft is 21
+PASS document.body.scrollTop is 54
+PASS document.documentElement.scrollLeft is 0
+PASS document.documentElement.scrollTop is 0
+PASS window.scrollX is 21
+PASS window.scrollY is 54
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/dom/Element/body-scrollTop-basics-quirks.html b/LayoutTests/fast/dom/Element/body-scrollTop-basics-quirks.html
new file mode 100644 (file)
index 0000000..e8f1d89
--- /dev/null
@@ -0,0 +1,175 @@
+<html>
+    <head>
+        <style>
+            div {
+                height: 9999px;
+                width: 9999px;
+            }
+        </style>
+        <script src="../../../resources/js-test-pre.js"></script>
+        <script>
+            jsTestIsAsync = true;
+
+            function runTest() {
+                description('Test the "scrollTop" properties on the body element in quirks mode.');
+
+                debug("Initial values");
+                shouldBe("document.body.scrollLeft", "0");
+                shouldBe("document.body.scrollTop", "0");
+                shouldBe("document.documentElement.scrollLeft", "0");
+                shouldBe("document.documentElement.scrollTop", "0");
+                shouldBe("window.scrollX", "0");
+                shouldBe("window.scrollY", "0");
+
+                debug("");
+                debug("Let set the scrollTop value on the main body element (document.body), in quirks mode, this should change the main frame's scroll position.");
+                shouldBe("document.body.scrollTop = 42", "42");
+                shouldBe("document.body.scrollLeft", "0");
+                shouldBe("document.body.scrollTop", "42");
+                shouldBe("document.documentElement.scrollLeft", "0");
+                shouldBe("document.documentElement.scrollTop", "0");
+                shouldBe("window.scrollX", "0");
+                shouldBe("window.scrollY", "42");
+
+                debug("");
+                debug("Change scrollX, this should have no effect on the vertical scrolling");
+                shouldBe("window.scrollBy(21, 0)", "undefined");
+                shouldBe("document.body.scrollLeft", "21");
+                shouldBe("document.body.scrollTop", "42");
+                shouldBe("document.documentElement.scrollLeft", "0");
+                shouldBe("document.documentElement.scrollTop", "0");
+                shouldBe("window.scrollX", "21");
+                shouldBe("window.scrollY", "42");
+
+                debug("");
+                debug("Now we create a body element, completely detached from the DOM tree. This should not change the scroll position in any way.");
+                floatingBody = document.createElement('body');
+                shouldBe("floatingBody.scrollLeft", "0");
+                shouldBe("floatingBody.scrollTop", "0");
+                shouldBe("document.body.scrollLeft", "21");
+                shouldBe("document.body.scrollTop", "42");
+                shouldBe("document.documentElement.scrollLeft", "0");
+                shouldBe("document.documentElement.scrollTop", "0");
+                shouldBe("window.scrollX", "21");
+                shouldBe("window.scrollY", "42");
+
+                debug("");
+                debug("Setting the scroll position on that detached body element should not affect the main frame since it is not the first body element of the document.");
+                shouldBe("floatingBody.scrollTop = 500", "500");
+                shouldBe("floatingBody.scrollLeft", "0");
+                shouldBe("floatingBody.scrollTop", "0");
+                shouldBe("document.body.scrollLeft", "21");
+                shouldBe("document.body.scrollTop", "42");
+                shouldBe("document.documentElement.scrollLeft", "0");
+                shouldBe("document.documentElement.scrollTop", "0");
+                shouldBe("window.scrollX", "21");
+                shouldBe("window.scrollY", "42");
+
+                secondSiblingBody = document.createElement('body');
+                document.documentElement.appendChild(secondSiblingBody);
+                debug("");
+                debug("We add a new body element after the first body element, this should have no impact on the state.");
+                shouldBe("secondSiblingBody.scrollLeft", "0");
+                shouldBe("secondSiblingBody.scrollTop", "0");
+                shouldBe("document.body.scrollLeft", "21");
+                shouldBe("document.body.scrollTop", "42");
+                shouldBe("document.documentElement.scrollLeft", "0");
+                shouldBe("document.documentElement.scrollTop", "0");
+                shouldBe("window.scrollX", "21");
+                shouldBe("window.scrollY", "42");
+
+                debug("");
+                debug("Setting a \"scrollTop\" on secondSiblingBody should not affect the main frame.");
+                shouldBe("secondSiblingBody.scrollTop = 321", "321");
+                shouldBe("secondSiblingBody.scrollLeft", "0");
+                shouldBe("secondSiblingBody.scrollTop", "0");
+                shouldBe("document.body.scrollLeft", "21");
+                shouldBe("document.body.scrollTop", "42");
+                shouldBe("document.documentElement.scrollLeft", "0");
+                shouldBe("document.documentElement.scrollTop", "0");
+                shouldBe("window.scrollX", "21");
+                shouldBe("window.scrollY", "42");
+
+                bodyChildOfMainBody = document.createElement('body');
+                document.body.appendChild(bodyChildOfMainBody);
+                debug("");
+                debug("We add a new body element inside the first body element, this should have no impact on the state.");
+                shouldBe("bodyChildOfMainBody.scrollLeft", "0");
+                shouldBe("bodyChildOfMainBody.scrollTop", "0");
+                shouldBe("document.body.scrollLeft", "21");
+                shouldBe("document.body.scrollTop", "42");
+                shouldBe("document.documentElement.scrollLeft", "0");
+                shouldBe("document.documentElement.scrollTop", "0");
+                shouldBe("window.scrollX", "21");
+                shouldBe("window.scrollY", "42");
+
+                debug("");
+                debug("Setting a \"scrollTop\" on bodyChildOfMainBody should not affect the main frame.");
+                shouldBe("bodyChildOfMainBody.scrollTop = 57", "57");
+                shouldBe("bodyChildOfMainBody.scrollLeft", "0");
+                shouldBe("bodyChildOfMainBody.scrollTop", "0");
+                shouldBe("document.body.scrollLeft", "21");
+                shouldBe("document.body.scrollTop", "42");
+                shouldBe("document.documentElement.scrollLeft", "0");
+                shouldBe("document.documentElement.scrollTop", "0");
+                shouldBe("window.scrollX", "21");
+                shouldBe("window.scrollY", "42");
+
+                debug("");
+                debug("Now we insert a new body element *before* the existing one. It will replace the existing element as the first body element of the document.");
+                oldBodyElement = document.body;
+                newMainBody = document.createElement('body');
+                document.documentElement.insertBefore(newMainBody, oldBodyElement);
+                shouldBeTrue("document.body === newMainBody");
+                shouldBeTrue("document.body !== oldBodyElement");
+
+                debug("Since we are in quirks mode, the new body element gets the scroll position from the frame, and the old one lose its scroll position.");
+                shouldBe("oldBodyElement.scrollLeft", "0");
+                shouldBe("oldBodyElement.scrollTop", "0");
+                shouldBe("document.body.scrollLeft", "21");
+                shouldBe("document.body.scrollTop", "42");
+                shouldBe("document.documentElement.scrollLeft", "0");
+                shouldBe("document.documentElement.scrollTop", "0");
+                shouldBe("window.scrollX", "21");
+                shouldBe("window.scrollY", "42");
+
+                debug("");
+                debug("Scrolling that new body should work as expected.");
+                shouldBe("document.body.scrollTop = 68", "68");
+                shouldBe("oldBodyElement.scrollTop = 894", "894");
+
+                shouldBe("oldBodyElement.scrollLeft", "0");
+                shouldBe("oldBodyElement.scrollTop", "0");
+                shouldBe("document.body.scrollLeft", "21");
+                shouldBe("document.body.scrollTop", "68");
+                shouldBe("document.documentElement.scrollLeft", "0");
+                shouldBe("document.documentElement.scrollTop", "0");
+                shouldBe("window.scrollX", "21");
+                shouldBe("window.scrollY", "68");
+
+                debug("");
+                debug("Scrolling the main frame should not require a renderer.");
+                shouldBe("document.body.style.display = 'none'", "'none'");
+                shouldBe("document.body.scrollTop = 54", "54");
+                shouldBe("oldBodyElement.scrollLeft", "0");
+                shouldBe("oldBodyElement.scrollTop", "0");
+                shouldBe("document.body.scrollLeft", "21");
+                shouldBe("document.body.scrollTop", "54");
+                shouldBe("document.documentElement.scrollLeft", "0");
+                shouldBe("document.documentElement.scrollTop", "0");
+                shouldBe("window.scrollX", "21");
+                shouldBe("window.scrollY", "54");
+
+                // Finally, let's clear the state to make this simpler for manual testing.
+                newMainBody.parentNode.removeChild(newMainBody);
+                window.scrollTo(0, 0);
+
+                finishJSTest();
+            }
+        </script>
+    </head>
+    <body onload="runTest()">
+        <div></div>
+        <script src="../../../resources/js-test-post.js"></script>
+    </body>
+</html>
diff --git a/LayoutTests/fast/dom/Element/body-scrollWidth-basics-quirks-expected.txt b/LayoutTests/fast/dom/Element/body-scrollWidth-basics-quirks-expected.txt
new file mode 100644 (file)
index 0000000..11524d7
--- /dev/null
@@ -0,0 +1,29 @@
+Test the "scrollWidth" properties on the body element in quirks mode.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Initial values
+PASS document.body.scrollWidth is document.documentElement.scrollWidth
+
+Now we create a body element, it should not have a scrollWidth since it is not the first body element of the document.
+PASS document.body.scrollWidth is document.documentElement.scrollWidth
+PASS floatingBody.scrollWidth is 0
+
+We add a new body element after the first body element, this should have no impact on the state.
+PASS document.body.scrollWidth is document.documentElement.scrollWidth
+PASS secondSiblingBody.scrollWidth is secondSiblingBody.clientWidth
+PASS document.body.scrollWidth is not secondSiblingBody.scrollWidth
+
+We add a new body element inside the first body element, this should have no impact on the state.
+PASS document.body.scrollWidth is document.documentElement.scrollWidth
+PASS bodyChildOfMainBody.scrollWidth is bodyChildOfMainBody.clientWidth
+PASS document.body.scrollWidth is not bodyChildOfMainBody.scrollWidth
+
+Getting the scrollWidth should not require a renderer.
+PASS document.body.style.display = 'none' is 'none'
+PASS document.body.scrollWidth is document.documentElement.scrollWidth
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/dom/Element/body-scrollWidth-basics-quirks.html b/LayoutTests/fast/dom/Element/body-scrollWidth-basics-quirks.html
new file mode 100644 (file)
index 0000000..c5a75c7
--- /dev/null
@@ -0,0 +1,58 @@
+<html>
+    <head>
+        <style>
+            div {
+                height: 9999px;
+                width: 9999px;
+            }
+        </style>
+        <script src="../../../resources/js-test-pre.js"></script>
+        <script>
+            jsTestIsAsync = true;
+
+            function runTest() {
+                description('Test the "scrollWidth" properties on the body element in quirks mode.');
+
+                debug("Initial values");
+                shouldBe("document.body.scrollWidth", "document.documentElement.scrollWidth");
+
+                debug("");
+                debug("Now we create a body element, it should not have a scrollWidth since it is not the first body element of the document.");
+                floatingBody = document.createElement('body');
+                shouldBe("document.body.scrollWidth", "document.documentElement.scrollWidth");
+                shouldBe("floatingBody.scrollWidth", "0");
+
+                secondSiblingBody = document.createElement('body');
+                document.documentElement.appendChild(secondSiblingBody);
+                debug("");
+                debug("We add a new body element after the first body element, this should have no impact on the state.");
+                shouldBe("document.body.scrollWidth", "document.documentElement.scrollWidth");
+                shouldBe("secondSiblingBody.scrollWidth", "secondSiblingBody.clientWidth");
+                shouldNotBe("document.body.scrollWidth", "secondSiblingBody.scrollWidth");
+
+                bodyChildOfMainBody = document.createElement('body');
+                document.body.appendChild(bodyChildOfMainBody);
+                debug("");
+                debug("We add a new body element inside the first body element, this should have no impact on the state.");
+                shouldBe("document.body.scrollWidth", "document.documentElement.scrollWidth");
+                shouldBe("bodyChildOfMainBody.scrollWidth", "bodyChildOfMainBody.clientWidth");
+                shouldNotBe("document.body.scrollWidth", "bodyChildOfMainBody.scrollWidth");
+
+                debug("");
+                debug("Getting the scrollWidth should not require a renderer.");
+                shouldBe("document.body.style.display = 'none'", "'none'");
+                shouldBe("document.body.scrollWidth", "document.documentElement.scrollWidth");
+
+                // Finally, let's clear the state to make this simpler for manual testing.
+                document.body.style.display = "block";
+                window.scrollTo(0, 0);
+
+                finishJSTest();
+            }
+        </script>
+    </head>
+    <body onload="runTest()">
+        <div></div>
+        <script src="../../../resources/js-test-post.js"></script>
+    </body>
+</html>
diff --git a/LayoutTests/fast/dom/Element/detached-body-element-does-not-scroll-main-frame-with-scrollLeft-expected.txt b/LayoutTests/fast/dom/Element/detached-body-element-does-not-scroll-main-frame-with-scrollLeft-expected.txt
new file mode 100644 (file)
index 0000000..1ae2bc3
--- /dev/null
@@ -0,0 +1,32 @@
+Tests that, for Quirks mode, changing the scrollTop property of a fake body element does not scroll the viewport
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+Initial state.
+PASS detachedBody.scrollTop is 0
+PASS detachedBody.scrollLeft is 0
+PASS document.body.scrollTop = 0 is 0
+PASS document.body.scrollLeft is 0
+PASS document.body.scrollTop is 0
+PASS document.documentElement.scrollLeft is 0
+PASS document.documentElement.scrollTop is 0
+PASS window.scrollX is 0
+PASS window.scrollY is 0
+
+Setting scrollTop on the detached body element should not change the main frame's scroll position.
+PASS detachedBody.scrollLeft = 542 is 542
+PASS detachedBody.scrollTop is 0
+PASS detachedBody.scrollLeft is 0
+PASS document.body.scrollTop = 0 is 0
+PASS document.body.scrollLeft is 0
+PASS document.body.scrollTop is 0
+PASS document.documentElement.scrollLeft is 0
+PASS document.documentElement.scrollTop is 0
+PASS window.scrollX is 0
+PASS window.scrollY is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/dom/Element/detached-body-element-does-not-scroll-main-frame-with-scrollLeft.html b/LayoutTests/fast/dom/Element/detached-body-element-does-not-scroll-main-frame-with-scrollLeft.html
new file mode 100644 (file)
index 0000000..bbdfb95
--- /dev/null
@@ -0,0 +1,51 @@
+<html>
+    <head>
+        <style>
+            div {
+                height: 9999px;
+                width: 9999px;
+            }
+        </style>
+        <script src="../../../resources/js-test-pre.js"></script>
+        <script>
+            jsTestIsAsync = true;
+
+            function runTest() {
+                description('Tests that, for Quirks mode, changing the scrollTop property of a fake body element does not scroll the viewport');
+
+                detachedBody = document.createElement('body');
+
+                debug("");
+                debug("Initial state.");
+                shouldBe("detachedBody.scrollTop", "0");
+                shouldBe("detachedBody.scrollLeft", "0");
+                shouldBe("document.body.scrollTop = 0", "0");
+                shouldBe("document.body.scrollLeft", "0");
+                shouldBe("document.body.scrollTop", "0");
+                shouldBe("document.documentElement.scrollLeft", "0");
+                shouldBe("document.documentElement.scrollTop", "0");
+                shouldBe("window.scrollX", "0");
+                shouldBe("window.scrollY", "0");
+
+                debug("");
+                debug("Setting scrollTop on the detached body element should not change the main frame's scroll position.");
+                shouldBe("detachedBody.scrollLeft = 542", "542");
+                shouldBe("detachedBody.scrollTop", "0");
+                shouldBe("detachedBody.scrollLeft", "0");
+                shouldBe("document.body.scrollTop = 0", "0");
+                shouldBe("document.body.scrollLeft", "0");
+                shouldBe("document.body.scrollTop", "0");
+                shouldBe("document.documentElement.scrollLeft", "0");
+                shouldBe("document.documentElement.scrollTop", "0");
+                shouldBe("window.scrollX", "0");
+                shouldBe("window.scrollY", "0");
+
+                finishJSTest();
+            }
+        </script>
+    </head>
+    <body onload="runTest()">
+        <div></div>
+        <script src="../../../resources/js-test-post.js"></script>
+    </body>
+</html>
diff --git a/LayoutTests/fast/dom/Element/detached-body-element-does-not-scroll-main-frame-with-scrollTop-expected.txt b/LayoutTests/fast/dom/Element/detached-body-element-does-not-scroll-main-frame-with-scrollTop-expected.txt
new file mode 100644 (file)
index 0000000..d8ee146
--- /dev/null
@@ -0,0 +1,31 @@
+Tests that, for Quirks mode, changing the scrollTop property of a fake body element does not scroll the viewport
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+Initial state.
+PASS detachedBody.scrollTop is 0
+PASS detachedBody.scrollLeft is 0
+PASS document.body.scrollTop = 0 is 0
+PASS document.body.scrollLeft is 0
+PASS document.body.scrollTop is 0
+PASS document.documentElement.scrollLeft is 0
+PASS document.documentElement.scrollTop is 0
+PASS window.scrollX is 0
+PASS window.scrollY is 0
+
+Setting scrollTop on the detached body element should not change the main frame's scroll position.
+PASS detachedBody.scrollTop = 500 is 500
+PASS document.body.scrollLeft is 0
+PASS document.body.scrollTop is 0
+PASS document.documentElement.scrollLeft is 0
+PASS document.documentElement.scrollTop is 0
+PASS window.scrollX is 0
+PASS window.scrollY is 0
+PASS detachedBody.scrollTop is 0
+PASS detachedBody.scrollLeft is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/dom/Element/detached-body-element-does-not-scroll-main-frame-with-scrollTop.html b/LayoutTests/fast/dom/Element/detached-body-element-does-not-scroll-main-frame-with-scrollTop.html
new file mode 100644 (file)
index 0000000..f64c6c3
--- /dev/null
@@ -0,0 +1,50 @@
+<html>
+    <head>
+        <style>
+            div {
+                height: 9999px;
+                width: 9999px;
+            }
+        </style>
+        <script src="../../../resources/js-test-pre.js"></script>
+        <script>
+            jsTestIsAsync = true;
+
+            function runTest() {
+                description('Tests that, for Quirks mode, changing the scrollTop property of a fake body element does not scroll the viewport');
+
+                detachedBody = document.createElement('body');
+
+                debug("");
+                debug("Initial state.");
+                shouldBe("detachedBody.scrollTop", "0");
+                shouldBe("detachedBody.scrollLeft", "0");
+                shouldBe("document.body.scrollTop = 0", "0");
+                shouldBe("document.body.scrollLeft", "0");
+                shouldBe("document.body.scrollTop", "0");
+                shouldBe("document.documentElement.scrollLeft", "0");
+                shouldBe("document.documentElement.scrollTop", "0");
+                shouldBe("window.scrollX", "0");
+                shouldBe("window.scrollY", "0");
+
+                debug("");
+                debug("Setting scrollTop on the detached body element should not change the main frame's scroll position.");
+                shouldBe("detachedBody.scrollTop = 500", "500");
+                shouldBe("document.body.scrollLeft", "0");
+                shouldBe("document.body.scrollTop", "0");
+                shouldBe("document.documentElement.scrollLeft", "0");
+                shouldBe("document.documentElement.scrollTop", "0");
+                shouldBe("window.scrollX", "0");
+                shouldBe("window.scrollY", "0");
+                shouldBe("detachedBody.scrollTop", "0");
+                shouldBe("detachedBody.scrollLeft", "0");
+
+                finishJSTest();
+            }
+        </script>
+    </head>
+    <body onload="runTest()">
+        <div></div>
+        <script src="../../../resources/js-test-post.js"></script>
+    </body>
+</html>
index 7697ca5..7147ed9 100644 (file)
@@ -1,3 +1,36 @@
+2015-04-12  Benjamin Poulain  <benjamin@webkit.org>
+
+        Legacy scroll behavior on HTMLBodyElement should only apply to the first body element of a document
+        https://bugs.webkit.org/show_bug.cgi?id=143651
+
+        Reviewed by Sam Weinig.
+
+        WebKit has some very weird behaviors for the scroll methods on body. This patch
+        address the first bug: only the first body element should have the legacy behavior.
+
+        The relevant text in spec:
+        -http://dev.w3.org/csswg/cssom-view/#dom-element-scrollleft
+        -http://dev.w3.org/csswg/cssom-view/#dom-element-scrolltop
+        -http://dev.w3.org/csswg/cssom-view/#dom-element-scrollwidth
+        -http://dev.w3.org/csswg/cssom-view/#dom-element-scrollheight
+
+        Tests: fast/dom/Element/body-scrollHeight-basics-quirks.html
+               fast/dom/Element/body-scrollLeft-basics-quirks.html
+               fast/dom/Element/body-scrollTop-basics-quirks.html
+               fast/dom/Element/body-scrollWidth-basics-quirks.html
+               fast/dom/Element/detached-body-element-does-not-scroll-main-frame-with-scrollLeft.html
+               fast/dom/Element/detached-body-element-does-not-scroll-main-frame-with-scrollTop.html
+
+        * html/HTMLBodyElement.cpp:
+        (WebCore::HTMLBodyElement::isFirstBodyElementOfDocument):
+        (WebCore::HTMLBodyElement::scrollLeft):
+        (WebCore::HTMLBodyElement::setScrollLeft):
+        (WebCore::HTMLBodyElement::scrollTop):
+        (WebCore::HTMLBodyElement::setScrollTop):
+        (WebCore::HTMLBodyElement::scrollHeight):
+        (WebCore::HTMLBodyElement::scrollWidth):
+        * html/HTMLBodyElement.h:
+
 2015-04-12  Sungmann Cho  <sungmann.cho@navercorp.com>
 
         Fix trival typos related to the word "coordinate".
index 3e11903..6d47691 100644 (file)
@@ -3,7 +3,7 @@
  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
  *           (C) 2000 Simon Hausmann (hausmann@kde.org)
  *           (C) 2001 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2004, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2006-2010, 2015 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -47,6 +47,13 @@ HTMLBodyElement::HTMLBodyElement(const QualifiedName& tagName, Document& documen
     ASSERT(hasTagName(bodyTag));
 }
 
+bool HTMLBodyElement::isFirstBodyElementOfDocument() const
+{
+    // By spec http://dev.w3.org/csswg/cssom-view/#the-html-body-element
+    // "The HTML body element is the first body HTML element child of the root HTML element html."
+    return document().body() == this;
+}
+
 Ref<HTMLBodyElement> HTMLBodyElement::create(Document& document)
 {
     return adoptRef(*new HTMLBodyElement(bodyTag, document));
@@ -225,76 +232,94 @@ static int adjustForZoom(int value, const Frame& frame)
 
 int HTMLBodyElement::scrollLeft()
 {
-    document().updateLayoutIgnorePendingStylesheets();
-    Frame* frame = document().frame();
-    if (!frame)
-        return 0;
-    FrameView* view = frame->view();
-    if (!view)
-        return 0;
-    return adjustForZoom(view->contentsScrollPosition().x(), *frame);
+    if (isFirstBodyElementOfDocument()) {
+        document().updateLayoutIgnorePendingStylesheets();
+        Frame* frame = document().frame();
+        if (!frame)
+            return 0;
+        FrameView* view = frame->view();
+        if (!view)
+            return 0;
+        return adjustForZoom(view->contentsScrollPosition().x(), *frame);
+    }
+    return HTMLElement::scrollLeft();
 }
 
 void HTMLBodyElement::setScrollLeft(int scrollLeft)
 {
-    document().updateLayoutIgnorePendingStylesheets();
-    Frame* frame = document().frame();
-    if (!frame)
-        return;
-    FrameView* view = frame->view();
-    if (!view)
-        return;
-    view->setScrollPosition(IntPoint(static_cast<int>(scrollLeft * frame->pageZoomFactor() * frame->frameScaleFactor()), view->scrollY()));
+    if (isFirstBodyElementOfDocument()) {
+        document().updateLayoutIgnorePendingStylesheets();
+        Frame* frame = document().frame();
+        if (!frame)
+            return;
+        FrameView* view = frame->view();
+        if (!view)
+            return;
+        view->setScrollPosition(IntPoint(static_cast<int>(scrollLeft * frame->pageZoomFactor() * frame->frameScaleFactor()), view->scrollY()));
+    }
+    HTMLElement::setScrollLeft(scrollLeft);
 }
 
 int HTMLBodyElement::scrollTop()
 {
-    document().updateLayoutIgnorePendingStylesheets();
-    Frame* frame = document().frame();
-    if (!frame)
-        return 0;
-    FrameView* view = frame->view();
-    if (!view)
-        return 0;
-    return adjustForZoom(view->contentsScrollPosition().y(), *frame);
+    if (isFirstBodyElementOfDocument()) {
+        document().updateLayoutIgnorePendingStylesheets();
+        Frame* frame = document().frame();
+        if (!frame)
+            return 0;
+        FrameView* view = frame->view();
+        if (!view)
+            return 0;
+        return adjustForZoom(view->contentsScrollPosition().y(), *frame);
+    }
+    return HTMLElement::scrollTop();
 }
 
 void HTMLBodyElement::setScrollTop(int scrollTop)
 {
-    document().updateLayoutIgnorePendingStylesheets();
-    Frame* frame = document().frame();
-    if (!frame)
-        return;
-    FrameView* view = frame->view();
-    if (!view)
-        return;
-    view->setScrollPosition(IntPoint(view->scrollX(), static_cast<int>(scrollTop * frame->pageZoomFactor() * frame->frameScaleFactor())));
+    if (isFirstBodyElementOfDocument()) {
+        document().updateLayoutIgnorePendingStylesheets();
+        Frame* frame = document().frame();
+        if (!frame)
+            return;
+        FrameView* view = frame->view();
+        if (!view)
+            return;
+        view->setScrollPosition(IntPoint(view->scrollX(), static_cast<int>(scrollTop * frame->pageZoomFactor() * frame->frameScaleFactor())));
+    }
+    return HTMLElement::setScrollTop(scrollTop);
 }
 
 int HTMLBodyElement::scrollHeight()
 {
-    // Update the document's layout.
-    document().updateLayoutIgnorePendingStylesheets();
-    Frame* frame = document().frame();
-    if (!frame)
-        return 0;
-    FrameView* view = frame->view();
-    if (!view)
-        return 0;
-    return adjustForZoom(view->contentsHeight(), *frame);
+    if (isFirstBodyElementOfDocument()) {
+        // Update the document's layout.
+        document().updateLayoutIgnorePendingStylesheets();
+        Frame* frame = document().frame();
+        if (!frame)
+            return 0;
+        FrameView* view = frame->view();
+        if (!view)
+            return 0;
+        return adjustForZoom(view->contentsHeight(), *frame);
+    }
+    return HTMLElement::scrollHeight();
 }
 
 int HTMLBodyElement::scrollWidth()
 {
-    // Update the document's layout.
-    document().updateLayoutIgnorePendingStylesheets();
-    Frame* frame = document().frame();
-    if (!frame)
-        return 0;
-    FrameView* view = frame->view();
-    if (!view)
-        return 0;
-    return adjustForZoom(view->contentsWidth(), *frame);
+    if (isFirstBodyElementOfDocument()) {
+        // Update the document's layout.
+        document().updateLayoutIgnorePendingStylesheets();
+        Frame* frame = document().frame();
+        if (!frame)
+            return 0;
+        FrameView* view = frame->view();
+        if (!view)
+            return 0;
+        return adjustForZoom(view->contentsWidth(), *frame);
+    }
+    return HTMLElement::scrollWidth();
 }
 
 void HTMLBodyElement::addSubresourceAttributeURLs(ListHashSet<URL>& urls) const
index ff99e33..c4cdfd5 100644 (file)
@@ -39,6 +39,8 @@ public:
 private:
     HTMLBodyElement(const QualifiedName&, Document&);
 
+    bool isFirstBodyElementOfDocument() const;
+
     virtual void parseAttribute(const QualifiedName&, const AtomicString&) override;
     virtual bool isPresentationAttribute(const QualifiedName&) const override;
     virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStyleProperties&) override;