| 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" |
| (...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 556 | 556 |
| 557 const AtomicString& CSSSelectorParser::determineNamespace(const AtomicString& pr
efix) | 557 const AtomicString& CSSSelectorParser::determineNamespace(const AtomicString& pr
efix) |
| 558 { | 558 { |
| 559 if (!m_styleSheet) | 559 if (!m_styleSheet) |
| 560 return defaultNamespace(); | 560 return defaultNamespace(); |
| 561 return m_styleSheet->determineNamespace(prefix); | 561 return m_styleSheet->determineNamespace(prefix); |
| 562 } | 562 } |
| 563 | 563 |
| 564 void CSSSelectorParser::prependTypeSelectorIfNeeded(const AtomicString& namespac
ePrefix, const AtomicString& elementName, CSSParserSelector* compoundSelector) | 564 void CSSSelectorParser::prependTypeSelectorIfNeeded(const AtomicString& namespac
ePrefix, const AtomicString& elementName, CSSParserSelector* compoundSelector) |
| 565 { | 565 { |
| 566 if (elementName.isNull() && defaultNamespace() == starAtom && !compoundSelec
tor->crossesTreeScopes()) | 566 if (elementName.isNull() && defaultNamespace() == starAtom && !compoundSelec
tor->needsImplicitShadowCrossingCombinatorForMatching()) |
| 567 return; | 567 return; |
| 568 | 568 |
| 569 AtomicString determinedElementName = elementName.isNull() ? starAtom : eleme
ntName; | 569 AtomicString determinedElementName = elementName.isNull() ? starAtom : eleme
ntName; |
| 570 AtomicString namespaceURI = determineNamespace(namespacePrefix); | 570 AtomicString namespaceURI = determineNamespace(namespacePrefix); |
| 571 if (namespaceURI.isNull()) | 571 if (namespaceURI.isNull()) |
| 572 return; | 572 return; |
| 573 QualifiedName tag = QualifiedName(namespacePrefix, determinedElementName, na
mespaceURI); | 573 QualifiedName tag = QualifiedName(namespacePrefix, determinedElementName, na
mespaceURI); |
| 574 | 574 |
| 575 if (compoundSelector->crossesTreeScopes()) | 575 if (compoundSelector->needsImplicitShadowCrossingCombinatorForMatching()) |
| 576 return rewriteSpecifiersWithElementNameForCustomPseudoElement(tag, compo
undSelector, elementName.isNull()); | 576 return rewriteSpecifiersWithElementNameForCustomPseudoElement(tag, compo
undSelector, elementName.isNull()); |
| 577 | 577 |
| 578 if (compoundSelector->pseudoType() == CSSSelector::PseudoContent) | 578 if (compoundSelector->pseudoType() == CSSSelector::PseudoContent) |
| 579 return rewriteSpecifiersWithElementNameForContentPseudoElement(tag, comp
oundSelector, elementName.isNull()); | 579 return rewriteSpecifiersWithElementNameForContentPseudoElement(tag, comp
oundSelector, elementName.isNull()); |
| 580 | 580 |
| 581 // *:host never matches, so we can't discard the * otherwise we can't tell t
he | 581 // *:host never matches, so we can't discard the * otherwise we can't tell t
he |
| 582 // difference between *:host and just :host. | 582 // difference between *:host and just :host. |
| 583 if (tag == anyQName() && !compoundSelector->hasHostPseudoSelector()) | 583 if (tag == anyQName() && !compoundSelector->hasHostPseudoSelector()) |
| 584 return; | 584 return; |
| 585 compoundSelector->prependTagSelector(tag, elementName.isNull()); | 585 compoundSelector->prependTagSelector(tag, elementName.isNull()); |
| 586 } | 586 } |
| 587 | 587 |
| 588 void CSSSelectorParser::rewriteSpecifiersWithElementNameForCustomPseudoElement(c
onst QualifiedName& tag, CSSParserSelector* specifiers, bool tagIsImplicit) | 588 void CSSSelectorParser::rewriteSpecifiersWithElementNameForCustomPseudoElement(c
onst QualifiedName& tag, CSSParserSelector* specifiers, bool tagIsImplicit) |
| 589 { | 589 { |
| 590 CSSParserSelector* lastShadowPseudo = specifiers; | 590 CSSParserSelector* lastShadowPseudo = specifiers; |
| 591 CSSParserSelector* history = specifiers; | 591 CSSParserSelector* history = specifiers; |
| 592 while (history->tagHistory()) { | 592 while (history->tagHistory()) { |
| 593 history = history->tagHistory(); | 593 history = history->tagHistory(); |
| 594 if (history->crossesTreeScopes() || history->hasShadowPseudo()) | 594 if (history->needsImplicitShadowCrossingCombinatorForMatching() |
| 595 || history->hasImplicitShadowCrossingCombinatorForMatching()) { |
| 595 lastShadowPseudo = history; | 596 lastShadowPseudo = history; |
| 597 } |
| 596 } | 598 } |
| 597 | 599 |
| 598 if (lastShadowPseudo->tagHistory()) { | 600 if (lastShadowPseudo->tagHistory()) { |
| 601 ASSERT(lastShadowPseudo->hasImplicitShadowCrossingCombinatorForMatching(
)); |
| 599 if (tag != anyQName()) | 602 if (tag != anyQName()) |
| 600 lastShadowPseudo->tagHistory()->prependTagSelector(tag, tagIsImplici
t); | 603 lastShadowPseudo->tagHistory()->prependTagSelector(tag, tagIsImplici
t); |
| 601 return; | 604 return; |
| 602 } | 605 } |
| 603 | 606 |
| 604 // For shadow-ID pseudo-elements to be correctly matched, the ShadowPseudo c
ombinator has to be used. | 607 // 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. '*'). | 608 // 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); | 609 OwnPtr<CSSParserSelector> elementNameSelector = CSSParserSelector::create(ta
g); |
| 607 lastShadowPseudo->setTagHistory(elementNameSelector.release()); | 610 lastShadowPseudo->setTagHistory(elementNameSelector.release()); |
| 608 lastShadowPseudo->setRelation(CSSSelector::ShadowPseudo); | 611 lastShadowPseudo->setRelation(CSSSelector::ShadowPseudo); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 655 // TODO(rune@opera.com): We should try to remove the need for the re-orderin
g tricks | 658 // TODO(rune@opera.com): We should try to remove the need for the re-orderin
g tricks |
| 656 // below and in the remaining rewrite* methods by using a more suitable stor
age | 659 // below and in the remaining rewrite* methods by using a more suitable stor
age |
| 657 // structure in CSSSelectorParser. | 660 // structure in CSSSelectorParser. |
| 658 // | 661 // |
| 659 // The code below is to keep ::content at the end of the compound, and to ke
ep the | 662 // The code below is to keep ::content at the end of the compound, and to ke
ep the |
| 660 // tagHistory order correct for implicit ShadowPseudo and juggling multiple
(two?) | 663 // tagHistory order correct for implicit ShadowPseudo and juggling multiple
(two?) |
| 661 // compounds. | 664 // compounds. |
| 662 | 665 |
| 663 CSSSelector::Relation relation = CSSSelector::SubSelector; | 666 CSSSelector::Relation relation = CSSSelector::SubSelector; |
| 664 | 667 |
| 665 if (simpleSelector->crossesTreeScopes() || simpleSelector->pseudoType() == C
SSSelector::PseudoContent) { | 668 if (simpleSelector->needsImplicitShadowCrossingCombinatorForMatching() || si
mpleSelector->pseudoType() == CSSSelector::PseudoContent) { |
| 666 if (simpleSelector->crossesTreeScopes()) | 669 if (simpleSelector->needsImplicitShadowCrossingCombinatorForMatching()) |
| 667 relation = CSSSelector::ShadowPseudo; | 670 relation = CSSSelector::ShadowPseudo; |
| 668 simpleSelector->appendTagHistory(relation, compoundSelector); | 671 simpleSelector->appendTagHistory(relation, compoundSelector); |
| 669 return simpleSelector; | 672 return simpleSelector; |
| 670 } | 673 } |
| 671 if (compoundSelector->crossesTreeScopes() || compoundSelector->pseudoType()
== CSSSelector::PseudoContent) { | 674 if (compoundSelector->needsImplicitShadowCrossingCombinatorForMatching() ||
compoundSelector->pseudoType() == CSSSelector::PseudoContent) { |
| 672 if (compoundSelector->crossesTreeScopes()) | 675 if (compoundSelector->needsImplicitShadowCrossingCombinatorForMatching()
) |
| 673 relation = CSSSelector::ShadowPseudo; | 676 relation = CSSSelector::ShadowPseudo; |
| 674 compoundSelector->insertTagHistory(CSSSelector::SubSelector, simpleSelec
tor, relation); | 677 compoundSelector->insertTagHistory(CSSSelector::SubSelector, simpleSelec
tor, relation); |
| 675 return compoundSelector; | 678 return compoundSelector; |
| 676 } | 679 } |
| 677 | 680 |
| 678 // All other simple selectors are added to the end of the compound. | 681 // All other simple selectors are added to the end of the compound. |
| 679 compoundSelector->appendTagHistory(CSSSelector::SubSelector, simpleSelector)
; | 682 compoundSelector->appendTagHistory(CSSSelector::SubSelector, simpleSelector)
; |
| 680 return compoundSelector; | 683 return compoundSelector; |
| 681 } | 684 } |
| 682 | 685 |
| 683 } // namespace blink | 686 } // namespace blink |
| OLD | NEW |