Changeset 207854 in webkit
- Timestamp:
- Oct 25, 2016 4:21:03 PM (7 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r207853 r207854 1 2016-10-25 Dave Hyatt <hyatt@apple.com> 2 3 [CSS Parser] Improvements to selector parsing 4 https://bugs.webkit.org/show_bug.cgi?id=163964 5 6 Reviewed by Zalan Bujtas. 7 8 * css/CSSSelector.cpp: 9 (WebCore::CSSSelector::setAttribute): 10 (WebCore::CSSSelector::setNth): 11 * css/CSSSelector.h: 12 (WebCore::CSSSelector::setAttributeValueMatchingIsCaseInsensitive): 13 * css/StyleSheetContents.cpp: 14 (WebCore::StyleSheetContents::StyleSheetContents): 15 (WebCore::StyleSheetContents::parserAppendRule): 16 (WebCore::StyleSheetContents::ruleAt): 17 (WebCore::StyleSheetContents::ruleCount): 18 (WebCore::StyleSheetContents::clearRules): 19 (WebCore::StyleSheetContents::wrapperInsertRule): 20 (WebCore::StyleSheetContents::wrapperDeleteRule): 21 * css/StyleSheetContents.h: 22 * css/parser/CSSParser.cpp: 23 (WebCore::CSSParserContext::CSSParserContext): 24 (WebCore::CSSParser::parseSelector): 25 * css/parser/CSSParserValues.h: 26 (WebCore::CSSParserSelector::setAttribute): 27 (WebCore::CSSParserSelector::setArgument): 28 (WebCore::CSSParserSelector::setNth): 29 * css/parser/CSSSelectorParser.cpp: 30 (WebCore::consumeLangArgumentList): 31 (WebCore::CSSSelectorParser::consumeCompoundSelector): 32 (WebCore::CSSSelectorParser::consumeAttribute): 33 (WebCore::isPseudoClassFunction): 34 (WebCore::isPseudoElementFunction): 35 (WebCore::CSSSelectorParser::consumePseudo): 36 (WebCore::CSSSelectorParser::consumeCombinator): 37 1 38 2016-10-25 Beth Dakin <bdakin@apple.com> 2 39 -
trunk/Source/WebCore/css/CSSSelector.cpp
r207536 r207854 764 764 } 765 765 766 void CSSSelector::setAttribute(const QualifiedName& value, bool convertToLowercase, AttributeMatchType matchType) 767 { 768 createRareData(); 769 m_data.m_rareData->m_attribute = value; 770 m_data.m_rareData->m_attributeCanonicalLocalName = convertToLowercase ? value.localName().convertToASCIILowercase() : value.localName(); 771 m_caseInsensitiveAttributeValueMatching = matchType == CaseInsensitive; 772 } 773 766 774 void CSSSelector::setArgument(const AtomicString& value) 767 775 { … … 782 790 } 783 791 792 void CSSSelector::setNth(int a, int b) 793 { 794 createRareData(); 795 m_parsedNth = true; // FIXME-NEWPARSER: Can remove this parsed boolean once old parser is gone. 796 m_data.m_rareData->m_a = a; 797 m_data.m_rareData->m_b = b; 798 } 799 800 // FIXME-NEWPARSER: All the code to parse nth-child stuff can be removed when 801 // the new parser is enabled. 784 802 bool CSSSelector::parseNth() const 785 803 { -
trunk/Source/WebCore/css/CSSSelector.h
r207536 r207854 245 245 246 246 void setValue(const AtomicString&); 247 void setAttribute(const QualifiedName&, bool isCaseInsensitive); 247 248 // FIXME-NEWPARSER: These two methods can go away once the old parser is gone. 249 void setAttribute(const QualifiedName&, bool); 250 void setAttributeValueMatchingIsCaseInsensitive(bool); 251 void setAttribute(const QualifiedName&, bool convertToLowercase, AttributeMatchType); 252 void setNth(int a, int b); 248 253 void setArgument(const AtomicString&); 249 void setAttributeValueMatchingIsCaseInsensitive(bool);250 254 void setLangArgumentList(std::unique_ptr<Vector<AtomicString>>); 251 255 void setSelectorList(std::unique_ptr<CSSSelectorList>); … … 586 590 m_caseInsensitiveAttributeValueMatching = isCaseInsensitive; 587 591 } 588 592 589 593 inline bool CSSSelector::attributeValueMatchingIsCaseInsensitive() const 590 594 { -
trunk/Source/WebCore/css/StyleSheetContents.cpp
r207767 r207854 81 81 , m_encodingFromCharsetRule(o.m_encodingFromCharsetRule) 82 82 , m_importRules(o.m_importRules.size()) 83 , m_namespaceRules(o.m_namespaceRules.size()) 83 84 , m_childRules(o.m_childRules.size()) 84 85 , m_namespaces(o.m_namespaces) … … 143 144 } 144 145 146 if (is<StyleRuleNamespace>(rule)) { 147 // Parser enforces that @namespace rules come before all rules other than 148 // import/charset rules 149 ASSERT(m_childRules.isEmpty()); 150 StyleRuleNamespace& namespaceRule = downcast<StyleRuleNamespace>(rule.get()); 151 parserAddNamespace(namespaceRule.prefix(), namespaceRule.uri()); 152 m_namespaceRules.append(downcast<StyleRuleNamespace>(rule.ptr())); 153 return; 154 } 155 145 156 if (is<StyleRuleMedia>(rule)) 146 157 reportMediaQueryWarningIfNeeded(singleOwnerDocument(), downcast<StyleRuleMedia>(rule.get()).mediaQueries()); … … 165 176 166 177 childVectorIndex -= m_importRules.size(); 178 179 if (childVectorIndex < m_namespaceRules.size()) 180 return m_namespaceRules[childVectorIndex].get(); 181 182 childVectorIndex -= m_namespaceRules.size(); 183 167 184 return m_childRules[childVectorIndex].get(); 168 185 } … … 172 189 unsigned result = 0; 173 190 result += m_importRules.size(); 191 result += m_namespaceRules.size(); 174 192 result += m_childRules.size(); 175 193 return result; … … 188 206 } 189 207 m_importRules.clear(); 208 m_namespaceRules.clear(); 190 209 m_childRules.clear(); 191 210 clearCharsetRule(); … … 222 241 childVectorIndex -= m_importRules.size(); 223 242 243 244 if (childVectorIndex < m_namespaceRules.size() || (childVectorIndex == m_namespaceRules.size() && rule->isNamespaceRule())) { 245 // Inserting non-namespace rules other than import rule before @namespace is 246 // not allowed. 247 if (!is<StyleRuleNamespace>(rule)) 248 return false; 249 // Inserting @namespace rule when rules other than import/namespace/charset 250 // are present is not allowed. 251 if (!m_childRules.isEmpty()) 252 return false; 253 254 StyleRuleNamespace& namespaceRule = downcast<StyleRuleNamespace>(rule.get()); 255 m_namespaceRules.insert(index, downcast<StyleRuleNamespace>(rule.ptr())); 256 257 // For now to be compatible with IE and Firefox if a namespace rule with the same 258 // prefix is added, it overwrites previous ones. 259 // FIXME: The eventual correct behavior would be to ensure that the last value in 260 // the list wins. 261 parserAddNamespace(namespaceRule.prefix(), namespaceRule.uri()); 262 return true; 263 } 264 if (is<StyleRuleNamespace>(rule)) 265 return false; 266 childVectorIndex -= m_namespaceRules.size(); 267 224 268 // If the number of selectors would overflow RuleData, we drop the operation. 225 269 if (is<StyleRule>(rule) && downcast<StyleRule>(rule.get()).selectorList().componentCount() > RuleData::maximumSelectorComponentCount) … … 242 286 } 243 287 childVectorIndex -= m_importRules.size(); 288 289 if (childVectorIndex < m_namespaceRules.size()) { 290 if (!m_childRules.isEmpty()) 291 return; 292 m_namespaceRules.remove(childVectorIndex); 293 return; 294 } 295 childVectorIndex -= m_namespaceRules.size(); 244 296 245 297 m_childRules.remove(childVectorIndex); -
trunk/Source/WebCore/css/StyleSheetContents.h
r207767 r207854 42 42 class StyleRuleBase; 43 43 class StyleRuleImport; 44 class StyleRuleNamespace; 44 45 45 46 class StyleSheetContents final : public RefCounted<StyleSheetContents> { … … 105 106 const Vector<RefPtr<StyleRuleBase>>& childRules() const { return m_childRules; } 106 107 const Vector<RefPtr<StyleRuleImport>>& importRules() const { return m_importRules; } 108 const Vector<RefPtr<StyleRuleNamespace>>& namespaceRules() const { return m_namespaceRules; } 107 109 108 110 void notifyLoadedSheet(const CachedCSSStyleSheet*); … … 155 157 String m_encodingFromCharsetRule; 156 158 Vector<RefPtr<StyleRuleImport>> m_importRules; 159 Vector<RefPtr<StyleRuleNamespace>> m_namespaceRules; 157 160 Vector<RefPtr<StyleRuleBase>> m_childRules; 158 161 typedef HashMap<AtomicString, AtomicString> PrefixNamespaceURIMap; -
trunk/Source/WebCore/css/parser/CSSParser.cpp
r207757 r207854 65 65 #include "CSSRevertValue.h" 66 66 #include "CSSSelector.h" 67 #include "CSSSelectorParser.h" 67 68 #include "CSSShadowValue.h" 68 69 #include "CSSStyleSheet.h" 69 70 #include "CSSTimingFunctionValue.h" 71 #include "CSSTokenizer.h" 70 72 #include "CSSUnicodeRangeValue.h" 71 73 #include "CSSUnsetValue.h" … … 1412 1414 void CSSParser::parseSelector(const String& string, CSSSelectorList& selectorList) 1413 1415 { 1416 if (m_context.useNewParser && m_context.mode != UASheetMode) { 1417 CSSTokenizer::Scope scope(string); 1418 selectorList = CSSSelectorParser::parseSelector(scope.tokenRange(), m_context, nullptr); 1419 return; 1420 } 1421 1414 1422 m_selectorListForParseSelector = &selectorList; 1415 1423 1416 1424 setupParser("@-webkit-selector{", string, "}"); 1417 1425 -
trunk/Source/WebCore/css/parser/CSSParserValues.cpp
r207790 r207854 411 411 m_selector->setLangArgumentList(WTFMove(argumentList)); 412 412 } 413 413 414 void CSSParserSelector::setLangArgumentList(std::unique_ptr<Vector<AtomicString>> argumentList) 415 { 416 ASSERT_WITH_MESSAGE(!argumentList->isEmpty(), "No CSS Selector takes an empty argument list."); 417 m_selector->setLangArgumentList(WTFMove(argumentList)); 418 } 419 414 420 void CSSParserSelector::setSelectorList(std::unique_ptr<CSSSelectorList> selectorList) 415 421 { -
trunk/Source/WebCore/css/parser/CSSParserValues.h
r207790 r207854 223 223 224 224 void setValue(const AtomicString& value) { m_selector->setValue(value); } 225 226 // FIXME-NEWPARSER: These two methods can go away once old parser is gone. 225 227 void setAttribute(const QualifiedName& value, bool isCaseInsensitive) { m_selector->setAttribute(value, isCaseInsensitive); } 228 void setAttributeValueMatchingIsCaseInsensitive(bool isCaseInsensitive) { m_selector->setAttributeValueMatchingIsCaseInsensitive(isCaseInsensitive); } 229 230 void setAttribute(const QualifiedName& value, bool convertToLowercase, CSSSelector::AttributeMatchType type) { m_selector->setAttribute(value, convertToLowercase, type); } 231 226 232 void setArgument(const AtomicString& value) { m_selector->setArgument(value); } 227 void set AttributeValueMatchingIsCaseInsensitive(bool isCaseInsensitive) { m_selector->setAttributeValueMatchingIsCaseInsensitive(isCaseInsensitive); }233 void setNth(int a, int b) { m_selector->setNth(a, b); } 228 234 void setMatch(CSSSelector::Match value) { m_selector->setMatch(value); } 229 235 void setRelation(CSSSelector::RelationType value) { m_selector->setRelation(value); } … … 236 242 void adoptSelectorVector(Vector<std::unique_ptr<CSSParserSelector>>& selectorVector); 237 243 void setLangArgumentList(const Vector<CSSParserString>& stringVector); 244 void setLangArgumentList(std::unique_ptr<Vector<AtomicString>>); 238 245 void setSelectorList(std::unique_ptr<CSSSelectorList>); 239 246 -
trunk/Source/WebCore/css/parser/CSSSelectorParser.cpp
r207790 r207854 101 101 } 102 102 103 static bool consumeLangArgumentList(std::unique_ptr<Vector<AtomicString>>& argumentList, CSSParserTokenRange& range) 104 { 105 const CSSParserToken& ident = range.consumeIncludingWhitespace(); 106 if (ident.type() != IdentToken && ident.type() != StringToken) 107 return false; 108 StringView string = ident.value(); 109 if (string.startsWith("--")) 110 return false; 111 argumentList->append(string.toAtomicString()); 112 while (!range.atEnd() && range.peek().type() == CommaToken) { 113 range.consumeIncludingWhitespace(); 114 const CSSParserToken& ident = range.consumeIncludingWhitespace(); 115 if (ident.type() != IdentToken && ident.type() != StringToken) 116 return false; 117 StringView string = ident.value(); 118 if (string.startsWith("--")) 119 return false; 120 argumentList->append(string.toAtomicString()); 121 } 122 return range.atEnd(); 123 } 124 103 125 namespace { 104 126 … … 258 280 compoundPseudoElement = compoundSelector->pseudoElementType(); 259 281 } 260 if (m_context.isHTMLDocument)261 elementName = elementName.convertToASCIILowercase();262 282 263 283 while (std::unique_ptr<CSSParserSelector> simpleSelector = consumeSimpleSelector(range)) { … … 401 421 block.consumeWhitespace(); 402 422 403 if (m_context.isHTMLDocument)404 attributeName = attributeName.convertToASCIILowercase();405 406 423 AtomicString namespaceURI = determineNamespace(namespacePrefix); 407 424 if (namespaceURI.isNull()) … … 415 432 416 433 if (block.atEnd()) { 417 selector->setAttribute(qualifiedName, CSSSelector::CaseSensitive);434 selector->setAttribute(qualifiedName, m_context.isHTMLDocument, CSSSelector::CaseSensitive); 418 435 selector->setMatch(CSSSelector::Set); 419 436 return selector; … … 426 443 return nullptr; 427 444 selector->setValue(attributeValue.value().toAtomicString()); 428 selector->setAttribute(qualifiedName, consumeAttributeFlags(block)); 445 446 selector->setAttribute(qualifiedName, m_context.isHTMLDocument, consumeAttributeFlags(block)); 429 447 430 448 if (!block.atEnd()) 431 449 return nullptr; 432 450 return selector; 451 } 452 453 static bool isPseudoClassFunction(CSSSelector::PseudoClassType pseudoClassType) 454 { 455 switch (pseudoClassType) { 456 case CSSSelector::PseudoClassNot: 457 case CSSSelector::PseudoClassMatches: 458 case CSSSelector::PseudoClassNthChild: 459 case CSSSelector::PseudoClassNthLastChild: 460 case CSSSelector::PseudoClassNthOfType: 461 case CSSSelector::PseudoClassNthLastOfType: 462 case CSSSelector::PseudoClassLang: 463 case CSSSelector::PseudoClassAny: 464 case CSSSelector::PseudoClassHost: 465 #if ENABLE_CSS_SELECTORS_LEVEL4 466 case CSSSelector::PseudoClassDir: 467 case CSSSelector::PseudoClassRole: 468 #endif 469 return true; 470 default: 471 break; 472 } 473 return false; 474 } 475 476 static bool isPseudoElementFunction(CSSSelector::PseudoElementType pseudoElementType) 477 { 478 switch (pseudoElementType) { 479 case CSSSelector::PseudoElementCue: 480 case CSSSelector::PseudoElementSlotted: 481 return true; 482 default: 483 break; 484 } 485 return false; 433 486 } 434 487 … … 460 513 if (token.type() == IdentToken) { 461 514 range.consume(); 462 if ((selector->match() == CSSSelector::PseudoElement && selector->pseudoElementType() == CSSSelector::PseudoElementUnknown) || (selector->match() == CSSSelector::PseudoClass && selector->pseudoClassType() == CSSSelector::PseudoClassUnknown)) 515 if ((selector->match() == CSSSelector::PseudoElement && (selector->pseudoElementType() == CSSSelector::PseudoElementUnknown || isPseudoElementFunction(selector->pseudoElementType()))) 516 || (selector->match() == CSSSelector::PseudoClass && (selector->pseudoClassType() == CSSSelector::PseudoClassUnknown || isPseudoClassFunction(selector->pseudoClassType())))) 463 517 return nullptr; 464 518 return selector; … … 470 524 return nullptr; 471 525 472 switch (selector->pseudoClassType()) { 473 case CSSSelector::PseudoClassNot: { 474 std::unique_ptr<CSSParserSelector> innerSelector = consumeCompoundSelector(block); 475 block.consumeWhitespace(); 476 if (!innerSelector || !block.atEnd()) 477 return nullptr; 478 Vector<std::unique_ptr<CSSParserSelector>> selectorVector; 479 selectorVector.append(WTFMove(innerSelector)); 480 selector->adoptSelectorVector(selectorVector); 481 return selector; 482 } 483 case CSSSelector::PseudoClassNthChild: 484 case CSSSelector::PseudoClassNthLastChild: 485 case CSSSelector::PseudoClassNthOfType: 486 case CSSSelector::PseudoClassNthLastOfType: { 487 std::pair<int, int> ab; 488 if (!consumeANPlusB(block, ab)) 489 return nullptr; 490 block.consumeWhitespace(); 491 if (!block.atEnd()) 492 return nullptr; 493 selector->setArgument(AtomicString::number(ab.first * ab.second)); 494 return selector; 495 } 496 case CSSSelector::PseudoClassLang: { 497 // FIXME: CSS Selectors Level 4 allows :lang(*-foo) 498 const CSSParserToken& ident = block.consumeIncludingWhitespace(); 499 if (ident.type() != IdentToken || !block.atEnd()) 500 return nullptr; 501 selector->setArgument(ident.value().toAtomicString()); 502 return selector; 503 } 504 // FIXME-NEWPARSER: Support :host-context 505 case CSSSelector::PseudoClassAny: 506 case CSSSelector::PseudoClassHost: { 507 DisallowPseudoElementsScope scope(this); 508 std::unique_ptr<CSSSelectorList> selectorList = std::unique_ptr<CSSSelectorList>(new CSSSelectorList()); 509 *selectorList = consumeCompoundSelectorList(block); 510 if (!selectorList->isValid() || !block.atEnd()) 511 return nullptr; 512 selector->setSelectorList(WTFMove(selectorList)); 513 return selector; 514 } 515 default: 516 break; 517 } 518 519 switch (selector->pseudoElementType()) { 520 case CSSSelector::PseudoElementCue: { 521 DisallowPseudoElementsScope scope(this); 522 std::unique_ptr<CSSSelectorList> selectorList = std::unique_ptr<CSSSelectorList>(new CSSSelectorList()); 523 *selectorList = consumeCompoundSelectorList(block); 524 if (!selectorList->isValid() || !block.atEnd()) 525 return nullptr; 526 selector->setSelectorList(WTFMove(selectorList)); 527 return selector; 528 } 529 case CSSSelector::PseudoElementSlotted: { 530 DisallowPseudoElementsScope scope(this); 531 532 std::unique_ptr<CSSParserSelector> innerSelector = consumeCompoundSelector(block); 533 block.consumeWhitespace(); 534 if (!innerSelector || !block.atEnd()) 535 return nullptr; 536 Vector<std::unique_ptr<CSSParserSelector>> selectorVector; 537 selectorVector.append(WTFMove(innerSelector)); 538 selector->adoptSelectorVector(selectorVector); 539 return selector; 540 } 541 default: 542 break; 526 if (selector->match() == CSSSelector::PseudoClass) { 527 switch (selector->pseudoClassType()) { 528 case CSSSelector::PseudoClassNot: { 529 DisallowPseudoElementsScope scope(this); 530 std::unique_ptr<CSSSelectorList> selectorList = std::unique_ptr<CSSSelectorList>(new CSSSelectorList()); 531 *selectorList = consumeComplexSelectorList(block); 532 if (!selectorList->componentCount() || !block.atEnd()) 533 return nullptr; 534 selector->setSelectorList(WTFMove(selectorList)); 535 return selector; 536 } 537 case CSSSelector::PseudoClassNthChild: 538 case CSSSelector::PseudoClassNthLastChild: 539 case CSSSelector::PseudoClassNthOfType: 540 case CSSSelector::PseudoClassNthLastOfType: { 541 std::pair<int, int> ab; 542 if (!consumeANPlusB(block, ab)) 543 return nullptr; 544 block.consumeWhitespace(); 545 if (!block.atEnd()) { 546 if (block.peek().type() != IdentToken) 547 return nullptr; 548 const CSSParserToken& ident = block.consume(); 549 if (!equalIgnoringASCIICase(ident.value(), "of")) 550 return nullptr; 551 DisallowPseudoElementsScope scope(this); 552 block.consumeWhitespace(); 553 std::unique_ptr<CSSSelectorList> selectorList = std::unique_ptr<CSSSelectorList>(new CSSSelectorList()); 554 *selectorList = consumeComplexSelectorList(block); 555 if (!selectorList->componentCount() || !block.atEnd()) 556 return nullptr; 557 selector->setSelectorList(WTFMove(selectorList)); 558 } 559 selector->setNth(ab.first, ab.second); 560 return selector; 561 } 562 case CSSSelector::PseudoClassLang: { 563 // FIXME: CSS Selectors Level 4 allows :lang(*-foo) 564 auto argumentList = std::make_unique<Vector<AtomicString>>(); 565 if (!consumeLangArgumentList(argumentList, block)) 566 return nullptr; 567 selector->setLangArgumentList(WTFMove(argumentList)); 568 return selector; 569 } 570 case CSSSelector::PseudoClassMatches: { 571 std::unique_ptr<CSSSelectorList> selectorList = std::unique_ptr<CSSSelectorList>(new CSSSelectorList()); 572 *selectorList = consumeComplexSelectorList(block); 573 if (!selectorList->componentCount() || !block.atEnd()) 574 return nullptr; 575 selector->setSelectorList(WTFMove(selectorList)); 576 return selector; 577 } 578 // FIXME-NEWPARSER: Support :host-context 579 case CSSSelector::PseudoClassAny: 580 case CSSSelector::PseudoClassHost: { 581 DisallowPseudoElementsScope scope(this); 582 std::unique_ptr<CSSSelectorList> selectorList = std::unique_ptr<CSSSelectorList>(new CSSSelectorList()); 583 *selectorList = consumeCompoundSelectorList(block); 584 if (!selectorList->componentCount() || !block.atEnd()) 585 return nullptr; 586 selector->setSelectorList(WTFMove(selectorList)); 587 return selector; 588 } 589 #if ENABLE_CSS_SELECTORS_LEVEL4 590 case CSSSelector::PseudoClassDir: 591 case CSSSelector::PseudoClassRole: { 592 const CSSParserToken& ident = block.consumeIncludingWhitespace(); 593 if (ident.type() != IdentToken) 594 return nullptr; 595 selector->setArgument(ident.value().toAtomicString()); 596 return selector; 597 } 598 #endif 599 default: 600 break; 601 } 602 603 } 604 605 if (selector->match() == CSSSelector::PseudoElement) { 606 switch (selector->pseudoElementType()) { 607 case CSSSelector::PseudoElementCue: { 608 DisallowPseudoElementsScope scope(this); 609 std::unique_ptr<CSSSelectorList> selectorList = std::unique_ptr<CSSSelectorList>(new CSSSelectorList()); 610 *selectorList = consumeCompoundSelectorList(block); 611 if (!selectorList->isValid() || !block.atEnd()) 612 return nullptr; 613 selector->setSelectorList(WTFMove(selectorList)); 614 return selector; 615 } 616 case CSSSelector::PseudoElementSlotted: { 617 DisallowPseudoElementsScope scope(this); 618 619 std::unique_ptr<CSSParserSelector> innerSelector = consumeCompoundSelector(block); 620 block.consumeWhitespace(); 621 if (!innerSelector || !block.atEnd()) 622 return nullptr; 623 Vector<std::unique_ptr<CSSParserSelector>> selectorVector; 624 selectorVector.append(WTFMove(innerSelector)); 625 selector->adoptSelectorVector(selectorVector); 626 return selector; 627 } 628 default: 629 break; 630 } 543 631 } 544 632 … … 565 653 if (delimiter == '~') 566 654 return CSSSelector::IndirectAdjacent; 655 #if ENABLE_CSS_SELECTORS_LEVEL4 656 // FIXME-NEWPARSER: Need to set that this was a >> so serialization is correct 657 if (delimiter == '>' && range.peek().type() == DelimiterToken && range.peek().delimiter() == '>') { 658 range.consumeIncludingWhitespace(); 659 return CSSSelector::Descendant; 660 } 661 #endif 567 662 return CSSSelector::Child; 568 663 }
Note: See TracChangeset
for help on using the changeset viewer.