bool StyleInvalidator::invalidate(Element& element, RecursionData& recursionData, SiblingData& siblingData)
{
    siblingData.advance();
    RecursionCheckpoint checkpoint(&recursionData);

    bool thisElementNeedsStyleRecalc = checkInvalidationSetsAgainstElement(element, recursionData, siblingData);

    bool someChildrenNeedStyleRecalc = false;
    if (recursionData.hasInvalidationSets() || element.childNeedsStyleInvalidation())
        someChildrenNeedStyleRecalc = invalidateChildren(element, recursionData);

    if (thisElementNeedsStyleRecalc) {
        ASSERT(!recursionData.wholeSubtreeInvalid());
        element.setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::StyleInvalidator));
    } else if (recursionData.hasInvalidationSets() && someChildrenNeedStyleRecalc) {
        // Clone the ComputedStyle in order to preserve correct style sharing, if possible. Otherwise recalc style.
        if (LayoutObject* layoutObject = element.layoutObject()) {
            layoutObject->setStyleInternal(ComputedStyle::clone(layoutObject->styleRef()));
        } else {
            TRACE_STYLE_INVALIDATOR_INVALIDATION_IF_ENABLED(element, PreventStyleSharingForParent);
            element.setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::StyleInvalidator));
        }
    }

    if (recursionData.insertionPointCrossing() && element.isInsertionPoint())
        element.setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::StyleInvalidator));
    if (recursionData.invalidatesSlotted() && isHTMLSlotElement(element))
        invalidateSlotDistributedElements(toHTMLSlotElement(element), recursionData);

    element.clearChildNeedsStyleInvalidation();
    element.clearNeedsStyleInvalidation();

    return thisElementNeedsStyleRecalc;
}
ContainerNode* FlatTreeTraversal::traverseParent(const Node& node, ParentTraversalDetails* details)
{
    // TODO(hayato): Stop this hack for a pseudo element because a pseudo element is not a child of its parentOrShadowHostNode() in a flat tree.
    if (node.isPseudoElement())
        return node.parentOrShadowHostNode();

    if (node.isChildOfV1ShadowHost()) {
        HTMLSlotElement* slot = finalDestinationSlotFor(node);
        if (!slot)
            return nullptr;
        return traverseParent(*slot);
    }

    Element* parent = node.parentElement();
    if (parent && isHTMLSlotElement(parent)) {
        HTMLSlotElement& slot = toHTMLSlotElement(*parent);
        if (!slot.assignedNodes().isEmpty())
            return nullptr;
        return traverseParent(slot, details);
    }

    if (canBeDistributedToInsertionPoint(node))
        return traverseParentForV0(node, details);

    DCHECK(!shadowWhereNodeCanBeDistributed(node));
    return traverseParentOrHost(node);
}
예제 #3
0
void SlotAssignment::assign(Node& hostChild, HTMLSlotElement& slot)
{
    m_assignment.add(&hostChild, &slot);
    slot.appendAssignedNode(hostChild);
    if (isHTMLSlotElement(hostChild))
        slot.appendDistributedNodes(toHTMLSlotElement(hostChild).getDistributedNodes());
    else
        slot.appendDistributedNode(hostChild);
}
Node* FlatTreeTraversal::resolveDistributionStartingAt(const Node* node, TraversalDirection direction)
{
    if (!node)
        return nullptr;
    for (const Node* sibling = node; sibling; sibling = (direction == TraversalDirectionForward ? sibling->nextSibling() : sibling->previousSibling())) {
        if (isHTMLSlotElement(*sibling)) {
            const HTMLSlotElement& slot = toHTMLSlotElement(*sibling);
            if (Node* found = (direction == TraversalDirectionForward ? slot.firstDistributedNode() : slot.lastDistributedNode()))
                return found;
            continue;
        }
        if (node->isInV0ShadowTree())
            return v0ResolveDistributionStartingAt(*sibling, direction);
        return const_cast<Node*>(sibling);
    }
    return nullptr;
}