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 "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 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
464 { | 467 { |
465 OwnPtr<CSSParserSelector> innerSelector = consumeCompoundSelector(bl ock); | 468 OwnPtr<CSSParserSelector> innerSelector = consumeCompoundSelector(bl ock); |
466 block.consumeWhitespace(); | 469 block.consumeWhitespace(); |
467 if (!innerSelector || !innerSelector->isSimple() || !block.atEnd()) | 470 if (!innerSelector || !innerSelector->isSimple() || !block.atEnd()) |
468 return nullptr; | 471 return nullptr; |
469 Vector<OwnPtr<CSSParserSelector>> selectorVector; | 472 Vector<OwnPtr<CSSParserSelector>> selectorVector; |
470 selectorVector.append(innerSelector.release()); | 473 selectorVector.append(innerSelector.release()); |
471 selector->adoptSelectorVector(selectorVector); | 474 selector->adoptSelectorVector(selectorVector); |
472 return selector.release(); | 475 return selector.release(); |
473 } | 476 } |
477 case CSSSelector::PseudoSlotted: | |
478 { | |
479 DisallowPseudoElementsScope scope(this); | |
480 | |
481 OwnPtr<CSSParserSelector> innerSelector = consumeCompoundSelector(bl ock); | |
482 block.consumeWhitespace(); | |
483 if (!innerSelector || !block.atEnd() || !RuntimeEnabledFeatures::sha dowDOMV1Enabled()) | |
484 return nullptr; | |
485 Vector<OwnPtr<CSSParserSelector>> selectorVector; | |
486 selectorVector.append(innerSelector.release()); | |
487 selector->adoptSelectorVector(selectorVector); | |
488 return selector.release(); | |
489 } | |
474 case CSSSelector::PseudoLang: | 490 case CSSSelector::PseudoLang: |
475 { | 491 { |
476 // FIXME: CSS Selectors Level 4 allows :lang(*-foo) | 492 // FIXME: CSS Selectors Level 4 allows :lang(*-foo) |
477 const CSSParserToken& ident = block.consumeIncludingWhitespace(); | 493 const CSSParserToken& ident = block.consumeIncludingWhitespace(); |
478 if (ident.type() != IdentToken || !block.atEnd()) | 494 if (ident.type() != IdentToken || !block.atEnd()) |
479 return nullptr; | 495 return nullptr; |
480 selector->setArgument(ident.value()); | 496 selector->setArgument(ident.value()); |
481 return selector.release(); | 497 return selector.release(); |
482 } | 498 } |
483 case CSSSelector::PseudoNthChild: | 499 case CSSSelector::PseudoNthChild: |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
657 | 673 |
658 const AtomicString& CSSSelectorParser::determineNamespace(const AtomicString& pr efix) | 674 const AtomicString& CSSSelectorParser::determineNamespace(const AtomicString& pr efix) |
659 { | 675 { |
660 if (!m_styleSheet) | 676 if (!m_styleSheet) |
661 return defaultNamespace(); | 677 return defaultNamespace(); |
662 return m_styleSheet->determineNamespace(prefix); | 678 return m_styleSheet->determineNamespace(prefix); |
663 } | 679 } |
664 | 680 |
665 void CSSSelectorParser::prependTypeSelectorIfNeeded(const AtomicString& namespac ePrefix, const AtomicString& elementName, CSSParserSelector* compoundSelector) | 681 void CSSSelectorParser::prependTypeSelectorIfNeeded(const AtomicString& namespac ePrefix, const AtomicString& elementName, CSSParserSelector* compoundSelector) |
666 { | 682 { |
667 if (elementName.isNull() && defaultNamespace() == starAtom && !compoundSelec tor->needsImplicitShadowCrossingCombinatorForMatching()) | 683 if (elementName.isNull() && defaultNamespace() == starAtom && !compoundSelec tor->needsImplicitShadowCrossingCombinatorForMatching() && compoundSelector->pse udoType() != CSSSelector::PseudoSlotted) |
668 return; | 684 return; |
669 | 685 |
670 AtomicString determinedElementName = elementName.isNull() ? starAtom : eleme ntName; | 686 AtomicString determinedElementName = elementName.isNull() ? starAtom : eleme ntName; |
671 AtomicString namespaceURI = determineNamespace(namespacePrefix); | 687 AtomicString namespaceURI = determineNamespace(namespacePrefix); |
672 if (namespaceURI.isNull()) { | 688 if (namespaceURI.isNull()) { |
673 m_failedParsing = true; | 689 m_failedParsing = true; |
674 return; | 690 return; |
675 } | 691 } |
676 QualifiedName tag = QualifiedName(namespacePrefix, determinedElementName, na mespaceURI); | 692 QualifiedName tag = QualifiedName(namespacePrefix, determinedElementName, na mespaceURI); |
677 | 693 |
678 // *:host/*:host-context never matches, so we can't discard the *, | 694 // *:host/*:host-context never matches, so we can't discard the *, |
679 // otherwise we can't tell the difference between *:host and just :host. | 695 // otherwise we can't tell the difference between *:host and just :host. |
680 // | 696 // |
681 // Also, selectors where we use a ShadowPseudo combinator between the | 697 // Also, selectors where we use a ShadowPseudo combinator between the |
682 // element and the pseudo element for matching (custom pseudo elements, | 698 // element and the pseudo element for matching (custom pseudo elements, |
683 // ::cue, ::shadow), we need a universal selector to set the combinator | 699 // ::cue, ::shadow), we need a universal selector to set the combinator |
684 // (relation) on in the cases where there are no simple selectors preceding | 700 // (relation) on in the cases where there are no simple selectors preceding |
685 // the pseudo element. | 701 // the pseudo element. |
686 if (tag != anyQName() || compoundSelector->isHostPseudoSelector() || compoun dSelector->needsImplicitShadowCrossingCombinatorForMatching()) | 702 if (tag != anyQName() || compoundSelector->isHostPseudoSelector() || compoun dSelector->needsImplicitShadowCrossingCombinatorForMatching() || compoundSelecto r->pseudoType() == CSSSelector::PseudoSlotted) |
687 compoundSelector->prependTagSelector(tag, elementName.isNull()); | 703 compoundSelector->prependTagSelector(tag, elementName.isNull()); |
688 } | 704 } |
689 | 705 |
690 PassOwnPtr<CSSParserSelector> CSSSelectorParser::addSimpleSelectorToCompound(Pas sOwnPtr<CSSParserSelector> compoundSelector, PassOwnPtr<CSSParserSelector> simpl eSelector) | 706 PassOwnPtr<CSSParserSelector> CSSSelectorParser::addSimpleSelectorToCompound(Pas sOwnPtr<CSSParserSelector> compoundSelector, PassOwnPtr<CSSParserSelector> simpl eSelector) |
691 { | 707 { |
692 compoundSelector->appendTagHistory(CSSSelector::SubSelector, simpleSelector) ; | 708 compoundSelector->appendTagHistory(CSSSelector::SubSelector, simpleSelector) ; |
693 return compoundSelector; | 709 return compoundSelector; |
694 } | 710 } |
695 | 711 |
696 PassOwnPtr<CSSParserSelector> CSSSelectorParser::splitCompoundAtImplicitShadowCr ossingCombinator(PassOwnPtr<CSSParserSelector> compoundSelector) | 712 PassOwnPtr<CSSParserSelector> CSSSelectorParser::splitCompoundAtImplicitShadowCr ossingCombinator(PassOwnPtr<CSSParserSelector> compoundSelector) |
697 { | 713 { |
698 // The tagHistory is a linked list that stores combinator separated compound selectors | 714 // The tagHistory is a linked list that stores combinator separated compound selectors |
699 // from right-to-left. Yet, within a single compound selector, stores the si mple selectors | 715 // from right-to-left. Yet, within a single compound selector, stores the si mple selectors |
700 // from left-to-right. | 716 // from left-to-right. |
701 // | 717 // |
702 // ".a.b > div#id" is stored in a tagHistory as [div, #id, .a, .b], each ele ment in the | 718 // ".a.b > div#id" is stored in a tagHistory as [div, #id, .a, .b], each ele ment in the |
703 // list stored with an associated relation (combinator or SubSelector). | 719 // list stored with an associated relation (combinator or SubSelector). |
704 // | 720 // |
705 // ::cue, ::shadow, and custom pseudo elements have an implicit ShadowPseudo combinator | 721 // ::cue, ::shadow, and custom pseudo elements have an implicit ShadowPseudo combinator |
706 // to their left, which really makes for a new compound selector, yet it's c onsumed by | 722 // to their left, which really makes for a new compound selector, yet it's c onsumed by |
707 // the selector parser as a single compound selector. | 723 // the selector parser as a single compound selector. |
708 // | 724 // |
709 // Example: input#x::-webkit-clear-button -> [ ::-webkit-clear-button, input , #x ] | 725 // Example: input#x::-webkit-clear-button -> [ ::-webkit-clear-button, input , #x ] |
710 | 726 // |
727 // Likewise, ::slotted() pseudo element has an implicit ShadowSlot combinato r to its left | |
728 // for finding matching slot element in other TreeScope. | |
729 // | |
730 // Example: slot[name=foo]::slotted(div) -> [ ::slotted(div), slot, [name=fo o] ] | |
711 CSSParserSelector* splitAfter = compoundSelector.get(); | 731 CSSParserSelector* splitAfter = compoundSelector.get(); |
712 | 732 |
713 while (splitAfter->tagHistory() && !splitAfter->tagHistory()->needsImplicitS hadowCrossingCombinatorForMatching()) | 733 while (splitAfter->tagHistory() && !splitAfter->tagHistory()->needsImplicitS hadowCrossingCombinatorForMatching() && splitAfter->tagHistory()->pseudoType() ! = CSSSelector::PseudoSlotted) |
rune
2016/01/19 09:16:09
You may move the PseudoSlotted into needsImplicitS
kochi
2016/01/19 11:09:12
Done.
| |
714 splitAfter = splitAfter->tagHistory(); | 734 splitAfter = splitAfter->tagHistory(); |
715 | 735 |
716 if (!splitAfter || !splitAfter->tagHistory()) | 736 if (!splitAfter || !splitAfter->tagHistory()) |
717 return compoundSelector; | 737 return compoundSelector; |
718 | 738 |
719 OwnPtr<CSSParserSelector> secondCompound = splitAfter->releaseTagHistory(); | 739 OwnPtr<CSSParserSelector> secondCompound = splitAfter->releaseTagHistory(); |
720 secondCompound->appendTagHistory(CSSSelector::ShadowPseudo, compoundSelector ); | 740 secondCompound->appendTagHistory(secondCompound->pseudoType() == CSSSelector ::PseudoSlotted ? CSSSelector::ShadowSlot : CSSSelector::ShadowPseudo, compoundS elector); |
721 return secondCompound.release(); | 741 return secondCompound.release(); |
722 } | 742 } |
723 | 743 |
724 } // namespace blink | 744 } // namespace blink |
OLD | NEW |