Title: [295767] trunk/Source/WebCore/rendering
Revision
295767
Author
za...@apple.com
Date
2022-06-22 20:22:03 -0700 (Wed, 22 Jun 2022)

Log Message

RenderElement::addLayers should check for dialog content before inserting layers
https://bugs.webkit.org/show_bug.cgi?id=241874

Reviewed by Simon Fraser.

addLayers stops (recursive) descending in the render tree soon after it finds a root (R) with layer.
It says that if a subtree root (R) has a layer then all layers in this subtree must have already been inserted into the layer tree at an earlier time.
(it simply assumes that any layer in the subtree is a child of (R), or some other layers in the subtree)

<div id=container>
  <div id=R>
    <div id=child>

The insertion is bottom to top; we attach
1, (child) to (R) first
2, followed by (R) to (container)
addLayers assumes that when (R) is being inserted (#2), we don't have to descend into (R)'s subtree since any renderer's layer that was inserted before (at #1) must have already been parented.

However toplayer/backdrop content is an exception where the parent layer may be outside of the subtree but still accessible. In such cases subsequent insertions (and the recursive nature of finding layer parents) could lead to double parenting where we try to insert the same layer into the layer tree multiple times.

* Source/WebCore/rendering/RenderElement.cpp:
(WebCore::addLayers):
(WebCore::RenderElement::insertedIntoTree):
(WebCore::RenderElement::addLayers): Deleted.
* Source/WebCore/rendering/RenderElement.h:

Canonical link: https://commits.webkit.org/251772@main

Modified Paths

Diff

Modified: trunk/Source/WebCore/rendering/RenderElement.cpp (295766 => 295767)


--- trunk/Source/WebCore/rendering/RenderElement.cpp	2022-06-23 02:56:36 UTC (rev 295766)
+++ trunk/Source/WebCore/rendering/RenderElement.cpp	2022-06-23 03:22:03 UTC (rev 295767)
@@ -636,28 +636,28 @@
     return findNextLayer(*renderer.parent(), parentLayer, &renderer);
 }
 
-static void addLayers(const RenderElement& addedRenderer, RenderElement& currentRenderer, RenderLayer* parentLayer)
+static void addLayers(const RenderElement& insertedRenderer, RenderElement& currentRenderer, RenderLayer& parentLayer)
 {
     if (currentRenderer.hasLayer()) {
-        if (isInTopLayerOrBackdrop(currentRenderer.style(), currentRenderer.element()))
-            parentLayer = addedRenderer.view().layer();
-        RenderLayer* beforeChild = layerNextSiblingRespectingTopLayer(addedRenderer, *parentLayer);
-        parentLayer->addChild(*downcast<RenderLayerModelObject>(currentRenderer).layer(), beforeChild);
+        auto* layerToUse = &parentLayer;
+        if (isInTopLayerOrBackdrop(currentRenderer.style(), currentRenderer.element())) {
+            // The special handling of a toplayer/backdrop content may result in trying to insert the associated
+            // layer twice as we connect subtrees.
+            if (auto* parentLayer = downcast<RenderLayerModelObject>(currentRenderer).layer()->parent()) {
+                ASSERT(parentLayer == currentRenderer.view().layer());
+                return;
+            }
+            layerToUse = insertedRenderer.view().layer();
+        }
+        auto* beforeChild = layerNextSiblingRespectingTopLayer(insertedRenderer, *layerToUse);
+        layerToUse->addChild(*downcast<RenderLayerModelObject>(currentRenderer).layer(), beforeChild);
         return;
     }
 
     for (auto& child : childrenOfType<RenderElement>(currentRenderer))
-        addLayers(addedRenderer, child, parentLayer);
+        addLayers(insertedRenderer, child, parentLayer);
 }
 
-void RenderElement::addLayers(RenderLayer* parentLayer)
-{
-    if (!parentLayer)
-        return;
-
-    WebCore::addLayers(*this, *this, parentLayer);
-}
-
 void RenderElement::removeLayers()
 {
     RenderLayer* parentLayer = layerParent();
@@ -937,8 +937,8 @@
     // and don't have a layer attached to ourselves.
     RenderLayer* parentLayer = nullptr;
     if (firstChild() || hasLayer()) {
-        auto* parentLayer = layerParent();
-        addLayers(parentLayer);
+        if (auto* parentLayer = layerParent())
+            addLayers(*this, *this, *parentLayer);
     }
 
     // If |this| is visible but this object was not, tell the layer it has some visible content

Modified: trunk/Source/WebCore/rendering/RenderElement.h (295766 => 295767)


--- trunk/Source/WebCore/rendering/RenderElement.h	2022-06-23 02:56:36 UTC (rev 295766)
+++ trunk/Source/WebCore/rendering/RenderElement.h	2022-06-23 03:22:03 UTC (rev 295767)
@@ -119,7 +119,6 @@
     // can contain a mixture of boxes and other object types, these functions need to be in the base class.
     RenderLayer* layerParent() const;
     RenderLayer* layerNextSibling(RenderLayer& parentLayer) const;
-    void addLayers(RenderLayer* parentLayer);
     void removeLayers();
     void moveLayers(RenderLayer& newParent);
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to