bool SelectorChecker::checkPseudoClass(const CSSSelector& selector) { switch (selector.pseudoType()) { case CSSSelector::PseudoFocus: m_matchedFocusSelector = true; return matchesFocusPseudoClass(m_element); case CSSSelector::PseudoHover: m_matchedHoverSelector = true; return m_element.hovered(); case CSSSelector::PseudoActive: m_matchedActiveSelector = true; return m_element.active(); case CSSSelector::PseudoLang: { AtomicString value = m_element.computeInheritedLanguage(); const AtomicString& argument = selector.argument(); if (value.isEmpty() || !value.startsWith(argument, false)) break; if (value.length() != argument.length() && value[argument.length()] != '-') break; return true; } case CSSSelector::PseudoHost: { // We can only get here if the selector was defined in the right // scope so we don't need to check it. // For empty parameter case, i.e. just :host or :host(). if (!selector.selectorList()) return true; for (const CSSSelector* current = selector.selectorList()->first(); current; current = CSSSelectorList::next(*current)) { if (match(*current)) return true; } return false; } case CSSSelector::PseudoUnknown: case CSSSelector::PseudoNotParsed: case CSSSelector::PseudoUserAgentCustomElement: return false; } ASSERT_NOT_REACHED(); return false; }
bool SelectorChecker::checkPseudoClass(const SelectorCheckingContext& context) const { ASSERT(context.element); Element& element = *context.element; ASSERT(context.selector); const CSSSelector& selector = *context.selector; ASSERT(selector.match() == CSSSelector::PseudoClass); // Normal element pseudo class checking. switch (selector.pseudoType()) { case CSSSelector::PseudoFocus: if (m_mode == ResolvingStyle) { if (context.elementStyle) context.elementStyle->setAffectedByFocus(); } return matchesFocusPseudoClass(element); case CSSSelector::PseudoHover: if (m_mode == ResolvingStyle) { if (context.elementStyle) context.elementStyle->setAffectedByHover(); } return element.hovered(); case CSSSelector::PseudoActive: if (m_mode == ResolvingStyle) { if (context.elementStyle) context.elementStyle->setAffectedByActive(); } return element.active(); case CSSSelector::PseudoLang: { AtomicString value = element.computeInheritedLanguage(); const AtomicString& argument = selector.argument(); if (value.isEmpty() || !value.startsWith(argument, false)) break; if (value.length() != argument.length() && value[argument.length()] != '-') break; return true; } case CSSSelector::PseudoUnresolved: return element.isUnresolvedCustomElement(); case CSSSelector::PseudoHost: { if (m_mode == SharingRules) return true; // :host only matches a shadow host when :host is in a shadow tree of the shadow host. if (!context.scope) return false; const ContainerNode* shadowHost = context.scope->shadowHost(); if (!shadowHost || shadowHost != element) return false; ASSERT(element.shadow()); // For empty parameter case, i.e. just :host or :host(). if (!selector.selectorList()) return true; SelectorCheckingContext subContext(context); subContext.contextFlags = TreatShadowHostAsNormalScope; for (subContext.selector = selector.selectorList()->first(); subContext.selector; subContext.selector = CSSSelectorList::next(*subContext.selector)) { if (match(subContext)) return true; } return false; } case CSSSelector::PseudoUnknown: case CSSSelector::PseudoNotParsed: case CSSSelector::PseudoUserAgentCustomElement: return false; } ASSERT_NOT_REACHED(); return false; }