Title: [276549] trunk
Revision
276549
Author
[email protected]
Date
2021-04-24 06:42:04 -0700 (Sat, 24 Apr 2021)

Log Message

[RenderTreeBuilder] Subtree moving should clear the floats on all the descendants
https://bugs.webkit.org/show_bug.cgi?id=224996
<rdar://76837320>

Reviewed by Antti Koivisto.

Source/WebCore:

While moving a subtree, we invalidate the floating object list so that we don't end up with incorrectly placed floats (they'll get regenerated during the subsequent layout).
A float can be "assigned" to more than one RenderBlockFlow (e.g intruding floats). It's very common that a set of descendant RenderBlockFlow
renderers "see" the same set of floats (each RenderBlockFlow has its own list of floating objects).
Now the invalidation is based on ancestor-to-descendant direction starting with finding the outer most containing block for a particular float (see outermostBlockContainingFloatingObject)
The invalidation logic also expects no gaps in the ancestor chain e.g.

   RenderBlockFlow (A) -> float X
     RenderBlockFlow (B) -> float X
       RenderBlockFlow (C) -> float X
   if float X is assigned to both A and C, then it must be assigned to B as well.

RenderBlockFlow::removeFloatingObjects() simply removes the float from the renderer. It does not invalidate the ancestor/descendant chain.
e.g. calling B.removeFloatingObjects() would just remove float X from RenderBlockFlow (B)

   RenderBlockFlow (A) -> float X
     RenderBlockFlow (B)
       RenderBlockFlow (C) -> float X

and any subsequent invalidation attempt would fail to clear up A or C (depending on whether it is initiated on A or C).

Test: fast/multicol/floating-boxes-moved-under-multi-column.html

* rendering/updating/RenderTreeBuilder.cpp:
(WebCore::RenderTreeBuilder::moveChildren):

LayoutTests:

* fast/multicol/floating-boxes-moved-under-multi-column-expected.txt: Added.
* fast/multicol/floating-boxes-moved-under-multi-column.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (276548 => 276549)


--- trunk/LayoutTests/ChangeLog	2021-04-24 13:10:44 UTC (rev 276548)
+++ trunk/LayoutTests/ChangeLog	2021-04-24 13:42:04 UTC (rev 276549)
@@ -1,3 +1,14 @@
+2021-04-24  Zalan Bujtas  <[email protected]>
+
+        [RenderTreeBuilder] Subtree moving should clear the floats on all the descendants
+        https://bugs.webkit.org/show_bug.cgi?id=224996
+        <rdar://76837320>
+
+        Reviewed by Antti Koivisto.
+
+        * fast/multicol/floating-boxes-moved-under-multi-column-expected.txt: Added.
+        * fast/multicol/floating-boxes-moved-under-multi-column.html: Added.
+
 2021-04-24  Rob Buis  <[email protected]>
 
         Move selectedOptions cache invalidation timing

Added: trunk/LayoutTests/fast/multicol/floating-boxes-moved-under-multi-column-expected.txt (0 => 276549)


--- trunk/LayoutTests/fast/multicol/floating-boxes-moved-under-multi-column-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/multicol/floating-boxes-moved-under-multi-column-expected.txt	2021-04-24 13:42:04 UTC (rev 276549)
@@ -0,0 +1 @@
+

Added: trunk/LayoutTests/fast/multicol/floating-boxes-moved-under-multi-column.html (0 => 276549)


--- trunk/LayoutTests/fast/multicol/floating-boxes-moved-under-multi-column.html	                        (rev 0)
+++ trunk/LayoutTests/fast/multicol/floating-boxes-moved-under-multi-column.html	2021-04-24 13:42:04 UTC (rev 276549)
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<style>
+  :focus-within {
+    column-width: 1px;
+    width: 0;
+  }
+  :nth-last-child(3) {
+    margin-block-end: 1px;
+    float: right;
+  }
+  :nth-last-child(3)::first-letter {
+    background: grey;
+  }
+</style>
+<script>
+  if (window.testRunner)
+    testRunner.dumpAsText();
+  
+  _onload_ = () => {
+    document.body.appendChild(document.createElement('span'));
+    document.body.appendChild(document.createElement('div'));
+    document.body.appendChild(document.createElement('span'));
+    document.designMode = 'on';
+    document.execCommand('SelectAll');
+    document.body.appendChild(document.createElement('div'));
+  };
+</script>
+<body>
+</body>

