Changeset 107205 in webkit
- Timestamp:
- Feb 9, 2012 2:21:42 AM (12 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r107204 r107205 1 2012-02-09 Roland Steiner <rolandsteiner@chromium.org> 2 3 Unreviewed, rolling out r107197. 4 http://trac.webkit.org/changeset/107197 5 https://bugs.webkit.org/show_bug.cgi?id=77525 6 7 broke Chromium Linux 8 9 * css/CSSStyleSelector.cpp: 10 (WebCore::CSSStyleSelector::checkSelector): 11 * css/SelectorChecker.cpp: 12 (WebCore::SelectorChecker::checkSelector): 13 (WebCore): 14 (WebCore::SelectorChecker::checkOneSelector): 15 * css/SelectorChecker.h: 16 1 17 2012-02-09 Kentaro Hara <haraken@chromium.org> 2 18 -
trunk/Source/WebCore/css/CSSStyleSelector.cpp
r107197 r107205 2093 2093 2094 2094 // Slow path. 2095 SelectorChecker::SelectorCheckingContext context(ruleData.selector(), m_element, SelectorChecker::VisitedMatchEnabled, style(), m_parentNode ? m_parentNode->renderStyle() : 0); 2096 SelectorChecker::SelectorMatch match = m_checker.checkSelector(context, m_dynamicPseudo); 2095 SelectorChecker::SelectorMatch match = m_checker.checkSelector(ruleData.selector(), m_element, m_dynamicPseudo, false, SelectorChecker::VisitedMatchEnabled, style(), m_parentNode ? m_parentNode->renderStyle() : 0); 2097 2096 if (match != SelectorChecker::SelectorMatches) 2098 2097 return false; -
trunk/Source/WebCore/css/SelectorChecker.cpp
r107197 r107205 269 269 bool SelectorChecker::checkSelector(CSSSelector* sel, Element* element, bool isFastCheckableSelector) const 270 270 { 271 PseudoId dynamicPseudo = NOPSEUDO; 271 272 if (isFastCheckableSelector && !element->isSVGElement()) { 272 273 if (!fastCheckRightmostSelector(sel, element, VisitedMatchDisabled)) … … 274 275 return fastCheckSelector(sel, element); 275 276 } 276 277 PseudoId dynamicPseudo = NOPSEUDO; 278 return checkSelector(SelectorCheckingContext(sel, element, SelectorChecker::VisitedMatchDisabled), dynamicPseudo) == SelectorMatches; 277 return checkSelector(sel, element, dynamicPseudo, false, VisitedMatchDisabled) == SelectorMatches; 279 278 } 280 279 … … 444 443 // * SelectorFailsAllSiblings - the selector fails for e and any sibling of e 445 444 // * SelectorFailsCompletely - the selector fails for e and any sibling or ancestor of e 446 SelectorChecker::SelectorMatch SelectorChecker::checkSelector( const SelectorCheckingContext& context, PseudoId& dynamicPseudo) const445 SelectorChecker::SelectorMatch SelectorChecker::checkSelector(CSSSelector* sel, Element* e, PseudoId& dynamicPseudo, bool isSubSelector, VisitedMatchType visitedMatchType, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const 447 446 { 448 447 #if ENABLE(SVG) 449 448 // Spec: CSS2 selectors cannot be applied to the (conceptually) cloned DOM tree 450 449 // because its contents are not part of the formal document structure. 451 if ( context.element->isSVGShadowRoot())450 if (e->isSVGShadowRoot()) 452 451 return SelectorFailsCompletely; 453 452 #endif 454 453 455 454 // first selector has to match 456 if (!checkOneSelector( context, dynamicPseudo))455 if (!checkOneSelector(sel, e, dynamicPseudo, isSubSelector, visitedMatchType, elementStyle, elementParentStyle)) 457 456 return SelectorFailsLocally; 458 457 459 458 // The rest of the selectors has to match 460 CSSSelector::Relation relation = context.selector->relation();461 462 // Prepare next sel ector463 CSSSelector* historySelector = context.selector->tagHistory();464 if (! historySelector)459 CSSSelector::Relation relation = sel->relation(); 460 461 // Prepare next sel 462 sel = sel->tagHistory(); 463 if (!sel) 465 464 return SelectorMatches; 466 467 SelectorCheckingContext nextContext(context);468 nextContext.selector = historySelector;469 465 470 466 if (relation != CSSSelector::SubSelector) { … … 474 470 475 471 // Disable :visited matching when we see the first link or try to match anything else than an ancestors. 476 if (! context.isSubSelector && (context.element->isLink() || (relation != CSSSelector::Descendant && relation != CSSSelector::Child)))477 nextContext.visitedMatchType = VisitedMatchDisabled;472 if (!isSubSelector && (e->isLink() || (relation != CSSSelector::Descendant && relation != CSSSelector::Child))) 473 visitedMatchType = VisitedMatchDisabled; 478 474 } 479 475 480 476 switch (relation) { 481 477 case CSSSelector::Descendant: 482 nextContext.element = context.element->parentElement();483 nextContext.isSubSelector = false;484 nextContext.elementStyle = 0;485 nextContext.elementParentStyle = 0;486 for (; nextContext.element; nextContext.element = nextContext.element->parentElement()) {487 SelectorMatch match = checkSelector( nextContext, dynamicPseudo);478 while (true) { 479 ContainerNode* n = e->parentNode(); 480 if (!n || !n->isElementNode()) 481 return SelectorFailsCompletely; 482 e = static_cast<Element*>(n); 483 SelectorMatch match = checkSelector(sel, e, dynamicPseudo, false, visitedMatchType); 488 484 if (match == SelectorMatches || match == SelectorFailsCompletely) 489 485 return match; 490 486 } 491 return SelectorFailsCompletely; 492 487 break; 493 488 case CSSSelector::Child: 494 nextContext.element = context.element->parentElement(); 495 if (!nextContext.element) 496 return SelectorFailsCompletely; 497 nextContext.isSubSelector = false; 498 nextContext.elementStyle = 0; 499 nextContext.elementParentStyle = 0; 500 return checkSelector(nextContext, dynamicPseudo); 501 489 { 490 ContainerNode* n = e->parentNode(); 491 if (!n || !n->isElementNode()) 492 return SelectorFailsCompletely; 493 e = static_cast<Element*>(n); 494 return checkSelector(sel, e, dynamicPseudo, false, visitedMatchType); 495 } 502 496 case CSSSelector::DirectAdjacent: 503 if (!m_isCollectingRulesOnly && context.element->parentElement()) { 504 RenderStyle* parentStyle = context.elementStyle ? context.elementParentStyle : context.element->parentNode()->renderStyle(); 505 if (parentStyle) 506 parentStyle->setChildrenAffectedByDirectAdjacentRules(); 507 } 508 nextContext.element = context.element->previousElementSibling(); 509 if (!nextContext.element) 510 return SelectorFailsAllSiblings; 511 nextContext.isSubSelector = false; 512 nextContext.elementStyle = 0; 513 nextContext.elementParentStyle = 0; 514 return checkSelector(nextContext, dynamicPseudo); 515 497 { 498 if (!m_isCollectingRulesOnly && e->parentNode() && e->parentNode()->isElementNode()) { 499 RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle(); 500 if (parentStyle) 501 parentStyle->setChildrenAffectedByDirectAdjacentRules(); 502 } 503 e = e->previousElementSibling(); 504 if (!e) 505 return SelectorFailsAllSiblings; 506 return checkSelector(sel, e, dynamicPseudo, false, visitedMatchType); 507 } 516 508 case CSSSelector::IndirectAdjacent: 517 if (!m_isCollectingRulesOnly && context.element->parentElement()) {518 RenderStyle* parentStyle = context.elementStyle ? context.elementParentStyle : context.element->parentNode()->renderStyle();509 if (!m_isCollectingRulesOnly && e->parentNode() && e->parentNode()->isElementNode()) { 510 RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle(); 519 511 if (parentStyle) 520 512 parentStyle->setChildrenAffectedByForwardPositionalRules(); 521 513 } 522 nextContext.element = context.element->previousElementSibling(); 523 nextContext.isSubSelector = false; 524 nextContext.elementStyle = 0; 525 nextContext.elementParentStyle = 0; 526 for (; nextContext.element; nextContext.element = nextContext.element->previousElementSibling()) { 527 SelectorMatch match = checkSelector(nextContext, dynamicPseudo); 514 while (true) { 515 e = e->previousElementSibling(); 516 if (!e) 517 return SelectorFailsAllSiblings; 518 SelectorMatch match = checkSelector(sel, e, dynamicPseudo, false, visitedMatchType); 528 519 if (match == SelectorMatches || match == SelectorFailsAllSiblings || match == SelectorFailsCompletely) 529 520 return match; 530 521 }; 531 return SelectorFailsAllSiblings; 532 522 break; 533 523 case CSSSelector::SubSelector: 534 524 // a selector is invalid if something follows a pseudo-element 535 525 // We make an exception for scrollbar pseudo elements and allow a set of pseudo classes (but nothing else) 536 526 // to follow the pseudo elements. 537 if (( context.elementStyle || m_isCollectingRulesOnly) && dynamicPseudo != NOPSEUDO && dynamicPseudo != SELECTION538 && !((RenderScrollbar::scrollbarForStyleResolve() || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER) && context.selector->m_match == CSSSelector::PseudoClass))527 if ((elementStyle || m_isCollectingRulesOnly) && dynamicPseudo != NOPSEUDO && dynamicPseudo != SELECTION 528 && !((RenderScrollbar::scrollbarForStyleResolve() || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER) && sel->m_match == CSSSelector::PseudoClass)) 539 529 return SelectorFailsCompletely; 540 nextContext.isSubSelector = true; 541 return checkSelector(nextContext, dynamicPseudo); 542 530 return checkSelector(sel, e, dynamicPseudo, true, visitedMatchType, elementStyle, elementParentStyle); 543 531 case CSSSelector::ShadowDescendant: 544 532 { 545 Node* shadowHostNode = context.element->shadowAncestorNode();546 if (shadowHostNode == context.element|| !shadowHostNode->isElementNode())533 Node* shadowHostNode = e->shadowAncestorNode(); 534 if (shadowHostNode == e || !shadowHostNode->isElementNode()) 547 535 return SelectorFailsCompletely; 548 nextContext.element = toElement(shadowHostNode); 549 nextContext.isSubSelector = false; 550 nextContext.elementStyle = 0; 551 nextContext.elementParentStyle = 0; 552 return checkSelector(nextContext, dynamicPseudo); 553 } 554 } 555 556 ASSERT_NOT_REACHED(); 536 e = static_cast<Element*>(shadowHostNode); 537 return checkSelector(sel, e, dynamicPseudo, false, visitedMatchType); 538 } 539 } 540 557 541 return SelectorFailsCompletely; 558 542 } … … 704 688 } 705 689 706 bool SelectorChecker::checkOneSelector(const SelectorCheckingContext& context, PseudoId& dynamicPseudo) const 707 { 708 Element* const & element = context.element; 709 CSSSelector* const & selector = context.selector; 710 ASSERT(element); 711 ASSERT(selector); 712 713 if (!SelectorChecker::tagMatches(element, selector)) 690 bool SelectorChecker::checkOneSelector(CSSSelector* sel, Element* e, PseudoId& dynamicPseudo, bool isSubSelector, VisitedMatchType visitedMatchType, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const 691 { 692 ASSERT(e); 693 if (!SelectorChecker::tagMatches(e, sel)) 714 694 return false; 715 695 716 if (sel ector->m_match == CSSSelector::Class)717 return e lement->hasClass() && static_cast<StyledElement*>(element)->classNames().contains(selector->value());718 719 if (sel ector->m_match == CSSSelector::Id)720 return e lement->hasID() && element->idForStyleResolution() == selector->value();721 722 if (sel ector->isAttributeSelector()) {723 const QualifiedName& attr = sel ector->attribute();724 725 if (!e lement->hasAttributes())696 if (sel->m_match == CSSSelector::Class) 697 return e->hasClass() && static_cast<StyledElement*>(e)->classNames().contains(sel->value()); 698 699 if (sel->m_match == CSSSelector::Id) 700 return e->hasID() && e->idForStyleResolution() == sel->value(); 701 702 if (sel->isAttributeSelector()) { 703 const QualifiedName& attr = sel->attribute(); 704 705 if (!e->hasAttributes()) 726 706 return false; 727 707 728 708 bool caseSensitive = !m_documentIsHTML || !htmlAttributeHasCaseInsensitiveValue(attr); 729 709 730 if (!anyAttributeMatches(e lement, static_cast<CSSSelector::Match>(selector->m_match), attr, selector->value(), caseSensitive))731 return false; 732 } 733 734 if (sel ector->m_match == CSSSelector::PseudoClass) {710 if (!anyAttributeMatches(e, static_cast<CSSSelector::Match>(sel->m_match), attr, sel->value(), caseSensitive)) 711 return false; 712 } 713 714 if (sel->m_match == CSSSelector::PseudoClass) { 735 715 // Handle :not up front. 736 if (selector->pseudoType() == CSSSelector::PseudoNot) { 737 ASSERT(selector->selectorList()); 738 SelectorCheckingContext subContext(context); 739 subContext.isSubSelector = true; 740 for (subContext.selector = selector->selectorList()->first(); subContext.selector; subContext.selector = subContext.selector->tagHistory()) { 716 if (sel->pseudoType() == CSSSelector::PseudoNot) { 717 ASSERT(sel->selectorList()); 718 for (CSSSelector* subSel = sel->selectorList()->first(); subSel; subSel = subSel->tagHistory()) { 741 719 // :not cannot nest. I don't really know why this is a 742 720 // restriction in CSS3, but it is, so let's honor it. 743 721 // the parser enforces that this never occurs 744 ASSERT(sub Context.selector->pseudoType() != CSSSelector::PseudoNot);722 ASSERT(subSel->pseudoType() != CSSSelector::PseudoNot); 745 723 // We select between :visited and :link when applying. We don't know which one applied (or not) yet. 746 if (sub Context.selector->pseudoType() == CSSSelector::PseudoVisited || (subContext.selector->pseudoType() == CSSSelector::PseudoLink && subContext.visitedMatchType == VisitedMatchEnabled))724 if (subSel->pseudoType() == CSSSelector::PseudoVisited || (subSel->pseudoType() == CSSSelector::PseudoLink && visitedMatchType == VisitedMatchEnabled)) 747 725 return true; 748 if (!checkOneSelector(sub Context, dynamicPseudo))726 if (!checkOneSelector(subSel, e, dynamicPseudo, true, visitedMatchType, elementStyle, elementParentStyle)) 749 727 return true; 750 728 } … … 752 730 // CSS scrollbars match a specific subset of pseudo classes, and they have specialized rules for each 753 731 // (since there are no elements involved). 754 return checkScrollbarPseudoClass(sel ector, dynamicPseudo);732 return checkScrollbarPseudoClass(sel, dynamicPseudo); 755 733 } else if (dynamicPseudo == SELECTION) { 756 if (sel ector->pseudoType() == CSSSelector::PseudoWindowInactive)734 if (sel->pseudoType() == CSSSelector::PseudoWindowInactive) 757 735 return !m_document->page()->focusController()->isActive(); 758 736 } 759 737 760 738 // Normal element pseudo class checking. 761 switch (sel ector->pseudoType()) {739 switch (sel->pseudoType()) { 762 740 // Pseudo classes: 763 741 case CSSSelector::PseudoNot: … … 766 744 { 767 745 bool result = true; 768 for (Node* n = e lement->firstChild(); n; n = n->nextSibling()) {746 for (Node* n = e->firstChild(); n; n = n->nextSibling()) { 769 747 if (n->isElementNode()) { 770 748 result = false; … … 780 758 } 781 759 if (!m_isCollectingRulesOnly) { 782 if ( context.elementStyle)783 context.elementStyle->setEmptyState(result);784 else if (e lement->renderStyle() && (element->document()->usesSiblingRules() || element->renderStyle()->unique()))785 e lement->renderStyle()->setEmptyState(result);760 if (elementStyle) 761 elementStyle->setEmptyState(result); 762 else if (e->renderStyle() && (e->document()->usesSiblingRules() || e->renderStyle()->unique())) 763 e->renderStyle()->setEmptyState(result); 786 764 } 787 765 return result; … … 789 767 case CSSSelector::PseudoFirstChild: 790 768 // first-child matches the first child that is an element 791 if (e lement->parentElement()) {769 if (e->parentElement()) { 792 770 bool result = false; 793 if (!e lement->previousElementSibling())771 if (!e->previousElementSibling()) 794 772 result = true; 795 773 if (!m_isCollectingRulesOnly) { 796 RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element->renderStyle();797 RenderStyle* parentStyle = context.elementStyle ? context.elementParentStyle : element->parentNode()->renderStyle();774 RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle(); 775 RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle(); 798 776 if (parentStyle) 799 777 parentStyle->setChildrenAffectedByFirstChildRules(); … … 806 784 case CSSSelector::PseudoFirstOfType: 807 785 // first-of-type matches the first element of its type 808 if (e lement->parentElement()) {786 if (e->parentElement()) { 809 787 bool result = true; 810 const QualifiedName& type = e lement->tagQName();811 for (const Element* sibling = e lement->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) {788 const QualifiedName& type = e->tagQName(); 789 for (const Element* sibling = e->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) { 812 790 if (sibling->hasTagName(type)) { 813 791 result = false; … … 816 794 } 817 795 if (!m_isCollectingRulesOnly) { 818 RenderStyle* parentStyle = context.elementStyle ? context.elementParentStyle : element->parentNode()->renderStyle();796 RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle(); 819 797 if (parentStyle) 820 798 parentStyle->setChildrenAffectedByForwardPositionalRules(); … … 825 803 case CSSSelector::PseudoLastChild: 826 804 // last-child matches the last child that is an element 827 if (Element* parentElement = e lement->parentElement()) {828 bool result = parentElement->isFinishedParsingChildren() && !e lement->nextElementSibling();805 if (Element* parentElement = e->parentElement()) { 806 bool result = parentElement->isFinishedParsingChildren() && !e->nextElementSibling(); 829 807 if (!m_isCollectingRulesOnly) { 830 RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element->renderStyle();831 RenderStyle* parentStyle = context.elementStyle ? context.elementParentStyle : parentElement->renderStyle();808 RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle(); 809 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle(); 832 810 if (parentStyle) 833 811 parentStyle->setChildrenAffectedByLastChildRules(); … … 840 818 case CSSSelector::PseudoLastOfType: 841 819 // last-of-type matches the last element of its type 842 if (Element* parentElement = e lement->parentElement()) {820 if (Element* parentElement = e->parentElement()) { 843 821 if (!m_isCollectingRulesOnly) { 844 RenderStyle* parentStyle = context.elementStyle ? context.elementParentStyle : parentElement->renderStyle();822 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle(); 845 823 if (parentStyle) 846 824 parentStyle->setChildrenAffectedByBackwardPositionalRules(); … … 848 826 if (!parentElement->isFinishedParsingChildren()) 849 827 return false; 850 const QualifiedName& type = e lement->tagQName();851 for (const Element* sibling = e lement->nextElementSibling(); sibling; sibling = sibling->nextElementSibling()) {828 const QualifiedName& type = e->tagQName(); 829 for (const Element* sibling = e->nextElementSibling(); sibling; sibling = sibling->nextElementSibling()) { 852 830 if (sibling->hasTagName(type)) 853 831 return false; … … 857 835 break; 858 836 case CSSSelector::PseudoOnlyChild: 859 if (Element* parentElement = e lement->parentElement()) {860 bool firstChild = !e lement->previousElementSibling();861 bool onlyChild = firstChild && parentElement->isFinishedParsingChildren() && !e lement->nextElementSibling();837 if (Element* parentElement = e->parentElement()) { 838 bool firstChild = !e->previousElementSibling(); 839 bool onlyChild = firstChild && parentElement->isFinishedParsingChildren() && !e->nextElementSibling(); 862 840 863 841 if (!m_isCollectingRulesOnly) { 864 RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element->renderStyle();865 RenderStyle* parentStyle = context.elementStyle ? context.elementParentStyle : parentElement->renderStyle();842 RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle(); 843 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle(); 866 844 if (parentStyle) { 867 845 parentStyle->setChildrenAffectedByFirstChildRules(); … … 878 856 case CSSSelector::PseudoOnlyOfType: 879 857 // FIXME: This selector is very slow. 880 if (Element* parentElement = e lement->parentElement()) {858 if (Element* parentElement = e->parentElement()) { 881 859 if (!m_isCollectingRulesOnly) { 882 RenderStyle* parentStyle = context.elementStyle ? context.elementParentStyle : parentElement->renderStyle();860 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle(); 883 861 if (parentStyle) { 884 862 parentStyle->setChildrenAffectedByForwardPositionalRules(); … … 888 866 if (!parentElement->isFinishedParsingChildren()) 889 867 return false; 890 const QualifiedName& type = e lement->tagQName();891 for (const Element* sibling = e lement->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) {868 const QualifiedName& type = e->tagQName(); 869 for (const Element* sibling = e->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) { 892 870 if (sibling->hasTagName(type)) 893 871 return false; 894 872 } 895 for (const Element* sibling = e lement->nextElementSibling(); sibling; sibling = sibling->nextElementSibling()) {873 for (const Element* sibling = e->nextElementSibling(); sibling; sibling = sibling->nextElementSibling()) { 896 874 if (sibling->hasTagName(type)) 897 875 return false; … … 901 879 break; 902 880 case CSSSelector::PseudoNthChild: 903 if (!sel ector->parseNth())881 if (!sel->parseNth()) 904 882 break; 905 if (Element* parentElement = e lement->parentElement()) {883 if (Element* parentElement = e->parentElement()) { 906 884 int count = 1; 907 for (const Element* sibling = e lement->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) {885 for (const Element* sibling = e->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) { 908 886 RenderStyle* s = sibling->renderStyle(); 909 887 unsigned index = s ? s->childIndex() : 0; … … 916 894 917 895 if (!m_isCollectingRulesOnly) { 918 RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element->renderStyle();919 RenderStyle* parentStyle = context.elementStyle ? context.elementParentStyle : parentElement->renderStyle();896 RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle(); 897 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle(); 920 898 if (childStyle) 921 899 childStyle->setChildIndex(count); … … 924 902 } 925 903 926 if (sel ector->matchNth(count))904 if (sel->matchNth(count)) 927 905 return true; 928 906 } 929 907 break; 930 908 case CSSSelector::PseudoNthOfType: 931 if (!sel ector->parseNth())909 if (!sel->parseNth()) 932 910 break; 933 if (Element* parentElement = e lement->parentElement()) {911 if (Element* parentElement = e->parentElement()) { 934 912 int count = 1; 935 const QualifiedName& type = e lement->tagQName();936 for (const Element* sibling = e lement->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) {913 const QualifiedName& type = e->tagQName(); 914 for (const Element* sibling = e->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) { 937 915 if (sibling->hasTagName(type)) 938 916 ++count; 939 917 } 940 918 if (!m_isCollectingRulesOnly) { 941 RenderStyle* parentStyle = context.elementStyle ? context.elementParentStyle : parentElement->renderStyle();919 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle(); 942 920 if (parentStyle) 943 921 parentStyle->setChildrenAffectedByForwardPositionalRules(); 944 922 } 945 923 946 if (sel ector->matchNth(count))924 if (sel->matchNth(count)) 947 925 return true; 948 926 } 949 927 break; 950 928 case CSSSelector::PseudoNthLastChild: 951 if (!sel ector->parseNth())929 if (!sel->parseNth()) 952 930 break; 953 if (Element* parentElement = e lement->parentElement()) {931 if (Element* parentElement = e->parentElement()) { 954 932 if (!m_isCollectingRulesOnly) { 955 RenderStyle* parentStyle = context.elementStyle ? context.elementParentStyle : parentElement->renderStyle();933 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle(); 956 934 if (parentStyle) 957 935 parentStyle->setChildrenAffectedByBackwardPositionalRules(); … … 960 938 return false; 961 939 int count = 1; 962 for (const Element* sibling = e lement->nextElementSibling(); sibling; sibling = sibling->nextElementSibling())940 for (const Element* sibling = e->nextElementSibling(); sibling; sibling = sibling->nextElementSibling()) 963 941 ++count; 964 if (sel ector->matchNth(count))942 if (sel->matchNth(count)) 965 943 return true; 966 944 } 967 945 break; 968 946 case CSSSelector::PseudoNthLastOfType: 969 if (!sel ector->parseNth())947 if (!sel->parseNth()) 970 948 break; 971 if (Element* parentElement = e lement->parentElement()) {949 if (Element* parentElement = e->parentElement()) { 972 950 if (!m_isCollectingRulesOnly) { 973 RenderStyle* parentStyle = context.elementStyle ? context.elementParentStyle : parentElement->renderStyle();951 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle(); 974 952 if (parentStyle) 975 953 parentStyle->setChildrenAffectedByBackwardPositionalRules(); … … 978 956 return false; 979 957 int count = 1; 980 const QualifiedName& type = e lement->tagQName();981 for (const Element* sibling = e lement->nextElementSibling(); sibling; sibling = sibling->nextElementSibling()) {958 const QualifiedName& type = e->tagQName(); 959 for (const Element* sibling = e->nextElementSibling(); sibling; sibling = sibling->nextElementSibling()) { 982 960 if (sibling->hasTagName(type)) 983 961 ++count; 984 962 } 985 if (sel ector->matchNth(count))963 if (sel->matchNth(count)) 986 964 return true; 987 965 } 988 966 break; 989 967 case CSSSelector::PseudoTarget: 990 if (e lement == element->document()->cssTarget())968 if (e == e->document()->cssTarget()) 991 969 return true; 992 970 break; 993 971 case CSSSelector::PseudoAny: 994 { 995 SelectorCheckingContext subContext(context); 996 subContext.isSubSelector = true; 997 for (subContext.selector = selector->selectorList()->first(); subContext.selector; subContext.selector = CSSSelectorList::next(subContext.selector)) { 998 if (checkSelector(subContext, dynamicPseudo) == SelectorMatches) 999 return true; 1000 } 972 for (CSSSelector* selector = sel->selectorList()->first(); selector; selector = CSSSelectorList::next(selector)) { 973 if (checkSelector(selector, e, dynamicPseudo, true, visitedMatchType, elementStyle, elementParentStyle) == SelectorMatches) 974 return true; 1001 975 } 1002 976 break; 1003 977 case CSSSelector::PseudoAutofill: 1004 if (!e lement || !element->isFormControlElement())978 if (!e || !e->isFormControlElement()) 1005 979 break; 1006 if (HTMLInputElement* inputElement = e lement->toInputElement())980 if (HTMLInputElement* inputElement = e->toInputElement()) 1007 981 return inputElement->isAutofilled(); 1008 982 break; … … 1010 984 case CSSSelector::PseudoLink: 1011 985 // :visited and :link matches are separated later when applying the style. Here both classes match all links... 1012 return e lement->isLink();986 return e->isLink(); 1013 987 case CSSSelector::PseudoVisited: 1014 988 // ...except if :visited matching is disabled for ancestor/sibling matching. 1015 return e lement->isLink() && context.visitedMatchType == VisitedMatchEnabled;989 return e->isLink() && visitedMatchType == VisitedMatchEnabled; 1016 990 case CSSSelector::PseudoDrag: 1017 if ( context.elementStyle)1018 context.elementStyle->setAffectedByDragRules(true);1019 else if (e lement->renderStyle())1020 e lement->renderStyle()->setAffectedByDragRules(true);1021 if (e lement->renderer() && element->renderer()->isDragging())991 if (elementStyle) 992 elementStyle->setAffectedByDragRules(true); 993 else if (e->renderStyle()) 994 e->renderStyle()->setAffectedByDragRules(true); 995 if (e->renderer() && e->renderer()->isDragging()) 1022 996 return true; 1023 997 break; 1024 998 case CSSSelector::PseudoFocus: 1025 return matchesFocusPseudoClass(e lement);999 return matchesFocusPseudoClass(e); 1026 1000 case CSSSelector::PseudoHover: 1027 1001 // If we're in quirks mode, then hover should never match anchors with no 1028 1002 // href and *:hover should not match anything. This is important for sites like wsj.com. 1029 if (m_strictParsing || context.isSubSelector || (selector->hasTag() && !element->hasTagName(aTag)) || element->isLink()) {1030 if ( context.elementStyle)1031 context.elementStyle->setAffectedByHoverRules(true);1032 else if (e lement->renderStyle())1033 e lement->renderStyle()->setAffectedByHoverRules(true);1034 if (e lement->hovered() || InspectorInstrumentation::forcePseudoState(element, CSSSelector::PseudoHover))1003 if (m_strictParsing || isSubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) { 1004 if (elementStyle) 1005 elementStyle->setAffectedByHoverRules(true); 1006 else if (e->renderStyle()) 1007 e->renderStyle()->setAffectedByHoverRules(true); 1008 if (e->hovered() || InspectorInstrumentation::forcePseudoState(e, CSSSelector::PseudoHover)) 1035 1009 return true; 1036 1010 } … … 1039 1013 // If we're in quirks mode, then :active should never match anchors with no 1040 1014 // href and *:active should not match anything. 1041 if (m_strictParsing || context.isSubSelector || (selector->hasTag() && !element->hasTagName(aTag)) || element->isLink()) {1042 if ( context.elementStyle)1043 context.elementStyle->setAffectedByActiveRules(true);1044 else if (e lement->renderStyle())1045 e lement->renderStyle()->setAffectedByActiveRules(true);1046 if (e lement->active() || InspectorInstrumentation::forcePseudoState(element, CSSSelector::PseudoActive))1015 if (m_strictParsing || isSubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) { 1016 if (elementStyle) 1017 elementStyle->setAffectedByActiveRules(true); 1018 else if (e->renderStyle()) 1019 e->renderStyle()->setAffectedByActiveRules(true); 1020 if (e->active() || InspectorInstrumentation::forcePseudoState(e, CSSSelector::PseudoActive)) 1047 1021 return true; 1048 1022 } 1049 1023 break; 1050 1024 case CSSSelector::PseudoEnabled: 1051 if (e lement && element->isFormControlElement())1052 return e lement->isEnabledFormControl();1025 if (e && e->isFormControlElement()) 1026 return e->isEnabledFormControl(); 1053 1027 break; 1054 1028 case CSSSelector::PseudoFullPageMedia: 1055 return e lement && element->document() && element->document()->isMediaDocument();1029 return e && e->document() && e->document()->isMediaDocument(); 1056 1030 break; 1057 1031 case CSSSelector::PseudoDefault: 1058 return e lement && element->isDefaultButtonForForm();1032 return e && e->isDefaultButtonForForm(); 1059 1033 case CSSSelector::PseudoDisabled: 1060 if (e lement && element->isFormControlElement())1061 return !e lement->isEnabledFormControl();1034 if (e && e->isFormControlElement()) 1035 return !e->isEnabledFormControl(); 1062 1036 break; 1063 1037 case CSSSelector::PseudoReadOnly: 1064 if (!e lement || !element->isFormControlElement())1065 return false; 1066 return e lement->isTextFormControl() && element->isReadOnlyFormControl();1038 if (!e || !e->isFormControlElement()) 1039 return false; 1040 return e->isTextFormControl() && e->isReadOnlyFormControl(); 1067 1041 case CSSSelector::PseudoReadWrite: 1068 if (!e lement || !element->isFormControlElement())1069 return false; 1070 return e lement->isTextFormControl() && !element->isReadOnlyFormControl();1042 if (!e || !e->isFormControlElement()) 1043 return false; 1044 return e->isTextFormControl() && !e->isReadOnlyFormControl(); 1071 1045 case CSSSelector::PseudoOptional: 1072 return e lement && element->isOptionalFormControl();1046 return e && e->isOptionalFormControl(); 1073 1047 case CSSSelector::PseudoRequired: 1074 return e lement && element->isRequiredFormControl();1048 return e && e->isRequiredFormControl(); 1075 1049 case CSSSelector::PseudoValid: 1076 if (!e lement)1077 return false; 1078 e lement->document()->setContainsValidityStyleRules();1079 return e lement->willValidate() && element->isValidFormControlElement();1050 if (!e) 1051 return false; 1052 e->document()->setContainsValidityStyleRules(); 1053 return e->willValidate() && e->isValidFormControlElement(); 1080 1054 case CSSSelector::PseudoInvalid: 1081 if (!e lement)1082 return false; 1083 e lement->document()->setContainsValidityStyleRules();1084 return (e lement->willValidate() && !element->isValidFormControlElement()) || element->hasUnacceptableValue();1055 if (!e) 1056 return false; 1057 e->document()->setContainsValidityStyleRules(); 1058 return (e->willValidate() && !e->isValidFormControlElement()) || e->hasUnacceptableValue(); 1085 1059 case CSSSelector::PseudoChecked: 1086 1060 { 1087 if (!e lement || !element->isFormControlElement())1061 if (!e || !e->isFormControlElement()) 1088 1062 break; 1089 1063 // Even though WinIE allows checked and indeterminate to co-exist, the CSS selector spec says that 1090 1064 // you can't be both checked and indeterminate. We will behave like WinIE behind the scenes and just 1091 1065 // obey the CSS spec here in the test for matching the pseudo. 1092 HTMLInputElement* inputElement = e lement->toInputElement();1066 HTMLInputElement* inputElement = e->toInputElement(); 1093 1067 if (inputElement && inputElement->shouldAppearChecked() && !inputElement->isIndeterminate()) 1094 1068 return true; 1095 if (e lement->hasTagName(optionTag) && toHTMLOptionElement(element)->selected())1069 if (e->hasTagName(optionTag) && toHTMLOptionElement(e)->selected()) 1096 1070 return true; 1097 1071 break; … … 1099 1073 case CSSSelector::PseudoIndeterminate: 1100 1074 { 1101 if (!e lement || !element->isFormControlElement())1075 if (!e || !e->isFormControlElement()) 1102 1076 break; 1103 1077 #if ENABLE(PROGRESS_TAG) 1104 if (e lement->hasTagName(progressTag)) {1105 HTMLProgressElement* progress = static_cast<HTMLProgressElement*>(e lement);1078 if (e->hasTagName(progressTag)) { 1079 HTMLProgressElement* progress = static_cast<HTMLProgressElement*>(e); 1106 1080 if (progress && !progress->isDeterminate()) 1107 1081 return true; … … 1109 1083 } 1110 1084 #endif 1111 HTMLInputElement* inputElement = e lement->toInputElement();1085 HTMLInputElement* inputElement = e->toInputElement(); 1112 1086 if (inputElement && inputElement->isIndeterminate()) 1113 1087 return true; … … 1115 1089 } 1116 1090 case CSSSelector::PseudoRoot: 1117 if (e lement == element->document()->documentElement())1091 if (e == e->document()->documentElement()) 1118 1092 return true; 1119 1093 break; 1120 1094 case CSSSelector::PseudoLang: 1121 1095 { 1122 AtomicString value = e lement->computeInheritedLanguage();1123 const AtomicString& argument = sel ector->argument();1096 AtomicString value = e->computeInheritedLanguage(); 1097 const AtomicString& argument = sel->argument(); 1124 1098 if (value.isEmpty() || !value.startsWith(argument, false)) 1125 1099 break; … … 1134 1108 // that element. Also, an <iframe>, <object> or <embed> element whose child browsing 1135 1109 // context's Document is in the fullscreen state has the 'full-screen' pseudoclass applied. 1136 if (e lement->isFrameElementBase() && static_cast<HTMLFrameElementBase*>(element)->containsFullScreenElement())1110 if (e->isFrameElementBase() && static_cast<HTMLFrameElementBase*>(e)->containsFullScreenElement()) 1137 1111 return true; 1138 if (!e lement->document()->webkitIsFullScreen())1139 return false; 1140 return e lement == element->document()->webkitCurrentFullScreenElement();1112 if (!e->document()->webkitIsFullScreen()) 1113 return false; 1114 return e == e->document()->webkitCurrentFullScreenElement(); 1141 1115 case CSSSelector::PseudoAnimatingFullScreenTransition: 1142 if (e lement != element->document()->webkitCurrentFullScreenElement())1143 return false; 1144 return e lement->document()->isAnimatingFullScreen();1116 if (e != e->document()->webkitCurrentFullScreenElement()) 1117 return false; 1118 return e->document()->isAnimatingFullScreen(); 1145 1119 case CSSSelector::PseudoFullScreenAncestor: 1146 return e lement->containsFullScreenElement();1120 return e->containsFullScreenElement(); 1147 1121 case CSSSelector::PseudoFullScreenDocument: 1148 1122 // While a Document is in the fullscreen state, the 'full-screen-document' pseudoclass applies 1149 1123 // to all elements of that Document. 1150 if (!e lement->document()->webkitIsFullScreen())1124 if (!e->document()->webkitIsFullScreen()) 1151 1125 return false; 1152 1126 return true; 1153 1127 #endif 1154 1128 case CSSSelector::PseudoInRange: 1155 if (!e lement)1156 return false; 1157 e lement->document()->setContainsValidityStyleRules();1158 return e lement->isInRange();1129 if (!e) 1130 return false; 1131 e->document()->setContainsValidityStyleRules(); 1132 return e->isInRange(); 1159 1133 case CSSSelector::PseudoOutOfRange: 1160 if (!e lement)1161 return false; 1162 e lement->document()->setContainsValidityStyleRules();1163 return e lement->isOutOfRange();1134 if (!e) 1135 return false; 1136 e->document()->setContainsValidityStyleRules(); 1137 return e->isOutOfRange(); 1164 1138 case CSSSelector::PseudoUnknown: 1165 1139 case CSSSelector::PseudoNotParsed: … … 1170 1144 return false; 1171 1145 } 1172 if (sel ector->m_match == CSSSelector::PseudoElement) {1173 if (! context.elementStyle && !m_isCollectingRulesOnly)1174 return false; 1175 1176 if (sel ector->isUnknownPseudoElement()) {1146 if (sel->m_match == CSSSelector::PseudoElement) { 1147 if (!elementStyle && !m_isCollectingRulesOnly) 1148 return false; 1149 1150 if (sel->isUnknownPseudoElement()) { 1177 1151 m_hasUnknownPseudoElements = true; 1178 return e lement->shadowPseudoId() == selector->value();1179 } 1180 1181 PseudoId pseudoId = CSSSelector::pseudoId(sel ector->pseudoType());1152 return e->shadowPseudoId() == sel->value(); 1153 } 1154 1155 PseudoId pseudoId = CSSSelector::pseudoId(sel->pseudoType()); 1182 1156 if (pseudoId == FIRST_LETTER) { 1183 if (Document* document = e lement->document())1157 if (Document* document = e->document()) 1184 1158 document->setUsesFirstLetterRules(true); 1185 1159 } -
trunk/Source/WebCore/css/SelectorChecker.h
r107197 r107205 52 52 enum SelectorMatch { SelectorMatches, SelectorFailsLocally, SelectorFailsAllSiblings, SelectorFailsCompletely }; 53 53 enum VisitedMatchType { VisitedMatchDisabled, VisitedMatchEnabled }; 54 55 struct SelectorCheckingContext {56 // Initial selector constructor57 SelectorCheckingContext(CSSSelector* selector, Element* element, VisitedMatchType visitedMatchType, RenderStyle* elementStyle = 0, RenderStyle* elementParentStyle = 0)58 : selector(selector)59 , element(element)60 , visitedMatchType(visitedMatchType)61 , elementStyle(elementStyle)62 , elementParentStyle(elementParentStyle)63 , isSubSelector(false)64 { }65 66 CSSSelector* selector;67 Element* element;68 VisitedMatchType visitedMatchType;69 RenderStyle* elementStyle;70 RenderStyle* elementParentStyle;71 bool isSubSelector;72 };73 74 54 bool checkSelector(CSSSelector*, Element*, bool isFastCheckableSelector = false) const; 75 SelectorMatch checkSelector( const SelectorCheckingContext&, PseudoId&) const;55 SelectorMatch checkSelector(CSSSelector*, Element*, PseudoId& dynamicPseudo, bool isSubSelector, VisitedMatchType, RenderStyle* = 0, RenderStyle* elementParentStyle = 0) const; 76 56 static bool isFastCheckableSelector(const CSSSelector*); 77 57 bool fastCheckSelector(const CSSSelector*, const Element*) const; … … 117 97 118 98 private: 119 bool checkOneSelector( const SelectorCheckingContext&, PseudoId&) const;99 bool checkOneSelector(CSSSelector*, Element*, PseudoId& dynamicPseudo, bool isSubSelector, VisitedMatchType, RenderStyle*, RenderStyle* elementParentStyle) const; 120 100 bool checkScrollbarPseudoClass(CSSSelector*, PseudoId& dynamicPseudo) const; 121 101 static bool isFrameFocused(const Element*);
Note: See TracChangeset
for help on using the changeset viewer.