diff options
Diffstat (limited to 'Source/WebCore/css/SelectorChecker.h')
-rw-r--r-- | Source/WebCore/css/SelectorChecker.h | 147 |
1 files changed, 67 insertions, 80 deletions
diff --git a/Source/WebCore/css/SelectorChecker.h b/Source/WebCore/css/SelectorChecker.h index ac6886287..85e94ceb0 100644 --- a/Source/WebCore/css/SelectorChecker.h +++ b/Source/WebCore/css/SelectorChecker.h @@ -2,7 +2,7 @@ * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com) - * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2005-2016 Apple Inc. All rights reserved. * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) @@ -25,14 +25,12 @@ * Boston, MA 02110-1301, USA. */ -#ifndef SelectorChecker_h -#define SelectorChecker_h +#pragma once #include "CSSSelector.h" #include "Element.h" #include "SpaceSplitString.h" -#include <wtf/HashSet.h> -#include <wtf/Vector.h> +#include "StyleRelations.h" namespace WebCore { @@ -43,101 +41,90 @@ class RenderStyle; class SelectorChecker { WTF_MAKE_NONCOPYABLE(SelectorChecker); - enum Match { SelectorMatches, SelectorFailsLocally, SelectorFailsAllSiblings, SelectorFailsCompletely }; + enum class Match { SelectorMatches, SelectorFailsLocally, SelectorFailsAllSiblings, SelectorFailsCompletely }; + + enum class MatchType { VirtualPseudoElementOnly, Element }; + + struct MatchResult { + Match match; + MatchType matchType; + + static MatchResult matches(MatchType matchType) + { + return { Match::SelectorMatches, matchType }; + } + + static MatchResult updateWithMatchType(MatchResult result, MatchType matchType) + { + if (matchType == MatchType::VirtualPseudoElementOnly) + result.matchType = MatchType::VirtualPseudoElementOnly; + return result; + } + + static MatchResult fails(Match match) + { + return { match, MatchType::Element }; + } + }; public: - enum VisitedMatchType { VisitedMatchDisabled, VisitedMatchEnabled }; - enum Mode { ResolvingStyle = 0, CollectingRules, QueryingRules, SharingRules }; - - SelectorChecker(Document&, Mode); - - struct SelectorCheckingContext { - // Initial selector constructor - SelectorCheckingContext(const CSSSelector* selector, Element* element, VisitedMatchType visitedMatchType) - : selector(selector) - , element(element) - , scope(0) - , visitedMatchType(visitedMatchType) - , pseudoId(NOPSEUDO) - , elementStyle(0) - , scrollbar(0) - , scrollbarPart(NoPart) - , isSubSelector(false) - , hasScrollbarPseudo(false) - , hasSelectionPseudo(false) + enum class Mode : unsigned char { + ResolvingStyle = 0, CollectingRules, CollectingRulesIgnoringVirtualPseudoElements, QueryingRules + }; + + SelectorChecker(Document&); + + struct CheckingContext { + CheckingContext(SelectorChecker::Mode resolvingMode) + : resolvingMode(resolvingMode) { } - const CSSSelector* selector; - Element* element; - const ContainerNode* scope; - VisitedMatchType visitedMatchType; - PseudoId pseudoId; - RenderStyle* elementStyle; - RenderScrollbar* scrollbar; - ScrollbarPart scrollbarPart; - bool isSubSelector; - bool hasScrollbarPseudo; - bool hasSelectionPseudo; + const SelectorChecker::Mode resolvingMode; + PseudoId pseudoId { NOPSEUDO }; + RenderScrollbar* scrollbar { nullptr }; + ScrollbarPart scrollbarPart { NoPart }; + const ContainerNode* scope { nullptr }; + bool isMatchingHostPseudoClass { false }; + + // FIXME: It would be nicer to have a separate object for return values. This requires some more work in the selector compiler. + Style::Relations styleRelations; + PseudoIdSet pseudoIDSet; }; - bool match(const SelectorCheckingContext& context, PseudoId& pseudoId) const - { - return matchRecursively(context, pseudoId) == SelectorMatches; - } + bool match(const CSSSelector&, const Element&, CheckingContext&, unsigned& specificity) const; + + bool matchHostPseudoClass(const CSSSelector&, const Element&, CheckingContext&, unsigned& specificity) const; - static bool tagMatches(const Element*, const QualifiedName&); static bool isCommonPseudoClassSelector(const CSSSelector*); - static bool matchesFocusPseudoClass(const Element*); - static bool checkExactAttribute(const Element*, const CSSSelector*, const QualifiedName& selectorAttributeName, const AtomicStringImpl* value); + static bool matchesFocusPseudoClass(const Element&); + static bool attributeSelectorMatches(const Element&, const QualifiedName&, const AtomicString& attributeValue, const CSSSelector&); - enum LinkMatchMask { MatchLink = 1, MatchVisited = 2, MatchAll = MatchLink | MatchVisited }; + enum LinkMatchMask { MatchDefault = 0, MatchLink = 1, MatchVisited = 2, MatchAll = MatchLink | MatchVisited }; static unsigned determineLinkMatchType(const CSSSelector*); + struct LocalContext; + private: - Match matchRecursively(const SelectorCheckingContext&, PseudoId&) const; - bool checkOne(const SelectorCheckingContext&) const; + MatchResult matchRecursively(CheckingContext&, const LocalContext&, PseudoIdSet&, unsigned& specificity) const; + bool checkOne(CheckingContext&, const LocalContext&, PseudoIdSet&, MatchType&, unsigned& specificity) const; + bool matchSelectorList(CheckingContext&, const LocalContext&, const Element&, const CSSSelectorList&, unsigned& specificity) const; - bool checkScrollbarPseudoClass(const SelectorCheckingContext&, Document*, const CSSSelector*) const; + bool checkScrollbarPseudoClass(const CheckingContext&, const Element&, const CSSSelector&) const; bool m_strictParsing; bool m_documentIsHTML; - Mode m_mode; }; inline bool SelectorChecker::isCommonPseudoClassSelector(const CSSSelector* selector) { - if (selector->m_match != CSSSelector::PseudoClass) - return false; - CSSSelector::PseudoType pseudoType = selector->pseudoType(); - return pseudoType == CSSSelector::PseudoLink - || pseudoType == CSSSelector::PseudoAnyLink - || pseudoType == CSSSelector::PseudoVisited - || pseudoType == CSSSelector::PseudoFocus; -} - -inline bool SelectorChecker::tagMatches(const Element* element, const QualifiedName& tagQName) -{ - if (tagQName == anyQName()) - return true; - const AtomicString& localName = tagQName.localName(); - if (localName != starAtom && localName != element->localName()) - return false; - const AtomicString& namespaceURI = tagQName.namespaceURI(); - return namespaceURI == starAtom || namespaceURI == element->namespaceURI(); -} - -inline bool SelectorChecker::checkExactAttribute(const Element* element, const CSSSelector* selector, const QualifiedName& selectorAttributeName, const AtomicStringImpl* value) -{ - if (!element->hasAttributesWithoutUpdate()) + if (selector->match() != CSSSelector::PseudoClass) return false; - const AtomicString& localName = element->isHTMLElement() ? selector->attributeCanonicalLocalName() : selectorAttributeName.localName(); - for (const Attribute& attribute : element->attributesIterator()) { - if (attribute.matches(selectorAttributeName.prefix(), localName, selectorAttributeName.namespaceURI()) && (!value || attribute.value().impl() == value)) - return true; - } - return false; -} - + CSSSelector::PseudoClassType pseudoType = selector->pseudoClassType(); + return pseudoType == CSSSelector::PseudoClassLink + || pseudoType == CSSSelector::PseudoClassAnyLink + || pseudoType == CSSSelector::PseudoClassAnyLinkDeprecated + || pseudoType == CSSSelector::PseudoClassVisited + || pseudoType == CSSSelector::PseudoClassFocus; } -#endif +} // namespace WebCore |