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 740a207cdb3e824647b458898ea0a7494e5a4c30..1ea7a27ed694a7a35dcf644f61fba9cfa8555021 100644 |
--- a/third_party/WebKit/Source/core/css/RuleFeature.cpp |
+++ b/third_party/WebKit/Source/core/css/RuleFeature.cpp |
@@ -439,18 +439,24 @@ void RuleFeatureSet::updateInvalidationSets(const RuleData& ruleData) |
// addFeaturesToInvalidationSets for that one as well. |
InvalidationSetFeatures features; |
- const CSSSelector* nextCompound = extractInvalidationSetFeaturesFromCompound(ruleData.selector(), features, Subject); |
+ InvalidationSetFeatures* siblingFeatures = nullptr; |
+ |
+ const CSSSelector* lastInCompound = extractInvalidationSetFeaturesFromCompound(ruleData.selector(), features, Subject); |
if (!features.hasFeatures()) |
features.forceSubtree = true; |
- |
- if (nextCompound) |
- addFeaturesToInvalidationSets(*nextCompound, features); |
- else if (features.hasNthPseudo) |
+ if (features.hasNthPseudo) |
addFeaturesToInvalidationSet(ensureNthInvalidationSet(), features); |
- |
if (features.hasBeforeOrAfter) |
updateInvalidationSetsForContentAttribute(ruleData); |
+ |
+ const CSSSelector* nextCompound = lastInCompound ? lastInCompound->tagHistory() : &ruleData.selector(); |
+ if (!nextCompound) |
+ return; |
+ if (lastInCompound) |
+ updateFeaturesFromCombinator(*lastInCompound, nullptr, features, siblingFeatures, features); |
+ |
+ addFeaturesToInvalidationSets(*nextCompound, siblingFeatures, features); |
} |
void RuleFeatureSet::updateInvalidationSetsForContentAttribute(const RuleData& ruleData) |
@@ -482,12 +488,12 @@ void RuleFeatureSet::updateInvalidationSetsForContentAttribute(const RuleData& r |
} |
} |
-const CSSSelector* |
+RuleFeatureSet::FeatureInvalidationType |
RuleFeatureSet::extractInvalidationSetFeaturesFromSelectorList(const CSSSelector& simpleSelector, InvalidationSetFeatures& features, PositionType position) |
{ |
const CSSSelectorList* selectorList = simpleSelector.selectorList(); |
if (!selectorList) |
- return nullptr; |
+ return NormalInvalidation; |
DCHECK(supportsInvalidationWithSelectorList(simpleSelector.getPseudoType())); |
@@ -498,12 +504,12 @@ RuleFeatureSet::extractInvalidationSetFeaturesFromSelectorList(const CSSSelector |
for (; subSelector; subSelector = CSSSelectorList::next(*subSelector)) { |
InvalidationSetFeatures compoundFeatures; |
- if (extractInvalidationSetFeaturesFromCompound(*subSelector, compoundFeatures, position, simpleSelector.getPseudoType())) { |
- // A non-null selector return means the sub-selector contained a |
+ if (!extractInvalidationSetFeaturesFromCompound(*subSelector, compoundFeatures, position, simpleSelector.getPseudoType())) { |
+ // A null selector return means the sub-selector contained a |
// selector which requiresSubtreeInvalidation(). |
DCHECK(compoundFeatures.forceSubtree); |
features.forceSubtree = true; |
- return &simpleSelector; |
+ return RequiresSubtreeInvalidation; |
} |
if (allSubSelectorsHaveFeatures && !compoundFeatures.hasFeatures()) |
allSubSelectorsHaveFeatures = false; |
@@ -516,23 +522,26 @@ RuleFeatureSet::extractInvalidationSetFeaturesFromSelectorList(const CSSSelector |
// any invalidation set features. E.g. :-webkit-any(*, span). |
if (allSubSelectorsHaveFeatures) |
features.add(anyFeatures); |
- return nullptr; |
+ return NormalInvalidation; |
} |
const CSSSelector* |
RuleFeatureSet::extractInvalidationSetFeaturesFromCompound(const CSSSelector& compound, InvalidationSetFeatures& features, PositionType position, CSSSelector::PseudoType pseudo) |
{ |
+ // Extract invalidation set features and return a pointer to the the last |
+ // simple selector of the compound, or nullptr if one of the selectors |
+ // requiresSubtreeInvalidation(). |
+ |
const CSSSelector* simpleSelector = &compound; |
- for (; simpleSelector; simpleSelector = simpleSelector->tagHistory()) { |
+ for (;; simpleSelector = simpleSelector->tagHistory()) { |
// Fall back to use subtree invalidations, even for features in the |
- // rightmost compound selector. Returning the start &selector here |
- // will make addFeaturesToInvalidationSets start marking invalidation |
- // sets for subtree recalc for features in the rightmost compound |
- // selector. |
+ // rightmost compound selector. Returning nullptr here will make |
+ // addFeaturesToInvalidationSets start marking invalidation sets for |
+ // subtree recalc for features in the rightmost compound selector. |
if (requiresSubtreeInvalidation(*simpleSelector)) { |
features.forceSubtree = true; |
- return &compound; |
+ return nullptr; |
} |
// When inside a :not(), we should not use the found features for |
@@ -554,29 +563,14 @@ RuleFeatureSet::extractInvalidationSetFeaturesFromCompound(const CSSSelector& co |
invalidationSet->setInvalidatesSelf(); |
} |
- if (extractInvalidationSetFeaturesFromSelectorList(*simpleSelector, features, position)) { |
+ if (extractInvalidationSetFeaturesFromSelectorList(*simpleSelector, features, position) == RequiresSubtreeInvalidation) { |
DCHECK(features.forceSubtree); |
- return &compound; |
+ return nullptr; |
} |
- if (simpleSelector->relation() == CSSSelector::SubSelector) |
- continue; |
- |
- if (position == Subject) { |
- if (features.hasNthPseudo) { |
- DCHECK(m_nthInvalidationSet); |
- if (features.hasFeatures()) |
- addFeaturesToInvalidationSet(*m_nthInvalidationSet, features); |
- else |
- m_nthInvalidationSet->setWholeSubtreeInvalid(); |
- } |
- InvalidationSetFeatures* siblingFeatures = nullptr; |
- updateFeaturesFromCombinator(*simpleSelector, nullptr, features, siblingFeatures, features); |
- } |
- return simpleSelector->tagHistory(); |
+ if (!simpleSelector->tagHistory() || simpleSelector->relation() != CSSSelector::SubSelector) |
+ return simpleSelector; |
} |
- |
- return nullptr; |
} |
// Add features extracted from the rightmost compound selector to descendant invalidation |
@@ -671,14 +665,12 @@ const CSSSelector* RuleFeatureSet::addFeaturesToInvalidationSetsForCompoundSelec |
return simpleSelector; |
} |
-void RuleFeatureSet::addFeaturesToInvalidationSets(const CSSSelector& selector, InvalidationSetFeatures& descendantFeatures) |
+void RuleFeatureSet::addFeaturesToInvalidationSets(const CSSSelector& selector, InvalidationSetFeatures* siblingFeatures, InvalidationSetFeatures& descendantFeatures) |
{ |
// selector is the selector immediately to the left of the rightmost combinator. |
// descendantFeatures has the features of the rightmost compound selector. |
InvalidationSetFeatures lastCompoundInSiblingChainFeatures; |
- InvalidationSetFeatures* siblingFeatures = descendantFeatures.maxDirectAdjacentSelectors ? &descendantFeatures : nullptr; |
- |
const CSSSelector* compound = &selector; |
while (compound) { |
const CSSSelector* lastInCompound = addFeaturesToInvalidationSetsForCompoundSelector(*compound, siblingFeatures, descendantFeatures); |