Index: Source/core/css/RuleFeature.cpp |
diff --git a/Source/core/css/RuleFeature.cpp b/Source/core/css/RuleFeature.cpp |
index ec80d685e2b2b42e93d1641e445b7e5e0d2638e3..4d684e9be2156d84322f107762da3d161389ca9b 100644 |
--- a/Source/core/css/RuleFeature.cpp |
+++ b/Source/core/css/RuleFeature.cpp |
@@ -121,44 +121,30 @@ void RuleFeature::trace(Visitor* visitor) |
// This method is somewhat conservative in what it accepts. |
RuleFeatureSet::InvalidationSetMode RuleFeatureSet::invalidationSetModeForSelector(const CSSSelector& selector) |
{ |
- bool foundDescendantRelation = false; |
+ bool foundCombinator = false; |
bool foundIdent = false; |
for (const CSSSelector* component = &selector; component; component = component->tagHistory()) { |
if (component->match() == CSSSelector::Class || component->match() == CSSSelector::Id |
|| (component->match() == CSSSelector::Tag && component->tagQName().localName() != starAtom) |
|| component->isAttributeSelector() || component->isCustomPseudoElement()) { |
- if (!foundDescendantRelation) |
+ if (!foundCombinator) |
foundIdent = true; |
} else if (component->pseudoType() == CSSSelector::PseudoHost || component->pseudoType() == CSSSelector::PseudoAny) { |
if (const CSSSelectorList* selectorList = component->selectorList()) { |
for (const CSSSelector* selector = selectorList->first(); selector; selector = CSSSelectorList::next(*selector)) { |
InvalidationSetMode hostMode = invalidationSetModeForSelector(*selector); |
if (hostMode == UseSubtreeStyleChange) |
- return foundDescendantRelation ? UseLocalStyleChange : UseSubtreeStyleChange; |
- if (!foundDescendantRelation && hostMode == AddFeatures) |
+ return foundCombinator ? UseLocalStyleChange : UseSubtreeStyleChange; |
+ if (!foundCombinator && hostMode == AddFeatures) |
foundIdent = true; |
} |
} |
} else if (!isSkippableComponentForInvalidation(*component)) { |
- return foundDescendantRelation ? UseLocalStyleChange : UseSubtreeStyleChange; |
- } |
- switch (component->relation()) { |
- case CSSSelector::Descendant: |
- case CSSSelector::Child: |
- case CSSSelector::ShadowPseudo: |
- case CSSSelector::ShadowDeep: |
- foundDescendantRelation = true; |
- // Fall through! |
- case CSSSelector::SubSelector: |
- case CSSSelector::DirectAdjacent: |
- case CSSSelector::IndirectAdjacent: |
- continue; |
- default: |
- // All combinators should be handled above. |
- ASSERT_NOT_REACHED(); |
- return UseLocalStyleChange; |
+ return foundCombinator ? UseLocalStyleChange : UseSubtreeStyleChange; |
} |
+ if (component->relation() != CSSSelector::SubSelector) |
+ foundCombinator = true; |
} |
return foundIdent ? AddFeatures : UseLocalStyleChange; |
} |
@@ -202,6 +188,12 @@ DescendantInvalidationSet* RuleFeatureSet::invalidationSetForSelector(const CSSS |
return 0; |
} |
+// Given a selector, update the descendant invalidation sets for the features found |
+// in the selector. The first step is to extract the features from the rightmost |
+// compound selector (extractInvalidationSetFeatures). Secondly, those features will be |
+// added to the invalidation sets for the features found in the other compound selectors |
+// (addFeaturesToInvalidationSets). |
+ |
RuleFeatureSet::InvalidationSetMode RuleFeatureSet::updateInvalidationSets(const CSSSelector& selector) |
{ |
InvalidationSetMode mode = invalidationSetModeForSelector(selector); |
@@ -246,6 +238,17 @@ const CSSSelector* RuleFeatureSet::extractInvalidationSetFeatures(const CSSSelec |
return 0; |
} |
+// Add features extracted from the rightmost compound selector to descendant invalidation |
+// sets for features found in other compound selectors. |
+// |
+// Style invalidation is currently supported for descendants only, not for sibling subtrees. |
+// We use wholeSubtree invalidation for features found left of adjacent combinators as |
+// SubtreeStyleChange will force sibling subtree recalc in |
+// ContainerNode::checkForChildrenAdjacentRuleChanges. |
+// |
+// As we encounter a descendant type of combinator, the features only need to be checked |
+// against descendants in the same subtree only. Hence wholeSubtree is reset to false. |
+ |
void RuleFeatureSet::addFeaturesToInvalidationSets(const CSSSelector& selector, InvalidationSetFeatures& features) |
{ |
for (const CSSSelector* current = &selector; current; current = current->tagHistory()) { |