Index: Source/core/css/RuleFeature.cpp |
diff --git a/Source/core/css/RuleFeature.cpp b/Source/core/css/RuleFeature.cpp |
index 42f039951dff4ca6ccc4066cc9cb70779a21a559..0009922b77b2e9249db2f5d88519047305447a20 100644 |
--- a/Source/core/css/RuleFeature.cpp |
+++ b/Source/core/css/RuleFeature.cpp |
@@ -135,8 +135,12 @@ RuleFeatureSet::InvalidationSetMode RuleFeatureSet::invalidationSetModeForSelect |
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; |
} |
} |
@@ -181,11 +185,12 @@ RuleFeatureSet::InvalidationSetMode RuleFeatureSet::updateInvalidationSets(const |
InvalidationSetFeatures features; |
const CSSSelector* current = extractInvalidationSetFeatures(selector, features); |
- if (current) |
+ if (current) { |
+ bool wholeSubtree = current->relation() == CSSSelector::DirectAdjacent || current->relation() == CSSSelector::IndirectAdjacent; |
current = current->tagHistory(); |
- |
- if (current) |
- addFeaturesToInvalidationSets(*current, features); |
+ if (current) |
+ addFeaturesToInvalidationSets(*current, features, wholeSubtree); |
+ } |
return AddFeatures; |
} |
@@ -209,26 +214,48 @@ const CSSSelector* RuleFeatureSet::extractInvalidationSetFeatures(const CSSSelec |
return lastSelector; |
} |
-void RuleFeatureSet::addFeaturesToInvalidationSets(const CSSSelector& selector, const InvalidationSetFeatures& features) |
+void RuleFeatureSet::addFeaturesToInvalidationSets(const CSSSelector& selector, const InvalidationSetFeatures& features, bool wholeSubtree) |
{ |
for (const CSSSelector* current = &selector; current; current = current->tagHistory()) { |
if (DescendantInvalidationSet* invalidationSet = invalidationSetForSelector(*current)) { |
- if (!features.id.isEmpty()) |
- invalidationSet->addId(features.id); |
- if (!features.tagName.isEmpty()) |
- invalidationSet->addTagName(features.tagName); |
- for (Vector<AtomicString>::const_iterator it = features.classes.begin(); it != features.classes.end(); ++it) |
- invalidationSet->addClass(*it); |
- for (Vector<AtomicString>::const_iterator it = features.attributes.begin(); it != features.attributes.end(); ++it) |
- invalidationSet->addAttribute(*it); |
- if (features.customPseudoElement) |
- invalidationSet->setCustomPseudoInvalid(); |
+ if (wholeSubtree) { |
+ invalidationSet->setWholeSubtreeInvalid(); |
+ } else { |
+ if (!features.id.isEmpty()) |
+ invalidationSet->addId(features.id); |
+ if (!features.tagName.isEmpty()) |
+ invalidationSet->addTagName(features.tagName); |
+ for (Vector<AtomicString>::const_iterator it = features.classes.begin(); it != features.classes.end(); ++it) |
+ invalidationSet->addClass(*it); |
+ for (Vector<AtomicString>::const_iterator it = features.attributes.begin(); it != features.attributes.end(); ++it) |
+ invalidationSet->addAttribute(*it); |
+ if (features.customPseudoElement) |
+ invalidationSet->setCustomPseudoInvalid(); |
+ } |
} else if (current->pseudoType() == CSSSelector::PseudoHost || current->pseudoType() == CSSSelector::PseudoAny) { |
if (const CSSSelectorList* selectorList = current->selectorList()) { |
for (const CSSSelector* selector = selectorList->first(); selector; selector = CSSSelectorList::next(*selector)) |
- addFeaturesToInvalidationSets(*selector, features); |
+ addFeaturesToInvalidationSets(*selector, features, wholeSubtree); |
} |
} |
+ switch (current->relation()) { |
+ case CSSSelector::Descendant: |
+ case CSSSelector::Child: |
+ case CSSSelector::ShadowPseudo: |
+ case CSSSelector::ShadowDeep: |
+ wholeSubtree = false; |
+ break; |
+ case CSSSelector::DirectAdjacent: |
+ case CSSSelector::IndirectAdjacent: |
+ wholeSubtree = true; |
+ break; |
+ case CSSSelector::SubSelector: |
+ break; |
+ default: |
+ // All combinators should be handled above. |
+ ASSERT_NOT_REACHED(); |
+ break; |
+ } |
} |
} |