Chromium Code Reviews| Index: Source/core/css/RuleFeature.cpp |
| diff --git a/Source/core/css/RuleFeature.cpp b/Source/core/css/RuleFeature.cpp |
| index bca0970bc71b558ff69f5ec20adfc8c7c418899f..90bd6b4357903083cc30dbcdd73ca0c8cd6568ae 100644 |
| --- a/Source/core/css/RuleFeature.cpp |
| +++ b/Source/core/css/RuleFeature.cpp |
| @@ -166,7 +166,7 @@ RuleFeatureSet::RuleFeatureSet() |
| { |
| } |
| -DescendantInvalidationSet* RuleFeatureSet::invalidationSetForSelector(const CSSSelector& selector) |
| +DescendantInvalidationSet* RuleFeatureSet::invalidationSetForSelector(const CSSSelector& selector, bool seenCombinator) |
| { |
| if (selector.m_match == CSSSelector::Class) |
| return &ensureClassInvalidationSet(selector.value()); |
| @@ -174,6 +174,11 @@ DescendantInvalidationSet* RuleFeatureSet::invalidationSetForSelector(const CSSS |
| return &ensureAttributeInvalidationSet(selector.attribute().localName()); |
| if (selector.m_match == CSSSelector::Id) |
| return &ensureIdInvalidationSet(selector.value()); |
| + if (seenCombinator && selector.m_match == CSSSelector::PseudoClass) { |
| + CSSSelector::PseudoType pseudo = selector.pseudoType(); |
| + if (pseudo == CSSSelector::PseudoHover || pseudo == CSSSelector::PseudoActive || pseudo == CSSSelector::PseudoFocus) |
| + return &ensurePseudoInvalidationSet(pseudo); |
| + } |
| return 0; |
| } |
| @@ -200,7 +205,7 @@ const CSSSelector* RuleFeatureSet::extractInvalidationSetFeatures(const CSSSelec |
| for (; lastSelector; lastSelector = lastSelector->tagHistory()) { |
| extractInvalidationSetFeature(*lastSelector, features); |
| // Initialize the entry in the invalidation set map, if supported. |
| - invalidationSetForSelector(*lastSelector); |
| + invalidationSetForSelector(*lastSelector, false); |
| if (lastSelector->pseudoType() == CSSSelector::PseudoHost || lastSelector->pseudoType() == CSSSelector::PseudoAny) { |
| if (const CSSSelectorList* selectorList = lastSelector->selectorList()) { |
| for (const CSSSelector* selector = selectorList->first(); selector; selector = CSSSelectorList::next(*selector)) |
| @@ -217,7 +222,7 @@ const CSSSelector* RuleFeatureSet::extractInvalidationSetFeatures(const CSSSelec |
| 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 (DescendantInvalidationSet* invalidationSet = invalidationSetForSelector(*current, true)) { |
| if (wholeSubtree) { |
| invalidationSet->setWholeSubtreeInvalid(); |
| } else { |
| @@ -272,7 +277,7 @@ void RuleFeatureSet::collectFeaturesFromRuleData(const RuleData& ruleData) |
| if (m_targetedStyleRecalcEnabled) |
| mode = updateInvalidationSets(ruleData.selector()); |
| - collectFeaturesFromSelector(ruleData.selector(), metadata, mode); |
| + collectFeaturesFromSelector(ruleData.selector(), metadata, mode, false); |
| m_metadata.add(metadata); |
| if (metadata.foundSiblingSelector) |
| @@ -305,21 +310,29 @@ DescendantInvalidationSet& RuleFeatureSet::ensureIdInvalidationSet(const AtomicS |
| return *addResult.storedValue->value; |
| } |
| +DescendantInvalidationSet& RuleFeatureSet::ensurePseudoInvalidationSet(CSSSelector::PseudoType pseudoType) |
| +{ |
| + PseudoTypeInvalidationSetMap::AddResult addResult = m_pseudoInvalidationSets.add(pseudoType, nullptr); |
| + if (addResult.isNewEntry) |
| + addResult.storedValue->value = DescendantInvalidationSet::create(); |
| + return *addResult.storedValue->value; |
| +} |
| + |
| void RuleFeatureSet::collectFeaturesFromSelector(const CSSSelector& selector) |
| { |
| - collectFeaturesFromSelector(selector, m_metadata, UseSubtreeStyleChange); |
| + collectFeaturesFromSelector(selector, m_metadata, UseSubtreeStyleChange, false); |
| } |
| -void RuleFeatureSet::collectFeaturesFromSelector(const CSSSelector& selector, RuleFeatureSet::FeatureMetadata& metadata, InvalidationSetMode mode) |
| +void RuleFeatureSet::collectFeaturesFromSelector(const CSSSelector& selector, RuleFeatureSet::FeatureMetadata& metadata, InvalidationSetMode mode, bool seenCombinator) |
| { |
| unsigned maxDirectAdjacentSelectors = 0; |
| for (const CSSSelector* current = &selector; current; current = current->tagHistory()) { |
| - if (mode != AddFeatures && (current->m_match == CSSSelector::Class || current->m_match == CSSSelector::Id || current->isAttributeSelector())) { |
| - DescendantInvalidationSet* invalidationSet = invalidationSetForSelector(*current); |
| - ASSERT(invalidationSet); |
| - if (mode == UseSubtreeStyleChange) |
| - invalidationSet->setWholeSubtreeInvalid(); |
| + if (mode != AddFeatures) { |
| + if (DescendantInvalidationSet* invalidationSet = invalidationSetForSelector(*current, seenCombinator)) { |
| + if (mode == UseSubtreeStyleChange) |
| + invalidationSet->setWholeSubtreeInvalid(); |
| + } |
| } |
| if (current->pseudoType() == CSSSelector::PseudoFirstLine) |
| metadata.usesFirstLineRules = true; |
| @@ -333,22 +346,24 @@ void RuleFeatureSet::collectFeaturesFromSelector(const CSSSelector& selector, Ru |
| if (current->isSiblingSelector()) |
| metadata.foundSiblingSelector = true; |
| - collectFeaturesFromSelectorList(current->selectorList(), metadata, mode); |
| + collectFeaturesFromSelectorList(current->selectorList(), metadata, mode, seenCombinator); |
| - if (mode == UseLocalStyleChange && current->relation() != CSSSelector::SubSelector) |
| + if (mode == UseLocalStyleChange && current->relation() != CSSSelector::SubSelector) { |
| + seenCombinator = true; |
| mode = UseSubtreeStyleChange; |
| + } |
| } |
| ASSERT(!maxDirectAdjacentSelectors); |
| } |
| -void RuleFeatureSet::collectFeaturesFromSelectorList(const CSSSelectorList* selectorList, RuleFeatureSet::FeatureMetadata& metadata, InvalidationSetMode mode) |
| +void RuleFeatureSet::collectFeaturesFromSelectorList(const CSSSelectorList* selectorList, RuleFeatureSet::FeatureMetadata& metadata, InvalidationSetMode mode, bool seenCombinator) |
| { |
| if (!selectorList) |
| return; |
| for (const CSSSelector* selector = selectorList->first(); selector; selector = CSSSelectorList::next(*selector)) |
| - collectFeaturesFromSelector(*selector, metadata, mode); |
| + collectFeaturesFromSelector(*selector, metadata, mode, seenCombinator); |
| } |
| void RuleFeatureSet::FeatureMetadata::add(const FeatureMetadata& other) |
| @@ -372,6 +387,8 @@ void RuleFeatureSet::add(const RuleFeatureSet& other) |
| ensureAttributeInvalidationSet(it->key).combine(*it->value); |
| for (InvalidationSetMap::const_iterator it = other.m_idInvalidationSets.begin(); it != other.m_idInvalidationSets.end(); ++it) |
| ensureIdInvalidationSet(it->key).combine(*it->value); |
| + for (PseudoTypeInvalidationSetMap::const_iterator it = other.m_pseudoInvalidationSets.begin(); it != other.m_pseudoInvalidationSets.end(); ++it) |
| + ensurePseudoInvalidationSet(static_cast<CSSSelector::PseudoType>(it->key)).combine(*it->value); |
|
esprehn
2014/04/11 20:23:01
Why do you need the cast?
rune
2014/04/11 22:34:36
It's because of the use of IntHash:
typedef Has
|
| m_metadata.add(other.m_metadata); |
| @@ -452,6 +469,12 @@ void RuleFeatureSet::scheduleStyleInvalidationForIdChange(const AtomicString& ol |
| } |
| } |
| +void RuleFeatureSet::scheduleStyleInvalidationForPseudoChange(CSSSelector::PseudoType pseudo, Element& element) |
| +{ |
| + if (RefPtr<DescendantInvalidationSet> invalidationSet = m_pseudoInvalidationSets.get(pseudo)) |
| + m_styleInvalidator.scheduleInvalidation(invalidationSet, element); |
| +} |
| + |
| void RuleFeatureSet::addClassToInvalidationSet(const AtomicString& className, Element& element) |
| { |
| if (RefPtr<DescendantInvalidationSet> invalidationSet = m_classInvalidationSets.get(className)) |