Changeset 165465 in webkit


Ignore:
Timestamp:
Mar 12, 2014, 3:18:47 AM (11 years ago)
Author:
Antti Koivisto
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.

Location:
trunk/Source/WebCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r165464 r165465  
     12014-03-12  Antti Koivisto  <antti@apple.com>
     2
     3        Don't use NodeRenderingTraversal for pseudo elements
     4        https://bugs.webkit.org/show_bug.cgi?id=130091
     5
     6        Reviewed by Andreas Kling.
     7
     8        Make traversing during style resolve more comprehensible by handling before/after pseudo elements explicitly.
     9
     10        With this patch NodeRenderingTraversal is only needed for InsertionPoints (which are nothing but an implementation
     11        detail of the <details> element at this point).
     12
     13        * dom/Element.cpp:
     14        (WebCore::shouldUseNodeRenderingTraversalSlowPath):
     15       
     16            PseudoElements don't need the slow path anymore.
     17
     18        (WebCore::Element::setBeforePseudoElement):
     19        (WebCore::Element::setAfterPseudoElement):
     20        (WebCore::Element::clearBeforePseudoElement):
     21        (WebCore::Element::clearAfterPseudoElement):
     22        * dom/NodeRenderingTraversal.cpp:
     23        (WebCore::NodeRenderingTraversal::traverseParent):
     24        (WebCore::NodeRenderingTraversal::firstChildSlow):
     25        (WebCore::NodeRenderingTraversal::nextSiblingSlow):
     26        (WebCore::NodeRenderingTraversal::previousSiblingSlow):
     27        * dom/NodeRenderingTraversal.h:
     28        (WebCore::NodeRenderingTraversal::firstChild):
     29        * style/StyleResolveTree.cpp:
     30        (WebCore::Style::nextSiblingRenderer):
     31       
     32            Add ::before/::after pseudo element handling here.
     33
     34        (WebCore::Style::shouldCreateRenderer):
     35        (WebCore::Style::elementInsideRegionNeedsRenderer):
     36        (WebCore::Style::createRendererIfNeeded):
     37        (WebCore::Style::previousSiblingRenderer):
     38       
     39            Add ::before pseudo element handling here (text node can't be ::after).
     40
     41        (WebCore::Style::reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded):
     42        (WebCore::Style::textRendererIsNeeded):
     43        (WebCore::Style::createTextRendererIfNeeded):
     44        (WebCore::Style::attachTextRenderer):
     45        (WebCore::Style::updateTextRendererAfterContentChange):
     46        (WebCore::Style::attachChildren):
     47        (WebCore::Style::attachDistributedChildren):
     48       
     49            Handle InsertionPoints in one place.
     50
     51        (WebCore::Style::attachShadowRoot):
     52        (WebCore::Style::attachBeforeOrAfterPseudoElementIfNeeded):
     53        (WebCore::Style::attachRenderTree):
     54        (WebCore::Style::resolveLocal):
     55        (WebCore::Style::updateTextStyle):
     56        (WebCore::Style::resolveShadowTree):
     57        (WebCore::Style::updateBeforeOrAfterPseudoElement):
     58        (WebCore::Style::resolveTree):
     59       
     60            Pass the rendering parent around to various functions instead of determining it repeatedly by calling
     61            NodeRenderingTraversal::parent. It is always the same for all direct children being resolved and generally just
     62            the parent element.
     63
    1642014-03-12  Frédéric Wang  <fred.wang@free.fr>
    265
  • trunk/Source/WebCore/css/StyleResolver.cpp

    r164869 r165465  
    9393#include "PageRuleCollector.h"
    9494#include "Pair.h"
     95#include "PseudoElement.h"
    9596#include "QuotesData.h"
    9697#include "Rect.h"
     
    411412
    412413    if (e) {
    413         m_parentNode = NodeRenderingTraversal::parent(e);
     414        m_parentNode = e->isPseudoElement() ? toPseudoElement(e)->hostElement() : NodeRenderingTraversal::parent(e);
    414415        bool resetStyleInheritance = hasShadowRootParent(*e) && toShadowRoot(e->parentNode())->resetStyleInheritance();
    415416        m_parentStyle = resetStyleInheritance ? 0 :
  • trunk/Source/WebCore/dom/Element.cpp

    r165185 r165465  
    14111411    if (element.isShadowRoot())
    14121412        return true;
    1413     if (element.isPseudoElement() || element.beforePseudoElement() || element.afterPseudoElement())
    1414         return true;
    14151413    return element.isInsertionPoint() || element.shadowRoot();
    14161414}
     
    22512249{
    22522250    ensureElementRareData().setBeforePseudoElement(element);
    2253     resetNeedsNodeRenderingTraversalSlowPath();
    22542251}
    22552252
     
    22572254{
    22582255    ensureElementRareData().setAfterPseudoElement(element);
    2259     resetNeedsNodeRenderingTraversalSlowPath();
    22602256}
    22612257
     
    22762272    disconnectPseudoElement(elementRareData()->beforePseudoElement());
    22772273    elementRareData()->setBeforePseudoElement(nullptr);
    2278     resetNeedsNodeRenderingTraversalSlowPath();
    22792274}
    22802275
     
    22852280    disconnectPseudoElement(elementRareData()->afterPseudoElement());
    22862281    elementRareData()->setAfterPseudoElement(nullptr);
    2287     resetNeedsNodeRenderingTraversalSlowPath();
    22882282}
    22892283
  • trunk/Source/WebCore/dom/NodeRenderingTraversal.cpp

    r155292 r165465  
    3030
    3131#include "InsertionPoint.h"
    32 #include "PseudoElement.h"
    3332#include "ShadowRoot.h"
    3433
     
    122121static ContainerNode* traverseParent(const Node* node, ShadowRootCrossing shadowRootCrossing)
    123122{
    124     if (node->isPseudoElement())
    125         return toPseudoElement(node)->hostElement();
    126 
    127123    if (shadowRootCrossing == DontCrossShadowRoot  && node->isShadowRoot())
    128124        return 0;
     
    223219}
    224220
     221Node* firstChildSlow(const Node* node)
     222{
     223    ASSERT(!node->isShadowRoot());
     224
     225    return traverseFirstChild(node, DontCrossShadowRoot);
     226}
     227
    225228Node* nextSiblingSlow(const Node* node)
    226229{
    227230    ASSERT(!node->isShadowRoot());
    228231
    229     // FIXME: Why do these functions deal with before/after when other code here doesn't?
    230     Node* nextSibling = 0;
    231     if (node->isBeforePseudoElement()) {
    232         nextSibling = traverseParent(node, CrossShadowRoot);
    233         nextSibling = traverseFirstChild(nextSibling, CrossShadowRoot);
    234     } else
    235         nextSibling = traverseNextSibling(node);
    236 
    237     if (nextSibling || node->isAfterPseudoElement())
    238         return nextSibling;
    239 
    240     Node* parent = traverseParent(node, CrossShadowRoot);
    241     if (parent && parent->isElementNode())
    242         return toElement(parent)->afterPseudoElement();
    243 
    244     return 0;
     232    return traverseNextSibling(node);
    245233}
    246234
     
    249237    ASSERT(!node->isShadowRoot());
    250238
    251     Node* previousSibling = 0;
    252     if (node->isAfterPseudoElement()) {
    253         ContainerNode* parent = traverseParent(node, CrossShadowRoot);
    254         previousSibling = traverseLastChild(parent, CrossShadowRoot);
    255     } else
    256         previousSibling = traversePreviousSibling(node);
    257 
    258     if (previousSibling || node->isBeforePseudoElement())
    259         return previousSibling;
    260 
    261     ContainerNode* parent = traverseParent(node, CrossShadowRoot);
    262     if (parent && parent->isElementNode())
    263         return toElement(parent)->beforePseudoElement();
    264 
    265     return 0;
     239    return traversePreviousSibling(node);
    266240}
    267241
  • trunk/Source/WebCore/dom/NodeRenderingTraversal.h

    r155303 r165465  
    3636
    3737ContainerNode* parent(const Node*);
     38Node* firstChild(const Node*);
    3839Node* nextSibling(const Node*);
    3940Node* previousSibling(const Node*);
     
    4546
    4647ContainerNode* parentSlow(const Node*);
     48Node* firstChildSlow(const Node*);
    4749Node* nextSiblingSlow(const Node*);
    4850Node* previousSiblingSlow(const Node*);
     
    5052inline ContainerNode* parent(const Node* node)
    5153{
     54    ASSERT(!node->isPseudoElement());
    5255    if (node->needsNodeRenderingTraversalSlowPath())
    5356        return parentSlow(node);
     
    5760}
    5861
     62inline Node* firstChild(const Node* node)
     63{
     64    ASSERT(!node->isPseudoElement());
     65    if (node->needsNodeRenderingTraversalSlowPath())
     66        return firstChildSlow(node);
     67
     68    ASSERT(nextSiblingSlow(node) == node->nextSibling());
     69    return node->firstChild();
     70}
     71
    5972inline Node* nextSibling(const Node* node)
    6073{
     74    ASSERT(!node->isPseudoElement());
    6175    if (node->needsNodeRenderingTraversalSlowPath())
    6276        return nextSiblingSlow(node);
     
    6882inline Node* previousSibling(const Node* node)
    6983{
     84    ASSERT(!node->isPseudoElement());
    7085    if (node->needsNodeRenderingTraversalSlowPath())
    7186        return previousSiblingSlow(node);
  • trunk/Source/WebCore/style/StyleResolveTree.cpp

    r163969 r165465  
    6161enum DetachType { NormalDetach, ReattachDetach };
    6262
    63 static void attachRenderTree(Element&, PassRefPtr<RenderStyle>);
    64 static void attachTextRenderer(Text&);
     63static void attachRenderTree(Element&, ContainerNode& renderingParentNode, PassRefPtr<RenderStyle>);
     64static void attachTextRenderer(Text&, ContainerNode& renderingParentNode);
    6565static void detachRenderTree(Element&, DetachType);
    66 static void resolveTree(Element&, Change);
     66static void resolveTree(Element&, ContainerNode& renderingParentNode, Change);
    6767
    6868Change determineChange(const RenderStyle* s1, const RenderStyle* s2)
     
    127127}
    128128
    129 static RenderObject* nextSiblingRenderer(const Element& element, const ContainerNode* renderingParentNode)
    130 {
     129static RenderObject* nextSiblingRenderer(const Node& node, const ContainerNode& renderingParentNode)
     130{
     131    if (!renderingParentNode.isElementNode())
     132        return nullptr;
     133    const Element& renderingParentElement = toElement(renderingParentNode);
    131134    // Avoid an O(N^2) problem with this function by not checking for
    132135    // nextRenderer() when the parent element hasn't attached yet.
    133136    // FIXME: Why would we get here anyway if parent is not attached?
    134     if (renderingParentNode && !renderingParentNode->renderer())
     137    if (!renderingParentElement.renderer())
    135138        return nullptr;
    136     for (Node* sibling = NodeRenderingTraversal::nextSibling(&element); sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) {
     139    if (node.isAfterPseudoElement())
     140        return nullptr;
     141    Node* sibling = node.isBeforePseudoElement() ? NodeRenderingTraversal::firstChild(&renderingParentNode) : NodeRenderingTraversal::nextSibling(&node);
     142    for (; sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) {
    137143        RenderObject* renderer = sibling->renderer();
    138144        if (renderer && !isRendererReparented(renderer))
    139145            return renderer;
    140146    }
     147    if (PseudoElement* after = renderingParentElement.afterPseudoElement())
     148        return after->renderer();
    141149    return nullptr;
    142150}
    143151
    144 static bool shouldCreateRenderer(const Element& element, const ContainerNode* renderingParent)
     152static bool shouldCreateRenderer(const Element& element, const ContainerNode& renderingParent)
    145153{
    146154    if (!element.document().shouldCreateRenderers())
    147155        return false;
    148     if (!renderingParent)
    149         return false;
    150     RenderObject* parentRenderer = renderingParent->renderer();
     156    RenderObject* parentRenderer = renderingParent.renderer();
    151157    if (!parentRenderer)
    152158        return false;
    153159    if (!parentRenderer->canHaveChildren() && !(element.isPseudoElement() && parentRenderer->canHaveGeneratedChildren()))
    154160        return false;
    155     if (!renderingParent->childShouldCreateRenderer(element))
     161    if (!renderingParent.childShouldCreateRenderer(element))
    156162        return false;
    157163    return true;
     
    159165
    160166// Check the specific case of elements that are children of regions but are flowed into a flow thread themselves.
    161 static bool elementInsideRegionNeedsRenderer(Element& element, const ContainerNode* renderingParentNode, RefPtr<RenderStyle>& style)
     167static bool elementInsideRegionNeedsRenderer(Element& element, const ContainerNode& renderingParentNode, RefPtr<RenderStyle>& style)
    162168{
    163169#if ENABLE(CSS_REGIONS)
    164170    // The parent of a region should always be an element.
    165     const RenderElement* parentRenderer = renderingParentNode ? renderingParentNode->renderer() : 0;
     171    const RenderElement* parentRenderer = renderingParentNode.renderer();
    166172
    167173    bool parentIsRegion = parentRenderer && !parentRenderer->canHaveChildren() && parentRenderer->isRenderNamedFlowFragmentContainer();
     
    199205#endif
    200206
    201 static void createRendererIfNeeded(Element& element, PassRefPtr<RenderStyle> resolvedStyle)
     207static void createRendererIfNeeded(Element& element, ContainerNode& renderingParentNode, PassRefPtr<RenderStyle> resolvedStyle)
    202208{
    203209    ASSERT(!element.renderer());
    204 
    205     ContainerNode* renderingParentNode = NodeRenderingTraversal::parent(&element);
    206210
    207211    RefPtr<RenderStyle> style = resolvedStyle;
     
    230234    } else {
    231235        // FIXME: Make this path Element only, handle the root special case separately.
    232         parentRenderer = renderingParentNode->renderer();
     236        parentRenderer = renderingParentNode.renderer();
    233237        nextRenderer = nextSiblingRenderer(element, renderingParentNode);
    234238    }
     
    276280            return renderer;
    277281    }
    278     return 0;
    279 }
    280 
    281 static RenderObject* nextSiblingRenderer(const Text& textNode)
    282 {
    283     if (textNode.renderer())
    284         return textNode.renderer()->nextSibling();
    285     for (Node* sibling = NodeRenderingTraversal::nextSibling(&textNode); sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) {
    286         RenderObject* renderer = sibling->renderer();
    287         if (renderer && !isRendererReparented(renderer))
    288             return renderer;
    289     }
    290     return 0;
    291 }
    292 
    293 static void reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(Node& current)
     282    if (PseudoElement* before = textNode.parentElement()->beforePseudoElement())
     283        return before->renderer();
     284    return nullptr;
     285}
     286
     287static void reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(Node& current, ContainerNode& renderingParentNode)
    294288{
    295289    if (isInsertionPoint(current))
     
    297291    // This function finds sibling text renderers where the results of textRendererIsNeeded may have changed as a result of
    298292    // the current node gaining or losing the renderer. This can only affect white space text nodes.
    299     for (Node* sibling = NodeRenderingTraversal::nextSibling(&current); sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) {
     293    for (Node* sibling = current.nextSibling(); sibling; sibling = sibling->nextSibling()) {
    300294        // Siblings haven't been attached yet. They will be handled normally when they are.
    301295        if (sibling->styleChangeType() == ReconstructRenderTree)
     
    315309        bool hadRenderer = whitespaceTextSibling.renderer();
    316310        detachTextRenderer(whitespaceTextSibling);
    317         attachTextRenderer(whitespaceTextSibling);
     311        attachTextRenderer(whitespaceTextSibling, renderingParentNode);
    318312        // No changes, futher renderers can't be affected.
    319313        if (hadRenderer == !!whitespaceTextSibling.renderer())
     
    353347        while (first && first->isFloatingOrOutOfFlowPositioned())
    354348            first = first->nextSibling();
    355         RenderObject* nextRenderer = nextSiblingRenderer(textNode);
     349        RenderObject* nextRenderer = nextSiblingRenderer(textNode, *textNode.parentNode());
    356350        if (!first || nextRenderer == first) {
    357351            // Whitespace at the start of a block just goes away. Don't even make a render object for this text.
     
    362356}
    363357
    364 static void createTextRendererIfNeeded(Text& textNode)
     358static void createTextRendererIfNeeded(Text& textNode, ContainerNode& renderingParentNode)
    365359{
    366360    ASSERT(!textNode.renderer());
    367361
    368     ContainerNode* renderingParentNode = NodeRenderingTraversal::parent(&textNode);
    369     if (!renderingParentNode)
    370         return;
    371     RenderElement* parentRenderer = renderingParentNode->renderer();
     362    RenderElement* parentRenderer = renderingParentNode.renderer();
    372363    if (!parentRenderer || !parentRenderer->canHaveChildren())
    373364        return;
    374     if (!renderingParentNode->childShouldCreateRenderer(textNode))
     365    if (!renderingParentNode.childShouldCreateRenderer(textNode))
    375366        return;
    376367
     
    390381    newRenderer->setFlowThreadState(parentRenderer->flowThreadState());
    391382
    392     RenderObject* nextRenderer = nextSiblingRenderer(textNode);
     383    RenderObject* nextRenderer = nextSiblingRenderer(textNode, renderingParentNode);
    393384    textNode.setRenderer(newRenderer.get());
    394385    // Parent takes care of the animations, no need to call setAnimatableStyle.
     
    396387}
    397388
    398 void attachTextRenderer(Text& textNode)
    399 {
    400     createTextRendererIfNeeded(textNode);
     389void attachTextRenderer(Text& textNode, ContainerNode& renderingParent)
     390{
     391    createTextRendererIfNeeded(textNode, renderingParent);
    401392
    402393    textNode.clearNeedsStyleRecalc();
     
    413404{
    414405    RenderText* textRenderer = textNode.renderer();
     406    ContainerNode* renderingParentNode = NodeRenderingTraversal::parent(&textNode);
     407    if (!renderingParentNode)
     408        return;
    415409    if (!textRenderer) {
    416         attachTextRenderer(textNode);
    417         reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(textNode);
    418         return;
    419     }
    420     RenderObject* parentRenderer = NodeRenderingTraversal::parent(&textNode)->renderer();
    421     if (!textRendererIsNeeded(textNode, *parentRenderer, textRenderer->style())) {
     410        attachTextRenderer(textNode, *renderingParentNode);
     411        reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(textNode, *renderingParentNode);
     412        return;
     413    }
     414    if (!textRendererIsNeeded(textNode, *renderingParentNode->renderer(), textRenderer->style())) {
    422415        detachTextRenderer(textNode);
    423         attachTextRenderer(textNode);
    424         reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(textNode);
     416        attachTextRenderer(textNode, *renderingParentNode);
     417        reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(textNode, *renderingParentNode);
    425418        return;
    426419    }
     
    428421}
    429422
    430 static void attachDistributedChildren(InsertionPoint& insertionPoint)
     423static void attachChildren(ContainerNode& current, ContainerNode& renderingParentNode)
     424{
     425    for (Node* child = current.firstChild(); child; child = child->nextSibling()) {
     426        ASSERT((!child->renderer() || child->inNamedFlow()) || current.shadowRoot());
     427        if (child->renderer())
     428            continue;
     429        if (child->isTextNode()) {
     430            attachTextRenderer(*toText(child), renderingParentNode);
     431            continue;
     432        }
     433        if (child->isElementNode())
     434            attachRenderTree(*toElement(child), renderingParentNode, nullptr);
     435    }
     436}
     437
     438static void attachDistributedChildren(InsertionPoint& insertionPoint, ContainerNode& renderingParentNode)
    431439{
    432440    if (ShadowRoot* shadowRoot = insertionPoint.containingShadowRoot())
    433441        ContentDistributor::ensureDistribution(shadowRoot);
     442
    434443    for (Node* current = insertionPoint.firstDistributed(); current; current = insertionPoint.nextDistributedTo(current)) {
    435444        if (current->isTextNode()) {
    436445            if (current->renderer())
    437446                continue;
    438             attachTextRenderer(*toText(current));
     447            attachTextRenderer(*toText(current), renderingParentNode);
    439448            continue;
    440449        }
    441450        if (current->isElementNode()) {
    442             if (current->renderer())
    443                 detachRenderTree(*toElement(current));
    444             attachRenderTree(*toElement(current), nullptr);
    445         }
    446     }
    447 }
    448 
    449 static void attachChildren(ContainerNode& current)
    450 {
    451     if (isInsertionPoint(current))
    452         attachDistributedChildren(toInsertionPoint(current));
    453 
    454     for (Node* child = current.firstChild(); child; child = child->nextSibling()) {
    455         ASSERT((!child->renderer() || child->inNamedFlow()) || current.shadowRoot() || isInsertionPoint(current));
    456         if (child->renderer())
    457             continue;
    458         if (child->isTextNode()) {
    459             attachTextRenderer(*toText(child));
    460             continue;
    461         }
    462         if (child->isElementNode())
    463             attachRenderTree(*toElement(child), nullptr);
    464     }
     451            Element& currentElement = toElement(*current);
     452            if (currentElement.renderer())
     453                detachRenderTree(currentElement);
     454            attachRenderTree(currentElement, renderingParentNode, nullptr);
     455        }
     456    }
     457    // Use actual children as fallback content.
     458    if (!insertionPoint.hasDistribution())
     459        attachChildren(insertionPoint, renderingParentNode);
    465460}
    466461
    467462static void attachShadowRoot(ShadowRoot& shadowRoot)
    468463{
    469     attachChildren(shadowRoot);
     464    attachChildren(shadowRoot, *shadowRoot.hostElement());
    470465
    471466    shadowRoot.clearNeedsStyleRecalc();
     
    520515    RefPtr<PseudoElement> pseudoElement = PseudoElement::create(current, pseudoId);
    521516    setBeforeOrAfterPseudoElement(current, pseudoElement, pseudoId);
    522     attachRenderTree(*pseudoElement, nullptr);
    523 }
    524 
    525 static void attachRenderTree(Element& current, PassRefPtr<RenderStyle> resolvedStyle)
     517    attachRenderTree(*pseudoElement, current, nullptr);
     518}
     519
     520static void attachRenderTree(Element& current, ContainerNode& renderingParentNode, PassRefPtr<RenderStyle> resolvedStyle)
    526521{
    527522    PostAttachCallbackDisabler callbackDisabler(current.document());
     
    531526        current.willAttachRenderers();
    532527
    533     createRendererIfNeeded(current, resolvedStyle);
     528    createRendererIfNeeded(current, renderingParentNode, resolvedStyle);
    534529
    535530    if (current.parentElement() && current.parentElement()->isInCanvasSubtree())
     
    540535    StyleResolverParentPusher parentPusher(&current);
    541536
    542     // When a shadow root exists, it does the work of attaching the children.
    543537    if (ShadowRoot* shadowRoot = current.shadowRoot()) {
    544538        parentPusher.push();
     
    547541        parentPusher.push();
    548542
    549     attachChildren(current);
     543    if (isInsertionPoint(current))
     544        attachDistributedChildren(toInsertionPoint(current), renderingParentNode);
     545    else
     546        attachChildren(current, current);
    550547
    551548    current.clearNeedsStyleRecalc();
     
    657654}
    658655
    659 static Change resolveLocal(Element& current, Change inheritedChange)
     656static Change resolveLocal(Element& current, ContainerNode& renderingParentNode, Change inheritedChange)
    660657{
    661658    Change localChange = Detach;
     
    671668        if (current.renderer() || current.inNamedFlow())
    672669            detachRenderTree(current, ReattachDetach);
    673         attachRenderTree(current, newStyle.release());
    674         reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(current);
     670        attachRenderTree(current, renderingParentNode, newStyle.release());
     671        reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(current, renderingParentNode);
    675672
    676673        return Detach;
     
    703700}
    704701
    705 static void updateTextStyle(Text& text)
     702static void updateTextStyle(Text& text, ContainerNode& renderingParentNode)
    706703{
    707704    RenderText* renderer = text.renderer();
     
    712709        renderer->setText(text.dataImpl());
    713710    else {
    714         attachTextRenderer(text);
    715         reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(text);
     711        attachTextRenderer(text, renderingParentNode);
     712        reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(text, renderingParentNode);
    716713    }
    717714    text.clearNeedsStyleRecalc();
    718715}
    719716
    720 static void resolveShadowTree(ShadowRoot* shadowRoot, Style::Change change)
    721 {
    722     if (!shadowRoot)
    723         return;
    724 
    725     for (Node* child = shadowRoot->firstChild(); child; child = child->nextSibling()) {
     717static void resolveShadowTree(ShadowRoot& shadowRoot, Style::Change change)
     718{
     719    for (Node* child = shadowRoot.firstChild(); child; child = child->nextSibling()) {
    726720        if (child->isTextNode()) {
    727             updateTextStyle(*toText(child));
     721            updateTextStyle(*toText(child), *shadowRoot.hostElement());
    728722            continue;
    729723        }
    730724        if (child->isElementNode())
    731             resolveTree(*toElement(child), change);
    732     }
    733 
    734     shadowRoot->clearNeedsStyleRecalc();
    735     shadowRoot->clearChildNeedsStyleRecalc();
     725            resolveTree(*toElement(child), *shadowRoot.hostElement(), change);
     726    }
     727
     728    shadowRoot.clearNeedsStyleRecalc();
     729    shadowRoot.clearChildNeedsStyleRecalc();
    736730}
    737731
     
    740734    if (PseudoElement* existingPseudoElement = beforeOrAfterPseudoElement(current, pseudoId)) {
    741735        if (needsPseudeElement(current, pseudoId))
    742             resolveTree(*existingPseudoElement, current.needsStyleRecalc() ? Force : change);
     736            resolveTree(*existingPseudoElement, current, current.needsStyleRecalc() ? Force : change);
    743737        else
    744738            clearBeforeOrAfterPseudoElement(current, pseudoId);
     
    800794#endif // PLATFORM(IOS)
    801795
    802 void resolveTree(Element& current, Change change)
     796void resolveTree(Element& current, ContainerNode& renderingParentNode, Change change)
    803797{
    804798    ASSERT(change != Detach);
     
    809803    }
    810804
    811     ContainerNode* renderingParentNode = NodeRenderingTraversal::parent(&current);
    812     bool hasParentStyle = renderingParentNode && renderingParentNode->renderStyle();
     805    bool hasParentStyle = renderingParentNode.renderStyle();
    813806    bool hasDirectAdjacentRules = current.childrenAffectedByDirectAdjacentRules();
    814807    bool hasIndirectAdjacentRules = current.childrenAffectedByForwardPositionalRules();
     
    822815
    823816    if (hasParentStyle && (change >= Inherit || current.needsStyleRecalc()))
    824         change = resolveLocal(current, change);
     817        change = resolveLocal(current, renderingParentNode, change);
    825818
    826819    if (change != Detach) {
     
    830823            if (change >= Inherit || shadowRoot->childNeedsStyleRecalc() || shadowRoot->needsStyleRecalc()) {
    831824                parentPusher.push();
    832                 resolveShadowTree(shadowRoot, change);
     825                resolveShadowTree(*shadowRoot, change);
    833826            }
    834827        }
     
    843836        for (Node* child = current.firstChild(); child; child = child->nextSibling()) {
    844837            if (child->isTextNode()) {
    845                 updateTextStyle(*toText(child));
     838                updateTextStyle(*toText(child), current);
    846839                continue;
    847840            }
     
    854847            if (change >= Inherit || childElement->childNeedsStyleRecalc() || childElement->needsStyleRecalc()) {
    855848                parentPusher.push();
    856                 resolveTree(*childElement, change);
     849                resolveTree(*childElement, current, change);
    857850            }
    858851            forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjacentRules;
     
    895888    if (change < Inherit && !documentElement->childNeedsStyleRecalc() && !documentElement->needsStyleRecalc())
    896889        return;
    897     resolveTree(*documentElement, change);
     890    resolveTree(*documentElement, document, change);
    898891}
    899892
Note: See TracChangeset for help on using the changeset viewer.