Chromium Code Reviews| 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..ee736d1405d87629bacf2343519069adc59a8209 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,24 @@ void RuleFeatureSet::collectInvalidationSetsForClass(InvalidationLists& invalida |
| } |
| } |
| +void RuleFeatureSet::collectSiblingInvalidationSetForClass(InvalidationLists& invalidationLists, Element& element, const AtomicString& className, unsigned minDirectAdjacent) 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); |
| + if (siblingSet->maxDirectAdjacentSelectors() < minDirectAdjacent) |
| + return; |
| + |
| + 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 +773,24 @@ void RuleFeatureSet::collectInvalidationSetsForId(InvalidationLists& invalidatio |
| } |
| } |
| +void RuleFeatureSet::collectSiblingInvalidationSetForId(InvalidationLists& invalidationLists, Element& element, const AtomicString& id, unsigned minDirectAdjacent) 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); |
| + if (siblingSet->maxDirectAdjacentSelectors() < minDirectAdjacent) |
| + return; |
| + |
| + 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 +812,24 @@ void RuleFeatureSet::collectInvalidationSetsForAttribute(InvalidationLists& inva |
| } |
| } |
| +void RuleFeatureSet::collectSiblingInvalidationSetForAttribute(InvalidationLists& invalidationLists, Element& element, const QualifiedName& attributeName, unsigned minDirectAdjacent) 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); |
| + if (siblingSet->maxDirectAdjacentSelectors() < minDirectAdjacent) |
|
esprehn
2016/06/25 01:54:07
Can you explain why we can skip collecting the set
rune
2016/06/25 11:06:34
The min that is passed in is the distance from the
esprehn
2016/06/29 04:52:08
Interesting, I wonder if we should do that in a se
rune
2016/06/29 07:44:21
Yeah. I didn't add any tests for that either, so I
rune
2016/06/29 08:26:06
Done.
|
| + return; |
| + |
| + 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 +851,31 @@ void RuleFeatureSet::collectInvalidationSetsForPseudoClass(InvalidationLists& in |
| } |
| } |
| +void RuleFeatureSet::collectUniversalSiblingInvalidationSet(InvalidationLists& invalidationLists, unsigned minDirectAdjacent) const |
| +{ |
| + if (m_universalSiblingInvalidationSet && m_universalSiblingInvalidationSet->maxDirectAdjacentSelectors() >= minDirectAdjacent) |
| + 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); |