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)) |