| 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 31227852af3a4d175212a7e44d971750f30ffc63..20c25d92c6d56877a8b710bfaa97481e1ec7b2a5 100644
|
| --- a/third_party/WebKit/Source/core/css/RuleFeature.cpp
|
| +++ b/third_party/WebKit/Source/core/css/RuleFeature.cpp
|
| @@ -347,18 +347,28 @@ void RuleFeatureSet::extractInvalidationSetFeaturesFromSimpleSelector(
|
| if (selector.match() == CSSSelector::Tag &&
|
| selector.tagQName().localName() != starAtom) {
|
| features.tagNames.push_back(selector.tagQName().localName());
|
| + features.setRuleSetInvalidationFeature(
|
| + selector.tagQName().localName(),
|
| + InvalidationSetFeatures::RuleSetFeatureType::Tag);
|
| return;
|
| }
|
| if (selector.match() == CSSSelector::Id) {
|
| features.ids.push_back(selector.value());
|
| + features.setRuleSetInvalidationFeature(
|
| + selector.value(), InvalidationSetFeatures::RuleSetFeatureType::Id);
|
| return;
|
| }
|
| if (selector.match() == CSSSelector::Class) {
|
| features.classes.push_back(selector.value());
|
| + features.setRuleSetInvalidationFeature(
|
| + selector.value(), InvalidationSetFeatures::RuleSetFeatureType::Class);
|
| return;
|
| }
|
| if (selector.isAttributeSelector()) {
|
| features.attributes.push_back(selector.attribute().localName());
|
| + features.setRuleSetInvalidationFeature(
|
| + selector.attribute().localName(),
|
| + InvalidationSetFeatures::RuleSetFeatureType::Attribute);
|
| return;
|
| }
|
| switch (selector.getPseudoType()) {
|
| @@ -456,7 +466,7 @@ void RuleFeatureSet::updateInvalidationSets(const RuleData& ruleData) {
|
| Subject);
|
|
|
| if (features.forceSubtree)
|
| - features.hasFeaturesForRuleSetInvalidation = false;
|
| + features.clearRuleSetInvalidationFeature();
|
| else if (!features.hasFeatures())
|
| features.forceSubtree = true;
|
| if (features.hasNthPseudo)
|
| @@ -467,8 +477,7 @@ void RuleFeatureSet::updateInvalidationSets(const RuleData& ruleData) {
|
| const CSSSelector* nextCompound =
|
| lastInCompound ? lastInCompound->tagHistory() : &ruleData.selector();
|
| if (!nextCompound) {
|
| - if (!features.hasFeaturesForRuleSetInvalidation)
|
| - m_metadata.needsFullRecalcForRuleSetInvalidation = true;
|
| + processRuleSetInvalidationFeature(features);
|
| return;
|
| }
|
| if (lastInCompound)
|
| @@ -476,9 +485,45 @@ void RuleFeatureSet::updateInvalidationSets(const RuleData& ruleData) {
|
| siblingFeatures, features);
|
|
|
| addFeaturesToInvalidationSets(*nextCompound, siblingFeatures, features);
|
| + processRuleSetInvalidationFeature(features);
|
| +}
|
| +
|
| +void RuleFeatureSet::processRuleSetInvalidationFeature(
|
| + const InvalidationSetFeatures& features) {
|
| + InvalidationSetMap* map = nullptr;
|
| + switch (features.ruleSetInvalidationFeatureType) {
|
| + case InvalidationSetFeatures::RuleSetFeatureType::None:
|
| + m_metadata.needsFullRecalcForRuleSetInvalidation = true;
|
| + return;
|
| + case InvalidationSetFeatures::RuleSetFeatureType::Tag: {
|
| + DescendantInvalidationSet& typeSet = ensureTypeRuleInvalidationSet();
|
| + typeSet.addTagName(features.ruleSetInvalidationFeature);
|
| + return;
|
| + }
|
| + case InvalidationSetFeatures::RuleSetFeatureType::Attribute:
|
| + map = &m_attributeInvalidationSets;
|
| + break;
|
| + case InvalidationSetFeatures::RuleSetFeatureType::Class:
|
| + map = &m_classInvalidationSets;
|
| + break;
|
| + case InvalidationSetFeatures::RuleSetFeatureType::Id:
|
| + map = &m_idInvalidationSets;
|
| + break;
|
| + }
|
|
|
| - if (!features.hasFeaturesForRuleSetInvalidation)
|
| - m_metadata.needsFullRecalcForRuleSetInvalidation = true;
|
| + DCHECK(map);
|
| + InvalidationSetMap::const_iterator it =
|
| + map->find(features.ruleSetInvalidationFeature);
|
| + if (it == map->end())
|
| + return;
|
| +
|
| + DescendantInvalidationSet* descendants;
|
| + SiblingInvalidationSet* siblings;
|
| + extractInvalidationSets(it->value.get(), descendants, siblings);
|
| + if (descendants)
|
| + descendants->setAppliesToRuleSetInvalidations();
|
| + if (siblings)
|
| + siblings->setAppliesToRuleSetInvalidations();
|
| }
|
|
|
| void RuleFeatureSet::updateInvalidationSetsForContentAttribute(
|
| @@ -550,7 +595,9 @@ RuleFeatureSet::extractInvalidationSetFeaturesFromSelectorList(
|
| else
|
| allSubSelectorsHaveFeatures = false;
|
| }
|
| - // Don't add any features if one of the sub-selectors of does not contain
|
| + if (!selectorList->hasOneSelector())
|
| + anyFeatures.clearRuleSetInvalidationFeature();
|
| + // Don't add any features if one of the sub-selectors does not contain
|
| // any invalidation set features. E.g. :-webkit-any(*, span).
|
| if (allSubSelectorsHaveFeatures)
|
| features.add(anyFeatures);
|
| @@ -607,8 +654,6 @@ const CSSSelector* RuleFeatureSet::extractInvalidationSetFeaturesFromCompound(
|
|
|
| if (!simpleSelector->tagHistory() ||
|
| simpleSelector->relation() != CSSSelector::SubSelector) {
|
| - features.hasFeaturesForRuleSetInvalidation =
|
| - features.hasTagIdClassOrAttribute();
|
| return simpleSelector;
|
| }
|
| }
|
| @@ -660,25 +705,24 @@ void RuleFeatureSet::addFeaturesToInvalidationSetsForSelectorList(
|
|
|
| DCHECK(supportsInvalidationWithSelectorList(simpleSelector.getPseudoType()));
|
|
|
| - bool hadFeaturesForRuleSetInvalidation =
|
| - descendantFeatures.hasFeaturesForRuleSetInvalidation;
|
| - bool selectorListContainsUniversal =
|
| - simpleSelector.getPseudoType() == CSSSelector::PseudoNot ||
|
| - simpleSelector.getPseudoType() == CSSSelector::PseudoHostContext;
|
| + AtomicString prevRuleSetFeature =
|
| + descendantFeatures.ruleSetInvalidationFeature;
|
| + InvalidationSetFeatures::RuleSetFeatureType prevRuleSetFeatureType =
|
| + descendantFeatures.ruleSetInvalidationFeatureType;
|
|
|
| for (const CSSSelector* subSelector = simpleSelector.selectorList()->first();
|
| subSelector; subSelector = CSSSelectorList::next(*subSelector)) {
|
| - descendantFeatures.hasFeaturesForRuleSetInvalidation = false;
|
| -
|
| addFeaturesToInvalidationSetsForCompoundSelector(
|
| *subSelector, siblingFeatures, descendantFeatures);
|
| -
|
| - if (!descendantFeatures.hasFeaturesForRuleSetInvalidation)
|
| - selectorListContainsUniversal = true;
|
| }
|
|
|
| - descendantFeatures.hasFeaturesForRuleSetInvalidation =
|
| - hadFeaturesForRuleSetInvalidation || !selectorListContainsUniversal;
|
| + if (simpleSelector.getPseudoType() == CSSSelector::PseudoNot ||
|
| + simpleSelector.getPseudoType() == CSSSelector::PseudoHostContext ||
|
| + !simpleSelector.selectorList()->hasOneSelector()) {
|
| + descendantFeatures.clearRuleSetInvalidationFeature();
|
| + descendantFeatures.setRuleSetInvalidationFeature(prevRuleSetFeature,
|
| + prevRuleSetFeatureType);
|
| + }
|
| }
|
|
|
| void RuleFeatureSet::addFeaturesToInvalidationSetsForSimpleSelector(
|
| @@ -726,17 +770,17 @@ RuleFeatureSet::addFeaturesToInvalidationSetsForCompoundSelector(
|
| for (; simpleSelector; simpleSelector = simpleSelector->tagHistory()) {
|
| addFeaturesToInvalidationSetsForSimpleSelector(
|
| *simpleSelector, siblingFeatures, descendantFeatures);
|
| - if (simpleSelector->isIdClassOrAttributeSelector())
|
| + if (simpleSelector->isIdClassOrAttributeSelector()) {
|
| + descendantFeatures.setRuleSetFeatureFromSimpleSelector(*simpleSelector);
|
| compoundHasIdClassOrAttribute = true;
|
| + }
|
| if (simpleSelector->relation() != CSSSelector::SubSelector)
|
| break;
|
| if (!simpleSelector->tagHistory())
|
| break;
|
| }
|
|
|
| - if (compoundHasIdClassOrAttribute)
|
| - descendantFeatures.hasFeaturesForRuleSetInvalidation = true;
|
| - else if (siblingFeatures)
|
| + if (!compoundHasIdClassOrAttribute && siblingFeatures)
|
| addFeaturesToUniversalSiblingInvalidationSet(*siblingFeatures,
|
| descendantFeatures);
|
|
|
| @@ -933,7 +977,8 @@ void RuleFeatureSet::clear() {
|
| void RuleFeatureSet::collectInvalidationSetsForClass(
|
| InvalidationLists& invalidationLists,
|
| Element& element,
|
| - const AtomicString& className) const {
|
| + const AtomicString& className,
|
| + InvalidationSetFilter filter) const {
|
| InvalidationSetMap::const_iterator it =
|
| m_classInvalidationSets.find(className);
|
| if (it == m_classInvalidationSets.end())
|
| @@ -943,13 +988,15 @@ void RuleFeatureSet::collectInvalidationSetsForClass(
|
| SiblingInvalidationSet* siblings;
|
| extractInvalidationSets(it->value.get(), descendants, siblings);
|
|
|
| - if (descendants) {
|
| + if (descendants && (filter == InvalidationSetFilter::None ||
|
| + descendants->appliesToRuleSetInvalidations())) {
|
| TRACE_SCHEDULE_STYLE_INVALIDATION(element, *descendants, classChange,
|
| className);
|
| invalidationLists.descendants.push_back(descendants);
|
| }
|
|
|
| - if (siblings) {
|
| + if (siblings && (filter == InvalidationSetFilter::None ||
|
| + siblings->appliesToRuleSetInvalidations())) {
|
| TRACE_SCHEDULE_STYLE_INVALIDATION(element, *siblings, classChange,
|
| className);
|
| invalidationLists.siblings.push_back(siblings);
|
| @@ -983,7 +1030,8 @@ void RuleFeatureSet::collectSiblingInvalidationSetForClass(
|
| void RuleFeatureSet::collectInvalidationSetsForId(
|
| InvalidationLists& invalidationLists,
|
| Element& element,
|
| - const AtomicString& id) const {
|
| + const AtomicString& id,
|
| + InvalidationSetFilter filter) const {
|
| InvalidationSetMap::const_iterator it = m_idInvalidationSets.find(id);
|
| if (it == m_idInvalidationSets.end())
|
| return;
|
| @@ -992,12 +1040,14 @@ void RuleFeatureSet::collectInvalidationSetsForId(
|
| SiblingInvalidationSet* siblings;
|
| extractInvalidationSets(it->value.get(), descendants, siblings);
|
|
|
| - if (descendants) {
|
| + if (descendants && (filter == InvalidationSetFilter::None ||
|
| + descendants->appliesToRuleSetInvalidations())) {
|
| TRACE_SCHEDULE_STYLE_INVALIDATION(element, *descendants, idChange, id);
|
| invalidationLists.descendants.push_back(descendants);
|
| }
|
|
|
| - if (siblings) {
|
| + if (siblings && (filter == InvalidationSetFilter::None ||
|
| + siblings->appliesToRuleSetInvalidations())) {
|
| TRACE_SCHEDULE_STYLE_INVALIDATION(element, *siblings, idChange, id);
|
| invalidationLists.siblings.push_back(siblings);
|
| }
|
| @@ -1028,7 +1078,8 @@ void RuleFeatureSet::collectSiblingInvalidationSetForId(
|
| void RuleFeatureSet::collectInvalidationSetsForAttribute(
|
| InvalidationLists& invalidationLists,
|
| Element& element,
|
| - const QualifiedName& attributeName) const {
|
| + const QualifiedName& attributeName,
|
| + InvalidationSetFilter filter) const {
|
| InvalidationSetMap::const_iterator it =
|
| m_attributeInvalidationSets.find(attributeName.localName());
|
| if (it == m_attributeInvalidationSets.end())
|
| @@ -1038,13 +1089,15 @@ void RuleFeatureSet::collectInvalidationSetsForAttribute(
|
| SiblingInvalidationSet* siblings;
|
| extractInvalidationSets(it->value.get(), descendants, siblings);
|
|
|
| - if (descendants) {
|
| + if (descendants && (filter == InvalidationSetFilter::None ||
|
| + descendants->appliesToRuleSetInvalidations())) {
|
| TRACE_SCHEDULE_STYLE_INVALIDATION(element, *descendants, attributeChange,
|
| attributeName);
|
| invalidationLists.descendants.push_back(descendants);
|
| }
|
|
|
| - if (siblings) {
|
| + if (siblings && (filter == InvalidationSetFilter::None ||
|
| + siblings->appliesToRuleSetInvalidations())) {
|
| TRACE_SCHEDULE_STYLE_INVALIDATION(element, *siblings, attributeChange,
|
| attributeName);
|
| invalidationLists.siblings.push_back(siblings);
|
| @@ -1128,6 +1181,24 @@ DescendantInvalidationSet& RuleFeatureSet::ensureNthInvalidationSet() {
|
| return *m_nthInvalidationSet;
|
| }
|
|
|
| +void RuleFeatureSet::collectTypeRuleInvalidationSet(
|
| + InvalidationLists& invalidationLists,
|
| + ContainerNode& rootNode) const {
|
| + if (m_typeRuleInvalidationSet) {
|
| + invalidationLists.descendants.push_back(m_typeRuleInvalidationSet);
|
| + TRACE_SCHEDULE_STYLE_INVALIDATION(rootNode, *m_typeRuleInvalidationSet,
|
| + typeInvalidation);
|
| + }
|
| +}
|
| +
|
| +DescendantInvalidationSet& RuleFeatureSet::ensureTypeRuleInvalidationSet() {
|
| + if (!m_typeRuleInvalidationSet) {
|
| + m_typeRuleInvalidationSet = DescendantInvalidationSet::create();
|
| + m_typeRuleInvalidationSet->setAppliesToRuleSetInvalidations();
|
| + }
|
| + return *m_typeRuleInvalidationSet;
|
| +}
|
| +
|
| void RuleFeatureSet::addFeaturesToUniversalSiblingInvalidationSet(
|
| const InvalidationSetFeatures& siblingFeatures,
|
| const InvalidationSetFeatures& descendantFeatures) {
|
| @@ -1167,6 +1238,8 @@ void RuleFeatureSet::InvalidationSetFeatures::add(
|
| contentPseudoCrossing |= other.contentPseudoCrossing;
|
| invalidatesSlotted |= other.invalidatesSlotted;
|
| hasNthPseudo |= other.hasNthPseudo;
|
| + setRuleSetInvalidationFeature(other.ruleSetInvalidationFeature,
|
| + other.ruleSetInvalidationFeatureType);
|
| }
|
|
|
| bool RuleFeatureSet::InvalidationSetFeatures::hasFeatures() const {
|
| @@ -1174,9 +1247,19 @@ bool RuleFeatureSet::InvalidationSetFeatures::hasFeatures() const {
|
| !tagNames.isEmpty() || customPseudoElement;
|
| }
|
|
|
| -bool RuleFeatureSet::InvalidationSetFeatures::hasTagIdClassOrAttribute() const {
|
| - return !classes.isEmpty() || !attributes.isEmpty() || !ids.isEmpty() ||
|
| - !tagNames.isEmpty();
|
| +void RuleFeatureSet::InvalidationSetFeatures::
|
| + setRuleSetFeatureFromSimpleSelector(const CSSSelector& selector) {
|
| + if (selector.match() == CSSSelector::Id) {
|
| + setRuleSetInvalidationFeature(selector.value(), RuleSetFeatureType::Id);
|
| + return;
|
| + }
|
| + if (selector.match() == CSSSelector::Class) {
|
| + setRuleSetInvalidationFeature(selector.value(), RuleSetFeatureType::Class);
|
| + return;
|
| + }
|
| + DCHECK(selector.isAttributeSelector());
|
| + setRuleSetInvalidationFeature(selector.attribute().localName(),
|
| + RuleSetFeatureType::Attribute);
|
| }
|
|
|
| } // namespace blink
|
|
|