Changeset 107205 in webkit


Ignore:
Timestamp:
Feb 9, 2012 2:21:42 AM (12 years ago)
Author:
rolandsteiner@chromium.org
Message:

Unreviewed, rolling out r107197.
http://trac.webkit.org/changeset/107197
https://bugs.webkit.org/show_bug.cgi?id=77525

broke Chromium Linux

  • css/CSSStyleSelector.cpp:

(WebCore::CSSStyleSelector::checkSelector):

  • css/SelectorChecker.cpp:

(WebCore::SelectorChecker::checkSelector):
(WebCore):
(WebCore::SelectorChecker::checkOneSelector):

  • css/SelectorChecker.h:
Location:
trunk/Source/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r107204 r107205  
     12012-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
    1172012-02-09  Kentaro Hara  <haraken@chromium.org>
    218
  • trunk/Source/WebCore/css/CSSStyleSelector.cpp

    r107197 r107205  
    20932093
    20942094    // 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);
    20972096    if (match != SelectorChecker::SelectorMatches)
    20982097        return false;
  • trunk/Source/WebCore/css/SelectorChecker.cpp

    r107197 r107205  
    269269bool SelectorChecker::checkSelector(CSSSelector* sel, Element* element, bool isFastCheckableSelector) const
    270270{
     271    PseudoId dynamicPseudo = NOPSEUDO;
    271272    if (isFastCheckableSelector && !element->isSVGElement()) {
    272273        if (!fastCheckRightmostSelector(sel, element, VisitedMatchDisabled))
     
    274275        return fastCheckSelector(sel, element);
    275276    }
    276 
    277     PseudoId dynamicPseudo = NOPSEUDO;
    278     return checkSelector(SelectorCheckingContext(sel, element, SelectorChecker::VisitedMatchDisabled), dynamicPseudo) == SelectorMatches;
     277    return checkSelector(sel, element, dynamicPseudo, false, VisitedMatchDisabled) == SelectorMatches;
    279278}
    280279
     
    444443// * SelectorFailsAllSiblings - the selector fails for e and any sibling of e
    445444// * SelectorFailsCompletely  - the selector fails for e and any sibling or ancestor of e
    446 SelectorChecker::SelectorMatch SelectorChecker::checkSelector(const SelectorCheckingContext& context, PseudoId& dynamicPseudo) const
     445SelectorChecker::SelectorMatch SelectorChecker::checkSelector(CSSSelector* sel, Element* e, PseudoId& dynamicPseudo, bool isSubSelector, VisitedMatchType visitedMatchType, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const
    447446{
    448447#if ENABLE(SVG)
    449448    // Spec: CSS2 selectors cannot be applied to the (conceptually) cloned DOM tree
    450449    // because its contents are not part of the formal document structure.
    451     if (context.element->isSVGShadowRoot())
     450    if (e->isSVGShadowRoot())
    452451        return SelectorFailsCompletely;
    453452#endif
    454453
    455454    // first selector has to match
    456     if (!checkOneSelector(context, dynamicPseudo))
     455    if (!checkOneSelector(sel, e, dynamicPseudo, isSubSelector, visitedMatchType, elementStyle, elementParentStyle))
    457456        return SelectorFailsLocally;
    458457
    459458    // The rest of the selectors has to match
    460     CSSSelector::Relation relation = context.selector->relation();
    461 
    462     // Prepare next selector
    463     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)
    465464        return SelectorMatches;
    466 
    467     SelectorCheckingContext nextContext(context);
    468     nextContext.selector = historySelector;
    469465
    470466    if (relation != CSSSelector::SubSelector) {
     
    474470
    475471        // 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;
    478474    }
    479475
    480476    switch (relation) {
    481477    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);
    488484            if (match == SelectorMatches || match == SelectorFailsCompletely)
    489485                return match;
    490486        }
    491         return SelectorFailsCompletely;
    492 
     487        break;
    493488    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        }
    502496    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        }
    516508    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();
    519511            if (parentStyle)
    520512                parentStyle->setChildrenAffectedByForwardPositionalRules();
    521513        }
    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);
    528519            if (match == SelectorMatches || match == SelectorFailsAllSiblings || match == SelectorFailsCompletely)
    529520                return match;
    530521        };
    531         return SelectorFailsAllSiblings;
    532 
     522        break;
    533523    case CSSSelector::SubSelector:
    534524        // a selector is invalid if something follows a pseudo-element
    535525        // We make an exception for scrollbar pseudo elements and allow a set of pseudo classes (but nothing else)
    536526        // to follow the pseudo elements.
    537         if ((context.elementStyle || m_isCollectingRulesOnly) && dynamicPseudo != NOPSEUDO && dynamicPseudo != SELECTION
    538              && !((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))
    539529            return SelectorFailsCompletely;
    540         nextContext.isSubSelector = true;
    541         return checkSelector(nextContext, dynamicPseudo);
    542 
     530        return checkSelector(sel, e, dynamicPseudo, true, visitedMatchType, elementStyle, elementParentStyle);
    543531    case CSSSelector::ShadowDescendant:
    544532        {
    545             Node* shadowHostNode = context.element->shadowAncestorNode();
    546             if (shadowHostNode == context.element || !shadowHostNode->isElementNode())
     533            Node* shadowHostNode = e->shadowAncestorNode();
     534            if (shadowHostNode == e || !shadowHostNode->isElementNode())
    547535                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
    557541    return SelectorFailsCompletely;
    558542}
     
    704688}
    705689
    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))
     690bool 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))
    714694        return false;
    715695
    716     if (selector->m_match == CSSSelector::Class)
    717         return element->hasClass() && static_cast<StyledElement*>(element)->classNames().contains(selector->value());
    718 
    719     if (selector->m_match == CSSSelector::Id)
    720         return element->hasID() && element->idForStyleResolution() == selector->value();
    721 
    722     if (selector->isAttributeSelector()) {
    723         const QualifiedName& attr = selector->attribute();
    724 
    725         if (!element->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())
    726706            return false;
    727707
    728708        bool caseSensitive = !m_documentIsHTML || !htmlAttributeHasCaseInsensitiveValue(attr);
    729709
    730         if (!anyAttributeMatches(element, static_cast<CSSSelector::Match>(selector->m_match), attr, selector->value(), caseSensitive))
    731             return false;
    732     }
    733 
    734     if (selector->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) {
    735715        // 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()) {
    741719                // :not cannot nest. I don't really know why this is a
    742720                // restriction in CSS3, but it is, so let's honor it.
    743721                // the parser enforces that this never occurs
    744                 ASSERT(subContext.selector->pseudoType() != CSSSelector::PseudoNot);
     722                ASSERT(subSel->pseudoType() != CSSSelector::PseudoNot);
    745723                // We select between :visited and :link when applying. We don't know which one applied (or not) yet.
    746                 if (subContext.selector->pseudoType() == CSSSelector::PseudoVisited || (subContext.selector->pseudoType() == CSSSelector::PseudoLink && subContext.visitedMatchType == VisitedMatchEnabled))
     724                if (subSel->pseudoType() == CSSSelector::PseudoVisited || (subSel->pseudoType() == CSSSelector::PseudoLink && visitedMatchType == VisitedMatchEnabled))
    747725                    return true;
    748                 if (!checkOneSelector(subContext, dynamicPseudo))
     726                if (!checkOneSelector(subSel, e, dynamicPseudo, true, visitedMatchType, elementStyle, elementParentStyle))
    749727                    return true;
    750728            }
     
    752730            // CSS scrollbars match a specific subset of pseudo classes, and they have specialized rules for each
    753731            // (since there are no elements involved).
    754             return checkScrollbarPseudoClass(selector, dynamicPseudo);
     732            return checkScrollbarPseudoClass(sel, dynamicPseudo);
    755733        } else if (dynamicPseudo == SELECTION) {
    756             if (selector->pseudoType() == CSSSelector::PseudoWindowInactive)
     734            if (sel->pseudoType() == CSSSelector::PseudoWindowInactive)
    757735                return !m_document->page()->focusController()->isActive();
    758736        }
    759737
    760738        // Normal element pseudo class checking.
    761         switch (selector->pseudoType()) {
     739        switch (sel->pseudoType()) {
    762740            // Pseudo classes:
    763741        case CSSSelector::PseudoNot:
     
    766744            {
    767745                bool result = true;
    768                 for (Node* n = element->firstChild(); n; n = n->nextSibling()) {
     746                for (Node* n = e->firstChild(); n; n = n->nextSibling()) {
    769747                    if (n->isElementNode()) {
    770748                        result = false;
     
    780758                }
    781759                if (!m_isCollectingRulesOnly) {
    782                     if (context.elementStyle)
    783                         context.elementStyle->setEmptyState(result);
    784                     else if (element->renderStyle() && (element->document()->usesSiblingRules() || element->renderStyle()->unique()))
    785                         element->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);
    786764                }
    787765                return result;
     
    789767        case CSSSelector::PseudoFirstChild:
    790768            // first-child matches the first child that is an element
    791             if (element->parentElement()) {
     769            if (e->parentElement()) {
    792770                bool result = false;
    793                 if (!element->previousElementSibling())
     771                if (!e->previousElementSibling())
    794772                    result = true;
    795773                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();
    798776                    if (parentStyle)
    799777                        parentStyle->setChildrenAffectedByFirstChildRules();
     
    806784        case CSSSelector::PseudoFirstOfType:
    807785            // first-of-type matches the first element of its type
    808             if (element->parentElement()) {
     786            if (e->parentElement()) {
    809787                bool result = true;
    810                 const QualifiedName& type = element->tagQName();
    811                 for (const Element* sibling = element->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) {
     788                const QualifiedName& type = e->tagQName();
     789                for (const Element* sibling = e->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) {
    812790                    if (sibling->hasTagName(type)) {
    813791                        result = false;
     
    816794                }
    817795                if (!m_isCollectingRulesOnly) {
    818                     RenderStyle* parentStyle = context.elementStyle ? context.elementParentStyle : element->parentNode()->renderStyle();
     796                    RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
    819797                    if (parentStyle)
    820798                        parentStyle->setChildrenAffectedByForwardPositionalRules();
     
    825803        case CSSSelector::PseudoLastChild:
    826804            // last-child matches the last child that is an element
    827             if (Element* parentElement = element->parentElement()) {
    828                 bool result = parentElement->isFinishedParsingChildren() && !element->nextElementSibling();
     805            if (Element* parentElement = e->parentElement()) {
     806                bool result = parentElement->isFinishedParsingChildren() && !e->nextElementSibling();
    829807                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();
    832810                    if (parentStyle)
    833811                        parentStyle->setChildrenAffectedByLastChildRules();
     
    840818        case CSSSelector::PseudoLastOfType:
    841819            // last-of-type matches the last element of its type
    842             if (Element* parentElement = element->parentElement()) {
     820            if (Element* parentElement = e->parentElement()) {
    843821                if (!m_isCollectingRulesOnly) {
    844                     RenderStyle* parentStyle = context.elementStyle ? context.elementParentStyle : parentElement->renderStyle();
     822                    RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
    845823                    if (parentStyle)
    846824                        parentStyle->setChildrenAffectedByBackwardPositionalRules();
     
    848826                if (!parentElement->isFinishedParsingChildren())
    849827                    return false;
    850                 const QualifiedName& type = element->tagQName();
    851                 for (const Element* sibling = element->nextElementSibling(); sibling; sibling = sibling->nextElementSibling()) {
     828                const QualifiedName& type = e->tagQName();
     829                for (const Element* sibling = e->nextElementSibling(); sibling; sibling = sibling->nextElementSibling()) {
    852830                    if (sibling->hasTagName(type))
    853831                        return false;
     
    857835            break;
    858836        case CSSSelector::PseudoOnlyChild:
    859             if (Element* parentElement = element->parentElement()) {
    860                 bool firstChild = !element->previousElementSibling();
    861                 bool onlyChild = firstChild && parentElement->isFinishedParsingChildren() && !element->nextElementSibling();
     837            if (Element* parentElement = e->parentElement()) {
     838                bool firstChild = !e->previousElementSibling();
     839                bool onlyChild = firstChild && parentElement->isFinishedParsingChildren() && !e->nextElementSibling();
    862840
    863841                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();
    866844                    if (parentStyle) {
    867845                        parentStyle->setChildrenAffectedByFirstChildRules();
     
    878856        case CSSSelector::PseudoOnlyOfType:
    879857            // FIXME: This selector is very slow.
    880             if (Element* parentElement = element->parentElement()) {
     858            if (Element* parentElement = e->parentElement()) {
    881859                if (!m_isCollectingRulesOnly) {
    882                     RenderStyle* parentStyle = context.elementStyle ? context.elementParentStyle : parentElement->renderStyle();
     860                    RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
    883861                    if (parentStyle) {
    884862                        parentStyle->setChildrenAffectedByForwardPositionalRules();
     
    888866                if (!parentElement->isFinishedParsingChildren())
    889867                    return false;
    890                 const QualifiedName& type = element->tagQName();
    891                 for (const Element* sibling = element->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) {
     868                const QualifiedName& type = e->tagQName();
     869                for (const Element* sibling = e->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) {
    892870                    if (sibling->hasTagName(type))
    893871                        return false;
    894872                }
    895                 for (const Element* sibling = element->nextElementSibling(); sibling; sibling = sibling->nextElementSibling()) {
     873                for (const Element* sibling = e->nextElementSibling(); sibling; sibling = sibling->nextElementSibling()) {
    896874                    if (sibling->hasTagName(type))
    897875                        return false;
     
    901879            break;
    902880        case CSSSelector::PseudoNthChild:
    903             if (!selector->parseNth())
     881            if (!sel->parseNth())
    904882                break;
    905             if (Element* parentElement = element->parentElement()) {
     883            if (Element* parentElement = e->parentElement()) {
    906884                int count = 1;
    907                 for (const Element* sibling = element->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) {
     885                for (const Element* sibling = e->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) {
    908886                    RenderStyle* s = sibling->renderStyle();
    909887                    unsigned index = s ? s->childIndex() : 0;
     
    916894
    917895                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();
    920898                    if (childStyle)
    921899                        childStyle->setChildIndex(count);
     
    924902                }
    925903
    926                 if (selector->matchNth(count))
     904                if (sel->matchNth(count))
    927905                    return true;
    928906            }
    929907            break;
    930908        case CSSSelector::PseudoNthOfType:
    931             if (!selector->parseNth())
     909            if (!sel->parseNth())
    932910                break;
    933             if (Element* parentElement = element->parentElement()) {
     911            if (Element* parentElement = e->parentElement()) {
    934912                int count = 1;
    935                 const QualifiedName& type = element->tagQName();
    936                 for (const Element* sibling = element->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) {
     913                const QualifiedName& type = e->tagQName();
     914                for (const Element* sibling = e->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) {
    937915                    if (sibling->hasTagName(type))
    938916                        ++count;
    939917                }
    940918                if (!m_isCollectingRulesOnly) {
    941                     RenderStyle* parentStyle = context.elementStyle ? context.elementParentStyle : parentElement->renderStyle();
     919                    RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
    942920                    if (parentStyle)
    943921                        parentStyle->setChildrenAffectedByForwardPositionalRules();
    944922                }
    945923
    946                 if (selector->matchNth(count))
     924                if (sel->matchNth(count))
    947925                    return true;
    948926            }
    949927            break;
    950928        case CSSSelector::PseudoNthLastChild:
    951             if (!selector->parseNth())
     929            if (!sel->parseNth())
    952930                break;
    953             if (Element* parentElement = element->parentElement()) {
     931            if (Element* parentElement = e->parentElement()) {
    954932                if (!m_isCollectingRulesOnly) {
    955                     RenderStyle* parentStyle = context.elementStyle ? context.elementParentStyle : parentElement->renderStyle();
     933                    RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
    956934                    if (parentStyle)
    957935                        parentStyle->setChildrenAffectedByBackwardPositionalRules();
     
    960938                    return false;
    961939                int count = 1;
    962                 for (const Element* sibling = element->nextElementSibling(); sibling; sibling = sibling->nextElementSibling())
     940                for (const Element* sibling = e->nextElementSibling(); sibling; sibling = sibling->nextElementSibling())
    963941                    ++count;
    964                 if (selector->matchNth(count))
     942                if (sel->matchNth(count))
    965943                    return true;
    966944            }
    967945            break;
    968946        case CSSSelector::PseudoNthLastOfType:
    969             if (!selector->parseNth())
     947            if (!sel->parseNth())
    970948                break;
    971             if (Element* parentElement = element->parentElement()) {
     949            if (Element* parentElement = e->parentElement()) {
    972950                if (!m_isCollectingRulesOnly) {
    973                     RenderStyle* parentStyle = context.elementStyle ? context.elementParentStyle : parentElement->renderStyle();
     951                    RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
    974952                    if (parentStyle)
    975953                        parentStyle->setChildrenAffectedByBackwardPositionalRules();
     
    978956                    return false;
    979957                int count = 1;
    980                 const QualifiedName& type = element->tagQName();
    981                 for (const Element* sibling = element->nextElementSibling(); sibling; sibling = sibling->nextElementSibling()) {
     958                const QualifiedName& type = e->tagQName();
     959                for (const Element* sibling = e->nextElementSibling(); sibling; sibling = sibling->nextElementSibling()) {
    982960                    if (sibling->hasTagName(type))
    983961                        ++count;
    984962                }
    985                 if (selector->matchNth(count))
     963                if (sel->matchNth(count))
    986964                    return true;
    987965            }
    988966            break;
    989967        case CSSSelector::PseudoTarget:
    990             if (element == element->document()->cssTarget())
     968            if (e == e->document()->cssTarget())
    991969                return true;
    992970            break;
    993971        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;
    1001975            }
    1002976            break;
    1003977        case CSSSelector::PseudoAutofill:
    1004             if (!element || !element->isFormControlElement())
     978            if (!e || !e->isFormControlElement())
    1005979                break;
    1006             if (HTMLInputElement* inputElement = element->toInputElement())
     980            if (HTMLInputElement* inputElement = e->toInputElement())
    1007981                return inputElement->isAutofilled();
    1008982            break;
     
    1010984        case CSSSelector::PseudoLink:
    1011985            // :visited and :link matches are separated later when applying the style. Here both classes match all links...
    1012             return element->isLink();
     986            return e->isLink();
    1013987        case CSSSelector::PseudoVisited:
    1014988            // ...except if :visited matching is disabled for ancestor/sibling matching.
    1015             return element->isLink() && context.visitedMatchType == VisitedMatchEnabled;
     989            return e->isLink() && visitedMatchType == VisitedMatchEnabled;
    1016990        case CSSSelector::PseudoDrag:
    1017             if (context.elementStyle)
    1018                 context.elementStyle->setAffectedByDragRules(true);
    1019             else if (element->renderStyle())
    1020                 element->renderStyle()->setAffectedByDragRules(true);
    1021             if (element->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())
    1022996                return true;
    1023997            break;
    1024998        case CSSSelector::PseudoFocus:
    1025             return matchesFocusPseudoClass(element);
     999            return matchesFocusPseudoClass(e);
    10261000        case CSSSelector::PseudoHover:
    10271001            // If we're in quirks mode, then hover should never match anchors with no
    10281002            // 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 (element->renderStyle())
    1033                     element->renderStyle()->setAffectedByHoverRules(true);
    1034                 if (element->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))
    10351009                    return true;
    10361010            }
     
    10391013            // If we're in quirks mode, then :active should never match anchors with no
    10401014            // 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 (element->renderStyle())
    1045                     element->renderStyle()->setAffectedByActiveRules(true);
    1046                 if (element->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))
    10471021                    return true;
    10481022            }
    10491023            break;
    10501024        case CSSSelector::PseudoEnabled:
    1051             if (element && element->isFormControlElement())
    1052                 return element->isEnabledFormControl();
     1025            if (e && e->isFormControlElement())
     1026                return e->isEnabledFormControl();
    10531027            break;
    10541028        case CSSSelector::PseudoFullPageMedia:
    1055             return element && element->document() && element->document()->isMediaDocument();
     1029            return e && e->document() && e->document()->isMediaDocument();
    10561030            break;
    10571031        case CSSSelector::PseudoDefault:
    1058             return element && element->isDefaultButtonForForm();
     1032            return e && e->isDefaultButtonForForm();
    10591033        case CSSSelector::PseudoDisabled:
    1060             if (element && element->isFormControlElement())
    1061                 return !element->isEnabledFormControl();
     1034            if (e && e->isFormControlElement())
     1035                return !e->isEnabledFormControl();
    10621036            break;
    10631037        case CSSSelector::PseudoReadOnly:
    1064             if (!element || !element->isFormControlElement())
    1065                 return false;
    1066             return element->isTextFormControl() && element->isReadOnlyFormControl();
     1038            if (!e || !e->isFormControlElement())
     1039                return false;
     1040            return e->isTextFormControl() && e->isReadOnlyFormControl();
    10671041        case CSSSelector::PseudoReadWrite:
    1068             if (!element || !element->isFormControlElement())
    1069                 return false;
    1070             return element->isTextFormControl() && !element->isReadOnlyFormControl();
     1042            if (!e || !e->isFormControlElement())
     1043                return false;
     1044            return e->isTextFormControl() && !e->isReadOnlyFormControl();
    10711045        case CSSSelector::PseudoOptional:
    1072             return element && element->isOptionalFormControl();
     1046            return e && e->isOptionalFormControl();
    10731047        case CSSSelector::PseudoRequired:
    1074             return element && element->isRequiredFormControl();
     1048            return e && e->isRequiredFormControl();
    10751049        case CSSSelector::PseudoValid:
    1076             if (!element)
    1077                 return false;
    1078             element->document()->setContainsValidityStyleRules();
    1079             return element->willValidate() && element->isValidFormControlElement();
     1050            if (!e)
     1051                return false;
     1052            e->document()->setContainsValidityStyleRules();
     1053            return e->willValidate() && e->isValidFormControlElement();
    10801054        case CSSSelector::PseudoInvalid:
    1081             if (!element)
    1082                 return false;
    1083             element->document()->setContainsValidityStyleRules();
    1084             return (element->willValidate() && !element->isValidFormControlElement()) || element->hasUnacceptableValue();
     1055            if (!e)
     1056                return false;
     1057            e->document()->setContainsValidityStyleRules();
     1058            return (e->willValidate() && !e->isValidFormControlElement()) || e->hasUnacceptableValue();
    10851059        case CSSSelector::PseudoChecked:
    10861060            {
    1087                 if (!element || !element->isFormControlElement())
     1061                if (!e || !e->isFormControlElement())
    10881062                    break;
    10891063                // Even though WinIE allows checked and indeterminate to co-exist, the CSS selector spec says that
    10901064                // you can't be both checked and indeterminate. We will behave like WinIE behind the scenes and just
    10911065                // obey the CSS spec here in the test for matching the pseudo.
    1092                 HTMLInputElement* inputElement = element->toInputElement();
     1066                HTMLInputElement* inputElement = e->toInputElement();
    10931067                if (inputElement && inputElement->shouldAppearChecked() && !inputElement->isIndeterminate())
    10941068                    return true;
    1095                 if (element->hasTagName(optionTag) && toHTMLOptionElement(element)->selected())
     1069                if (e->hasTagName(optionTag) && toHTMLOptionElement(e)->selected())
    10961070                    return true;
    10971071                break;
     
    10991073        case CSSSelector::PseudoIndeterminate:
    11001074            {
    1101                 if (!element || !element->isFormControlElement())
     1075                if (!e || !e->isFormControlElement())
    11021076                    break;
    11031077#if ENABLE(PROGRESS_TAG)
    1104                 if (element->hasTagName(progressTag)) {
    1105                     HTMLProgressElement* progress = static_cast<HTMLProgressElement*>(element);
     1078                if (e->hasTagName(progressTag)) {
     1079                    HTMLProgressElement* progress = static_cast<HTMLProgressElement*>(e);
    11061080                    if (progress && !progress->isDeterminate())
    11071081                        return true;
     
    11091083                }
    11101084#endif
    1111                 HTMLInputElement* inputElement = element->toInputElement();
     1085                HTMLInputElement* inputElement = e->toInputElement();
    11121086                if (inputElement && inputElement->isIndeterminate())
    11131087                    return true;
     
    11151089            }
    11161090        case CSSSelector::PseudoRoot:
    1117             if (element == element->document()->documentElement())
     1091            if (e == e->document()->documentElement())
    11181092                return true;
    11191093            break;
    11201094        case CSSSelector::PseudoLang:
    11211095            {
    1122                 AtomicString value = element->computeInheritedLanguage();
    1123                 const AtomicString& argument = selector->argument();
     1096                AtomicString value = e->computeInheritedLanguage();
     1097                const AtomicString& argument = sel->argument();
    11241098                if (value.isEmpty() || !value.startsWith(argument, false))
    11251099                    break;
     
    11341108            // that element. Also, an <iframe>, <object> or <embed> element whose child browsing
    11351109            // context's Document is in the fullscreen state has the 'full-screen' pseudoclass applied.
    1136             if (element->isFrameElementBase() && static_cast<HTMLFrameElementBase*>(element)->containsFullScreenElement())
     1110            if (e->isFrameElementBase() && static_cast<HTMLFrameElementBase*>(e)->containsFullScreenElement())
    11371111                return true;
    1138             if (!element->document()->webkitIsFullScreen())
    1139                 return false;
    1140             return element == element->document()->webkitCurrentFullScreenElement();
     1112            if (!e->document()->webkitIsFullScreen())
     1113                return false;
     1114            return e == e->document()->webkitCurrentFullScreenElement();
    11411115        case CSSSelector::PseudoAnimatingFullScreenTransition:
    1142             if (element != element->document()->webkitCurrentFullScreenElement())
    1143                 return false;
    1144             return element->document()->isAnimatingFullScreen();
     1116            if (e != e->document()->webkitCurrentFullScreenElement())
     1117                return false;
     1118            return e->document()->isAnimatingFullScreen();
    11451119        case CSSSelector::PseudoFullScreenAncestor:
    1146             return element->containsFullScreenElement();
     1120            return e->containsFullScreenElement();
    11471121        case CSSSelector::PseudoFullScreenDocument:
    11481122            // While a Document is in the fullscreen state, the 'full-screen-document' pseudoclass applies
    11491123            // to all elements of that Document.
    1150             if (!element->document()->webkitIsFullScreen())
     1124            if (!e->document()->webkitIsFullScreen())
    11511125                return false;
    11521126            return true;
    11531127#endif
    11541128        case CSSSelector::PseudoInRange:
    1155             if (!element)
    1156                 return false;
    1157             element->document()->setContainsValidityStyleRules();
    1158             return element->isInRange();
     1129            if (!e)
     1130                return false;
     1131            e->document()->setContainsValidityStyleRules();
     1132            return e->isInRange();
    11591133        case CSSSelector::PseudoOutOfRange:
    1160             if (!element)
    1161                 return false;
    1162             element->document()->setContainsValidityStyleRules();
    1163             return element->isOutOfRange();
     1134            if (!e)
     1135                return false;
     1136            e->document()->setContainsValidityStyleRules();
     1137            return e->isOutOfRange();
    11641138        case CSSSelector::PseudoUnknown:
    11651139        case CSSSelector::PseudoNotParsed:
     
    11701144        return false;
    11711145    }
    1172     if (selector->m_match == CSSSelector::PseudoElement) {
    1173         if (!context.elementStyle && !m_isCollectingRulesOnly)
    1174             return false;
    1175 
    1176         if (selector->isUnknownPseudoElement()) {
     1146    if (sel->m_match == CSSSelector::PseudoElement) {
     1147        if (!elementStyle && !m_isCollectingRulesOnly)
     1148            return false;
     1149
     1150        if (sel->isUnknownPseudoElement()) {
    11771151            m_hasUnknownPseudoElements = true;
    1178             return element->shadowPseudoId() == selector->value();
    1179         }
    1180 
    1181         PseudoId pseudoId = CSSSelector::pseudoId(selector->pseudoType());
     1152            return e->shadowPseudoId() == sel->value();
     1153        }
     1154
     1155        PseudoId pseudoId = CSSSelector::pseudoId(sel->pseudoType());
    11821156        if (pseudoId == FIRST_LETTER) {
    1183             if (Document* document = element->document())
     1157            if (Document* document = e->document())
    11841158                document->setUsesFirstLetterRules(true);
    11851159        }
  • trunk/Source/WebCore/css/SelectorChecker.h

    r107197 r107205  
    5252    enum SelectorMatch { SelectorMatches, SelectorFailsLocally, SelectorFailsAllSiblings, SelectorFailsCompletely };
    5353    enum VisitedMatchType { VisitedMatchDisabled, VisitedMatchEnabled };
    54 
    55     struct SelectorCheckingContext {
    56         // Initial selector constructor
    57         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 
    7454    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;
    7656    static bool isFastCheckableSelector(const CSSSelector*);
    7757    bool fastCheckSelector(const CSSSelector*, const Element*) const;
     
    11797
    11898private:
    119     bool checkOneSelector(const SelectorCheckingContext&, PseudoId&) const;
     99    bool checkOneSelector(CSSSelector*, Element*, PseudoId& dynamicPseudo, bool isSubSelector, VisitedMatchType, RenderStyle*, RenderStyle* elementParentStyle) const;
    120100    bool checkScrollbarPseudoClass(CSSSelector*, PseudoId& dynamicPseudo) const;
    121101    static bool isFrameFocused(const Element*);
Note: See TracChangeset for help on using the changeset viewer.