Sticky positioning is broken for table rows
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 28 Jan 2014 22:21:47 +0000 (22:21 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 28 Jan 2014 22:21:47 +0000 (22:21 +0000)
https://bugs.webkit.org/show_bug.cgi?id=112024

Patch by Viatcheslav Ostapenko <sl.ostapenko@samsung.com> on 2014-01-28
Reviewed by Simon Fraser.

Source/WebCore:

Enable sticky positioning for table elements.
Also includes fix for bug ​wkb.ug/105654
I don't have access to this bug, but from related commit message I
assume it says about "Heap use after free problem".
Debugging showed that it wasn't heap use after free.
The real problem that RenderObject::container() returns object which is
not RenderBlock and it is used as RenderBlock in
RenderBox::containingBlockLogicalHeightForPositioned() method.
Added extra isRenderBlock check and search for containingBlock if
current block is not RenderBlock.

Tests: fast/css/sticky/sticky-table-row-top.html
       fast/css/sticky/sticky-table-thead-top.html

* css/StyleResolver.cpp:
(WebCore::StyleResolver::adjustRenderStyle):
* rendering/RenderBox.cpp:
(WebCore::RenderBox::containingBlockLogicalHeightForPositioned):
* rendering/RenderTableRow.h:

LayoutTests:

Add layout tests for sticky positioned table row and table thead.

* fast/css/sticky/sticky-table-row-top-expected.html: Added.
* fast/css/sticky/sticky-table-row-top.html: Added.
* fast/css/sticky/sticky-table-thead-top-expected.html: Added.
* fast/css/sticky/sticky-table-thead-top.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/fast/css/sticky/sticky-table-row-top-expected.html [new file with mode: 0644]
LayoutTests/fast/css/sticky/sticky-table-row-top.html [new file with mode: 0644]
LayoutTests/fast/css/sticky/sticky-table-thead-top-expected.html [new file with mode: 0644]
LayoutTests/fast/css/sticky/sticky-table-thead-top.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/css/StyleResolver.cpp
Source/WebCore/rendering/RenderBox.cpp
Source/WebCore/rendering/RenderTableRow.h

index 2c1188b..17e14dd 100644 (file)
@@ -1,3 +1,17 @@
+2014-01-28  Viatcheslav Ostapenko  <sl.ostapenko@samsung.com>
+
+        Sticky positioning is broken for table rows
+        https://bugs.webkit.org/show_bug.cgi?id=112024
+
+        Reviewed by Simon Fraser.
+
+        Add layout tests for sticky positioned table row and table thead.
+
+        * fast/css/sticky/sticky-table-row-top-expected.html: Added.
+        * fast/css/sticky/sticky-table-row-top.html: Added.
+        * fast/css/sticky/sticky-table-thead-top-expected.html: Added.
+        * fast/css/sticky/sticky-table-thead-top.html: Added.
+
 2014-01-28  Myles C. Maxfield  <mmaxfield@apple.com>
 
         Fixing several incorrect assumptions with handling isolated inlines.
diff --git a/LayoutTests/fast/css/sticky/sticky-table-row-top-expected.html b/LayoutTests/fast/css/sticky/sticky-table-row-top-expected.html
new file mode 100644 (file)
index 0000000..cab8adf
--- /dev/null
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+<style>
+    body {
+        margin: 0;
+        height: 2000px;
+        overflow: hidden; /* hide scrollbars */
+    }
+
+    .group {
+        display: inline-block;
+        position: relative;
+        width: 250px;
+        height: 500px;
+    }
+
+    .container {
+        width: 200px;
+        height: 400px;
+        outline: 2px solid black;
+    }
+
+    .box {
+        width: 200px;
+        height: 200px;
+    }
+
+    .sticky {
+        position: absolute;
+        background-color: green;
+    }
+
+    .indicator {
+        position: absolute;
+        top: 0;
+        left: 0;
+        background-color: red;
+    }
+</style>
+</head>
+<body>
+    <div class="group" style="top: -100px;">
+        <div class="indicator box" style="top: 200px;"></div>
+        <div class="container">
+            <div class="sticky box" style="top: 200px;"></div>
+        </div>
+    </div>
+
+    <div class="group" style="top: 0">
+        <div class="indicator box" style="top: 100px;"></div>
+        <div class="container">
+            <div class="sticky box" style="top: 100px;"></div>
+        </div>
+    </div>
+
+    <div class="group" style="top: 100px">
+        <div class="indicator box" style="top: 0;"></div>
+        <div class="container">
+            <div class="sticky box" style="top: 0;"></div>
+        </div>
+    </div>
+    <div style="position: absolute; top: 520px;">
+    This test checks that sticky positioned table rows are contained by their table.
+    There should be no red.
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/fast/css/sticky/sticky-table-row-top.html b/LayoutTests/fast/css/sticky/sticky-table-row-top.html
new file mode 100644 (file)
index 0000000..2a1c4ff
--- /dev/null
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+<style>
+    body {
+        margin: 0;
+        height: 2000px;
+        overflow: hidden; /* hide scrollbars */
+    }
+
+    .group {
+        display: inline-block;
+        position: relative;
+        width: 250px;
+        height: 500px;
+    }
+
+    .container {
+        width: 200px;
+        height: 400px;
+        outline: 2px solid black;
+        border: hidden;
+        border-width: 0px;
+        border-spacing: 0px !important;
+        border-collapse:collapse;
+        cellspacing: 0;
+        cellpadding: 0;
+        padding: 0;
+    }
+
+    .box {
+        width: 200px;
+        height: 198px;
+    }
+
+    .sticky {
+        position: -webkit-sticky;
+        top: 100px;
+        background-color: green;
+    }
+
+    .indicator {
+        position: absolute;
+        top: 0;
+        left: 0;
+        background-color: red;
+    }
+</style>
+<script>
+    function doTest()
+    {
+        window.scrollTo(0, 100);
+    }
+    window.addEventListener('load', doTest, false);
+</script>
+</head>
+<body>
+    <div class="group">
+        <div class="indicator box" style="top: 200px;"></div>
+        <table class="container">
+            <tbody>
+                <tr class="sticky">
+                    <td class="box"></td>
+                </tr>
+                <tr>
+                    <td></td>
+                </tr>
+            </tbody>
+        </table>
+    </div>
+
+    <div class="group" style="top: 100px">
+        <div class="indicator box" style="top: 100px;"></div>
+        <table class="container" style="">
+            <tbody>
+                <tr class="sticky">
+                    <td class="box"></td>
+                </tr>
+                <tr>
+                    <td></td>
+                </tr>
+            </tbody>
+        </table>
+    </div>
+
+    <div class="group" style="top: 200px">
+        <div class="indicator box" style="top: 0;"></div>
+        <table class="container" style="">
+            <tbody>
+                <tr class="sticky">
+                    <td class="box"></td>
+                </tr>
+                <tr>
+                    <td></td>
+                </tr>
+            </tbody>
+        </table>
+    </div>
+    <div style="position: absolute; top: 620px;">
+    This test checks that sticky positioned table rows are contained by their table.
+    There should be no red.
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/fast/css/sticky/sticky-table-thead-top-expected.html b/LayoutTests/fast/css/sticky/sticky-table-thead-top-expected.html
new file mode 100644 (file)
index 0000000..ccb6f91
--- /dev/null
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+<style>
+    body {
+        margin: 0;
+        height: 2000px;
+        overflow: hidden; /* hide scrollbars */
+    }
+
+    .group {
+        display: inline-block;
+        position: relative;
+        width: 250px;
+        height: 500px;
+    }
+
+    .container {
+        width: 200px;
+        height: 400px;
+        outline: 2px solid black;
+    }
+
+    .box {
+        width: 200px;
+        height: 200px;
+    }
+
+    .sticky {
+        position: absolute;
+        background-color: green;
+    }
+
+    .indicator {
+        position: absolute;
+        top: 0;
+        left: 0;
+        background-color: red;
+    }
+</style>
+</head>
+<body>
+    <div class="group" style="top: -100px;">
+        <div class="indicator box" style="top: 200px;"></div>
+        <div class="container">
+            <div class="sticky box" style="top: 200px;"></div>
+        </div>
+    </div>
+
+    <div class="group" style="top: 0">
+        <div class="indicator box" style="top: 100px;"></div>
+        <div class="container">
+            <div class="sticky box" style="top: 100px;"></div>
+        </div>
+    </div>
+
+    <div class="group" style="top: 100px">
+        <div class="indicator box" style="top: 0;"></div>
+        <div class="container">
+            <div class="sticky box" style="top: 0;"></div>
+        </div>
+    </div>
+    <div style="position: absolute; top: 520px;">
+    This test checks that sticky positioned table theads are contained by their table.
+    There should be no red.
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/fast/css/sticky/sticky-table-thead-top.html b/LayoutTests/fast/css/sticky/sticky-table-thead-top.html
new file mode 100644 (file)
index 0000000..a6baa87
--- /dev/null
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+<style>
+    body {
+        margin: 0;
+        height: 2000px;
+        overflow: hidden; /* hide scrollbars */
+    }
+
+    .group {
+        display: inline-block;
+        position: relative;
+        width: 250px;
+        height: 500px;
+    }
+
+    .container {
+        width: 200px;
+        height: 400px;
+        outline: 2px solid black;
+        border: hidden;
+        border-width: 0px;
+        border-spacing: 0px !important;
+        border-collapse:collapse;
+        cellspacing: 0;
+        cellpadding: 0;
+        padding: 0;
+    }
+
+    .box {
+        width: 200px;
+        height: 198px;
+    }
+
+    .sticky {
+        position: -webkit-sticky;
+        top: 100px;
+        background-color: green;
+    }
+
+    .indicator {
+        position: absolute;
+        top: 0;
+        left: 0;
+        background-color: red;
+    }
+</style>
+<script>
+    function doTest()
+    {
+        window.scrollTo(0, 100);
+    }
+    window.addEventListener('load', doTest, false);
+</script>
+</head>
+<body>
+    <div class="group">
+        <div class="indicator box" style="top: 200px;"></div>
+        <table class="container">
+            <thead class="sticky">
+                <tr>
+                    <td class="box"></td>
+                </tr>
+            </thead>
+            <tbody>
+                <tr>
+                    <td></td>
+                </tr>
+            </tbody>
+        </table>
+    </div>
+
+    <div class="group" style="top: 100px">
+        <div class="indicator box" style="top: 100px;"></div>
+        <table class="container" style="">
+            <thead class="sticky">
+                <tr>
+                    <td class="box"></td>
+                </tr>
+            </thead>
+            <tbody>
+                <tr>
+                    <td></td>
+                </tr>
+            </tbody>
+        </table>
+    </div>
+
+    <div class="group" style="top: 200px">
+        <div class="indicator box" style="top: 0;"></div>
+        <table class="container" style="">
+            <thead class="sticky">
+                <tr>
+                    <td class="box"></td>
+                </tr>
+            </thead>
+            <tbody>
+                <tr>
+                    <td></td>
+                </tr>
+            </tbody>
+        </table>
+    </div>
+    <div style="position: absolute; top: 620px;">
+    This test checks that sticky positioned table theads are contained by their table.
+    There should be no red.
+    </div>
+</body>
+</html>
index 3b54e68..c3852d3 100644 (file)
@@ -1,3 +1,30 @@
+2014-01-28  Viatcheslav Ostapenko  <sl.ostapenko@samsung.com>
+
+        Sticky positioning is broken for table rows
+        https://bugs.webkit.org/show_bug.cgi?id=112024
+
+        Reviewed by Simon Fraser.
+
+        Enable sticky positioning for table elements. 
+        Also includes fix for bug ​wkb.ug/105654
+        I don't have access to this bug, but from related commit message I 
+        assume it says about "Heap use after free problem".
+        Debugging showed that it wasn't heap use after free. 
+        The real problem that RenderObject::container() returns object which is
+        not RenderBlock and it is used as RenderBlock in 
+        RenderBox::containingBlockLogicalHeightForPositioned() method.
+        Added extra isRenderBlock check and search for containingBlock if 
+        current block is not RenderBlock.
+        
+        Tests: fast/css/sticky/sticky-table-row-top.html
+               fast/css/sticky/sticky-table-thead-top.html
+
+        * css/StyleResolver.cpp:
+        (WebCore::StyleResolver::adjustRenderStyle):
+        * rendering/RenderBox.cpp:
+        (WebCore::RenderBox::containingBlockLogicalHeightForPositioned):
+        * rendering/RenderTableRow.h:
+
 2014-01-28  Myles C. Maxfield  <mmaxfield@apple.com>
 
         Fixing several incorrect assumptions with handling isolated inlines.
index ccf7c67..4bcc0ed 100644 (file)
@@ -1252,7 +1252,7 @@ void StyleResolver::adjustRenderStyle(RenderStyle& style, const RenderStyle& par
         // on some sites).
         if ((style.display() == TABLE_HEADER_GROUP || style.display() == TABLE_ROW_GROUP
             || style.display() == TABLE_FOOTER_GROUP || style.display() == TABLE_ROW)
-            && style.hasInFlowPosition())
+            && style.position() == RelativePosition)
             style.setPosition(StaticPosition);
 
         // writing-mode does not apply to table row groups, table column groups, table rows, and table columns.
index 76ee6a0..cb905a6 100644 (file)
@@ -3090,7 +3090,7 @@ LayoutUnit RenderBox::containingBlockLogicalHeightForPositioned(const RenderBoxM
         if (isFixedPosition && containingBlock->isRenderView())
             return toRenderView(containingBlock)->clientLogicalHeightForFixedPosition();
 
-        const RenderBlock* cb = toRenderBlock(containingBlock);
+        const RenderBlock* cb = containingBlock->isRenderBlock() ? toRenderBlock(containingBlock) : containingBlock->containingBlock();
         LayoutUnit result = cb->clientLogicalHeight();
         RenderFlowThread* flowThread = flowThreadContainingBlock();
         if (flowThread && containingBlock->isRenderFlowThread() && flowThread->isHorizontalWritingMode() == containingBlock->isHorizontalWritingMode()) {
index 3de96a0..6470e6f 100644 (file)
@@ -103,7 +103,7 @@ private:
     virtual void layout() override;
     virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const override;
 
-    virtual bool requiresLayer() const override { return hasOverflowClip() || hasTransform() || hasHiddenBackface() || hasClipPath() || createsGroup(); }
+    virtual bool requiresLayer() const override { return hasOverflowClip() || hasTransform() || hasHiddenBackface() || hasClipPath() || createsGroup() || isStickyPositioned(); }
 
     virtual void paint(PaintInfo&, const LayoutPoint&) override;