ALWAYS_INLINE bool StyleInvalidator::checkInvalidationSetsAgainstElement(Element& element, RecursionData& recursionData, SiblingData& siblingData) { if (element.styleChangeType() >= SubtreeStyleChange || recursionData.wholeSubtreeInvalid()) { recursionData.setWholeSubtreeInvalid(); return false; } bool thisElementNeedsStyleRecalc = recursionData.matchesCurrentInvalidationSets(element); if (UNLIKELY(!siblingData.isEmpty())) thisElementNeedsStyleRecalc |= siblingData.matchCurrentInvalidationSets(element, recursionData); if (UNLIKELY(element.needsStyleInvalidation())) pushInvalidationSetsForElement(element, recursionData, siblingData); return thisElementNeedsStyleRecalc; }
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)); element.clearChildNeedsStyleInvalidation(); element.clearNeedsStyleInvalidation(); return thisElementNeedsStyleRecalc; }
void StyleInvalidator::pushInvalidationSetsForElement(Element& element, RecursionData& recursionData, SiblingData& siblingData) { PendingInvalidations* pendingInvalidations = m_pendingInvalidationMap.get(&element); ASSERT(pendingInvalidations); for (const auto& invalidationSet : pendingInvalidations->siblings()) siblingData.pushInvalidationSet(toSiblingInvalidationSet(*invalidationSet)); if (!pendingInvalidations->descendants().isEmpty()) { for (const auto& invalidationSet : pendingInvalidations->descendants()) recursionData.pushInvalidationSet(toDescendantInvalidationSet(*invalidationSet)); if (UNLIKELY(*s_tracingEnabled)) { TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.invalidationTracking"), "StyleInvalidatorInvalidationTracking", TRACE_EVENT_SCOPE_THREAD, "data", InspectorStyleInvalidatorInvalidateEvent::invalidationList(element, pendingInvalidations->descendants())); } } }
void StyleInvalidator::pushInvalidationSetsForContainerNode(ContainerNode& node, RecursionData& recursionData, SiblingData& siblingData) { PendingInvalidations* pendingInvalidations = m_pendingInvalidationMap.get(&node); ASSERT(pendingInvalidations); for (const auto& invalidationSet : pendingInvalidations->siblings()) siblingData.pushInvalidationSet(toSiblingInvalidationSet(*invalidationSet)); if (node.getStyleChangeType() >= SubtreeStyleChange) return; if (!pendingInvalidations->descendants().isEmpty()) { for (const auto& invalidationSet : pendingInvalidations->descendants()) recursionData.pushInvalidationSet(*invalidationSet); if (UNLIKELY(*s_tracingEnabled)) { TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.invalidationTracking"), "StyleInvalidatorInvalidationTracking", TRACE_EVENT_SCOPE_THREAD, "data", InspectorStyleInvalidatorInvalidateEvent::invalidationList(node, pendingInvalidations->descendants())); } } }