Skip to content
Browse files
RenderElement::addLayers should check for dialog content before inser…
…ting layers

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::RenderElement::addLayers): Deleted.
* Source/WebCore/rendering/RenderElement.h:

Canonical link:
git-svn-id: 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
alanbujtas committed Jun 23, 2022
1 parent daa5f7a commit 21bee4cd6c6720a415c3dc66eafc8100b07d4f54
Showing 2 changed files with 16 additions and 17 deletions.
@@ -636,26 +636,26 @@ static RenderLayer* layerNextSiblingRespectingTopLayer(const RenderElement& rend
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.element()))
parentLayer = addedRenderer.view().layer();
RenderLayer* beforeChild = layerNextSiblingRespectingTopLayer(addedRenderer, *parentLayer);
parentLayer->addChild(*downcast<RenderLayerModelObject>(currentRenderer).layer(), beforeChild);
auto* layerToUse = &parentLayer;
if (isInTopLayerOrBackdrop(, 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());
layerToUse = insertedRenderer.view().layer();
auto* beforeChild = layerNextSiblingRespectingTopLayer(insertedRenderer, *layerToUse);
layerToUse->addChild(*downcast<RenderLayerModelObject>(currentRenderer).layer(), beforeChild);

for (auto& child : childrenOfType<RenderElement>(currentRenderer))
addLayers(addedRenderer, child, parentLayer);

void RenderElement::addLayers(RenderLayer* parentLayer)
if (!parentLayer)

WebCore::addLayers(*this, *this, parentLayer);
addLayers(insertedRenderer, child, parentLayer);

void RenderElement::removeLayers()
@@ -937,8 +937,8 @@ void RenderElement::insertedIntoTree(IsInternalMove isInternalMove)
// and don't have a layer attached to ourselves.
RenderLayer* parentLayer = nullptr;
if (firstChild() || hasLayer()) {
auto* parentLayer = layerParent();
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
@@ -119,7 +119,6 @@ class RenderElement : public RenderObject {
// 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);

0 comments on commit 21bee4c

Please sign in to comment.