Modified: trunk/Source/WebCore/ChangeLog (276548 => 276549)


--- trunk/Source/WebCore/ChangeLog	2021-04-24 13:10:44 UTC (rev 276548)
+++ trunk/Source/WebCore/ChangeLog	2021-04-24 13:42:04 UTC (rev 276549)
@@ -1,5 +1,38 @@
 2021-04-24  Zalan Bujtas  <[email protected]>
 
+        [RenderTreeBuilder] Subtree moving should clear the floats on all the descendants
+        https://bugs.webkit.org/show_bug.cgi?id=224996
+        <rdar://76837320>
+
+        Reviewed by Antti Koivisto.
+
+        While moving a subtree, we invalidate the floating object list so that we don't end up with incorrectly placed floats (they'll get regenerated during the subsequent layout).
+        A float can be "assigned" to more than one RenderBlockFlow (e.g intruding floats). It's very common that a set of descendant RenderBlockFlow
+        renderers "see" the same set of floats (each RenderBlockFlow has its own list of floating objects).
+        Now the invalidation is based on ancestor-to-descendant direction starting with finding the outer most containing block for a particular float (see outermostBlockContainingFloatingObject)
+        The invalidation logic also expects no gaps in the ancestor chain e.g.
+
+           RenderBlockFlow (A) -> float X
+             RenderBlockFlow (B) -> float X
+               RenderBlockFlow (C) -> float X
+           if float X is assigned to both A and C, then it must be assigned to B as well.
+
+        RenderBlockFlow::removeFloatingObjects() simply removes the float from the renderer. It does not invalidate the ancestor/descendant chain.
+        e.g. calling B.removeFloatingObjects() would just remove float X from RenderBlockFlow (B)
+
+           RenderBlockFlow (A) -> float X
+             RenderBlockFlow (B)
+               RenderBlockFlow (C) -> float X
+
+        and any subsequent invalidation attempt would fail to clear up A or C (depending on whether it is initiated on A or C).
+
+        Test: fast/multicol/floating-boxes-moved-under-multi-column.html
+
+        * rendering/updating/RenderTreeBuilder.cpp:
+        (WebCore::RenderTreeBuilder::moveChildren):
+
+2021-04-24  Zalan Bujtas  <[email protected]>
+
         [LFC] Ignore content height and width when 'contain: size' is present
         https://bugs.webkit.org/show_bug.cgi?id=225013
 

Modified: trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.cpp (276548 => 276549)


--- trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.cpp	2021-04-24 13:10:44 UTC (rev 276548)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.cpp	2021-04-24 13:42:04 UTC (rev 276549)
@@ -531,8 +531,22 @@
     // or when fullRemoveInsert is false.
     if (normalizeAfterInsertion == NormalizeAfterInsertion::Yes && is<RenderBlock>(from)) {
         downcast<RenderBlock>(from).removePositionedObjects(nullptr);
-        if (is<RenderBlockFlow>(from))
-            downcast<RenderBlockFlow>(from).removeFloatingObjects();
+        auto removeFloatingObjectsIfApplicable = [&] {
+            if (from.renderTreeBeingDestroyed())
+                return;
+            if (!is<RenderBlockFlow>(from))
+                return;
+            auto* floatingObjects = downcast<RenderBlockFlow>(from).floatingObjectSet();
+            if (!floatingObjects)
+                return;
+            // Here we remove the floating objects from the descendants as well.
+            auto copyOfFloatingObjects = WTF::map(*floatingObjects, [](auto& floatingObject) { 
+                return floatingObject.get();
+            });
+            for (auto* floatingObject : copyOfFloatingObjects)
+                floatingObject->renderer().removeFloatingOrPositionedChildFromBlockLists();
+        };
+        removeFloatingObjectsIfApplicable();
     }
 
     ASSERT(!beforeChild || &to == beforeChild->parent());
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to