std::pair<const CSSSelector*, RuleFeatureSet::UseFeaturesType> RuleFeatureSet::extractInvalidationSetFeatures(const CSSSelector& selector, InvalidationSetFeatures& features, PositionType position, CSSSelector::PseudoType pseudo) { bool foundFeatures = false; for (const CSSSelector* current = &selector; current; current = current->tagHistory()) { if (pseudo != CSSSelector::PseudoNot) 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(); } else { if (requiresSubtreeInvalidation(*current)) { // 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. return std::make_pair(&selector, ForceSubtree); } if (const CSSSelectorList* selectorList = current->selectorList()) { ASSERT(supportsInvalidationWithSelectorList(current->pseudoType())); const CSSSelector* subSelector = selectorList->first(); bool allSubSelectorsHaveFeatures = !!subSelector; for (; subSelector; subSelector = CSSSelectorList::next(*subSelector)) { auto result = extractInvalidationSetFeatures(*subSelector, features, position, current->pseudoType()); if (result.first) { // A non-null selector return means the sub-selector contained a // selector which requiresSubtreeInvalidation(). Return the rightmost // selector to mark for subtree recalcs like above. return std::make_pair(&selector, ForceSubtree); } allSubSelectorsHaveFeatures &= result.second == UseFeatures; } foundFeatures |= allSubSelectorsHaveFeatures; } } if (current->relation() == CSSSelector::SubSelector) continue; features.treeBoundaryCrossing = current->isShadowSelector(); features.adjacent = current->isAdjacentSelector(); if (current->relation() == CSSSelector::DirectAdjacent) features.maxDirectAdjacentSelectors = 1; return std::make_pair(current->tagHistory(), foundFeatures ? UseFeatures : ForceSubtree); } return std::make_pair(nullptr, foundFeatures ? UseFeatures : ForceSubtree); }
const CSSSelector* RuleFeatureSet::extractInvalidationSetFeatures(const CSSSelector& selector, InvalidationSetFeatures& features) { const CSSSelector* lastSelector = &selector; for (; lastSelector; lastSelector = lastSelector->tagHistory()) { extractInvalidationSetFeature(*lastSelector, features); // Initialize the entry in the invalidation set map, if supported. invalidationSetForSelector(*lastSelector); 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)) extractInvalidationSetFeatures(*selector, features); } } if (lastSelector->relation() != CSSSelector::SubSelector) break; } return lastSelector; }