Title: [165465] trunk/Source/WebCore
Revision
165465
Author
[email protected]
Date
2014-03-12 03:18:47 -0700 (Wed, 12 Mar 2014)

Log Message

Don't use NodeRenderingTraversal for pseudo elements
https://bugs.webkit.org/show_bug.cgi?id=130091

Reviewed by Andreas Kling.

Make traversing during style resolve more comprehensible by handling before/after pseudo elements explicitly.

With this patch NodeRenderingTraversal is only needed for InsertionPoints (which are nothing but an implementation
detail of the <details> element at this point).

* dom/Element.cpp:
(WebCore::shouldUseNodeRenderingTraversalSlowPath):
        
    PseudoElements don't need the slow path anymore.

(WebCore::Element::setBeforePseudoElement):
(WebCore::Element::setAfterPseudoElement):
(WebCore::Element::clearBeforePseudoElement):
(WebCore::Element::clearAfterPseudoElement):
* dom/NodeRenderingTraversal.cpp:
(WebCore::NodeRenderingTraversal::traverseParent):
(WebCore::NodeRenderingTraversal::firstChildSlow):
(WebCore::NodeRenderingTraversal::nextSiblingSlow):
(WebCore::NodeRenderingTraversal::previousSiblingSlow):
* dom/NodeRenderingTraversal.h:
(WebCore::NodeRenderingTraversal::firstChild):
* style/StyleResolveTree.cpp:
(WebCore::Style::nextSiblingRenderer):
        
    Add ::before/::after pseudo element handling here.

