Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(204)

Side by Side Diff: third_party/WebKit/Source/core/css/parser/CSSSelectorParser.cpp

Issue 1523843004: Add support for new CSS ::slotted() pseudo element (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: tentative fix for crash / querySelector test Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "core/css/parser/CSSSelectorParser.h" 5 #include "core/css/parser/CSSSelectorParser.h"
6 6
7 #include "core/css/CSSSelectorList.h" 7 #include "core/css/CSSSelectorList.h"
8 #include "core/css/StyleSheetContents.h" 8 #include "core/css/StyleSheetContents.h"
9 #include "core/frame/UseCounter.h" 9 #include "core/frame/UseCounter.h"
10 #include "platform/RuntimeEnabledFeatures.h" 10 #include "platform/RuntimeEnabledFeatures.h"
11 11
12 namespace blink { 12 namespace blink {
13 13
14 static void recordSelectorStats(const CSSParserContext& context, const CSSSelect orList& selectorList) 14 static void recordSelectorStats(const CSSParserContext& context, const CSSSelect orList& selectorList)
15 { 15 {
16 if (!context.useCounter()) 16 if (!context.useCounter())
17 return; 17 return;
18 18
19 for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(*selector)) { 19 for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(*selector)) {
20 for (const CSSSelector* current = selector; current ; current = current- >tagHistory()) { 20 for (const CSSSelector* current = selector; current ; current = current- >tagHistory()) {
21 UseCounter::Feature feature = UseCounter::NumberOfFeatures; 21 UseCounter::Feature feature = UseCounter::NumberOfFeatures;
22 switch (current->pseudoType()) { 22 switch (current->pseudoType()) {
23 case CSSSelector::PseudoUnresolved: 23 case CSSSelector::PseudoUnresolved:
24 feature = UseCounter::CSSSelectorPseudoUnresolved; 24 feature = UseCounter::CSSSelectorPseudoUnresolved;
25 break; 25 break;
26 case CSSSelector::PseudoSlotted:
27 feature = UseCounter::CSSSelectorPseudoSlotted;
28 break;
26 case CSSSelector::PseudoContent: 29 case CSSSelector::PseudoContent:
27 feature = UseCounter::CSSSelectorPseudoContent; 30 feature = UseCounter::CSSSelectorPseudoContent;
28 break; 31 break;
29 case CSSSelector::PseudoHost: 32 case CSSSelector::PseudoHost:
30 feature = UseCounter::CSSSelectorPseudoHost; 33 feature = UseCounter::CSSSelectorPseudoHost;
31 break; 34 break;
32 case CSSSelector::PseudoHostContext: 35 case CSSSelector::PseudoHostContext:
33 feature = UseCounter::CSSSelectorPseudoHostContext; 36 feature = UseCounter::CSSSelectorPseudoHostContext;
34 break; 37 break;
35 case CSSSelector::PseudoFullScreenAncestor: 38 case CSSSelector::PseudoFullScreenAncestor:
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 { 366 {
364 OwnPtr<CSSParserSelector> innerSelector = consumeCompoundSelector(bl ock); 367 OwnPtr<CSSParserSelector> innerSelector = consumeCompoundSelector(bl ock);
365 block.consumeWhitespace(); 368 block.consumeWhitespace();
366 if (!innerSelector || !innerSelector->isSimple() || !block.atEnd()) 369 if (!innerSelector || !innerSelector->isSimple() || !block.atEnd())
367 return nullptr; 370 return nullptr;
368 Vector<OwnPtr<CSSParserSelector>> selectorVector; 371 Vector<OwnPtr<CSSParserSelector>> selectorVector;
369 selectorVector.append(innerSelector.release()); 372 selectorVector.append(innerSelector.release());
370 selector->adoptSelectorVector(selectorVector); 373 selector->adoptSelectorVector(selectorVector);
371 return selector.release(); 374 return selector.release();
372 } 375 }
376 case CSSSelector::PseudoSlotted:
377 {
378 OwnPtr<CSSParserSelector> innerSelector = consumeCompoundSelector(bl ock);
379 block.consumeWhitespace();
380 if (!innerSelector || !block.atEnd())
381 return nullptr;
382 Vector<OwnPtr<CSSParserSelector>> selectorVector;
383 selectorVector.append(innerSelector.release());
384 selector->adoptSelectorVector(selectorVector);
385 selector->setRelationIsAffectedByPseudoSlotted();
386 return selector.release();
387 }
373 case CSSSelector::PseudoLang: 388 case CSSSelector::PseudoLang:
374 { 389 {
375 // FIXME: CSS Selectors Level 4 allows :lang(*-foo) 390 // FIXME: CSS Selectors Level 4 allows :lang(*-foo)
376 const CSSParserToken& ident = block.consumeIncludingWhitespace(); 391 const CSSParserToken& ident = block.consumeIncludingWhitespace();
377 if (ident.type() != IdentToken || !block.atEnd()) 392 if (ident.type() != IdentToken || !block.atEnd())
378 return nullptr; 393 return nullptr;
379 selector->setArgument(ident.value()); 394 selector->setArgument(ident.value());
380 return selector.release(); 395 return selector.release();
381 } 396 }
382 case CSSSelector::PseudoNthChild: 397 case CSSSelector::PseudoNthChild:
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
556 571
557 const AtomicString& CSSSelectorParser::determineNamespace(const AtomicString& pr efix) 572 const AtomicString& CSSSelectorParser::determineNamespace(const AtomicString& pr efix)
558 { 573 {
559 if (!m_styleSheet) 574 if (!m_styleSheet)
560 return defaultNamespace(); 575 return defaultNamespace();
561 return m_styleSheet->determineNamespace(prefix); 576 return m_styleSheet->determineNamespace(prefix);
562 } 577 }
563 578
564 void CSSSelectorParser::prependTypeSelectorIfNeeded(const AtomicString& namespac ePrefix, const AtomicString& elementName, CSSParserSelector* compoundSelector) 579 void CSSSelectorParser::prependTypeSelectorIfNeeded(const AtomicString& namespac ePrefix, const AtomicString& elementName, CSSParserSelector* compoundSelector)
565 { 580 {
566 if (elementName.isNull() && defaultNamespace() == starAtom && !compoundSelec tor->crossesTreeScopes()) 581 if (elementName.isNull() && defaultNamespace() == starAtom && !compoundSelec tor->crossesTreeScopes() && !compoundSelector->relationIsAffectedByPseudoSlotted ())
567 return; 582 return;
568 583
569 AtomicString determinedElementName = elementName.isNull() ? starAtom : eleme ntName; 584 AtomicString determinedElementName = elementName.isNull() ? starAtom : eleme ntName;
570 AtomicString namespaceURI = determineNamespace(namespacePrefix); 585 AtomicString namespaceURI = determineNamespace(namespacePrefix);
571 if (namespaceURI.isNull()) 586 if (namespaceURI.isNull())
572 return; 587 return;
573 QualifiedName tag = QualifiedName(namespacePrefix, determinedElementName, na mespaceURI); 588 QualifiedName tag = QualifiedName(namespacePrefix, determinedElementName, na mespaceURI);
574 589
575 if (compoundSelector->crossesTreeScopes()) 590 if (compoundSelector->crossesTreeScopes())
576 return rewriteSpecifiersWithElementNameForCustomPseudoElement(tag, compo undSelector, elementName.isNull()); 591 return rewriteSpecifiersWithElementNameForCustomPseudoElement(tag, compo undSelector, elementName.isNull());
577 592
578 if (compoundSelector->pseudoType() == CSSSelector::PseudoContent) 593 if (compoundSelector->pseudoType() == CSSSelector::PseudoContent || compound Selector->pseudoType() == CSSSelector::PseudoSlotted)
579 return rewriteSpecifiersWithElementNameForContentPseudoElement(tag, comp oundSelector, elementName.isNull()); 594 return rewriteSpecifiersWithElementNameForContentOrSlottedPseudoElement( tag, compoundSelector, elementName.isNull());
580 595
581 // *:host never matches, so we can't discard the * otherwise we can't tell t he 596 // *:host never matches, so we can't discard the * otherwise we can't tell t he
582 // difference between *:host and just :host. 597 // difference between *:host and just :host.
583 if (tag == anyQName() && !compoundSelector->hasHostPseudoSelector()) 598 if (tag == anyQName() && !compoundSelector->hasHostPseudoSelector())
584 return; 599 return;
585 compoundSelector->prependTagSelector(tag, elementName.isNull()); 600 compoundSelector->prependTagSelector(tag, elementName.isNull());
586 } 601 }
587 602
588 void CSSSelectorParser::rewriteSpecifiersWithElementNameForCustomPseudoElement(c onst QualifiedName& tag, CSSParserSelector* specifiers, bool tagIsImplicit) 603 void CSSSelectorParser::rewriteSpecifiersWithElementNameForCustomPseudoElement(c onst QualifiedName& tag, CSSParserSelector* specifiers, bool tagIsImplicit)
589 { 604 {
(...skipping 11 matching lines...) Expand all
601 return; 616 return;
602 } 617 }
603 618
604 // For shadow-ID pseudo-elements to be correctly matched, the ShadowPseudo c ombinator has to be used. 619 // For shadow-ID pseudo-elements to be correctly matched, the ShadowPseudo c ombinator has to be used.
605 // We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*'). 620 // We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*').
606 OwnPtr<CSSParserSelector> elementNameSelector = CSSParserSelector::create(ta g); 621 OwnPtr<CSSParserSelector> elementNameSelector = CSSParserSelector::create(ta g);
607 lastShadowPseudo->setTagHistory(elementNameSelector.release()); 622 lastShadowPseudo->setTagHistory(elementNameSelector.release());
608 lastShadowPseudo->setRelation(CSSSelector::ShadowPseudo); 623 lastShadowPseudo->setRelation(CSSSelector::ShadowPseudo);
609 } 624 }
610 625
611 void CSSSelectorParser::rewriteSpecifiersWithElementNameForContentPseudoElement( const QualifiedName& tag, CSSParserSelector* specifiers, bool tagIsImplicit) 626 void CSSSelectorParser::rewriteSpecifiersWithElementNameForContentOrSlottedPseud oElement(const QualifiedName& tag, CSSParserSelector* specifiers, bool tagIsImpl icit)
612 { 627 {
613 CSSParserSelector* last = specifiers; 628 CSSParserSelector* last = specifiers;
614 CSSParserSelector* history = specifiers; 629 CSSParserSelector* history = specifiers;
615 while (history->tagHistory()) { 630 while (history->tagHistory()) {
616 history = history->tagHistory(); 631 history = history->tagHistory();
617 if (history->pseudoType() == CSSSelector::PseudoContent || history->rela tionIsAffectedByPseudoContent()) 632 if (history->pseudoType() == CSSSelector::PseudoContent || history->rela tionIsAffectedByPseudoContent()
633 || history->pseudoType() == CSSSelector::PseudoSlotted || history->r elationIsAffectedByPseudoSlotted())
618 last = history; 634 last = history;
619 } 635 }
620 636
621 if (last->tagHistory()) { 637 if (last->tagHistory()) {
622 if (tag != anyQName()) 638 if (tag != anyQName())
623 last->tagHistory()->prependTagSelector(tag, tagIsImplicit); 639 last->tagHistory()->prependTagSelector(tag, tagIsImplicit);
624 return; 640 return;
625 } 641 }
626 642
627 // For shadow-ID pseudo-elements to be correctly matched, the ShadowPseudo c ombinator has to be used.
628 // We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*').
629 OwnPtr<CSSParserSelector> elementNameSelector = CSSParserSelector::create(ta g); 643 OwnPtr<CSSParserSelector> elementNameSelector = CSSParserSelector::create(ta g);
630 last->setTagHistory(elementNameSelector.release()); 644 last->setTagHistory(elementNameSelector.release());
645 if (last->pseudoType() == CSSSelector::PseudoSlotted)
646 last->setRelation(CSSSelector::ShadowSlot);
631 } 647 }
632 648
633 PassOwnPtr<CSSParserSelector> CSSSelectorParser::addSimpleSelectorToCompound(Pas sOwnPtr<CSSParserSelector> compoundSelector, PassOwnPtr<CSSParserSelector> simpl eSelector) 649 PassOwnPtr<CSSParserSelector> CSSSelectorParser::addSimpleSelectorToCompound(Pas sOwnPtr<CSSParserSelector> compoundSelector, PassOwnPtr<CSSParserSelector> simpl eSelector)
634 { 650 {
635 // The tagHistory is a linked list that stores combinator separated compound selectors 651 // The tagHistory is a linked list that stores combinator separated compound selectors
636 // from right-to-left. Yet, within a single compound selector, stores the si mple selectors 652 // from right-to-left. Yet, within a single compound selector, stores the si mple selectors
637 // from left-to-right. 653 // from left-to-right.
638 // 654 //
639 // ".a.b > div#id" is stored in a tagHistory as [div, #id, .a, .b], each ele ment in the 655 // ".a.b > div#id" is stored in a tagHistory as [div, #id, .a, .b], each ele ment in the
640 // list stored with an associated relation (combinator or SubSelector). 656 // list stored with an associated relation (combinator or SubSelector).
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
674 compoundSelector->insertTagHistory(CSSSelector::SubSelector, simpleSelec tor, relation); 690 compoundSelector->insertTagHistory(CSSSelector::SubSelector, simpleSelec tor, relation);
675 return compoundSelector; 691 return compoundSelector;
676 } 692 }
677 693
678 // All other simple selectors are added to the end of the compound. 694 // All other simple selectors are added to the end of the compound.
679 compoundSelector->appendTagHistory(CSSSelector::SubSelector, simpleSelector) ; 695 compoundSelector->appendTagHistory(CSSSelector::SubSelector, simpleSelector) ;
680 return compoundSelector; 696 return compoundSelector;
681 } 697 }
682 698
683 } // namespace blink 699 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698