2 * Copyright (C) 2003 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010, 2014 Apple Inc. All rights reserved.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
23 #include "CSSSelector.h"
24 #include "CSSValueKeywords.h"
25 #include "CSSValueList.h"
26 #include <wtf/text/AtomicString.h>
27 #include <wtf/text/AtomicStringHash.h>
28 #include <wtf/text/WTFString.h>
35 // This should be a StringView but currently it can't because it's used as an element of a union in CSSParserValue.
36 struct CSSParserString {
37 void init(LChar* characters, unsigned length)
39 m_data.characters8 = characters;
44 void init(UChar* characters, unsigned length)
46 m_data.characters16 = characters;
51 void init(const String& string)
53 m_length = string.length();
54 if (!m_length || string.is8Bit()) {
55 m_data.characters8 = const_cast<LChar*>(string.characters8());
58 m_data.characters16 = const_cast<UChar*>(string.characters16());
65 m_data.characters8 = 0;
70 bool is8Bit() const { return m_is8Bit; }
71 LChar* characters8() const { ASSERT(is8Bit()); return m_data.characters8; }
72 UChar* characters16() const { ASSERT(!is8Bit()); return m_data.characters16; }
73 template<typename CharacterType> CharacterType* characters() const;
75 unsigned length() const { return m_length; }
76 void setLength(unsigned length) { m_length = length; }
78 void convertToASCIILowercaseInPlace();
80 UChar operator[](unsigned i) const
82 ASSERT_WITH_SECURITY_IMPLICATION(i < m_length);
84 return m_data.characters8[i];
85 return m_data.characters16[i];
88 operator String() const { return is8Bit() ? String(m_data.characters8, m_length) : String(m_data.characters16, m_length); }
89 operator AtomicString() const { return is8Bit() ? AtomicString(m_data.characters8, m_length) : AtomicString(m_data.characters16, m_length); }
90 StringView toStringView() const { return is8Bit() ? StringView(m_data.characters8, m_length) : StringView(m_data.characters16, m_length); }
100 template<unsigned length> bool equalLettersIgnoringASCIICase(const CSSParserString&, const char (&lowercaseLetters)[length]);
102 struct CSSParserFunction;
103 struct CSSParserVariable;
105 struct CSSParserValue {
111 CSSParserString string;
112 CSSParserFunction* function;
113 CSSParserVariable* variable;
114 CSSParserValueList* valueList;
119 ValueList = 0x100002,
125 void setFromValueList(std::unique_ptr<CSSParserValueList>);
127 RefPtr<CSSValue> createCSSValue();
130 void destroy(const CSSParserValue&);
132 class CSSParserValueList {
133 WTF_MAKE_FAST_ALLOCATED;
139 ~CSSParserValueList();
141 void addValue(const CSSParserValue&);
142 void insertValueAt(unsigned, const CSSParserValue&);
143 void extend(CSSParserValueList&);
145 unsigned size() const { return m_values.size(); }
146 unsigned currentIndex() { return m_current; }
147 CSSParserValue* current() { return m_current < m_values.size() ? &m_values[m_current] : 0; }
148 CSSParserValue* next() { ++m_current; return current(); }
149 CSSParserValue* previous()
156 void setCurrentIndex(unsigned index)
158 ASSERT(index < m_values.size());
159 if (index < m_values.size())
163 CSSParserValue* valueAt(unsigned i) { return i < m_values.size() ? &m_values[i] : 0; }
165 void clear() { m_values.clear(); }
169 bool containsVariables() const;
173 Vector<CSSParserValue, 4> m_values;
176 struct CSSParserFunction {
177 WTF_MAKE_FAST_ALLOCATED;
179 CSSParserString name;
180 std::unique_ptr<CSSParserValueList> args;
183 struct CSSParserVariable {
184 WTF_MAKE_FAST_ALLOCATED;
186 CSSParserString name; // The custom property name
187 std::unique_ptr<CSSParserValueList> args; // The fallback args
190 enum class CSSParserSelectorCombinator {
193 #if ENABLE(CSS_SELECTORS_LEVEL4)
194 DescendantDoubleChild,
198 ShadowPseudo, // Special case of shadow DOM pseudo elements / shadow pseudo element
199 ShadowDeep, // /deep/ combinator
200 ShadowSlot // slotted to <slot> e
203 class CSSParserSelector {
204 WTF_MAKE_FAST_ALLOCATED;
206 // FIXME-NEWPARSER: Remove the CSSParserString-based parsing functions once the old parser is gone.
207 static CSSParserSelector* parsePagePseudoSelector(const CSSParserString& pseudoTypeString);
208 static CSSParserSelector* parsePseudoElementSelector(CSSParserString& pseudoTypeString);
209 static CSSParserSelector* parsePseudoElementCueFunctionSelector(const CSSParserString& functionIdentifier, Vector<std::unique_ptr<CSSParserSelector>>*);
210 static CSSParserSelector* parsePseudoElementSlottedFunctionSelector(const CSSParserString& functionIdentifier, CSSParserSelector*);
211 static CSSParserSelector* parsePseudoClassHostFunctionSelector(const CSSParserString& functionIdentifier, CSSParserSelector*);
212 static CSSParserSelector* parsePseudoClassAndCompatibilityElementSelector(CSSParserString& pseudoTypeString);
214 static CSSParserSelector* parsePseudoClassSelectorFromStringView(StringView&);
215 static CSSParserSelector* parsePseudoElementSelectorFromStringView(StringView&);
216 static CSSParserSelector* parsePagePseudoSelector(const AtomicString&);
219 explicit CSSParserSelector(const QualifiedName&);
220 ~CSSParserSelector();
222 std::unique_ptr<CSSSelector> releaseSelector() { return WTFMove(m_selector); }
224 void setValue(const AtomicString& value) { m_selector->setValue(value); }
225 void setAttribute(const QualifiedName& value, bool isCaseInsensitive) { m_selector->setAttribute(value, isCaseInsensitive); }
226 void setArgument(const AtomicString& value) { m_selector->setArgument(value); }
227 void setAttributeValueMatchingIsCaseInsensitive(bool isCaseInsensitive) { m_selector->setAttributeValueMatchingIsCaseInsensitive(isCaseInsensitive); }
228 void setMatch(CSSSelector::Match value) { m_selector->setMatch(value); }
229 void setRelation(CSSSelector::RelationType value) { m_selector->setRelation(value); }
230 void setForPage() { m_selector->setForPage(); }
232 CSSSelector::Match match() const { return m_selector->match(); }
233 CSSSelector::PseudoElementType pseudoElementType() const { return m_selector->pseudoElementType(); }
234 const CSSSelectorList* selectorList() const { return m_selector->selectorList(); }
236 void adoptSelectorVector(Vector<std::unique_ptr<CSSParserSelector>>& selectorVector);
237 void setLangArgumentList(const Vector<CSSParserString>& stringVector);
238 void setSelectorList(std::unique_ptr<CSSSelectorList>);
240 void setPseudoClassValue(const CSSParserString& pseudoClassString);
241 CSSSelector::PseudoClassType pseudoClassType() const { return m_selector->pseudoClassType(); }
242 bool isCustomPseudoElement() const { return m_selector->isCustomPseudoElement(); }
244 bool isPseudoElementCueFunction() const
246 #if ENABLE(VIDEO_TRACK)
247 return m_selector->match() == CSSSelector::PseudoElement && m_selector->pseudoElementType() == CSSSelector::PseudoElementCue;
253 bool hasShadowDescendant() const;
254 bool matchesPseudoElement() const;
256 bool isHostPseudoSelector() const;
258 // FIXME-NEWPARSER: Missing "shadow"
259 bool needsImplicitShadowCombinatorForMatching() const { return match() == CSSSelector::PseudoElement && (pseudoElementType() == CSSSelector::PseudoElementWebKitCustom || pseudoElementType() == CSSSelector::PseudoElementUserAgentCustom || pseudoElementType() == CSSSelector::PseudoElementWebKitCustomLegacyPrefixed || pseudoElementType() == CSSSelector::PseudoElementCue || pseudoElementType() == CSSSelector::PseudoElementSlotted); }
261 CSSParserSelector* tagHistory() const { return m_tagHistory.get(); }
262 void setTagHistory(std::unique_ptr<CSSParserSelector> selector) { m_tagHistory = WTFMove(selector); }
263 void clearTagHistory() { m_tagHistory.reset(); }
264 void insertTagHistory(CSSSelector::RelationType before, std::unique_ptr<CSSParserSelector>, CSSSelector::RelationType after);
265 void appendTagHistory(CSSSelector::RelationType, std::unique_ptr<CSSParserSelector>);
266 void appendTagHistory(CSSParserSelectorCombinator, std::unique_ptr<CSSParserSelector>);
267 void prependTagSelector(const QualifiedName&, bool tagIsForNamespaceRule = false);
268 std::unique_ptr<CSSParserSelector> releaseTagHistory();
271 #if ENABLE(CSS_SELECTORS_LEVEL4)
272 void setDescendantUseDoubleChildSyntax() { m_selector->setDescendantUseDoubleChildSyntax(); }
275 std::unique_ptr<CSSSelector> m_selector;
276 std::unique_ptr<CSSParserSelector> m_tagHistory;
279 inline bool CSSParserSelector::hasShadowDescendant() const
281 return m_selector->relation() == CSSSelector::ShadowDescendant;
284 inline void CSSParserValue::setFromValueList(std::unique_ptr<CSSParserValueList> valueList)
286 id = CSSValueInvalid;
287 this->valueList = valueList.release();
291 template<unsigned length> inline bool equalLettersIgnoringASCIICase(const CSSParserString& string, const char (&lowercaseLetters)[length])
293 return WTF::equalLettersIgnoringASCIICaseCommon(string, lowercaseLetters);