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 cc629c6dcde2b3bd6e5514401469f898af4441ea..8357290f1b22d41e9964103d47766d12bd42e9c7 100644 |
--- a/third_party/WebKit/Source/core/css/RuleFeature.cpp |
+++ b/third_party/WebKit/Source/core/css/RuleFeature.cpp |
@@ -443,7 +443,9 @@ void RuleFeatureSet::updateInvalidationSets(const RuleData& ruleData) |
const CSSSelector* lastInCompound = extractInvalidationSetFeaturesFromCompound(ruleData.selector(), features, Subject); |
- if (!features.hasFeatures()) |
+ if (features.forceSubtree) |
+ features.hasFeaturesForRuleSetInvalidation = false; |
+ else if (!features.hasFeatures()) |
features.forceSubtree = true; |
if (features.hasNthPseudo) |
addFeaturesToInvalidationSet(ensureNthInvalidationSet(), features); |
@@ -451,12 +453,18 @@ void RuleFeatureSet::updateInvalidationSets(const RuleData& ruleData) |
updateInvalidationSetsForContentAttribute(ruleData); |
const CSSSelector* nextCompound = lastInCompound ? lastInCompound->tagHistory() : &ruleData.selector(); |
- if (!nextCompound) |
+ if (!nextCompound) { |
+ if (!features.hasFeaturesForRuleSetInvalidation) |
+ m_metadata.needsFullRecalcForRuleSetInvalidation = true; |
return; |
+ } |
if (lastInCompound) |
updateFeaturesFromCombinator(*lastInCompound, nullptr, features, siblingFeatures, features); |
addFeaturesToInvalidationSets(*nextCompound, siblingFeatures, features); |
+ |
+ if (!features.hasFeaturesForRuleSetInvalidation) |
+ m_metadata.needsFullRecalcForRuleSetInvalidation = true; |
} |
void RuleFeatureSet::updateInvalidationSetsForContentAttribute(const RuleData& ruleData) |
@@ -570,8 +578,10 @@ RuleFeatureSet::extractInvalidationSetFeaturesFromCompound(const CSSSelector& co |
return nullptr; |
} |
- if (!simpleSelector->tagHistory() || simpleSelector->relation() != CSSSelector::SubSelector) |
+ if (!simpleSelector->tagHistory() || simpleSelector->relation() != CSSSelector::SubSelector) { |
+ features.hasFeaturesForRuleSetInvalidation = features.hasTagIdClassOrAttribute(); |
return simpleSelector; |
+ } |
} |
} |
@@ -617,8 +627,20 @@ void RuleFeatureSet::addFeaturesToInvalidationSetsForSelectorList(const CSSSelec |
DCHECK(supportsInvalidationWithSelectorList(simpleSelector.getPseudoType())); |
- for (const CSSSelector* subSelector = simpleSelector.selectorList()->first(); subSelector; subSelector = CSSSelectorList::next(*subSelector)) |
+ bool hadFeaturesForRuleSetInvalidation = descendantFeatures.hasFeaturesForRuleSetInvalidation; |
+ bool selectorListContainsUniversal = simpleSelector.getPseudoType() == CSSSelector::PseudoNot |
+ || simpleSelector.getPseudoType() == CSSSelector::PseudoHostContext; |
+ |
+ for (const CSSSelector* subSelector = simpleSelector.selectorList()->first(); subSelector; subSelector = CSSSelectorList::next(*subSelector)) { |
+ descendantFeatures.hasFeaturesForRuleSetInvalidation = false; |
+ |
addFeaturesToInvalidationSetsForCompoundSelector(*subSelector, siblingFeatures, descendantFeatures); |
+ |
+ if (!descendantFeatures.hasFeaturesForRuleSetInvalidation) |
+ selectorListContainsUniversal = true; |
+ } |
+ |
+ descendantFeatures.hasFeaturesForRuleSetInvalidation = hadFeaturesForRuleSetInvalidation || !selectorListContainsUniversal; |
} |
void RuleFeatureSet::addFeaturesToInvalidationSetsForSimpleSelector(const CSSSelector& simpleSelector, InvalidationSetFeatures* siblingFeatures, InvalidationSetFeatures& descendantFeatures) |
@@ -653,15 +675,17 @@ const CSSSelector* RuleFeatureSet::addFeaturesToInvalidationSetsForCompoundSelec |
const CSSSelector* simpleSelector = &compound; |
for (; simpleSelector; simpleSelector = simpleSelector->tagHistory()) { |
addFeaturesToInvalidationSetsForSimpleSelector(*simpleSelector, siblingFeatures, descendantFeatures); |
- if (siblingFeatures) |
- compoundHasIdClassOrAttribute |= simpleSelector->isIdClassOrAttributeSelector(); |
+ if (simpleSelector->isIdClassOrAttributeSelector()) |
+ compoundHasIdClassOrAttribute = true; |
if (simpleSelector->relation() != CSSSelector::SubSelector) |
break; |
if (!simpleSelector->tagHistory()) |
break; |
} |
- if (siblingFeatures && !compoundHasIdClassOrAttribute) |
+ if (compoundHasIdClassOrAttribute) |
+ descendantFeatures.hasFeaturesForRuleSetInvalidation = true; |
+ else if (siblingFeatures) |
addFeaturesToUniversalSiblingInvalidationSet(*siblingFeatures, descendantFeatures); |
return simpleSelector; |
@@ -774,8 +798,8 @@ RuleFeatureSet::SelectorPreMatch RuleFeatureSet::collectFeaturesFromSelector(con |
void RuleFeatureSet::FeatureMetadata::add(const FeatureMetadata& other) |
{ |
- usesFirstLineRules = usesFirstLineRules || other.usesFirstLineRules; |
- usesWindowInactiveSelector = usesWindowInactiveSelector || other.usesWindowInactiveSelector; |
+ usesFirstLineRules |= other.usesFirstLineRules; |
+ usesWindowInactiveSelector |= other.usesWindowInactiveSelector; |
maxDirectAdjacentSelectors = std::max(maxDirectAdjacentSelectors, other.maxDirectAdjacentSelectors); |
} |
@@ -785,6 +809,7 @@ void RuleFeatureSet::FeatureMetadata::clear() |
usesWindowInactiveSelector = false; |
foundSiblingSelector = false; |
foundInsertionPointCrossing = false; |
+ needsFullRecalcForRuleSetInvalidation = false; |
maxDirectAdjacentSelectors = 0; |
} |
@@ -1034,4 +1059,12 @@ bool RuleFeatureSet::InvalidationSetFeatures::hasFeatures() const |
|| customPseudoElement; |
} |
+bool RuleFeatureSet::InvalidationSetFeatures::hasTagIdClassOrAttribute() const |
+{ |
+ return !classes.isEmpty() |
+ || !attributes.isEmpty() |
+ || !ids.isEmpty() |
+ || !tagNames.isEmpty(); |
+} |
+ |
} // namespace blink |