bool SelectorChecker::checkOne(const CSSSelector& selector) { switch (selector.match()) { case CSSSelector::Tag: { const AtomicString& localName = selector.tagQName().localName(); return localName == starAtom || localName == m_element.localName(); } case CSSSelector::Class: return m_element.hasClass() && m_element.classNames().contains(selector.value()); case CSSSelector::Id: return m_element.hasID() && m_element.idForStyleResolution() == selector.value(); case CSSSelector::Exact: case CSSSelector::Set: if (anyAttributeMatches(m_element, selector.match(), selector)) { m_matchedAttributeSelector = true; return true; } return false; case CSSSelector::PseudoClass: return checkPseudoClass(selector); // FIXME(sky): Remove pseudo elements completely. case CSSSelector::PseudoElement: case CSSSelector::Unknown: return false; } ASSERT_NOT_REACHED(); return false; }
static inline MatchBasedOnRuleHash computeMatchBasedOnRuleHash(const CSSSelector& selector) { if (selector.tagHistory()) return MatchBasedOnRuleHash::None; if (selector.match() == CSSSelector::Tag) { const QualifiedName& tagQualifiedName = selector.tagQName(); const AtomicString& selectorNamespace = tagQualifiedName.namespaceURI(); if (selectorNamespace == starAtom || selectorNamespace == xhtmlNamespaceURI) { if (tagQualifiedName == anyQName()) return MatchBasedOnRuleHash::Universal; return MatchBasedOnRuleHash::ClassC; } return MatchBasedOnRuleHash::None; } if (SelectorChecker::isCommonPseudoClassSelector(&selector)) return MatchBasedOnRuleHash::ClassB; #if ENABLE(SHADOW_DOM) if (selector.match() == CSSSelector::PseudoClass && selector.pseudoClassType() == CSSSelector::PseudoClassHost) return MatchBasedOnRuleHash::ClassB; #endif if (selector.match() == CSSSelector::Id) return MatchBasedOnRuleHash::ClassA; if (selector.match() == CSSSelector::Class) return MatchBasedOnRuleHash::ClassB; return MatchBasedOnRuleHash::None; }
bool operator()(const CSSSelector& selector) { if (selector.match() == CSSSelector::Tag && selector.tagQName().prefix() != nullAtom && selector.tagQName().prefix() != starAtom) return true; if (selector.isAttributeSelector() && selector.attribute().prefix() != nullAtom && selector.attribute().prefix() != starAtom) return true; return false; }
void extractClassIdOrTag(const CSSSelector& selector, Vector<AtomicString>& classes, AtomicString& id, AtomicString& tagName) { if (selector.m_match == CSSSelector::Tag) tagName = selector.tagQName().localName(); else if (selector.m_match == CSSSelector::Id) id = selector.value(); else if (selector.m_match == CSSSelector::Class) classes.append(selector.value()); }
bool RuleFeatureSet::extractInvalidationSetFeature(const CSSSelector& selector, InvalidationSetFeatures& features) { if (selector.match() == CSSSelector::Tag && selector.tagQName().localName() != starAtom) features.tagName = selector.tagQName().localName(); else if (selector.match() == CSSSelector::Id) features.id = selector.value(); else if (selector.match() == CSSSelector::Class) features.classes.append(selector.value()); else if (selector.isAttributeSelector()) features.attributes.append(selector.attribute().localName()); else if (selector.pseudoType() == CSSSelector::PseudoWebKitCustomElement) features.customPseudoElement = true; else if (selector.pseudoType() == CSSSelector::PseudoBefore || selector.pseudoType() == CSSSelector::PseudoAfter) features.hasBeforeOrAfter = true; else return false; return true; }
static inline void collectDescendantSelectorIdentifierHashes(const CSSSelector& selector, unsigned*& hash) { switch (selector.match()) { case CSSSelector::Id: if (!selector.value().isEmpty()) (*hash++) = selector.value().impl()->existingHash() * IdAttributeSalt; break; case CSSSelector::Class: if (!selector.value().isEmpty()) (*hash++) = selector.value().impl()->existingHash() * ClassAttributeSalt; break; case CSSSelector::Tag: if (selector.tagQName().localName() != starAtom) (*hash++) = selector.tagQName().localName().impl()->existingHash() * TagNameSalt; break; default: break; } }
static inline bool isSelectorMatchingHTMLBasedOnRuleHash(const CSSSelector& selector) { if (selector.tagHistory()) return false; if (selector.match() == CSSSelector::Tag) { const AtomicString& selectorNamespace = selector.tagQName().namespaceURI(); return selectorNamespace == starAtom || selectorNamespace == xhtmlNamespaceURI; } if (SelectorChecker::isCommonPseudoClassSelector(&selector)) return true; return selector.match() == CSSSelector::Id || selector.match() == CSSSelector::Class; }
void RuleFeatureSet::extractInvalidationSetFeature(const CSSSelector& selector, InvalidationSetFeatures& features) { if (selector.m_match == CSSSelector::Tag) features.tagName = selector.tagQName().localName(); else if (selector.m_match == CSSSelector::Id) features.id = selector.value(); else if (selector.m_match == CSSSelector::Class) features.classes.append(selector.value()); else if (selector.isAttributeSelector()) features.attributes.append(selector.attribute().localName()); else if (selector.isCustomPseudoElement()) features.customPseudoElement = true; }
static inline bool isSelectorMatchingHTMLBasedOnRuleHash(const CSSSelector& selector) { if (selector.m_match == CSSSelector::Tag) { const AtomicString& selectorNamespace = selector.tagQName().namespaceURI(); if (selectorNamespace != starAtom && selectorNamespace != xhtmlNamespaceURI) return false; if (selector.relation() == CSSSelector::SubSelector) { ASSERT(selector.tagHistory()); return isSelectorMatchingHTMLBasedOnRuleHash(*selector.tagHistory()); } return true; } if (SelectorChecker::isCommonPseudoClassSelector(selector)) return true; return selector.m_match == CSSSelector::Id || selector.m_match == CSSSelector::Class; }
static unsigned simpleSelectorSpecificityInternal(const CSSSelector& simpleSelector, bool isComputingMaximumSpecificity) { ASSERT_WITH_MESSAGE(!simpleSelector.isForPage(), "At the time of this writing, page selectors are not treated as real selectors that are matched. The value computed here only account for real selectors."); switch (simpleSelector.match()) { case CSSSelector::Id: return static_cast<unsigned>(SelectorSpecificityIncrement::ClassA); case CSSSelector::PagePseudoClass: break; case CSSSelector::PseudoClass: if (simpleSelector.pseudoClassType() == CSSSelector::PseudoClassMatches) { ASSERT_WITH_MESSAGE(simpleSelector.selectorList() && simpleSelector.selectorList()->first(), "The parser should never generate a valid selector for an empty :matches()."); if (!isComputingMaximumSpecificity) return 0; return maxSpecificity(*simpleSelector.selectorList()); } if (simpleSelector.pseudoClassType() == CSSSelector::PseudoClassNot) { ASSERT_WITH_MESSAGE(simpleSelector.selectorList() && simpleSelector.selectorList()->first(), "The parser should never generate a valid selector for an empty :not()."); return maxSpecificity(*simpleSelector.selectorList()); } FALLTHROUGH; case CSSSelector::Exact: case CSSSelector::Class: case CSSSelector::Set: case CSSSelector::List: case CSSSelector::Hyphen: case CSSSelector::Contain: case CSSSelector::Begin: case CSSSelector::End: return static_cast<unsigned>(SelectorSpecificityIncrement::ClassB); case CSSSelector::Tag: return (simpleSelector.tagQName().localName() != starAtom) ? static_cast<unsigned>(SelectorSpecificityIncrement::ClassC) : 0; case CSSSelector::PseudoElement: return static_cast<unsigned>(SelectorSpecificityIncrement::ClassC); case CSSSelector::Unknown: return 0; } ASSERT_NOT_REACHED(); return 0; }