Index: third_party/WebKit/Source/core/css/RuleFeature.cpp |
diff --git a/third_party/WebKit/Source/core/css/RuleFeature.cpp b/third_party/WebKit/Source/core/css/RuleFeature.cpp |
index 2e2e24592a26c973f333022ba4435ee515d03738..b53fe7b64cf47a8a0b49a62fb63442aa0a0fc9f7 100644 |
--- a/third_party/WebKit/Source/core/css/RuleFeature.cpp |
+++ b/third_party/WebKit/Source/core/css/RuleFeature.cpp |
@@ -506,9 +506,13 @@ void RuleFeatureSet::addFeaturesToInvalidationSets(const CSSSelector* selector, |
// We set siblingFeatures to &localFeatures if we find a rightmost sibling combinator. |
InvalidationSetFeatures localFeatures; |
+ bool universalCompound = true; |
+ |
for (const CSSSelector* current = selector; current; current = current->tagHistory()) { |
InvalidationType type = siblingFeatures ? InvalidateSiblings : InvalidateDescendants; |
if (InvalidationSet* invalidationSet = invalidationSetForSelector(*current, type)) { |
+ if (current->match() != CSSSelector::PseudoClass) |
+ universalCompound = false; |
if (siblingFeatures) { |
SiblingInvalidationSet* siblingInvalidationSet = toSiblingInvalidationSet(invalidationSet); |
siblingInvalidationSet->updateMaxDirectAdjacentSelectors(siblingFeatures->maxDirectAdjacentSelectors); |
@@ -536,6 +540,10 @@ void RuleFeatureSet::addFeaturesToInvalidationSets(const CSSSelector* selector, |
if (current->relation() == CSSSelector::SubSelector) |
continue; |
+ if (universalCompound && siblingFeatures) |
+ addFeaturesToUniversalSiblingInvalidationSet(*siblingFeatures, descendantFeatures); |
+ universalCompound = true; |
+ |
if (current->relationIsAffectedByPseudoContent() || current->relation() == CSSSelector::ShadowSlot) { |
descendantFeatures.insertionPointCrossing = true; |
descendantFeatures.contentPseudoCrossing = true; |
@@ -565,6 +573,9 @@ void RuleFeatureSet::addFeaturesToInvalidationSets(const CSSSelector* selector, |
localFeatures.forceSubtree = result.second == ForceSubtree; |
siblingFeatures = &localFeatures; |
} |
+ |
+ if (universalCompound && siblingFeatures) |
+ addFeaturesToUniversalSiblingInvalidationSet(*siblingFeatures, descendantFeatures); |
} |
RuleFeatureSet::SelectorPreMatch RuleFeatureSet::collectFeaturesFromRuleData(const RuleData& ruleData) |
@@ -682,6 +693,8 @@ void RuleFeatureSet::add(const RuleFeatureSet& other) |
ensureInvalidationSet(m_idInvalidationSets, entry.key, entry.value->type()).combine(*entry.value); |
for (const auto& entry : other.m_pseudoInvalidationSets) |
ensureInvalidationSet(m_pseudoInvalidationSets, static_cast<CSSSelector::PseudoType>(entry.key), entry.value->type()).combine(*entry.value); |
+ if (other.m_universalSiblingInvalidationSet) |
+ ensureUniversalSiblingInvalidationSet().combine(*other.m_universalSiblingInvalidationSet); |
m_metadata.add(other.m_metadata); |
@@ -721,6 +734,21 @@ void RuleFeatureSet::collectInvalidationSetsForClass(InvalidationLists& invalida |
} |
} |
+void RuleFeatureSet::collectSiblingInvalidationSetForClass(InvalidationLists& invalidationLists, Element& element, const AtomicString& className) const |
+{ |
+ InvalidationSetMap::const_iterator it = m_classInvalidationSets.find(className); |
+ if (it == m_classInvalidationSets.end()) |
+ return; |
+ |
+ InvalidationSet* invalidationSet = it->value.get(); |
+ if (invalidationSet->type() == InvalidateDescendants) |
+ return; |
+ |
+ SiblingInvalidationSet* siblingSet = toSiblingInvalidationSet(invalidationSet); |
+ TRACE_SCHEDULE_STYLE_INVALIDATION(element, *siblingSet, classChange, className); |
+ invalidationLists.siblings.append(siblingSet); |
+} |
+ |
void RuleFeatureSet::collectInvalidationSetsForId(InvalidationLists& invalidationLists, Element& element, const AtomicString& id) const |
{ |
InvalidationSetMap::const_iterator it = m_idInvalidationSets.find(id); |
@@ -742,6 +770,21 @@ void RuleFeatureSet::collectInvalidationSetsForId(InvalidationLists& invalidatio |
} |
} |
+void RuleFeatureSet::collectSiblingInvalidationSetForId(InvalidationLists& invalidationLists, Element& element, const AtomicString& id) const |
+{ |
+ InvalidationSetMap::const_iterator it = m_idInvalidationSets.find(id); |
+ if (it == m_idInvalidationSets.end()) |
+ return; |
+ |
+ InvalidationSet* invalidationSet = it->value.get(); |
+ if (invalidationSet->type() == InvalidateDescendants) |
+ return; |
+ |
+ SiblingInvalidationSet* siblingSet = toSiblingInvalidationSet(invalidationSet); |
+ TRACE_SCHEDULE_STYLE_INVALIDATION(element, *siblingSet, idChange, id); |
+ invalidationLists.siblings.append(siblingSet); |
+} |
+ |
void RuleFeatureSet::collectInvalidationSetsForAttribute(InvalidationLists& invalidationLists, Element& element, const QualifiedName& attributeName) const |
{ |
InvalidationSetMap::const_iterator it = m_attributeInvalidationSets.find(attributeName.localName()); |
@@ -763,6 +806,21 @@ void RuleFeatureSet::collectInvalidationSetsForAttribute(InvalidationLists& inva |
} |
} |
+void RuleFeatureSet::collectSiblingInvalidationSetForAttribute(InvalidationLists& invalidationLists, Element& element, const QualifiedName& attributeName) const |
+{ |
+ InvalidationSetMap::const_iterator it = m_attributeInvalidationSets.find(attributeName.localName()); |
+ if (it == m_attributeInvalidationSets.end()) |
+ return; |
+ |
+ InvalidationSet* invalidationSet = it->value.get(); |
+ if (invalidationSet->type() == InvalidateDescendants) |
+ return; |
+ |
+ SiblingInvalidationSet* siblingSet = toSiblingInvalidationSet(invalidationSet); |
+ TRACE_SCHEDULE_STYLE_INVALIDATION(element, *siblingSet, attributeChange, attributeName); |
+ invalidationLists.siblings.append(siblingSet); |
+} |
+ |
void RuleFeatureSet::collectInvalidationSetsForPseudoClass(InvalidationLists& invalidationLists, Element& element, CSSSelector::PseudoType pseudo) const |
{ |
PseudoTypeInvalidationSetMap::const_iterator it = m_pseudoInvalidationSets.find(pseudo); |
@@ -784,6 +842,31 @@ void RuleFeatureSet::collectInvalidationSetsForPseudoClass(InvalidationLists& in |
} |
} |
+void RuleFeatureSet::collectUniversalSiblingInvalidationSet(InvalidationLists& invalidationLists) const |
+{ |
+ if (m_universalSiblingInvalidationSet) |
+ invalidationLists.siblings.append(m_universalSiblingInvalidationSet); |
+} |
+ |
+SiblingInvalidationSet& RuleFeatureSet::ensureUniversalSiblingInvalidationSet() |
+{ |
+ if (!m_universalSiblingInvalidationSet) |
+ m_universalSiblingInvalidationSet = SiblingInvalidationSet::create(nullptr); |
+ return *m_universalSiblingInvalidationSet; |
+} |
+ |
+void RuleFeatureSet::addFeaturesToUniversalSiblingInvalidationSet(const InvalidationSetFeatures& siblingFeatures, const InvalidationSetFeatures& descendantFeatures) |
+{ |
+ SiblingInvalidationSet& universalSet = ensureUniversalSiblingInvalidationSet(); |
+ addFeaturesToInvalidationSet(universalSet, siblingFeatures); |
+ universalSet.updateMaxDirectAdjacentSelectors(siblingFeatures.maxDirectAdjacentSelectors); |
+ |
+ if (&siblingFeatures == &descendantFeatures) |
+ universalSet.setInvalidatesSelf(); |
+ else |
+ addFeaturesToInvalidationSet(universalSet.ensureSiblingDescendants(), descendantFeatures); |
+} |
+ |
DEFINE_TRACE(RuleFeatureSet) |
{ |
visitor->trace(siblingRules); |