bool RuleFeatureSet::updateClassInvalidationSets(const CSSSelector& selector) { if (!supportsClassDescendantInvalidation(selector)) return false; Vector<AtomicString> classes; AtomicString id; AtomicString tagName; const CSSSelector* lastSelector = &selector; for (; lastSelector->relation() == CSSSelector::SubSelector; lastSelector = lastSelector->tagHistory()) { extractClassIdOrTag(*lastSelector, classes, id, tagName); } extractClassIdOrTag(*lastSelector, classes, id, tagName); for (const CSSSelector* current = &selector ; current; current = current->tagHistory()) { if (current->m_match == CSSSelector::Class) { DescendantInvalidationSet& invalidationSet = ensureClassInvalidationSet(current->value()); if (!id.isEmpty()) invalidationSet.addId(id); if (!tagName.isEmpty()) invalidationSet.addTagName(tagName); for (Vector<AtomicString>::const_iterator it = classes.begin(); it != classes.end(); ++it) { invalidationSet.addClass(*it); } } } return true; }
void RuleFeatureSet::collectFeaturesFromSelector(const CSSSelector& selector, RuleFeatureSet::FeatureMetadata& metadata, SelectorFeatureCollectionMode collectionMode) { unsigned maxDirectAdjacentSelectors = 0; for (const CSSSelector* current = &selector; current; current = current->tagHistory()) { if (current->m_match == CSSSelector::Id) { metadata.idsInRules.add(current->value()); } else if (current->m_match == CSSSelector::Class && collectionMode == ProcessClasses) { DescendantInvalidationSet& invalidationSet = ensureClassInvalidationSet(current->value()); invalidationSet.setWholeSubtreeInvalid(); } else if (current->isAttributeSelector()) { metadata.attrsInRules.add(current->attribute().localName()); } if (current->pseudoType() == CSSSelector::PseudoFirstLine) metadata.usesFirstLineRules = true; if (current->isDirectAdjacentSelector()) { maxDirectAdjacentSelectors++; } else if (maxDirectAdjacentSelectors) { if (maxDirectAdjacentSelectors > metadata.maxDirectAdjacentSelectors) metadata.maxDirectAdjacentSelectors = maxDirectAdjacentSelectors; maxDirectAdjacentSelectors = 0; } if (current->isSiblingSelector()) metadata.foundSiblingSelector = true; collectFeaturesFromSelectorList(current->selectorList(), metadata, collectionMode); } ASSERT(!maxDirectAdjacentSelectors); }
InvalidationSet* RuleFeatureSet::invalidationSetForSelector(const CSSSelector& selector) { if (selector.match() == CSSSelector::Class) return &ensureClassInvalidationSet(selector.value()); if (selector.isAttributeSelector()) return &ensureAttributeInvalidationSet(selector.attribute().localName()); if (selector.match() == CSSSelector::Id) return &ensureIdInvalidationSet(selector.value()); if (selector.match() == CSSSelector::PseudoClass) { switch (selector.pseudoType()) { case CSSSelector::PseudoEmpty: case CSSSelector::PseudoLink: case CSSSelector::PseudoVisited: case CSSSelector::PseudoAnyLink: case CSSSelector::PseudoAutofill: case CSSSelector::PseudoHover: case CSSSelector::PseudoFocus: case CSSSelector::PseudoActive: case CSSSelector::PseudoChecked: case CSSSelector::PseudoEnabled: case CSSSelector::PseudoDisabled: case CSSSelector::PseudoOptional: case CSSSelector::PseudoPlaceholderShown: case CSSSelector::PseudoRequired: case CSSSelector::PseudoValid: case CSSSelector::PseudoInvalid: case CSSSelector::PseudoIndeterminate: case CSSSelector::PseudoTarget: return &ensurePseudoInvalidationSet(selector.pseudoType()); default: break; } } return nullptr; }
void RuleFeatureSet::add(const RuleFeatureSet& other) { for (InvalidationSetMap::const_iterator it = other.m_classInvalidationSets.begin(); it != other.m_classInvalidationSets.end(); ++it) { ensureClassInvalidationSet(it->key).combine(*it->value); } m_metadata.add(other.m_metadata); siblingRules.append(other.siblingRules); uncommonAttributeRules.append(other.uncommonAttributeRules); }
DescendantInvalidationSet* RuleFeatureSet::invalidationSetForSelector(const CSSSelector& selector) { if (selector.m_match == CSSSelector::Class) return &ensureClassInvalidationSet(selector.value()); if (selector.isAttributeSelector()) return &ensureAttributeInvalidationSet(selector.attribute().localName()); if (selector.m_match == CSSSelector::Id) return &ensureIdInvalidationSet(selector.value()); if (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; }
void RuleFeatureSet::add(const RuleFeatureSet& other) { for (const auto& invalidationSet : other.m_classInvalidationSets) ensureClassInvalidationSet(invalidationSet.key).combine(*invalidationSet.value); for (const auto& invalidationSet : other.m_attributeInvalidationSets) ensureAttributeInvalidationSet(invalidationSet.key).combine(*invalidationSet.value); for (const auto& invalidationSet : other.m_idInvalidationSets) ensureIdInvalidationSet(invalidationSet.key).combine(*invalidationSet.value); for (const auto& invalidationSet : other.m_pseudoInvalidationSets) ensurePseudoInvalidationSet(static_cast<CSSSelector::PseudoType>(invalidationSet.key)).combine(*invalidationSet.value); m_metadata.add(other.m_metadata); siblingRules.appendVector(other.siblingRules); uncommonAttributeRules.appendVector(other.uncommonAttributeRules); }
void RuleFeatureSet::add(const RuleFeatureSet& other) { for (InvalidationSetMap::const_iterator it = other.m_classInvalidationSets.begin(); it != other.m_classInvalidationSets.end(); ++it) ensureClassInvalidationSet(it->key).combine(*it->value); for (InvalidationSetMap::const_iterator it = other.m_attributeInvalidationSets.begin(); it != other.m_attributeInvalidationSets.end(); ++it) 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); m_metadata.add(other.m_metadata); siblingRules.appendVector(other.siblingRules); uncommonAttributeRules.appendVector(other.uncommonAttributeRules); }
InvalidationSet* RuleFeatureSet::invalidationSetForSelector(const CSSSelector& selector, InvalidationType type) { if (selector.match() == CSSSelector::Class) return &ensureClassInvalidationSet(selector.value(), type); if (selector.isAttributeSelector()) return &ensureAttributeInvalidationSet(selector.attribute().localName(), type); if (selector.match() == CSSSelector::Id) return &ensureIdInvalidationSet(selector.value(), type); if (selector.match() == CSSSelector::PseudoClass) { switch (selector.pseudoType()) { case CSSSelector::PseudoEmpty: case CSSSelector::PseudoLink: case CSSSelector::PseudoVisited: case CSSSelector::PseudoAnyLink: case CSSSelector::PseudoAutofill: case CSSSelector::PseudoHover: case CSSSelector::PseudoDrag: case CSSSelector::PseudoFocus: case CSSSelector::PseudoActive: case CSSSelector::PseudoChecked: case CSSSelector::PseudoEnabled: // TODO([email protected]): crbug.com/557683 :default is currently not updated dynamically. // case CSSSelector::Default: case CSSSelector::PseudoDisabled: case CSSSelector::PseudoOptional: case CSSSelector::PseudoPlaceholderShown: case CSSSelector::PseudoRequired: case CSSSelector::PseudoReadOnly: case CSSSelector::PseudoReadWrite: case CSSSelector::PseudoValid: case CSSSelector::PseudoInvalid: case CSSSelector::PseudoIndeterminate: case CSSSelector::PseudoTarget: case CSSSelector::PseudoLang: case CSSSelector::PseudoInRange: case CSSSelector::PseudoOutOfRange: case CSSSelector::PseudoUnresolved: return &ensurePseudoInvalidationSet(selector.pseudoType(), type); default: break; } } return nullptr; }