Chromium Code Reviews| 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 fa5268046a1d7de88956888acfa1d51b42902d4e..0af9acc79aa6c38f73366e35d08752cd7bfb1222 100644 |
| --- a/third_party/WebKit/Source/core/css/RuleFeature.cpp |
| +++ b/third_party/WebKit/Source/core/css/RuleFeature.cpp |
| @@ -351,6 +351,14 @@ InvalidationSet* RuleFeatureSet::invalidationSetForSelector(const CSSSelector& s |
| case CSSSelector::PseudoUnresolved: |
| case CSSSelector::PseudoDefined: |
| return &ensurePseudoInvalidationSet(selector.getPseudoType(), type); |
| + case CSSSelector::PseudoFirstOfType: |
| + case CSSSelector::PseudoLastOfType: |
| + case CSSSelector::PseudoOnlyOfType: |
| + case CSSSelector::PseudoNthChild: |
| + case CSSSelector::PseudoNthOfType: |
| + case CSSSelector::PseudoNthLastChild: |
| + case CSSSelector::PseudoNthLastOfType: |
| + return &ensureNthInvalidationSet(); |
| default: |
| break; |
| } |
| @@ -371,9 +379,12 @@ void RuleFeatureSet::updateInvalidationSets(const RuleData& ruleData) |
| InvalidationSetFeatures features; |
| auto result = extractInvalidationSetFeatures(ruleData.selector(), features, Subject); |
| + features.forceSubtree = result.second == ForceSubtree; |
| if (result.first) { |
| - features.forceSubtree = result.second == ForceSubtree; |
| addFeaturesToInvalidationSets(result.first, features.adjacent ? &features : nullptr, features); |
| + } else if (features.hasNthPseudo) { |
| + DCHECK(m_nthInvalidationSet); |
| + addFeaturesToInvalidationSet(*m_nthInvalidationSet, features); |
| } |
| // If any ::before and ::after rules specify 'content: attr(...)', we |
| @@ -416,8 +427,12 @@ RuleFeatureSet::extractInvalidationSetFeatures(const CSSSelector& selector, Inva |
| foundFeatures |= extractInvalidationSetFeature(*current, features); |
| // Initialize the entry in the invalidation set map, if supported. |
| if (InvalidationSet* invalidationSet = invalidationSetForSelector(*current, InvalidateDescendants)) { |
| - if (position == Subject) |
| - invalidationSet->setInvalidatesSelf(); |
| + if (position == Subject) { |
| + if (invalidationSet == m_nthInvalidationSet) |
| + features.hasNthPseudo = true; |
| + else |
| + invalidationSet->setInvalidatesSelf(); |
| + } |
| } else { |
| if (requiresSubtreeInvalidation(*current)) { |
| // Fall back to use subtree invalidations, even for features in the |
| @@ -452,6 +467,13 @@ RuleFeatureSet::extractInvalidationSetFeatures(const CSSSelector& selector, Inva |
| if (current->relation() == CSSSelector::SubSelector) |
| continue; |
| + if (features.hasNthPseudo && position == Subject) { |
| + DCHECK(m_nthInvalidationSet); |
| + addFeaturesToInvalidationSet(*m_nthInvalidationSet, features); |
| + if (!foundFeatures) |
| + m_nthInvalidationSet->setWholeSubtreeInvalid(); |
|
esprehn
2016/08/11 10:32:55
If we're going to mark it for the whole subtree wh
rune
2016/08/12 11:03:14
Will fix.
|
| + } |
| + |
| features.treeBoundaryCrossing = current->isShadowSelector(); |
| if (current->relationIsAffectedByPseudoContent()) { |
| features.contentPseudoCrossing = true; |
| @@ -462,7 +484,7 @@ RuleFeatureSet::extractInvalidationSetFeatures(const CSSSelector& selector, Inva |
| features.maxDirectAdjacentSelectors = 1; |
| return std::make_pair(current->tagHistory(), foundFeatures ? UseFeatures : ForceSubtree); |
| } |
| - return std::make_pair(nullptr, foundFeatures ? UseFeatures : ForceSubtree); |
| + return std::make_pair(nullptr, foundFeatures ? UseFeatures : ForceSubtree); |
| } |
| // Add features extracted from the rightmost compound selector to descendant invalidation |
| @@ -516,7 +538,7 @@ void RuleFeatureSet::addFeaturesToInvalidationSets(const CSSSelector* selector, |
| if (InvalidationSet* invalidationSet = invalidationSetForSelector(*current, type)) { |
| if (current->match() != CSSSelector::PseudoClass) |
| universalCompound = false; |
| - if (siblingFeatures) { |
| + if (siblingFeatures && invalidationSet != m_nthInvalidationSet) { |
| SiblingInvalidationSet* siblingInvalidationSet = toSiblingInvalidationSet(invalidationSet); |
| siblingInvalidationSet->updateMaxDirectAdjacentSelectors(siblingFeatures->maxDirectAdjacentSelectors); |
| @@ -698,6 +720,8 @@ void RuleFeatureSet::add(const RuleFeatureSet& other) |
| ensureInvalidationSet(m_pseudoInvalidationSets, static_cast<CSSSelector::PseudoType>(entry.key), entry.value->type()).combine(*entry.value); |
| if (other.m_universalSiblingInvalidationSet) |
| ensureUniversalSiblingInvalidationSet().combine(*other.m_universalSiblingInvalidationSet); |
| + if (other.m_nthInvalidationSet) |
| + ensureNthInvalidationSet().combine(*other.m_nthInvalidationSet); |
| m_metadata.add(other.m_metadata); |
| @@ -867,6 +891,19 @@ SiblingInvalidationSet& RuleFeatureSet::ensureUniversalSiblingInvalidationSet() |
| return *m_universalSiblingInvalidationSet; |
| } |
| +void RuleFeatureSet::collectNthInvalidationSet(InvalidationLists& invalidationLists) const |
| +{ |
| + if (m_nthInvalidationSet) |
| + invalidationLists.descendants.append(m_nthInvalidationSet); |
| +} |
| + |
| +DescendantInvalidationSet& RuleFeatureSet::ensureNthInvalidationSet() |
| +{ |
| + if (!m_nthInvalidationSet) |
| + m_nthInvalidationSet = DescendantInvalidationSet::create(); |
| + return *m_nthInvalidationSet; |
| +} |
| + |
| void RuleFeatureSet::addFeaturesToUniversalSiblingInvalidationSet(const InvalidationSetFeatures& siblingFeatures, const InvalidationSetFeatures& descendantFeatures) |
| { |
| SiblingInvalidationSet& universalSet = ensureUniversalSiblingInvalidationSet(); |