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 "platform/RuntimeEnabledFeatures.h" | 10 #include "platform/RuntimeEnabledFeatures.h" |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 selector = consumeComplexSelector(); | 43 selector = consumeComplexSelector(); |
44 if (!selector) | 44 if (!selector) |
45 return; | 45 return; |
46 selectorList.append(selector.release()); | 46 selectorList.append(selector.release()); |
47 } | 47 } |
48 | 48 |
49 if (!m_failedParsing) | 49 if (!m_failedParsing) |
50 output.adoptSelectorVector(selectorList); | 50 output.adoptSelectorVector(selectorList); |
51 } | 51 } |
52 | 52 |
| 53 void CSSSelectorParser::consumeCompoundSelectorList(CSSSelectorList& output) |
| 54 { |
| 55 Vector<OwnPtr<CSSParserSelector> > selectorList; |
| 56 OwnPtr<CSSParserSelector> selector = consumeCompoundSelector(); |
| 57 if (!selector) |
| 58 return; |
| 59 selectorList.append(selector.release()); |
| 60 while (!m_tokenRange.atEnd() && m_tokenRange.peek().type() == CommaToken) { |
| 61 m_tokenRange.consumeIncludingWhitespaceAndComments(); |
| 62 selector = consumeCompoundSelector(); |
| 63 if (!selector) |
| 64 return; |
| 65 selectorList.append(selector.release()); |
| 66 } |
| 67 |
| 68 m_tokenRange.consumeWhitespaceAndComments(); |
| 69 |
| 70 if (!m_failedParsing) |
| 71 output.adoptSelectorVector(selectorList); |
| 72 } |
| 73 |
53 PassOwnPtr<CSSParserSelector> CSSSelectorParser::consumeComplexSelector() | 74 PassOwnPtr<CSSParserSelector> CSSSelectorParser::consumeComplexSelector() |
54 { | 75 { |
55 OwnPtr<CSSParserSelector> selector = consumeCompoundSelector(); | 76 OwnPtr<CSSParserSelector> selector = consumeCompoundSelector(); |
56 if (!selector) | 77 if (!selector) |
57 return nullptr; | 78 return nullptr; |
58 while (CSSSelector::Relation combinator = consumeCombinator()) { | 79 while (CSSSelector::Relation combinator = consumeCombinator()) { |
59 OwnPtr<CSSParserSelector> nextSelector = consumeCompoundSelector(); | 80 OwnPtr<CSSParserSelector> nextSelector = consumeCompoundSelector(); |
60 if (!nextSelector) | 81 if (!nextSelector) |
61 return combinator == CSSSelector::Descendant ? selector.release() :
nullptr; | 82 return combinator == CSSSelector::Descendant ? selector.release() :
nullptr; |
62 CSSParserSelector* end = nextSelector.get(); | 83 CSSParserSelector* end = nextSelector.get(); |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
233 selector->setAttribute(qualifiedName, consumeAttributeFlags()); | 254 selector->setAttribute(qualifiedName, consumeAttributeFlags()); |
234 | 255 |
235 if (!m_tokenRange.atEnd() && m_tokenRange.consumeIncludingComments().type()
!= RightBracketToken) | 256 if (!m_tokenRange.atEnd() && m_tokenRange.consumeIncludingComments().type()
!= RightBracketToken) |
236 return nullptr; | 257 return nullptr; |
237 | 258 |
238 return selector.release(); | 259 return selector.release(); |
239 } | 260 } |
240 | 261 |
241 PassOwnPtr<CSSParserSelector> CSSSelectorParser::consumePseudo() | 262 PassOwnPtr<CSSParserSelector> CSSSelectorParser::consumePseudo() |
242 { | 263 { |
243 // FIXME: Implement pseudo-element and pseudo-class parsing | 264 ASSERT(m_tokenRange.peek().type() == ColonToken); |
| 265 m_tokenRange.consumeIncludingComments(); |
| 266 |
| 267 int colons = 1; |
| 268 if (m_tokenRange.peek().type() == ColonToken) { |
| 269 m_tokenRange.consumeIncludingComments(); |
| 270 colons++; |
| 271 } |
| 272 |
| 273 const CSSParserToken& token = m_tokenRange.consumeIncludingComments(); |
| 274 if (token.type() != IdentToken && token.type() != FunctionToken) |
| 275 return nullptr; |
| 276 m_tokenRange.consumeWhitespaceAndComments(); |
| 277 |
| 278 OwnPtr<CSSParserSelector> selector = CSSParserSelector::create(); |
| 279 selector->setMatch(colons == 1 ? CSSSelector::PseudoClass : CSSSelector::Pse
udoElement); |
| 280 selector->setValue(AtomicString(token.value().lower())); |
| 281 |
| 282 if (token.type() == IdentToken) { |
| 283 if (selector->pseudoType() == CSSSelector::PseudoUnknown) |
| 284 return nullptr; |
| 285 return selector.release(); |
| 286 } |
| 287 |
| 288 if ((colons == 1 |
| 289 && (equalIgnoringCase(token.value(), "host") |
| 290 || equalIgnoringCase(token.value(), "host-context") |
| 291 || equalIgnoringCase(token.value(), "-webkit-any"))) |
| 292 || (colons == 2 && equalIgnoringCase(token.value(), "cue"))) { |
| 293 |
| 294 CSSSelectorList* selectorList = new CSSSelectorList(); |
| 295 consumeCompoundSelectorList(*selectorList); |
| 296 if (!selectorList->isValid() || (!m_tokenRange.atEnd() && m_tokenRange.c
onsumeIncludingComments().type() != RightParenthesisToken)) |
| 297 return nullptr; |
| 298 |
| 299 selector->setSelectorList(adoptPtr(selectorList)); |
| 300 selector->pseudoType(); // FIXME: Do we need to force the pseudo type to
be cached? |
| 301 ASSERT(selector->pseudoType() != CSSSelector::PseudoUnknown); |
| 302 return selector.release(); |
| 303 } |
| 304 |
| 305 if (colons == 1 && equalIgnoringCase(token.value(), "not")) { |
| 306 OwnPtr<CSSParserSelector> innerSelector = consumeCompoundSelector(); |
| 307 if (!innerSelector || !innerSelector->isSimple()) |
| 308 return nullptr; |
| 309 Vector<OwnPtr<CSSParserSelector> > selectorVector; |
| 310 selectorVector.append(innerSelector.release()); |
| 311 selector->adoptSelectorVector(selectorVector); |
| 312 if (!m_tokenRange.atEnd() && m_tokenRange.consumeIncludingComments().typ
e() != RightParenthesisToken) |
| 313 return nullptr; |
| 314 return selector.release(); |
| 315 } |
| 316 |
| 317 // FIXME: Support :nth-*(<an+b>) |
| 318 // FIXME: Support :lang(<ident>) |
| 319 |
244 return nullptr; | 320 return nullptr; |
245 } | 321 } |
246 | 322 |
247 CSSSelector::Relation CSSSelectorParser::consumeCombinator() | 323 CSSSelector::Relation CSSSelectorParser::consumeCombinator() |
248 { | 324 { |
249 CSSSelector::Relation fallbackResult = CSSSelector::SubSelector; | 325 CSSSelector::Relation fallbackResult = CSSSelector::SubSelector; |
250 while (m_tokenRange.peek().type() == WhitespaceToken || m_tokenRange.peek().
type() == CommentToken) { | 326 while (m_tokenRange.peek().type() == WhitespaceToken || m_tokenRange.peek().
type() == CommentToken) { |
251 if (m_tokenRange.consume().type() == WhitespaceToken) | 327 if (m_tokenRange.consume().type() == WhitespaceToken) |
252 fallbackResult = CSSSelector::Descendant; | 328 fallbackResult = CSSSelector::Descendant; |
253 } | 329 } |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 } | 486 } |
411 if (specifiers->isContentPseudoElement()) { | 487 if (specifiers->isContentPseudoElement()) { |
412 specifiers->insertTagHistory(CSSSelector::SubSelector, newSpecifier, CSS
Selector::SubSelector); | 488 specifiers->insertTagHistory(CSSSelector::SubSelector, newSpecifier, CSS
Selector::SubSelector); |
413 return specifiers; | 489 return specifiers; |
414 } | 490 } |
415 specifiers->appendTagHistory(CSSSelector::SubSelector, newSpecifier); | 491 specifiers->appendTagHistory(CSSSelector::SubSelector, newSpecifier); |
416 return specifiers; | 492 return specifiers; |
417 } | 493 } |
418 | 494 |
419 } // namespace blink | 495 } // namespace blink |
OLD | NEW |