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); }
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; }