OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "config.h" | 5 #include "config.h" |
6 #include "core/css/parser/CSSSelectorParser.h" | 6 #include "core/css/parser/CSSSelectorParser.h" |
7 | 7 |
8 #include "core/css/CSSSelectorList.h" | 8 #include "core/css/CSSSelectorList.h" |
9 #include "core/css/StyleSheetContents.h" | 9 #include "core/css/StyleSheetContents.h" |
10 #include "core/frame/UseCounter.h" | 10 #include "core/frame/UseCounter.h" |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 | 135 |
136 return selector.release(); | 136 return selector.release(); |
137 } | 137 } |
138 | 138 |
139 PassOwnPtr<CSSParserSelector> CSSSelectorParser::consumeCompoundSelector(CSSPars
erTokenRange& range) | 139 PassOwnPtr<CSSParserSelector> CSSSelectorParser::consumeCompoundSelector(CSSPars
erTokenRange& range) |
140 { | 140 { |
141 OwnPtr<CSSParserSelector> compoundSelector; | 141 OwnPtr<CSSParserSelector> compoundSelector; |
142 | 142 |
143 AtomicString namespacePrefix; | 143 AtomicString namespacePrefix; |
144 AtomicString elementName; | 144 AtomicString elementName; |
145 bool hasNamespace; | 145 if (!consumeName(range, elementName, namespacePrefix)) { |
146 if (!consumeName(range, elementName, namespacePrefix, hasNamespace)) { | |
147 compoundSelector = consumeSimpleSelector(range); | 146 compoundSelector = consumeSimpleSelector(range); |
148 if (!compoundSelector) | 147 if (!compoundSelector) |
149 return nullptr; | 148 return nullptr; |
150 } | 149 } |
151 if (m_context.isHTMLDocument()) | 150 if (m_context.isHTMLDocument()) |
152 elementName = elementName.lower(); | 151 elementName = elementName.lower(); |
153 | 152 |
154 while (OwnPtr<CSSParserSelector> simpleSelector = consumeSimpleSelector(rang
e)) { | 153 while (OwnPtr<CSSParserSelector> simpleSelector = consumeSimpleSelector(rang
e)) { |
155 if (compoundSelector) | 154 if (compoundSelector) |
156 compoundSelector = addSimpleSelectorToCompound(compoundSelector.rele
ase(), simpleSelector.release()); | 155 compoundSelector = addSimpleSelectorToCompound(compoundSelector.rele
ase(), simpleSelector.release()); |
157 else | 156 else |
158 compoundSelector = simpleSelector.release(); | 157 compoundSelector = simpleSelector.release(); |
159 } | 158 } |
160 | 159 |
161 if (!compoundSelector) { | 160 if (!compoundSelector) |
162 if (hasNamespace) | 161 return CSSParserSelector::create(determineNameInNamespace(namespacePrefi
x, elementName)); |
163 return CSSParserSelector::create(determineNameInNamespace(namespaceP
refix, elementName)); | |
164 return CSSParserSelector::create(QualifiedName(nullAtom, elementName, de
faultNamespace())); | |
165 } | |
166 prependTypeSelectorIfNeeded(namespacePrefix, elementName, compoundSelector.g
et()); | 162 prependTypeSelectorIfNeeded(namespacePrefix, elementName, compoundSelector.g
et()); |
167 return compoundSelector.release(); | 163 return compoundSelector.release(); |
168 } | 164 } |
169 | 165 |
170 PassOwnPtr<CSSParserSelector> CSSSelectorParser::consumeSimpleSelector(CSSParser
TokenRange& range) | 166 PassOwnPtr<CSSParserSelector> CSSSelectorParser::consumeSimpleSelector(CSSParser
TokenRange& range) |
171 { | 167 { |
172 const CSSParserToken& token = range.peek(); | 168 const CSSParserToken& token = range.peek(); |
173 OwnPtr<CSSParserSelector> selector; | 169 OwnPtr<CSSParserSelector> selector; |
174 if (token.type() == HashToken) | 170 if (token.type() == HashToken) |
175 selector = consumeId(range); | 171 selector = consumeId(range); |
176 else if (token.type() == DelimiterToken && token.delimiter() == '.') | 172 else if (token.type() == DelimiterToken && token.delimiter() == '.') |
177 selector = consumeClass(range); | 173 selector = consumeClass(range); |
178 else if (token.type() == LeftBracketToken) | 174 else if (token.type() == LeftBracketToken) |
179 selector = consumeAttribute(range); | 175 selector = consumeAttribute(range); |
180 else if (token.type() == ColonToken) | 176 else if (token.type() == ColonToken) |
181 selector = consumePseudo(range); | 177 selector = consumePseudo(range); |
182 else | 178 else |
183 return nullptr; | 179 return nullptr; |
184 if (!selector) | 180 if (!selector) |
185 m_failedParsing = true; | 181 m_failedParsing = true; |
186 return selector.release(); | 182 return selector.release(); |
187 } | 183 } |
188 | 184 |
189 bool CSSSelectorParser::consumeName(CSSParserTokenRange& range, AtomicString& na
me, AtomicString& namespacePrefix, bool& hasNamespace) | 185 bool CSSSelectorParser::consumeName(CSSParserTokenRange& range, AtomicString& na
me, AtomicString& namespacePrefix) |
190 { | 186 { |
191 name = nullAtom; | 187 name = nullAtom; |
192 namespacePrefix = nullAtom; | 188 namespacePrefix = nullAtom; |
193 hasNamespace = false; | |
194 | 189 |
195 const CSSParserToken& firstToken = range.peek(); | 190 const CSSParserToken& firstToken = range.peek(); |
196 if (firstToken.type() == IdentToken) { | 191 if (firstToken.type() == IdentToken) { |
197 name = firstToken.value(); | 192 name = firstToken.value(); |
198 range.consume(); | 193 range.consume(); |
199 } else if (firstToken.type() == DelimiterToken && firstToken.delimiter() ==
'*') { | 194 } else if (firstToken.type() == DelimiterToken && firstToken.delimiter() ==
'*') { |
200 name = starAtom; | 195 name = starAtom; |
201 range.consume(); | 196 range.consume(); |
202 } else if (firstToken.type() == DelimiterToken && firstToken.delimiter() ==
'|') { | 197 } else if (firstToken.type() == DelimiterToken && firstToken.delimiter() ==
'|') { |
203 // No namespace | 198 // This is an empty namespace, which'll get assigned this value below |
| 199 name = emptyAtom; |
204 } else { | 200 } else { |
205 return false; | 201 return false; |
206 } | 202 } |
207 | 203 |
208 if (range.peek().type() != DelimiterToken || range.peek().delimiter() != '|'
) | 204 if (range.peek().type() != DelimiterToken || range.peek().delimiter() != '|'
) |
209 return true; | 205 return true; |
210 range.consume(); | 206 range.consume(); |
211 | 207 |
212 hasNamespace = true; | |
213 namespacePrefix = name; | 208 namespacePrefix = name; |
214 const CSSParserToken& nameToken = range.consume(); | 209 const CSSParserToken& nameToken = range.consume(); |
215 if (nameToken.type() == IdentToken) { | 210 if (nameToken.type() == IdentToken) { |
216 name = nameToken.value(); | 211 name = nameToken.value(); |
217 } else if (nameToken.type() == DelimiterToken && nameToken.delimiter() == '*
') { | 212 } else if (nameToken.type() == DelimiterToken && nameToken.delimiter() == '*
') { |
218 name = starAtom; | 213 name = starAtom; |
219 } else { | 214 } else { |
220 name = nullAtom; | 215 name = nullAtom; |
221 namespacePrefix = nullAtom; | 216 namespacePrefix = nullAtom; |
222 return false; | 217 return false; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
258 } | 253 } |
259 | 254 |
260 PassOwnPtr<CSSParserSelector> CSSSelectorParser::consumeAttribute(CSSParserToken
Range& range) | 255 PassOwnPtr<CSSParserSelector> CSSSelectorParser::consumeAttribute(CSSParserToken
Range& range) |
261 { | 256 { |
262 ASSERT(range.peek().type() == LeftBracketToken); | 257 ASSERT(range.peek().type() == LeftBracketToken); |
263 CSSParserTokenRange block = range.consumeBlock(); | 258 CSSParserTokenRange block = range.consumeBlock(); |
264 block.consumeWhitespace(); | 259 block.consumeWhitespace(); |
265 | 260 |
266 AtomicString namespacePrefix; | 261 AtomicString namespacePrefix; |
267 AtomicString attributeName; | 262 AtomicString attributeName; |
268 bool hasNamespace; | 263 if (!consumeName(block, attributeName, namespacePrefix)) |
269 if (!consumeName(block, attributeName, namespacePrefix, hasNamespace)) | |
270 return nullptr; | 264 return nullptr; |
271 block.consumeWhitespace(); | 265 block.consumeWhitespace(); |
272 | 266 |
273 if (m_context.isHTMLDocument()) | 267 if (m_context.isHTMLDocument()) |
274 attributeName = attributeName.lower(); | 268 attributeName = attributeName.lower(); |
275 | 269 |
276 QualifiedName qualifiedName = hasNamespace | 270 QualifiedName qualifiedName = namespacePrefix.isNull() |
277 ? determineNameInNamespace(namespacePrefix, attributeName) | 271 ? QualifiedName(nullAtom, attributeName, nullAtom) |
278 : QualifiedName(nullAtom, attributeName, nullAtom); | 272 : determineNameInNamespace(namespacePrefix, attributeName); |
279 | 273 |
280 OwnPtr<CSSParserSelector> selector = CSSParserSelector::create(); | 274 OwnPtr<CSSParserSelector> selector = CSSParserSelector::create(); |
281 | 275 |
282 if (block.atEnd()) { | 276 if (block.atEnd()) { |
283 selector->setAttribute(qualifiedName, CSSSelector::CaseSensitive); | 277 selector->setAttribute(qualifiedName, CSSSelector::CaseSensitive); |
284 selector->setMatch(CSSSelector::AttributeSet); | 278 selector->setMatch(CSSSelector::AttributeSet); |
285 return selector.release(); | 279 return selector.release(); |
286 } | 280 } |
287 | 281 |
288 selector->setMatch(consumeAttributeMatch(block)); | 282 selector->setMatch(consumeAttributeMatch(block)); |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
548 return QualifiedName(prefix, localName, defaultNamespace()); | 542 return QualifiedName(prefix, localName, defaultNamespace()); |
549 return QualifiedName(prefix, localName, m_styleSheet->determineNamespace(pre
fix)); | 543 return QualifiedName(prefix, localName, m_styleSheet->determineNamespace(pre
fix)); |
550 } | 544 } |
551 | 545 |
552 void CSSSelectorParser::prependTypeSelectorIfNeeded(const AtomicString& namespac
ePrefix, const AtomicString& elementName, CSSParserSelector* compoundSelector) | 546 void CSSSelectorParser::prependTypeSelectorIfNeeded(const AtomicString& namespac
ePrefix, const AtomicString& elementName, CSSParserSelector* compoundSelector) |
553 { | 547 { |
554 if (elementName.isNull() && defaultNamespace() == starAtom && !compoundSelec
tor->crossesTreeScopes()) | 548 if (elementName.isNull() && defaultNamespace() == starAtom && !compoundSelec
tor->crossesTreeScopes()) |
555 return; | 549 return; |
556 | 550 |
557 AtomicString determinedElementName = elementName.isNull() ? starAtom : eleme
ntName; | 551 AtomicString determinedElementName = elementName.isNull() ? starAtom : eleme
ntName; |
558 AtomicString determinedNamespace = namespacePrefix != nullAtom && m_styleShe
et ? m_styleSheet->determineNamespace(namespacePrefix) : defaultNamespace(); | 552 QualifiedName tag = determineNameInNamespace(namespacePrefix, determinedElem
entName); |
559 QualifiedName tag(namespacePrefix, determinedElementName, determinedNamespac
e); | |
560 | 553 |
561 if (compoundSelector->crossesTreeScopes()) | 554 if (compoundSelector->crossesTreeScopes()) |
562 return rewriteSpecifiersWithElementNameForCustomPseudoElement(tag, compo
undSelector, elementName.isNull()); | 555 return rewriteSpecifiersWithElementNameForCustomPseudoElement(tag, compo
undSelector, elementName.isNull()); |
563 | 556 |
564 if (compoundSelector->pseudoType() == CSSSelector::PseudoContent) | 557 if (compoundSelector->pseudoType() == CSSSelector::PseudoContent) |
565 return rewriteSpecifiersWithElementNameForContentPseudoElement(tag, comp
oundSelector, elementName.isNull()); | 558 return rewriteSpecifiersWithElementNameForContentPseudoElement(tag, comp
oundSelector, elementName.isNull()); |
566 | 559 |
567 // *:host never matches, so we can't discard the * otherwise we can't tell t
he | 560 // *:host never matches, so we can't discard the * otherwise we can't tell t
he |
568 // difference between *:host and just :host. | 561 // difference between *:host and just :host. |
569 if (tag == anyQName() && !compoundSelector->hasHostPseudoSelector()) | 562 if (tag == anyQName() && !compoundSelector->hasHostPseudoSelector()) |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
660 compoundSelector->insertTagHistory(CSSSelector::SubSelector, simpleSelec
tor, relation); | 653 compoundSelector->insertTagHistory(CSSSelector::SubSelector, simpleSelec
tor, relation); |
661 return compoundSelector; | 654 return compoundSelector; |
662 } | 655 } |
663 | 656 |
664 // All other simple selectors are added to the end of the compound. | 657 // All other simple selectors are added to the end of the compound. |
665 compoundSelector->appendTagHistory(CSSSelector::SubSelector, simpleSelector)
; | 658 compoundSelector->appendTagHistory(CSSSelector::SubSelector, simpleSelector)
; |
666 return compoundSelector; | 659 return compoundSelector; |
667 } | 660 } |
668 | 661 |
669 } // namespace blink | 662 } // namespace blink |
OLD | NEW |