Stop searching for first-letter containers at multi-column boundary.
authorzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 20 Oct 2016 19:15:59 +0000 (19:15 +0000)
committerzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 20 Oct 2016 19:15:59 +0000 (19:15 +0000)
https://bugs.webkit.org/show_bug.cgi?id=163739
<rdar://problem/28810750>

Source/WebCore:

We should not cross the multi-column boundary while searching for the first-letter container.
While moving first-letter renderers to a multi-column parent, it could result in finding the wrong
container and end up adding a new wrapper under the original container (from where we are moving the renderers).

Reviewed by David Hyatt.

Test: fast/css-generated-content/first-letter-move-to-multicolumn-crash.html

* rendering/RenderBoxModelObject.cpp:
(WebCore::RenderBoxModelObject::moveChildrenTo):
* rendering/RenderTextFragment.cpp:
(WebCore::RenderTextFragment::blockForAccompanyingFirstLetter):

LayoutTests:

Reviewed by David Hyatt.

* fast/css-generated-content/first-letter-move-to-multicolumn-crash-expected.txt: Added.
* fast/css-generated-content/first-letter-move-to-multicolumn-crash.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/fast/css-generated-content/first-letter-move-to-multicolumn-crash-expected.txt [new file with mode: 0644]
LayoutTests/fast/css-generated-content/first-letter-move-to-multicolumn-crash.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderBoxModelObject.cpp
Source/WebCore/rendering/RenderTextFragment.cpp

index a2c3002..3fde3a8 100644 (file)
@@ -1,3 +1,14 @@
+2016-10-20  Zalan Bujtas  <zalan@apple.com>
+
+        Stop searching for first-letter containers at multi-column boundary.
+        https://bugs.webkit.org/show_bug.cgi?id=163739
+        <rdar://problem/28810750>
+
+        Reviewed by David Hyatt.
+
+        * fast/css-generated-content/first-letter-move-to-multicolumn-crash-expected.txt: Added.
+        * fast/css-generated-content/first-letter-move-to-multicolumn-crash.html: Added.
+
 2016-10-19  Dean Jackson  <dino@apple.com>
 
         Support CSS Shapes Level 1 without a prefix
diff --git a/LayoutTests/fast/css-generated-content/first-letter-move-to-multicolumn-crash-expected.txt b/LayoutTests/fast/css-generated-content/first-letter-move-to-multicolumn-crash-expected.txt
new file mode 100644 (file)
index 0000000..689c804
--- /dev/null
@@ -0,0 +1,2 @@
+PASS if no crash or ASSERT.
+f
diff --git a/LayoutTests/fast/css-generated-content/first-letter-move-to-multicolumn-crash.html b/LayoutTests/fast/css-generated-content/first-letter-move-to-multicolumn-crash.html
new file mode 100644 (file)
index 0000000..052da00
--- /dev/null
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>This tests that we can move first-letter elements to column content and back.</title>
+<style>
+.original::first-letter{ 
+    -webkit-columns: 2;
+}
+.newClass::first-letter{
+    float: left;
+}
+</style>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+
+function runTest() {
+    li.style.webkitColumns = "2";
+    li.offsetParent;
+
+    li.className = "newClass";
+    li.style.cssText = "letter-spacing: 10px;"
+    li.offsetParent;
+
+    li.style.webkitColumns = "2";
+    li.offsetParent;
+}
+</script>
+</head>
+<body onload="runTest()">
+PASS if no crash or ASSERT.
+<li class=original id="li">f<script></script>
+</li>
+</body>
+</html>
index 215c4f5..957a21e 100644 (file)
@@ -1,3 +1,22 @@
+2016-10-20  Zalan Bujtas  <zalan@apple.com>
+
+        Stop searching for first-letter containers at multi-column boundary.
+        https://bugs.webkit.org/show_bug.cgi?id=163739
+        <rdar://problem/28810750>
+
+        We should not cross the multi-column boundary while searching for the first-letter container.
+        While moving first-letter renderers to a multi-column parent, it could result in finding the wrong
+        container and end up adding a new wrapper under the original container (from where we are moving the renderers).    
+
+        Reviewed by David Hyatt.
+
+        Test: fast/css-generated-content/first-letter-move-to-multicolumn-crash.html
+
+        * rendering/RenderBoxModelObject.cpp:
+        (WebCore::RenderBoxModelObject::moveChildrenTo):
+        * rendering/RenderTextFragment.cpp:
+        (WebCore::RenderTextFragment::blockForAccompanyingFirstLetter):
+
 2016-10-19  Dean Jackson  <dino@apple.com>
 
         Support CSS Shapes Level 1 without a prefix
index 3e8e2b9..4cc4db4 100644 (file)
@@ -2529,9 +2529,11 @@ void RenderBoxModelObject::moveChildrenTo(RenderBoxModelObject* toBoxModelObject
         // Save our next sibling as moveChildTo will clear it.
         RenderObject* nextSibling = child->nextSibling();
         
+        // FIXME: This logic here fails to detect the first letter in certain cases
+        // and skips a valid sibling renderer (see webkit.org/b/163737).
         // Check to make sure we're not saving the firstLetter as the nextSibling.
         // When the |child| object will be moved, its firstLetter will be recreated,
-        // so saving it now in nextSibling would let us with a destroyed object.
+        // so saving it now in nextSibling would leave us with a stale object.
         if (is<RenderTextFragment>(*child) && is<RenderText>(nextSibling)) {
             RenderObject* firstLetterObj = nullptr;
             if (RenderBlock* block = downcast<RenderTextFragment>(*child).blockForAccompanyingFirstLetter()) {
index 4cfb804..8c74aa7 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "RenderBlock.h"
 #include "RenderIterator.h"
+#include "RenderMultiColumnFlowThread.h"
 #include "Text.h"
 
 namespace WebCore {
@@ -112,6 +113,8 @@ RenderBlock* RenderTextFragment::blockForAccompanyingFirstLetter()
     if (!m_firstLetter)
         return nullptr;
     for (auto& block : ancestorsOfType<RenderBlock>(*m_firstLetter)) {
+        if (is<RenderMultiColumnFlowThread>(block))
+            break;
         if (block.style().hasPseudoStyle(FIRST_LETTER) && block.canHaveChildren())
             return &block;
     }