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 47ea1b49ebe89349e0866fa400c42a2737d712ca..3d76fb5a2540f4e5152c8579711395270fc54fea 100644 |
--- a/third_party/WebKit/Source/core/css/RuleFeature.cpp |
+++ b/third_party/WebKit/Source/core/css/RuleFeature.cpp |
@@ -556,55 +556,90 @@ void RuleFeatureSet::addFeaturesToInvalidationSets(const CSSSelector* selector, |
} |
} |
-void RuleFeatureSet::collectFeaturesFromRuleData(const RuleData& ruleData) |
+RuleFeatureSet::SelectorPreMatch RuleFeatureSet::collectFeaturesFromRuleData(const RuleData& ruleData) |
{ |
- updateInvalidationSets(ruleData); |
- |
FeatureMetadata metadata; |
- collectFeaturesFromSelector(ruleData.selector(), metadata); |
+ if (collectFeaturesFromSelector(ruleData.selector(), metadata) == SelectorNeverMatches) |
+ return SelectorNeverMatches; |
+ |
m_metadata.add(metadata); |
if (metadata.foundSiblingSelector) |
siblingRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex(), ruleData.hasDocumentSecurityOrigin())); |
if (ruleData.containsUncommonAttributeSelector()) |
uncommonAttributeRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex(), ruleData.hasDocumentSecurityOrigin())); |
+ |
+ updateInvalidationSets(ruleData); |
+ return SelectorMayMatch; |
} |
-void RuleFeatureSet::collectFeaturesFromSelector(const CSSSelector& selector, RuleFeatureSet::FeatureMetadata& metadata) |
+RuleFeatureSet::SelectorPreMatch RuleFeatureSet::collectFeaturesFromSelector(const CSSSelector& selector, RuleFeatureSet::FeatureMetadata& metadata) |
{ |
unsigned maxDirectAdjacentSelectors = 0; |
+ CSSSelector::Relation relation = CSSSelector::Descendant; |
+ bool foundHostPseudo = false; |
for (const CSSSelector* current = &selector; current; current = current->tagHistory()) { |
- if (current->pseudoType() == CSSSelector::PseudoFirstLine) |
+ switch (current->pseudoType()) { |
+ case CSSSelector::PseudoFirstLine: |
metadata.usesFirstLineRules = true; |
- if (current->pseudoType() == CSSSelector::PseudoWindowInactive) |
+ break; |
+ case CSSSelector::PseudoWindowInactive: |
metadata.usesWindowInactiveSelector = true; |
- if (current->relation() == CSSSelector::DirectAdjacent) { |
+ break; |
+ case CSSSelector::PseudoEmpty: |
+ case CSSSelector::PseudoFirstChild: |
+ case CSSSelector::PseudoFirstOfType: |
+ case CSSSelector::PseudoLastChild: |
+ case CSSSelector::PseudoLastOfType: |
+ case CSSSelector::PseudoOnlyChild: |
+ case CSSSelector::PseudoOnlyOfType: |
+ case CSSSelector::PseudoNthChild: |
+ case CSSSelector::PseudoNthOfType: |
+ case CSSSelector::PseudoNthLastChild: |
+ case CSSSelector::PseudoNthLastOfType: |
+ if (!metadata.foundInsertionPointCrossing) |
+ metadata.foundSiblingSelector = true; |
+ break; |
+ case CSSSelector::PseudoHost: |
+ case CSSSelector::PseudoHostContext: |
+ if (relation == CSSSelector::SubSelector) |
+ return SelectorNeverMatches; |
+ if (!current->isLastInTagHistory() && current->tagHistory()->match() != CSSSelector::PseudoElement) |
+ return SelectorNeverMatches; |
+ foundHostPseudo = true; |
+ // fall through. |
+ default: |
+ if (const CSSSelectorList* selectorList = current->selectorList()) { |
+ for (const CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(*subSelector)) |
+ collectFeaturesFromSelector(*subSelector, metadata); |
+ } |
+ break; |
+ } |
+ |
+ if (current->relationIsAffectedByPseudoContent() || current->pseudoType() == CSSSelector::PseudoSlotted) |
+ metadata.foundInsertionPointCrossing = true; |
+ |
+ relation = current->relation(); |
+ |
+ if (foundHostPseudo && relation != CSSSelector::SubSelector) |
+ return SelectorNeverMatches; |
+ |
+ if (relation == CSSSelector::DirectAdjacent) { |
maxDirectAdjacentSelectors++; |
} else if (maxDirectAdjacentSelectors |
- && ((current->relation() != CSSSelector::SubSelector) || current->isLastInTagHistory())) { |
+ && ((relation != CSSSelector::SubSelector) || current->isLastInTagHistory())) { |
if (maxDirectAdjacentSelectors > metadata.maxDirectAdjacentSelectors) |
metadata.maxDirectAdjacentSelectors = maxDirectAdjacentSelectors; |
maxDirectAdjacentSelectors = 0; |
} |
- if (!metadata.foundInsertionPointCrossing && current->isSiblingPseudo()) |
- metadata.foundSiblingSelector = true; |
- if (const CSSSelectorList* selectorList = current->selectorList()) { |
- for (const CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(*subSelector)) |
- collectFeaturesFromSelector(*subSelector, metadata); |
- } |
- if (current->relationIsAffectedByPseudoContent() |
- || current->pseudoType() == CSSSelector::PseudoHost |
- || current->pseudoType() == CSSSelector::PseudoHostContext |
- || current->pseudoType() == CSSSelector::PseudoSlotted) { |
- metadata.foundInsertionPointCrossing = true; |
- } |
if (!metadata.foundInsertionPointCrossing && current->isAdjacentSelector()) |
metadata.foundSiblingSelector = true; |
} |
ASSERT(!maxDirectAdjacentSelectors); |
+ return SelectorMayMatch; |
} |
void RuleFeatureSet::FeatureMetadata::add(const FeatureMetadata& other) |