(WebCore::Style::shouldCreateRenderer):
(WebCore::Style::elementInsideRegionNeedsRenderer):
(WebCore::Style::createRendererIfNeeded):
(WebCore::Style::previousSiblingRenderer):
        
    Add ::before pseudo element handling here (text node can't be ::after).

(WebCore::Style::reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded):
(WebCore::Style::textRendererIsNeeded):
(WebCore::Style::createTextRendererIfNeeded):
(WebCore::Style::attachTextRenderer):
(WebCore::Style::updateTextRendererAfterContentChange):
(WebCore::Style::attachChildren):
(WebCore::Style::attachDistributedChildren):
        
    Handle InsertionPoints in one place.

(WebCore::Style::attachShadowRoot):
(WebCore::Style::attachBeforeOrAfterPseudoElementIfNeeded):
(WebCore::Style::attachRenderTree):
(WebCore::Style::resolveLocal):
(WebCore::Style::updateTextStyle):
(WebCore::Style::resolveShadowTree):
(WebCore::Style::updateBeforeOrAfterPseudoElement):
(WebCore::Style::resolveTree):
        
    Pass the rendering parent around to various functions instead of determining it repeatedly by calling 
    NodeRenderingTraversal::parent. It is always the same for all direct children being resolved and generally just
    the parent element.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (165464 => 165465)


--- trunk/Source/WebCore/ChangeLog	2014-03-12 09:49:59 UTC (rev 165464)
+++ trunk/Source/WebCore/ChangeLog	2014-03-12 10:18:47 UTC (rev 165465)
@@ -1,3 +1,66 @@
+2014-03-12  Antti Koivisto  <[email protected]>
+
+        Don't use NodeRenderingTraversal for pseudo elements
+        https://bugs.webkit.org/show_bug.cgi?id=130091
+
+        Reviewed by Andreas Kling.
+
+        Make traversing during style resolve more comprehensible by handling before/after pseudo elements explicitly.
+
+        With this patch NodeRenderingTraversal is only needed for InsertionPoints (which are nothing but an implementation
+        detail of the <details> element at this point).
+
+        * dom/Element.cpp:
+        (WebCore::shouldUseNodeRenderingTraversalSlowPath):
+        
+            PseudoElements don't need the slow path anymore.
+
+        (WebCore::Element::setBeforePseudoElement):
+        (WebCore::Element::setAfterPseudoElement):
+        (WebCore::Element::clearBeforePseudoElement):
+        (WebCore::Element::clearAfterPseudoElement):
+        * dom/NodeRenderingTraversal.cpp:
+        (WebCore::NodeRenderingTraversal::traverseParent):
+        (WebCore::NodeRenderingTraversal::firstChildSlow):
+        (WebCore::NodeRenderingTraversal::nextSiblingSlow):
+        (WebCore::NodeRenderingTraversal::previousSiblingSlow):
+        * dom/NodeRenderingTraversal.h:
+        (WebCore::NodeRenderingTraversal::firstChild):
+        * style/StyleResolveTree.cpp:
+        (WebCore::Style::nextSiblingRenderer):
+        
+            Add ::before/::after pseudo element handling here.
+
+        (WebCore::Style::shouldCreateRenderer):
+        (WebCore::Style::elementInsideRegionNeedsRenderer):
+        (WebCore::Style::createRendererIfNeeded):
+        (WebCore::Style::previousSiblingRenderer):
+        
+            Add ::before pseudo element handling here (text node can't be ::after).
+
+        (WebCore::Style::reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded):
+        (WebCore::Style::textRendererIsNeeded):
+        (WebCore::Style::createTextRendererIfNeeded):
+        (WebCore::Style::attachTextRenderer):
+        (WebCore::Style::updateTextRendererAfterContentChange):
+        (WebCore::Style::attachChildren):
+        (WebCore::Style::attachDistributedChildren):
+        
+            Handle InsertionPoints in one place.
+
+        (WebCore::Style::attachShadowRoot):
+        (WebCore::Style::attachBeforeOrAfterPseudoElementIfNeeded):
+        (WebCore::Style::attachRenderTree):
+        (WebCore::Style::resolveLocal):
+        (WebCore::Style::updateTextStyle):
+        (WebCore::Style::resolveShadowTree):
+        (WebCore::Style::updateBeforeOrAfterPseudoElement):
+        (WebCore::Style::resolveTree):
+        
+            Pass the rendering parent around to various functions instead of determining it repeatedly by calling 
+            NodeRenderingTraversal::parent. It is always the same for all direct children being resolved and generally just
+            the parent element.
+
 2014-03-12  Frédéric Wang  <[email protected]>
 
         Invisible Operators should not add space.

Modified: trunk/Source/WebCore/css/StyleResolver.cpp (165464 => 165465)


--- trunk/Source/WebCore/css/StyleResolver.cpp	2014-03-12 09:49:59 UTC (rev 165464)
+++ trunk/Source/WebCore/css/StyleResolver.cpp	2014-03-12 10:18:47 UTC (rev 165465)
@@ -92,6 +92,7 @@
 #include "Page.h"
 #include "PageRuleCollector.h"
 #include "Pair.h"
+#include "PseudoElement.h"
 #include "QuotesData.h"
 #include "Rect.h"
 #include "RenderRegion.h"
@@ -410,7 +411,7 @@
     m_regionForStyling = regionForStyling;
 
     if (e) {
-        m_parentNode = NodeRenderingTraversal::parent(e);
+        m_parentNode = e->isPseudoElement() ? toPseudoElement(e)->hostElement() : NodeRenderingTraversal::parent(e);
         bool resetStyleInheritance = hasShadowRootParent(*e) && toShadowRoot(e->parentNode())->resetStyleInheritance();
         m_parentStyle = resetStyleInheritance ? 0 :
             parentStyle ? parentStyle :

Modified: trunk/Source/WebCore/dom/Element.cpp (165464 => 165465)


--- trunk/Source/WebCore/dom/Element.cpp	2014-03-12 09:49:59 UTC (rev 165464)
+++ trunk/Source/WebCore/dom/Element.cpp	2014-03-12 10:18:47 UTC (rev 165465)
@@ -1410,8 +1410,6 @@
 {
     if (element.isShadowRoot())
         return true;
-    if (element.isPseudoElement() || element.beforePseudoElement() || element.afterPseudoElement())
-        return true;
     return element.isInsertionPoint() || element.shadowRoot();
 }
 
@@ -2250,13 +2248,11 @@
 void Element::setBeforePseudoElement(PassRefPtr<PseudoElement> element)
 {
     ensureElementRareData().setBeforePseudoElement(element);
-    resetNeedsNodeRenderingTraversalSlowPath();
 }
 
 void Element::setAfterPseudoElement(PassRefPtr<PseudoElement> element)
 {
     ensureElementRareData().setAfterPseudoElement(element);
-    resetNeedsNodeRenderingTraversalSlowPath();
 }
 
 static void disconnectPseudoElement(PseudoElement* pseudoElement)
@@ -2275,7 +2271,6 @@
         return;
     disconnectPseudoElement(elementRareData()->beforePseudoElement());
     elementRareData()->setBeforePseudoElement(nullptr);
-    resetNeedsNodeRenderingTraversalSlowPath();
 }
 
 void Element::clearAfterPseudoElement()
@@ -2284,7 +2279,6 @@
         return;
     disconnectPseudoElement(elementRareData()->afterPseudoElement());
     elementRareData()->setAfterPseudoElement(nullptr);
-    resetNeedsNodeRenderingTraversalSlowPath();
 }
 
 // ElementTraversal API

Modified: trunk/Source/WebCore/dom/NodeRenderingTraversal.cpp (165464 => 165465)


--- trunk/Source/WebCore/dom/NodeRenderingTraversal.cpp	2014-03-12 09:49:59 UTC (rev 165464)
+++ trunk/Source/WebCore/dom/NodeRenderingTraversal.cpp	2014-03-12 10:18:47 UTC (rev 165465)
@@ -29,7 +29,6 @@
 #include "NodeRenderingTraversal.h"
 
 #include "InsertionPoint.h"
-#include "PseudoElement.h"
 #include "ShadowRoot.h"
 
 namespace WebCore {
@@ -121,9 +120,6 @@
 
 static ContainerNode* traverseParent(const Node* node, ShadowRootCrossing shadowRootCrossing)
 {
-    if (node->isPseudoElement())
-        return toPseudoElement(node)->hostElement();
-
     if (shadowRootCrossing == DontCrossShadowRoot  && node->isShadowRoot())
         return 0;
 
@@ -222,47 +218,25 @@
     return traverseParent(node, CrossShadowRoot);
 }
 
-Node* nextSiblingSlow(const Node* node)
+Node* firstChildSlow(const Node* node)
 {
     ASSERT(!node->isShadowRoot());
 
-    // FIXME: Why do these functions deal with before/after when other code here doesn't?
-    Node* nextSibling = 0;
-    if (node->isBeforePseudoElement()) {
-        nextSibling = traverseParent(node, CrossShadowRoot);
-        nextSibling = traverseFirstChild(nextSibling, CrossShadowRoot);
-    } else
-        nextSibling = traverseNextSibling(node);
+    return traverseFirstChild(node, DontCrossShadowRoot);
+}
 
-    if (nextSibling || node->isAfterPseudoElement())
-        return nextSibling;
+Node* nextSiblingSlow(const Node* node)
+{
+    ASSERT(!node->isShadowRoot());
 
-    Node* parent = traverseParent(node, CrossShadowRoot);
-    if (parent && parent->isElementNode())
-        return toElement(parent)->afterPseudoElement();
-
-    return 0;
+    return traverseNextSibling(node);
 }
 
 Node* previousSiblingSlow(const Node* node)
 {
     ASSERT(!node->isShadowRoot());
 
-    Node* previousSibling = 0;
-    if (node->isAfterPseudoElement()) {
-        ContainerNode* parent = traverseParent(node, CrossShadowRoot);
-        previousSibling = traverseLastChild(parent, CrossShadowRoot);
-    } else
-        previousSibling = traversePreviousSibling(node);
-
-    if (previousSibling || node->isBeforePseudoElement())
-        return previousSibling;
-
-    ContainerNode* parent = traverseParent(node, CrossShadowRoot);
-    if (parent && parent->isElementNode())
-        return toElement(parent)->beforePseudoElement();
-
-    return 0;
+    return traversePreviousSibling(node);
 }
 
 Node* nextInScope(const Node* node)

Modified: trunk/Source/WebCore/dom/NodeRenderingTraversal.h (165464 => 165465)


--- trunk/Source/WebCore/dom/NodeRenderingTraversal.h	2014-03-12 09:49:59 UTC (rev 165464)
+++ trunk/Source/WebCore/dom/NodeRenderingTraversal.h	2014-03-12 10:18:47 UTC (rev 165465)
@@ -35,6 +35,7 @@
 namespace NodeRenderingTraversal {
 
 ContainerNode* parent(const Node*);
+Node* firstChild(const Node*);
 Node* nextSibling(const Node*);
 Node* previousSibling(const Node*);
 
@@ -44,11 +45,13 @@
 Node* lastChildInScope(const Node*);
 
 ContainerNode* parentSlow(const Node*);
+Node* firstChildSlow(const Node*);
 Node* nextSiblingSlow(const Node*);
 Node* previousSiblingSlow(const Node*);
 
 inline ContainerNode* parent(const Node* node)
 {
+    ASSERT(!node->isPseudoElement());
     if (node->needsNodeRenderingTraversalSlowPath())
         return parentSlow(node);
 
@@ -56,8 +59,19 @@
     return node->parentNodeGuaranteedHostFree();
 }
 
+inline Node* firstChild(const Node* node)
+{
+    ASSERT(!node->isPseudoElement());
+    if (node->needsNodeRenderingTraversalSlowPath())
+        return firstChildSlow(node);
+
+    ASSERT(nextSiblingSlow(node) == node->nextSibling());
+    return node->firstChild();
+}
+
 inline Node* nextSibling(const Node* node)
 {
+    ASSERT(!node->isPseudoElement());
     if (node->needsNodeRenderingTraversalSlowPath())
         return nextSiblingSlow(node);
 
@@ -67,6 +81,7 @@
 
 inline Node* previousSibling(const Node* node)
 {
+    ASSERT(!node->isPseudoElement());
     if (node->needsNodeRenderingTraversalSlowPath())
         return previousSiblingSlow(node);
 

Modified: trunk/Source/WebCore/style/StyleResolveTree.cpp (165464 => 165465)


--- trunk/Source/WebCore/style/StyleResolveTree.cpp	2014-03-12 09:49:59 UTC (rev 165464)
+++ trunk/Source/WebCore/style/StyleResolveTree.cpp	2014-03-12 10:18:47 UTC (rev 165465)
@@ -60,10 +60,10 @@
 
 enum DetachType { NormalDetach, ReattachDetach };
 
-static void attachRenderTree(Element&, PassRefPtr<RenderStyle>);
-static void attachTextRenderer(Text&);
+static void attachRenderTree(Element&, ContainerNode& renderingParentNode, PassRefPtr<RenderStyle>);
+static void attachTextRenderer(Text&, ContainerNode& renderingParentNode);
 static void detachRenderTree(Element&, DetachType);
-static void resolveTree(Element&, Change);
+static void resolveTree(Element&, ContainerNode& renderingParentNode, Change);
 
 Change determineChange(const RenderStyle* s1, const RenderStyle* s2)
 {
@@ -126,43 +126,49 @@
     return false;
 }
 
-static RenderObject* nextSiblingRenderer(const Element& element, const ContainerNode* renderingParentNode)
+static RenderObject* nextSiblingRenderer(const Node& node, const ContainerNode& renderingParentNode)
 {
+    if (!renderingParentNode.isElementNode())
+        return nullptr;
+    const Element& renderingParentElement = toElement(renderingParentNode);
     // Avoid an O(N^2) problem with this function by not checking for
     // nextRenderer() when the parent element hasn't attached yet.
     // FIXME: Why would we get here anyway if parent is not attached?
-    if (renderingParentNode && !renderingParentNode->renderer())
+    if (!renderingParentElement.renderer())
         return nullptr;
-    for (Node* sibling = NodeRenderingTraversal::nextSibling(&element); sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) {
+    if (node.isAfterPseudoElement())
+        return nullptr;
+    Node* sibling = node.isBeforePseudoElement() ? NodeRenderingTraversal::firstChild(&renderingParentNode) : NodeRenderingTraversal::nextSibling(&node);
+    for (; sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) {
         RenderObject* renderer = sibling->renderer();
         if (renderer && !isRendererReparented(renderer))
             return renderer;
     }
+    if (PseudoElement* after = renderingParentElement.afterPseudoElement())
+        return after->renderer();
     return nullptr;
 }
 
-static bool shouldCreateRenderer(const Element& element, const ContainerNode* renderingParent)
+static bool shouldCreateRenderer(const Element& element, const ContainerNode& renderingParent)
 {
     if (!element.document().shouldCreateRenderers())
         return false;
-    if (!renderingParent)
-        return false;
-    RenderObject* parentRenderer = renderingParent->renderer();
+    RenderObject* parentRenderer = renderingParent.renderer();
     if (!parentRenderer)
         return false;
     if (!parentRenderer->canHaveChildren() && !(element.isPseudoElement() && parentRenderer->canHaveGeneratedChildren()))
         return false;
-    if (!renderingParent->childShouldCreateRenderer(element))
+    if (!renderingParent.childShouldCreateRenderer(element))
         return false;
     return true;
 }
 
 // Check the specific case of elements that are children of regions but are flowed into a flow thread themselves.
-static bool elementInsideRegionNeedsRenderer(Element& element, const ContainerNode* renderingParentNode, RefPtr<RenderStyle>& style)
+static bool elementInsideRegionNeedsRenderer(Element& element, const ContainerNode& renderingParentNode, RefPtr<RenderStyle>& style)
 {
 #if ENABLE(CSS_REGIONS)
     // The parent of a region should always be an element.
-    const RenderElement* parentRenderer = renderingParentNode ? renderingParentNode->renderer() : 0;
+    const RenderElement* parentRenderer = renderingParentNode.renderer();
 
     bool parentIsRegion = parentRenderer && !parentRenderer->canHaveChildren() && parentRenderer->isRenderNamedFlowFragmentContainer();
     bool parentIsNonRenderedInsideRegion = !parentRenderer && element.parentElement() && element.parentElement()->isInsideRegion();
@@ -198,12 +204,10 @@
 }
 #endif
 
-static void createRendererIfNeeded(Element& element, PassRefPtr<RenderStyle> resolvedStyle)
+static void createRendererIfNeeded(Element& element, ContainerNode& renderingParentNode, PassRefPtr<RenderStyle> resolvedStyle)
 {
     ASSERT(!element.renderer());
 
-    ContainerNode* renderingParentNode = NodeRenderingTraversal::parent(&element);
-
     RefPtr<RenderStyle> style = resolvedStyle;
 
     element.setIsInsideRegion(false);
@@ -229,7 +233,7 @@
         nextRenderer = parentFlowRenderer->nextRendererForElement(element);
     } else {
         // FIXME: Make this path Element only, handle the root special case separately.
-        parentRenderer = renderingParentNode->renderer();
+        parentRenderer = renderingParentNode.renderer();
         nextRenderer = nextSiblingRenderer(element, renderingParentNode);
     }
 
@@ -275,28 +279,18 @@
         if (renderer && !isRendererReparented(renderer))
             return renderer;
     }
-    return 0;
+    if (PseudoElement* before = textNode.parentElement()->beforePseudoElement())
+        return before->renderer();
+    return nullptr;
 }
 
-static RenderObject* nextSiblingRenderer(const Text& textNode)
+static void reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(Node& current, ContainerNode& renderingParentNode)
 {
-    if (textNode.renderer())
-        return textNode.renderer()->nextSibling();
-    for (Node* sibling = NodeRenderingTraversal::nextSibling(&textNode); sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) {
-        RenderObject* renderer = sibling->renderer();
-        if (renderer && !isRendererReparented(renderer))
-            return renderer;
-    }
-    return 0;
-}
-
-static void reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(Node& current)
-{
     if (isInsertionPoint(current))
         return;
     // This function finds sibling text renderers where the results of textRendererIsNeeded may have changed as a result of
     // the current node gaining or losing the renderer. This can only affect white space text nodes.
-    for (Node* sibling = NodeRenderingTraversal::nextSibling(&current); sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) {
+    for (Node* sibling = current.nextSibling(); sibling; sibling = sibling->nextSibling()) {
         // Siblings haven't been attached yet. They will be handled normally when they are.
         if (sibling->styleChangeType() == ReconstructRenderTree)
             return;
@@ -314,7 +308,7 @@
         Text& whitespaceTextSibling = textSibling;
         bool hadRenderer = whitespaceTextSibling.renderer();
         detachTextRenderer(whitespaceTextSibling);
-        attachTextRenderer(whitespaceTextSibling);
+        attachTextRenderer(whitespaceTextSibling, renderingParentNode);
         // No changes, futher renderers can't be affected.
         if (hadRenderer == !!whitespaceTextSibling.renderer())
             return;
@@ -352,7 +346,7 @@
         RenderObject* first = toRenderElement(parentRenderer).firstChild();
         while (first && first->isFloatingOrOutOfFlowPositioned())
             first = first->nextSibling();
-        RenderObject* nextRenderer = nextSiblingRenderer(textNode);
+        RenderObject* nextRenderer = nextSiblingRenderer(textNode, *textNode.parentNode());
         if (!first || nextRenderer == first) {
             // Whitespace at the start of a block just goes away. Don't even make a render object for this text.
             return false;
@@ -361,17 +355,14 @@
     return true;
 }
 
-static void createTextRendererIfNeeded(Text& textNode)
+static void createTextRendererIfNeeded(Text& textNode, ContainerNode& renderingParentNode)
 {
     ASSERT(!textNode.renderer());
 
-    ContainerNode* renderingParentNode = NodeRenderingTraversal::parent(&textNode);
-    if (!renderingParentNode)
-        return;
-    RenderElement* parentRenderer = renderingParentNode->renderer();
+    RenderElement* parentRenderer = renderingParentNode.renderer();
     if (!parentRenderer || !parentRenderer->canHaveChildren())
         return;
-    if (!renderingParentNode->childShouldCreateRenderer(textNode))
+    if (!renderingParentNode.childShouldCreateRenderer(textNode))
         return;
 
     const auto& style = parentRenderer->style();
@@ -389,15 +380,15 @@
     // for the first time. Otherwise code using inRenderFlowThread() in the styleWillChange and styleDidChange will fail.
     newRenderer->setFlowThreadState(parentRenderer->flowThreadState());
 
-    RenderObject* nextRenderer = nextSiblingRenderer(textNode);
+    RenderObject* nextRenderer = nextSiblingRenderer(textNode, renderingParentNode);
     textNode.setRenderer(newRenderer.get());
     // Parent takes care of the animations, no need to call setAnimatableStyle.
     parentRenderer->addChild(newRenderer.leakPtr(), nextRenderer);
 }
 
-void attachTextRenderer(Text& textNode)
+void attachTextRenderer(Text& textNode, ContainerNode& renderingParent)
 {
-    createTextRendererIfNeeded(textNode);
+    createTextRendererIfNeeded(textNode, renderingParent);
 
     textNode.clearNeedsStyleRecalc();
 }
@@ -412,61 +403,65 @@
 void updateTextRendererAfterContentChange(Text& textNode, unsigned offsetOfReplacedData, unsigned lengthOfReplacedData)
 {
     RenderText* textRenderer = textNode.renderer();
+    ContainerNode* renderingParentNode = NodeRenderingTraversal::parent(&textNode);
+    if (!renderingParentNode)
+        return;
     if (!textRenderer) {
-        attachTextRenderer(textNode);
-        reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(textNode);
+        attachTextRenderer(textNode, *renderingParentNode);
+        reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(textNode, *renderingParentNode);
         return;
     }
-    RenderObject* parentRenderer = NodeRenderingTraversal::parent(&textNode)->renderer();
-    if (!textRendererIsNeeded(textNode, *parentRenderer, textRenderer->style())) {
+    if (!textRendererIsNeeded(textNode, *renderingParentNode->renderer(), textRenderer->style())) {
         detachTextRenderer(textNode);
-        attachTextRenderer(textNode);
-        reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(textNode);
+        attachTextRenderer(textNode, *renderingParentNode);
+        reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(textNode, *renderingParentNode);
         return;
     }
     textRenderer->setTextWithOffset(textNode.dataImpl(), offsetOfReplacedData, lengthOfReplacedData);
 }
 
-static void attachDistributedChildren(InsertionPoint& insertionPoint)
+static void attachChildren(ContainerNode& current, ContainerNode& renderingParentNode)
 {
+    for (Node* child = current.firstChild(); child; child = child->nextSibling()) {
+        ASSERT((!child->renderer() || child->inNamedFlow()) || current.shadowRoot());
+        if (child->renderer())
+            continue;
+        if (child->isTextNode()) {
+            attachTextRenderer(*toText(child), renderingParentNode);
+            continue;
+        }
+        if (child->isElementNode())
+            attachRenderTree(*toElement(child), renderingParentNode, nullptr);
+    }
+}
+
+static void attachDistributedChildren(InsertionPoint& insertionPoint, ContainerNode& renderingParentNode)
+{
     if (ShadowRoot* shadowRoot = insertionPoint.containingShadowRoot())
         ContentDistributor::ensureDistribution(shadowRoot);
+
     for (Node* current = insertionPoint.firstDistributed(); current; current = insertionPoint.nextDistributedTo(current)) {
         if (current->isTextNode()) {
             if (current->renderer())
                 continue;
-            attachTextRenderer(*toText(current));
+            attachTextRenderer(*toText(current), renderingParentNode);
             continue;
         }
         if (current->isElementNode()) {
-            if (current->renderer())
-                detachRenderTree(*toElement(current));
-            attachRenderTree(*toElement(current), nullptr);
+            Element& currentElement = toElement(*current);
+            if (currentElement.renderer())
+                detachRenderTree(currentElement);
+            attachRenderTree(currentElement, renderingParentNode, nullptr);
         }
     }
+    // Use actual children as fallback content.
+    if (!insertionPoint.hasDistribution())
+        attachChildren(insertionPoint, renderingParentNode);
 }
 
-static void attachChildren(ContainerNode& current)
-{
-    if (isInsertionPoint(current))
-        attachDistributedChildren(toInsertionPoint(current));
-
-    for (Node* child = current.firstChild(); child; child = child->nextSibling()) {
-        ASSERT((!child->renderer() || child->inNamedFlow()) || current.shadowRoot() || isInsertionPoint(current));
-        if (child->renderer())
-            continue;
-        if (child->isTextNode()) {
-            attachTextRenderer(*toText(child));
-            continue;
-        }
-        if (child->isElementNode())
-            attachRenderTree(*toElement(child), nullptr);
-    }
-}
-
 static void attachShadowRoot(ShadowRoot& shadowRoot)
 {
-    attachChildren(shadowRoot);
+    attachChildren(shadowRoot, *shadowRoot.hostElement());
 
     shadowRoot.clearNeedsStyleRecalc();
     shadowRoot.clearChildNeedsStyleRecalc();
@@ -519,10 +514,10 @@
         return;
     RefPtr<PseudoElement> pseudoElement = PseudoElement::create(current, pseudoId);
     setBeforeOrAfterPseudoElement(current, pseudoElement, pseudoId);
-    attachRenderTree(*pseudoElement, nullptr);
+    attachRenderTree(*pseudoElement, current, nullptr);
 }
 
-static void attachRenderTree(Element& current, PassRefPtr<RenderStyle> resolvedStyle)
+static void attachRenderTree(Element& current, ContainerNode& renderingParentNode, PassRefPtr<RenderStyle> resolvedStyle)
 {
     PostAttachCallbackDisabler callbackDisabler(current.document());
     WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
@@ -530,7 +525,7 @@
     if (current.hasCustomStyleResolveCallbacks())
         current.willAttachRenderers();
 
-    createRendererIfNeeded(current, resolvedStyle);
+    createRendererIfNeeded(current, renderingParentNode, resolvedStyle);
 
     if (current.parentElement() && current.parentElement()->isInCanvasSubtree())
         current.setIsInCanvasSubtree(true);
@@ -539,14 +534,16 @@
 
     StyleResolverParentPusher parentPusher(&current);
 
-    // When a shadow root exists, it does the work of attaching the children.
     if (ShadowRoot* shadowRoot = current.shadowRoot()) {
         parentPusher.push();
         attachShadowRoot(*shadowRoot);
     } else if (current.firstChild())
         parentPusher.push();
 
-    attachChildren(current);
+    if (isInsertionPoint(current))
+        attachDistributedChildren(toInsertionPoint(current), renderingParentNode);
+    else
+        attachChildren(current, current);
 
     current.clearNeedsStyleRecalc();
     current.clearChildNeedsStyleRecalc();
@@ -656,7 +653,7 @@
     return false;
 }
 
-static Change resolveLocal(Element& current, Change inheritedChange)
+static Change resolveLocal(Element& current, ContainerNode& renderingParentNode, Change inheritedChange)
 {
     Change localChange = Detach;
     RefPtr<RenderStyle> newStyle;
@@ -670,8 +667,8 @@
     if (localChange == Detach) {
         if (current.renderer() || current.inNamedFlow())
             detachRenderTree(current, ReattachDetach);
-        attachRenderTree(current, newStyle.release());
-        reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(current);
+        attachRenderTree(current, renderingParentNode, newStyle.release());
+        reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(current, renderingParentNode);
 
         return Detach;
     }
@@ -702,7 +699,7 @@
     return localChange;
 }
 
-static void updateTextStyle(Text& text)
+static void updateTextStyle(Text& text, ContainerNode& renderingParentNode)
 {
     RenderText* renderer = text.renderer();
 
@@ -711,35 +708,32 @@
     if (renderer)
         renderer->setText(text.dataImpl());
     else {
-        attachTextRenderer(text);
-        reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(text);
+        attachTextRenderer(text, renderingParentNode);
+        reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(text, renderingParentNode);
     }
     text.clearNeedsStyleRecalc();
 }
 
-static void resolveShadowTree(ShadowRoot* shadowRoot, Style::Change change)
+static void resolveShadowTree(ShadowRoot& shadowRoot, Style::Change change)
 {
-    if (!shadowRoot)
-        return;
-
-    for (Node* child = shadowRoot->firstChild(); child; child = child->nextSibling()) {
+    for (Node* child = shadowRoot.firstChild(); child; child = child->nextSibling()) {
         if (child->isTextNode()) {
-            updateTextStyle(*toText(child));
+            updateTextStyle(*toText(child), *shadowRoot.hostElement());
             continue;
         }
         if (child->isElementNode())
-            resolveTree(*toElement(child), change);
+            resolveTree(*toElement(child), *shadowRoot.hostElement(), change);
     }
 
-    shadowRoot->clearNeedsStyleRecalc();
-    shadowRoot->clearChildNeedsStyleRecalc();
+    shadowRoot.clearNeedsStyleRecalc();
+    shadowRoot.clearChildNeedsStyleRecalc();
 }
 
 static void updateBeforeOrAfterPseudoElement(Element& current, Change change, PseudoId pseudoId)
 {
     if (PseudoElement* existingPseudoElement = beforeOrAfterPseudoElement(current, pseudoId)) {
         if (needsPseudeElement(current, pseudoId))
-            resolveTree(*existingPseudoElement, current.needsStyleRecalc() ? Force : change);
+            resolveTree(*existingPseudoElement, current, current.needsStyleRecalc() ? Force : change);
         else
             clearBeforeOrAfterPseudoElement(current, pseudoId);
         return;
@@ -799,7 +793,7 @@
 };
 #endif // PLATFORM(IOS)
 
-void resolveTree(Element& current, Change change)
+void resolveTree(Element& current, ContainerNode& renderingParentNode, Change change)
 {
     ASSERT(change != Detach);
 
@@ -808,8 +802,7 @@
             return;
     }
 
-    ContainerNode* renderingParentNode = NodeRenderingTraversal::parent(&current);
-    bool hasParentStyle = renderingParentNode && renderingParentNode->renderStyle();
+    bool hasParentStyle = renderingParentNode.renderStyle();
     bool hasDirectAdjacentRules = current.childrenAffectedByDirectAdjacentRules();
     bool hasIndirectAdjacentRules = current.childrenAffectedByForwardPositionalRules();
 
@@ -821,7 +814,7 @@
         current.resetComputedStyle();
 
     if (hasParentStyle && (change >= Inherit || current.needsStyleRecalc()))
-        change = resolveLocal(current, change);
+        change = resolveLocal(current, renderingParentNode, change);
 
     if (change != Detach) {
         StyleResolverParentPusher parentPusher(&current);
@@ -829,7 +822,7 @@
         if (ShadowRoot* shadowRoot = current.shadowRoot()) {
             if (change >= Inherit || shadowRoot->childNeedsStyleRecalc() || shadowRoot->needsStyleRecalc()) {
                 parentPusher.push();
-                resolveShadowTree(shadowRoot, change);
+                resolveShadowTree(*shadowRoot, change);
             }
         }
 
@@ -842,7 +835,7 @@
         bool forceCheckOfAnyElementSibling = false;
         for (Node* child = current.firstChild(); child; child = child->nextSibling()) {
             if (child->isTextNode()) {
-                updateTextStyle(*toText(child));
+                updateTextStyle(*toText(child), current);
                 continue;
             }
             if (!child->isElementNode())
@@ -853,7 +846,7 @@
                 childElement->setNeedsStyleRecalc();
             if (change >= Inherit || childElement->childNeedsStyleRecalc() || childElement->needsStyleRecalc()) {
                 parentPusher.push();
-                resolveTree(*childElement, change);
+                resolveTree(*childElement, current, change);
             }
             forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjacentRules;
             forceCheckOfAnyElementSibling = forceCheckOfAnyElementSibling || (childRulesChanged && hasIndirectAdjacentRules);
@@ -894,7 +887,7 @@
         return;
     if (change < Inherit && !documentElement->childNeedsStyleRecalc() && !documentElement->needsStyleRecalc())
         return;
-    resolveTree(*documentElement, change);
+    resolveTree(*documentElement, document, change);
 }
 
 void detachRenderTree(Element& element)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to