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

Side by Side Diff: Source/core/css/SelectorChecker.cpp

Issue 149513011: Pass around CSSSelector by reference instead of pointer (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 6 years, 10 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
« no previous file with comments | « Source/core/css/SelectorChecker.h ('k') | Source/core/css/SelectorCheckerFastPath.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) 3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com) 4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved. 5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
6 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> 6 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
7 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> 7 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t orchmobile.com/) 8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t orchmobile.com/)
9 * Copyright (c) 2011, Code Aurora Forum. All rights reserved. 9 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
10 * Copyright (C) Research In Motion Limited 2011. All rights reserved. 10 * Copyright (C) Research In Motion Limited 2011. All rights reserved.
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 57
58 using namespace HTMLNames; 58 using namespace HTMLNames;
59 59
60 SelectorChecker::SelectorChecker(Document& document, Mode mode) 60 SelectorChecker::SelectorChecker(Document& document, Mode mode)
61 : m_strictParsing(!document.inQuirksMode()) 61 : m_strictParsing(!document.inQuirksMode())
62 , m_documentIsHTML(document.isHTMLDocument()) 62 , m_documentIsHTML(document.isHTMLDocument())
63 , m_mode(mode) 63 , m_mode(mode)
64 { 64 {
65 } 65 }
66 66
67 static bool matchesCustomPseudoElement(const Element* element, const CSSSelector * selector) 67 static bool matchesCustomPseudoElement(const Element* element, const CSSSelector & selector)
68 { 68 {
69 ShadowRoot* root = element->containingShadowRoot(); 69 ShadowRoot* root = element->containingShadowRoot();
70 if (!root || root->type() != ShadowRoot::UserAgentShadowRoot) 70 if (!root || root->type() != ShadowRoot::UserAgentShadowRoot)
71 return false; 71 return false;
72 72
73 if (element->shadowPseudoId() != selector->value()) 73 if (element->shadowPseudoId() != selector.value())
74 return false; 74 return false;
75 75
76 return true; 76 return true;
77 } 77 }
78 78
79 Element* SelectorChecker::parentElement(const SelectorCheckingContext& context, bool allowToCrossBoundary) const 79 Element* SelectorChecker::parentElement(const SelectorCheckingContext& context, bool allowToCrossBoundary) const
80 { 80 {
81 // CrossesBoundary means we don't care any context.scope. So we can walk up from a shadow root to its shadow host. 81 // CrossesBoundary means we don't care any context.scope. So we can walk up from a shadow root to its shadow host.
82 if (allowToCrossBoundary) 82 if (allowToCrossBoundary)
83 return context.element->parentOrShadowHostElement(); 83 return context.element->parentOrShadowHostElement();
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 template<typename SiblingTraversalStrategy> 126 template<typename SiblingTraversalStrategy>
127 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext& con text, const SiblingTraversalStrategy& siblingTraversalStrategy, MatchResult* res ult) const 127 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext& con text, const SiblingTraversalStrategy& siblingTraversalStrategy, MatchResult* res ult) const
128 { 128 {
129 // first selector has to match 129 // first selector has to match
130 unsigned specificity = 0; 130 unsigned specificity = 0;
131 if (!checkOne(context, siblingTraversalStrategy, &specificity)) 131 if (!checkOne(context, siblingTraversalStrategy, &specificity))
132 return SelectorFailsLocally; 132 return SelectorFailsLocally;
133 133
134 if (context.selector->m_match == CSSSelector::PseudoElement) { 134 if (context.selector->m_match == CSSSelector::PseudoElement) {
135 if (context.selector->isCustomPseudoElement()) { 135 if (context.selector->isCustomPseudoElement()) {
136 if (!matchesCustomPseudoElement(context.element, context.selector)) 136 if (!matchesCustomPseudoElement(context.element, *context.selector))
137 return SelectorFailsLocally; 137 return SelectorFailsLocally;
138 } else if (context.selector->isContentPseudoElement()) { 138 } else if (context.selector->isContentPseudoElement()) {
139 if (!context.element->isInShadowTree() || !context.element->isInsert ionPoint()) 139 if (!context.element->isInShadowTree() || !context.element->isInsert ionPoint())
140 return SelectorFailsLocally; 140 return SelectorFailsLocally;
141 } else { 141 } else {
142 if ((!context.elementStyle && m_mode == ResolvingStyle) || m_mode == QueryingRules) 142 if ((!context.elementStyle && m_mode == ResolvingStyle) || m_mode == QueryingRules)
143 return SelectorFailsLocally; 143 return SelectorFailsLocally;
144 144
145 PseudoId pseudoId = CSSSelector::pseudoId(context.selector->pseudoTy pe()); 145 PseudoId pseudoId = CSSSelector::pseudoId(context.selector->pseudoTy pe());
146 if (pseudoId == FIRST_LETTER) 146 if (pseudoId == FIRST_LETTER)
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 } 460 }
461 461
462 return false; 462 return false;
463 } 463 }
464 464
465 template<typename SiblingTraversalStrategy> 465 template<typename SiblingTraversalStrategy>
466 bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib lingTraversalStrategy& siblingTraversalStrategy, unsigned* specificity) const 466 bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib lingTraversalStrategy& siblingTraversalStrategy, unsigned* specificity) const
467 { 467 {
468 ASSERT(context.element); 468 ASSERT(context.element);
469 Element& element = *context.element; 469 Element& element = *context.element;
470 const CSSSelector* const & selector = context.selector; 470 ASSERT(context.selector);
471 ASSERT(selector); 471 const CSSSelector& selector = *context.selector;
472
472 bool elementIsHostInItsShadowTree = isHostInItsShadowTree(element, context.b ehaviorAtBoundary, context.scope); 473 bool elementIsHostInItsShadowTree = isHostInItsShadowTree(element, context.b ehaviorAtBoundary, context.scope);
473 474
474 if (selector->m_match == CSSSelector::Tag) 475 if (selector.m_match == CSSSelector::Tag)
475 return SelectorChecker::tagMatches(element, selector->tagQName(), elemen tIsHostInItsShadowTree ? MatchingHostInItsShadowTree : MatchingElement); 476 return SelectorChecker::tagMatches(element, selector.tagQName(), element IsHostInItsShadowTree ? MatchingHostInItsShadowTree : MatchingElement);
476 477
477 if (selector->m_match == CSSSelector::Class) 478 if (selector.m_match == CSSSelector::Class)
478 return element.hasClass() && element.classNames().contains(selector->val ue()) && !elementIsHostInItsShadowTree; 479 return element.hasClass() && element.classNames().contains(selector.valu e()) && !elementIsHostInItsShadowTree;
479 480
480 if (selector->m_match == CSSSelector::Id) 481 if (selector.m_match == CSSSelector::Id)
481 return element.hasID() && element.idForStyleResolution() == selector->va lue() && !elementIsHostInItsShadowTree; 482 return element.hasID() && element.idForStyleResolution() == selector.val ue() && !elementIsHostInItsShadowTree;
482 483
483 if (selector->isAttributeSelector()) { 484 if (selector.isAttributeSelector()) {
484 if (elementIsHostInItsShadowTree) 485 if (elementIsHostInItsShadowTree)
485 return false; 486 return false;
486 if (!anyAttributeMatches(element, static_cast<CSSSelector::Match>(select or->m_match), *selector)) 487 if (!anyAttributeMatches(element, static_cast<CSSSelector::Match>(select or.m_match), selector))
487 return false; 488 return false;
488 } 489 }
489 490
490 if (selector->m_match == CSSSelector::PseudoClass) { 491 if (selector.m_match == CSSSelector::PseudoClass) {
491 // Handle :not up front. 492 // Handle :not up front.
492 if (selector->pseudoType() == CSSSelector::PseudoNot) { 493 if (selector.pseudoType() == CSSSelector::PseudoNot) {
493 SelectorCheckingContext subContext(context); 494 SelectorCheckingContext subContext(context);
494 subContext.isSubSelector = true; 495 subContext.isSubSelector = true;
495 ASSERT(selector->selectorList()); 496 ASSERT(selector.selectorList());
496 for (subContext.selector = selector->selectorList()->first(); subCon text.selector; subContext.selector = subContext.selector->tagHistory()) { 497 for (subContext.selector = selector.selectorList()->first(); subCont ext.selector; subContext.selector = subContext.selector->tagHistory()) {
497 // :not cannot nest. I don't really know why this is a 498 // :not cannot nest. I don't really know why this is a
498 // restriction in CSS3, but it is, so let's honor it. 499 // restriction in CSS3, but it is, so let's honor it.
499 // the parser enforces that this never occurs 500 // the parser enforces that this never occurs
500 ASSERT(subContext.selector->pseudoType() != CSSSelector::PseudoN ot); 501 ASSERT(subContext.selector->pseudoType() != CSSSelector::PseudoN ot);
501 // We select between :visited and :link when applying. We don't know which one applied (or not) yet. 502 // We select between :visited and :link when applying. We don't know which one applied (or not) yet.
502 if (subContext.selector->pseudoType() == CSSSelector::PseudoVisi ted || (subContext.selector->pseudoType() == CSSSelector::PseudoLink && subConte xt.visitedMatchType == VisitedMatchEnabled)) 503 if (subContext.selector->pseudoType() == CSSSelector::PseudoVisi ted || (subContext.selector->pseudoType() == CSSSelector::PseudoLink && subConte xt.visitedMatchType == VisitedMatchEnabled))
503 return true; 504 return true;
504 if (!checkOne(subContext, DOMSiblingTraversalStrategy())) 505 if (!checkOne(subContext, DOMSiblingTraversalStrategy()))
505 return true; 506 return true;
506 } 507 }
507 } else if (context.hasScrollbarPseudo) { 508 } else if (context.hasScrollbarPseudo) {
508 // CSS scrollbars match a specific subset of pseudo classes, and the y have specialized rules for each 509 // CSS scrollbars match a specific subset of pseudo classes, and the y have specialized rules for each
509 // (since there are no elements involved). 510 // (since there are no elements involved).
510 return checkScrollbarPseudoClass(context, &element.document(), selec tor); 511 return checkScrollbarPseudoClass(context, &element.document(), selec tor);
511 } else if (context.hasSelectionPseudo) { 512 } else if (context.hasSelectionPseudo) {
512 if (selector->pseudoType() == CSSSelector::PseudoWindowInactive) 513 if (selector.pseudoType() == CSSSelector::PseudoWindowInactive)
513 return !element.document().page()->focusController().isActive(); 514 return !element.document().page()->focusController().isActive();
514 } 515 }
515 516
516 // Normal element pseudo class checking. 517 // Normal element pseudo class checking.
517 switch (selector->pseudoType()) { 518 switch (selector.pseudoType()) {
518 // Pseudo classes: 519 // Pseudo classes:
519 case CSSSelector::PseudoNot: 520 case CSSSelector::PseudoNot:
520 break; // Already handled up above. 521 break; // Already handled up above.
521 case CSSSelector::PseudoEmpty: 522 case CSSSelector::PseudoEmpty:
522 { 523 {
523 bool result = true; 524 bool result = true;
524 for (Node* n = element.firstChild(); n; n = n->nextSibling()) { 525 for (Node* n = element.firstChild(); n; n = n->nextSibling()) {
525 if (n->isElementNode()) { 526 if (n->isElementNode()) {
526 result = false; 527 result = false;
527 break; 528 break;
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
610 if (m_mode == ResolvingStyle) { 611 if (m_mode == ResolvingStyle) {
611 parent->setChildrenAffectedByForwardPositionalRules(); 612 parent->setChildrenAffectedByForwardPositionalRules();
612 parent->setChildrenAffectedByBackwardPositionalRules(); 613 parent->setChildrenAffectedByBackwardPositionalRules();
613 } 614 }
614 if (!parent->isFinishedParsingChildren()) 615 if (!parent->isFinishedParsingChildren())
615 return false; 616 return false;
616 return siblingTraversalStrategy.isFirstOfType(&element, element. tagQName()) && siblingTraversalStrategy.isLastOfType(&element, element.tagQName( )); 617 return siblingTraversalStrategy.isFirstOfType(&element, element. tagQName()) && siblingTraversalStrategy.isLastOfType(&element, element.tagQName( ));
617 } 618 }
618 break; 619 break;
619 case CSSSelector::PseudoNthChild: 620 case CSSSelector::PseudoNthChild:
620 if (!selector->parseNth()) 621 if (!selector.parseNth())
621 break; 622 break;
622 if (Element* parent = element.parentElement()) { 623 if (Element* parent = element.parentElement()) {
623 int count = 1 + siblingTraversalStrategy.countElementsBefore(&el ement); 624 int count = 1 + siblingTraversalStrategy.countElementsBefore(&el ement);
624 if (m_mode == ResolvingStyle) { 625 if (m_mode == ResolvingStyle) {
625 RenderStyle* childStyle = context.elementStyle ? context.ele mentStyle : element.renderStyle(); 626 RenderStyle* childStyle = context.elementStyle ? context.ele mentStyle : element.renderStyle();
626 element.setChildIndex(count); 627 element.setChildIndex(count);
627 if (childStyle) 628 if (childStyle)
628 childStyle->setUnique(); 629 childStyle->setUnique();
629 parent->setChildrenAffectedByForwardPositionalRules(); 630 parent->setChildrenAffectedByForwardPositionalRules();
630 } 631 }
631 632
632 if (selector->matchNth(count)) 633 if (selector.matchNth(count))
633 return true; 634 return true;
634 } 635 }
635 break; 636 break;
636 case CSSSelector::PseudoNthOfType: 637 case CSSSelector::PseudoNthOfType:
637 if (!selector->parseNth()) 638 if (!selector.parseNth())
638 break; 639 break;
639 if (Element* parent = element.parentElement()) { 640 if (Element* parent = element.parentElement()) {
640 int count = 1 + siblingTraversalStrategy.countElementsOfTypeBefo re(&element, element.tagQName()); 641 int count = 1 + siblingTraversalStrategy.countElementsOfTypeBefo re(&element, element.tagQName());
641 if (m_mode == ResolvingStyle) 642 if (m_mode == ResolvingStyle)
642 parent->setChildrenAffectedByForwardPositionalRules(); 643 parent->setChildrenAffectedByForwardPositionalRules();
643 644
644 if (selector->matchNth(count)) 645 if (selector.matchNth(count))
645 return true; 646 return true;
646 } 647 }
647 break; 648 break;
648 case CSSSelector::PseudoNthLastChild: 649 case CSSSelector::PseudoNthLastChild:
649 if (!selector->parseNth()) 650 if (!selector.parseNth())
650 break; 651 break;
651 if (Element* parent = element.parentElement()) { 652 if (Element* parent = element.parentElement()) {
652 if (m_mode == ResolvingStyle) 653 if (m_mode == ResolvingStyle)
653 parent->setChildrenAffectedByBackwardPositionalRules(); 654 parent->setChildrenAffectedByBackwardPositionalRules();
654 if (!parent->isFinishedParsingChildren()) 655 if (!parent->isFinishedParsingChildren())
655 return false; 656 return false;
656 int count = 1 + siblingTraversalStrategy.countElementsAfter(&ele ment); 657 int count = 1 + siblingTraversalStrategy.countElementsAfter(&ele ment);
657 if (selector->matchNth(count)) 658 if (selector.matchNth(count))
658 return true; 659 return true;
659 } 660 }
660 break; 661 break;
661 case CSSSelector::PseudoNthLastOfType: 662 case CSSSelector::PseudoNthLastOfType:
662 if (!selector->parseNth()) 663 if (!selector.parseNth())
663 break; 664 break;
664 if (Element* parent = element.parentElement()) { 665 if (Element* parent = element.parentElement()) {
665 if (m_mode == ResolvingStyle) 666 if (m_mode == ResolvingStyle)
666 parent->setChildrenAffectedByBackwardPositionalRules(); 667 parent->setChildrenAffectedByBackwardPositionalRules();
667 if (!parent->isFinishedParsingChildren()) 668 if (!parent->isFinishedParsingChildren())
668 return false; 669 return false;
669 670
670 int count = 1 + siblingTraversalStrategy.countElementsOfTypeAfte r(&element, element.tagQName()); 671 int count = 1 + siblingTraversalStrategy.countElementsOfTypeAfte r(&element, element.tagQName());
671 if (selector->matchNth(count)) 672 if (selector.matchNth(count))
672 return true; 673 return true;
673 } 674 }
674 break; 675 break;
675 case CSSSelector::PseudoTarget: 676 case CSSSelector::PseudoTarget:
676 if (element == element.document().cssTarget()) 677 if (element == element.document().cssTarget())
677 return true; 678 return true;
678 break; 679 break;
679 case CSSSelector::PseudoAny: 680 case CSSSelector::PseudoAny:
680 { 681 {
681 SelectorCheckingContext subContext(context); 682 SelectorCheckingContext subContext(context);
682 subContext.isSubSelector = true; 683 subContext.isSubSelector = true;
683 ASSERT(selector->selectorList()); 684 ASSERT(selector.selectorList());
684 for (subContext.selector = selector->selectorList()->first(); su bContext.selector; subContext.selector = CSSSelectorList::next(subContext.select or)) { 685 for (subContext.selector = selector.selectorList()->first(); sub Context.selector; subContext.selector = CSSSelectorList::next(*subContext.select or)) {
685 if (match(subContext, siblingTraversalStrategy) == SelectorM atches) 686 if (match(subContext, siblingTraversalStrategy) == SelectorM atches)
686 return true; 687 return true;
687 } 688 }
688 } 689 }
689 break; 690 break;
690 case CSSSelector::PseudoAutofill: 691 case CSSSelector::PseudoAutofill:
691 if (!element.isFormControlElement()) 692 if (!element.isFormControlElement())
692 break; 693 break;
693 return toHTMLFormControlElement(element).isAutofilled(); 694 return toHTMLFormControlElement(element).isAutofilled();
694 case CSSSelector::PseudoAnyLink: 695 case CSSSelector::PseudoAnyLink:
(...skipping 17 matching lines...) Expand all
712 if (m_mode == ResolvingStyle) { 713 if (m_mode == ResolvingStyle) {
713 if (context.elementStyle) 714 if (context.elementStyle)
714 context.elementStyle->setAffectedByFocus(); 715 context.elementStyle->setAffectedByFocus();
715 else 716 else
716 element.setChildrenAffectedByFocus(); 717 element.setChildrenAffectedByFocus();
717 } 718 }
718 return matchesFocusPseudoClass(element); 719 return matchesFocusPseudoClass(element);
719 case CSSSelector::PseudoHover: 720 case CSSSelector::PseudoHover:
720 // If we're in quirks mode, then hover should never match anchors wi th no 721 // If we're in quirks mode, then hover should never match anchors wi th no
721 // href and *:hover should not match anything. This is important for sites like wsj.com. 722 // href and *:hover should not match anything. This is important for sites like wsj.com.
722 if (m_strictParsing || context.isSubSelector || (selector->m_match = = CSSSelector::Tag && selector->tagQName() != anyQName() && !element.hasTagName( aTag)) || element.isLink()) { 723 if (m_strictParsing || context.isSubSelector || (selector.m_match == CSSSelector::Tag && selector.tagQName() != anyQName() && !element.hasTagName(aT ag)) || element.isLink()) {
723 if (m_mode == ResolvingStyle) { 724 if (m_mode == ResolvingStyle) {
724 if (context.elementStyle) 725 if (context.elementStyle)
725 context.elementStyle->setAffectedByHover(); 726 context.elementStyle->setAffectedByHover();
726 else 727 else
727 element.setChildrenAffectedByHover(); 728 element.setChildrenAffectedByHover();
728 } 729 }
729 if (element.hovered() || InspectorInstrumentation::forcePseudoSt ate(&element, CSSSelector::PseudoHover)) 730 if (element.hovered() || InspectorInstrumentation::forcePseudoSt ate(&element, CSSSelector::PseudoHover))
730 return true; 731 return true;
731 } 732 }
732 break; 733 break;
733 case CSSSelector::PseudoActive: 734 case CSSSelector::PseudoActive:
734 // If we're in quirks mode, then :active should never match anchors with no 735 // If we're in quirks mode, then :active should never match anchors with no
735 // href and *:active should not match anything. 736 // href and *:active should not match anything.
736 if (m_strictParsing || context.isSubSelector || (selector->m_match = = CSSSelector::Tag && selector->tagQName() != anyQName() && !element.hasTagName( aTag)) || element.isLink()) { 737 if (m_strictParsing || context.isSubSelector || (selector.m_match == CSSSelector::Tag && selector.tagQName() != anyQName() && !element.hasTagName(aT ag)) || element.isLink()) {
737 if (m_mode == ResolvingStyle) { 738 if (m_mode == ResolvingStyle) {
738 if (context.elementStyle) 739 if (context.elementStyle)
739 context.elementStyle->setAffectedByActive(); 740 context.elementStyle->setAffectedByActive();
740 else 741 else
741 element.setChildrenAffectedByActive(); 742 element.setChildrenAffectedByActive();
742 } 743 }
743 if (element.active() || InspectorInstrumentation::forcePseudoSta te(&element, CSSSelector::PseudoActive)) 744 if (element.active() || InspectorInstrumentation::forcePseudoSta te(&element, CSSSelector::PseudoActive))
744 return true; 745 return true;
745 } 746 }
746 break; 747 break;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
792 if (element == element.document().documentElement()) 793 if (element == element.document().documentElement())
793 return true; 794 return true;
794 break; 795 break;
795 case CSSSelector::PseudoLang: 796 case CSSSelector::PseudoLang:
796 { 797 {
797 AtomicString value; 798 AtomicString value;
798 if (element.isVTTElement()) 799 if (element.isVTTElement())
799 value = toVTTElement(element).language(); 800 value = toVTTElement(element).language();
800 else 801 else
801 value = element.computeInheritedLanguage(); 802 value = element.computeInheritedLanguage();
802 const AtomicString& argument = selector->argument(); 803 const AtomicString& argument = selector.argument();
803 if (value.isEmpty() || !value.startsWith(argument, false)) 804 if (value.isEmpty() || !value.startsWith(argument, false))
804 break; 805 break;
805 if (value.length() != argument.length() && value[argument.length ()] != '-') 806 if (value.length() != argument.length() && value[argument.length ()] != '-')
806 break; 807 break;
807 return true; 808 return true;
808 } 809 }
809 case CSSSelector::PseudoFullScreen: 810 case CSSSelector::PseudoFullScreen:
810 // While a Document is in the fullscreen state, and the document's c urrent fullscreen 811 // While a Document is in the fullscreen state, and the document's c urrent fullscreen
811 // element is an element in the document, the 'full-screen' pseudocl ass applies to 812 // element is an element in the document, the 'full-screen' pseudocl ass applies to
812 // that element. Also, an <iframe>, <object> or <embed> element whos e child browsing 813 // that element. Also, an <iframe>, <object> or <embed> element whos e child browsing
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
853 854
854 case CSSSelector::PseudoHost: 855 case CSSSelector::PseudoHost:
855 case CSSSelector::PseudoAncestor: 856 case CSSSelector::PseudoAncestor:
856 { 857 {
857 // :host only matches a shadow host when :host is in a shadow tr ee of the shadow host. 858 // :host only matches a shadow host when :host is in a shadow tr ee of the shadow host.
858 if (!context.scope || !(context.behaviorAtBoundary & ScopeIsShad owHost) || context.scope != element) 859 if (!context.scope || !(context.behaviorAtBoundary & ScopeIsShad owHost) || context.scope != element)
859 return false; 860 return false;
860 ASSERT(element.shadow()); 861 ASSERT(element.shadow());
861 862
862 // For empty parameter case, i.e. just :host or :host(). 863 // For empty parameter case, i.e. just :host or :host().
863 if (!selector->selectorList()) // Use *'s specificity. So just 0 . 864 if (!selector.selectorList()) // Use *'s specificity. So just 0.
864 return true; 865 return true;
865 866
866 SelectorCheckingContext subContext(context); 867 SelectorCheckingContext subContext(context);
867 subContext.isSubSelector = true; 868 subContext.isSubSelector = true;
868 869
869 bool matched = false; 870 bool matched = false;
870 unsigned maxSpecificity = 0; 871 unsigned maxSpecificity = 0;
871 872
872 // If one of simple selectors matches an element, returns Select orMatches. Just "OR". 873 // If one of simple selectors matches an element, returns Select orMatches. Just "OR".
873 for (subContext.selector = selector->selectorList()->first(); su bContext.selector; subContext.selector = CSSSelectorList::next(subContext.select or)) { 874 for (subContext.selector = selector.selectorList()->first(); sub Context.selector; subContext.selector = CSSSelectorList::next(*subContext.select or)) {
874 subContext.behaviorAtBoundary = ScopeIsShadowHostInPseudoHos tParameter; 875 subContext.behaviorAtBoundary = ScopeIsShadowHostInPseudoHos tParameter;
875 subContext.scope = context.scope; 876 subContext.scope = context.scope;
876 // Use NodeRenderingTraversal to traverse a composed ancesto r list of a given element. 877 // Use NodeRenderingTraversal to traverse a composed ancesto r list of a given element.
877 Element* nextElement = &element; 878 Element* nextElement = &element;
878 do { 879 do {
879 MatchResult subResult; 880 MatchResult subResult;
880 subContext.element = nextElement; 881 subContext.element = nextElement;
881 if (match(subContext, siblingTraversalStrategy, &subResu lt) == SelectorMatches) { 882 if (match(subContext, siblingTraversalStrategy, &subResu lt) == SelectorMatches) {
882 matched = true; 883 matched = true;
883 // Consider div:host(div:host(div:host(div:host...)) ). 884 // Consider div:host(div:host(div:host(div:host...)) ).
884 maxSpecificity = std::max(maxSpecificity, subContext .selector->specificity() + subResult.specificity); 885 maxSpecificity = std::max(maxSpecificity, subContext .selector->specificity() + subResult.specificity);
885 break; 886 break;
886 } 887 }
887 subContext.behaviorAtBoundary = DoesNotCrossBoundary; 888 subContext.behaviorAtBoundary = DoesNotCrossBoundary;
888 subContext.scope = 0; 889 subContext.scope = 0;
889 890
890 if (selector->pseudoType() == CSSSelector::PseudoHost) 891 if (selector.pseudoType() == CSSSelector::PseudoHost)
891 break; 892 break;
892 893
893 nextElement = NodeRenderingTraversal::parentElement(next Element); 894 nextElement = NodeRenderingTraversal::parentElement(next Element);
894 } while (nextElement); 895 } while (nextElement);
895 } 896 }
896 if (matched) { 897 if (matched) {
897 if (specificity) 898 if (specificity)
898 *specificity = maxSpecificity; 899 *specificity = maxSpecificity;
899 return true; 900 return true;
900 } 901 }
(...skipping 12 matching lines...) Expand all
913 case CSSSelector::PseudoCornerPresent: 914 case CSSSelector::PseudoCornerPresent:
914 return false; 915 return false;
915 916
916 case CSSSelector::PseudoUnknown: 917 case CSSSelector::PseudoUnknown:
917 case CSSSelector::PseudoNotParsed: 918 case CSSSelector::PseudoNotParsed:
918 default: 919 default:
919 ASSERT_NOT_REACHED(); 920 ASSERT_NOT_REACHED();
920 break; 921 break;
921 } 922 }
922 return false; 923 return false;
923 } 924 } else if (selector.m_match == CSSSelector::PseudoElement && selector.pseudo Type() == CSSSelector::PseudoCue) {
924 else if (selector->m_match == CSSSelector::PseudoElement && selector->pseudo Type() == CSSSelector::PseudoCue) {
925 SelectorCheckingContext subContext(context); 925 SelectorCheckingContext subContext(context);
926 subContext.isSubSelector = true; 926 subContext.isSubSelector = true;
927 subContext.behaviorAtBoundary = StaysWithinTreeScope; 927 subContext.behaviorAtBoundary = StaysWithinTreeScope;
928 928
929 const CSSSelector* const & selector = context.selector; 929 const CSSSelector* contextSelector = context.selector;
930 for (subContext.selector = selector->selectorList()->first(); subContext .selector; subContext.selector = CSSSelectorList::next(subContext.selector)) { 930 ASSERT(contextSelector);
931 for (subContext.selector = contextSelector->selectorList()->first(); sub Context.selector; subContext.selector = CSSSelectorList::next(*subContext.select or)) {
931 if (match(subContext, siblingTraversalStrategy) == SelectorMatches) 932 if (match(subContext, siblingTraversalStrategy) == SelectorMatches)
932 return true; 933 return true;
933 } 934 }
934 return false; 935 return false;
935 } 936 }
936 // ### add the rest of the checks... 937 // ### add the rest of the checks...
937 return true; 938 return true;
938 } 939 }
939 940
940 bool SelectorChecker::checkScrollbarPseudoClass(const SelectorCheckingContext& c ontext, Document* document, const CSSSelector* selector) const 941 bool SelectorChecker::checkScrollbarPseudoClass(const SelectorCheckingContext& c ontext, Document* document, const CSSSelector& selector) const
941 { 942 {
942 RenderScrollbar* scrollbar = context.scrollbar; 943 RenderScrollbar* scrollbar = context.scrollbar;
943 ScrollbarPart part = context.scrollbarPart; 944 ScrollbarPart part = context.scrollbarPart;
944 945
945 // FIXME: This is a temporary hack for resizers and scrollbar corners. Event ually :window-inactive should become a real 946 // FIXME: This is a temporary hack for resizers and scrollbar corners. Event ually :window-inactive should become a real
946 // pseudo class and just apply to everything. 947 // pseudo class and just apply to everything.
947 if (selector->pseudoType() == CSSSelector::PseudoWindowInactive) 948 if (selector.pseudoType() == CSSSelector::PseudoWindowInactive)
948 return !document->page()->focusController().isActive(); 949 return !document->page()->focusController().isActive();
949 950
950 if (!scrollbar) 951 if (!scrollbar)
951 return false; 952 return false;
952 953
953 ASSERT(selector->m_match == CSSSelector::PseudoClass); 954 ASSERT(selector.m_match == CSSSelector::PseudoClass);
954 switch (selector->pseudoType()) { 955 switch (selector.pseudoType()) {
955 case CSSSelector::PseudoEnabled: 956 case CSSSelector::PseudoEnabled:
956 return scrollbar->enabled(); 957 return scrollbar->enabled();
957 case CSSSelector::PseudoDisabled: 958 case CSSSelector::PseudoDisabled:
958 return !scrollbar->enabled(); 959 return !scrollbar->enabled();
959 case CSSSelector::PseudoHover: 960 case CSSSelector::PseudoHover:
960 { 961 {
961 ScrollbarPart hoveredPart = scrollbar->hoveredPart(); 962 ScrollbarPart hoveredPart = scrollbar->hoveredPart();
962 if (part == ScrollbarBGPart) 963 if (part == ScrollbarBGPart)
963 return hoveredPart != NoPart; 964 return hoveredPart != NoPart;
964 if (part == TrackBGPart) 965 if (part == TrackBGPart)
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1011 return buttonsPlacement == ScrollbarButtonsNone || buttonsPlacem ent == ScrollbarButtonsDoubleStart; 1012 return buttonsPlacement == ScrollbarButtonsNone || buttonsPlacem ent == ScrollbarButtonsDoubleStart;
1012 return false; 1013 return false;
1013 } 1014 }
1014 case CSSSelector::PseudoCornerPresent: 1015 case CSSSelector::PseudoCornerPresent:
1015 return scrollbar->scrollableArea()->isScrollCornerVisible(); 1016 return scrollbar->scrollableArea()->isScrollCornerVisible();
1016 default: 1017 default:
1017 return false; 1018 return false;
1018 } 1019 }
1019 } 1020 }
1020 1021
1021 unsigned SelectorChecker::determineLinkMatchType(const CSSSelector* selector) 1022 unsigned SelectorChecker::determineLinkMatchType(const CSSSelector& selector)
1022 { 1023 {
1023 unsigned linkMatchType = MatchAll; 1024 unsigned linkMatchType = MatchAll;
1024 1025
1025 // Statically determine if this selector will match a link in visited, unvis ited or any state, or never. 1026 // Statically determine if this selector will match a link in visited, unvis ited or any state, or never.
1026 // :visited never matches other elements than the innermost link element. 1027 // :visited never matches other elements than the innermost link element.
1027 for (; selector; selector = selector->tagHistory()) { 1028 for (const CSSSelector* current = &selector; current; current = current->tag History()) {
1028 switch (selector->pseudoType()) { 1029 switch (current->pseudoType()) {
1029 case CSSSelector::PseudoNot: 1030 case CSSSelector::PseudoNot:
1030 { 1031 {
1031 // :not(:visited) is equivalent to :link. Parser enforces that : not can't nest. 1032 // :not(:visited) is equivalent to :link. Parser enforces that : not can't nest.
1032 ASSERT(selector->selectorList()); 1033 ASSERT(current->selectorList());
1033 for (const CSSSelector* subSelector = selector->selectorList()-> first(); subSelector; subSelector = subSelector->tagHistory()) { 1034 for (const CSSSelector* subSelector = current->selectorList()->f irst(); subSelector; subSelector = subSelector->tagHistory()) {
1034 CSSSelector::PseudoType subType = subSelector->pseudoType(); 1035 CSSSelector::PseudoType subType = subSelector->pseudoType();
1035 if (subType == CSSSelector::PseudoVisited) 1036 if (subType == CSSSelector::PseudoVisited)
1036 linkMatchType &= ~SelectorChecker::MatchVisited; 1037 linkMatchType &= ~SelectorChecker::MatchVisited;
1037 else if (subType == CSSSelector::PseudoLink) 1038 else if (subType == CSSSelector::PseudoLink)
1038 linkMatchType &= ~SelectorChecker::MatchLink; 1039 linkMatchType &= ~SelectorChecker::MatchLink;
1039 } 1040 }
1040 } 1041 }
1041 break; 1042 break;
1042 case CSSSelector::PseudoLink: 1043 case CSSSelector::PseudoLink:
1043 linkMatchType &= ~SelectorChecker::MatchVisited; 1044 linkMatchType &= ~SelectorChecker::MatchVisited;
1044 break; 1045 break;
1045 case CSSSelector::PseudoVisited: 1046 case CSSSelector::PseudoVisited:
1046 linkMatchType &= ~SelectorChecker::MatchLink; 1047 linkMatchType &= ~SelectorChecker::MatchLink;
1047 break; 1048 break;
1048 default: 1049 default:
1049 // We don't support :link and :visited inside :-webkit-any. 1050 // We don't support :link and :visited inside :-webkit-any.
1050 break; 1051 break;
1051 } 1052 }
1052 CSSSelector::Relation relation = selector->relation(); 1053 CSSSelector::Relation relation = current->relation();
1053 if (relation == CSSSelector::SubSelector) 1054 if (relation == CSSSelector::SubSelector)
1054 continue; 1055 continue;
1055 if (relation != CSSSelector::Descendant && relation != CSSSelector::Chil d) 1056 if (relation != CSSSelector::Descendant && relation != CSSSelector::Chil d)
1056 return linkMatchType; 1057 return linkMatchType;
1057 if (linkMatchType != MatchAll) 1058 if (linkMatchType != MatchAll)
1058 return linkMatchType; 1059 return linkMatchType;
1059 } 1060 }
1060 return linkMatchType; 1061 return linkMatchType;
1061 } 1062 }
1062 1063
1063 bool SelectorChecker::isFrameFocused(const Element& element) 1064 bool SelectorChecker::isFrameFocused(const Element& element)
1064 { 1065 {
1065 return element.document().frame() && element.document().frame()->selection() .isFocusedAndActive(); 1066 return element.document().frame() && element.document().frame()->selection() .isFocusedAndActive();
1066 } 1067 }
1067 1068
1068 bool SelectorChecker::matchesFocusPseudoClass(const Element& element) 1069 bool SelectorChecker::matchesFocusPseudoClass(const Element& element)
1069 { 1070 {
1070 if (InspectorInstrumentation::forcePseudoState(const_cast<Element*>(&element ), CSSSelector::PseudoFocus)) 1071 if (InspectorInstrumentation::forcePseudoState(const_cast<Element*>(&element ), CSSSelector::PseudoFocus))
1071 return true; 1072 return true;
1072 return element.focused() && isFrameFocused(element); 1073 return element.focused() && isFrameFocused(element);
1073 } 1074 }
1074 1075
1075 template 1076 template
1076 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, co nst DOMSiblingTraversalStrategy&, MatchResult*) const; 1077 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, co nst DOMSiblingTraversalStrategy&, MatchResult*) const;
1077 1078
1078 template 1079 template
1079 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, co nst ShadowDOMSiblingTraversalStrategy&, MatchResult*) const; 1080 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, co nst ShadowDOMSiblingTraversalStrategy&, MatchResult*) const;
1080 1081
1081 } 1082 }
OLDNEW
« no previous file with comments | « Source/core/css/SelectorChecker.h ('k') | Source/core/css/SelectorCheckerFastPath.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698