Changeset 176623 in webkit


Ignore:
Timestamp:
Dec 1, 2014 6:29:53 PM (9 years ago)
Author:
benjamin@webkit.org
Message:

Add the dynamic specificity of the selector list argument when matching :nth-child() and :nth-last-child()
https://bugs.webkit.org/show_bug.cgi?id=139001

Reviewed by Andreas Kling.

Source/WebCore:

When matching :nth-child(An+B of selector list) or :nth-last-child(An+B of selector list),
we were previously ignoring the arguments.

That behavior seems to be confusing for users. We made the proposal to include the selector list
like when using :matches():

http://lists.w3.org/Archives/Public/www-style/2014Oct/0533.html

David Baron also agrees with this behavior:

http://lists.w3.org/Archives/Public/www-style/2014Oct/0534.html

This patch adds the specificity computation.

Tests: fast/css/nth-child-specificity-1.html

fast/css/nth-child-specificity-2.html
fast/css/nth-last-child-specificity-1.html
fast/css/nth-last-child-specificity-2.html

  • css/CSSSelector.cpp:

(WebCore::simpleSelectorFunctionalPseudoClassStaticSpecificity):

  • css/SelectorChecker.cpp:

(WebCore::SelectorChecker::checkOne):
(WebCore::SelectorChecker::matchSelectorList):

  • css/SelectorChecker.h:
  • cssjit/SelectorCompiler.cpp:

(WebCore::SelectorCompiler::addPseudoClassType):

LayoutTests:

  • fast/css/nth-child-specificity-1-expected.html: Added.
  • fast/css/nth-child-specificity-1.html: Added.
  • fast/css/nth-child-specificity-2-expected.html: Added.
  • fast/css/nth-child-specificity-2.html: Added.
  • fast/css/nth-child-specificity-3-expected.html: Added.
  • fast/css/nth-child-specificity-3.html: Added.
  • fast/css/nth-child-specificity-4-expected.html: Added.
  • fast/css/nth-child-specificity-4.html: Added.
  • fast/css/nth-last-child-specificity-1-expected.html: Added.
  • fast/css/nth-last-child-specificity-1.html: Added.
  • fast/css/nth-last-child-specificity-2-expected.html: Added.
  • fast/css/nth-last-child-specificity-2.html: Added.
  • fast/css/nth-last-child-specificity-3-expected.html: Added.
  • fast/css/nth-last-child-specificity-3.html: Added.
  • fast/css/nth-last-child-specificity-4-expected.html: Added.
  • fast/css/nth-last-child-specificity-4.html: Added.
Location:
trunk
Files:
16 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r176619 r176623  
     12014-12-01  Benjamin Poulain  <benjamin@webkit.org>
     2
     3        Add the dynamic specificity of the selector list argument when matching :nth-child() and :nth-last-child()
     4        https://bugs.webkit.org/show_bug.cgi?id=139001
     5
     6        Reviewed by Andreas Kling.
     7
     8        * fast/css/nth-child-specificity-1-expected.html: Added.
     9        * fast/css/nth-child-specificity-1.html: Added.
     10        * fast/css/nth-child-specificity-2-expected.html: Added.
     11        * fast/css/nth-child-specificity-2.html: Added.
     12        * fast/css/nth-child-specificity-3-expected.html: Added.
     13        * fast/css/nth-child-specificity-3.html: Added.
     14        * fast/css/nth-child-specificity-4-expected.html: Added.
     15        * fast/css/nth-child-specificity-4.html: Added.
     16        * fast/css/nth-last-child-specificity-1-expected.html: Added.
     17        * fast/css/nth-last-child-specificity-1.html: Added.
     18        * fast/css/nth-last-child-specificity-2-expected.html: Added.
     19        * fast/css/nth-last-child-specificity-2.html: Added.
     20        * fast/css/nth-last-child-specificity-3-expected.html: Added.
     21        * fast/css/nth-last-child-specificity-3.html: Added.
     22        * fast/css/nth-last-child-specificity-4-expected.html: Added.
     23        * fast/css/nth-last-child-specificity-4.html: Added.
     24
     25
    1262014-12-01  Zalan Bujtas  <zalan@apple.com>
    227
  • trunk/Source/WebCore/ChangeLog

    r176621 r176623  
     12014-12-01  Benjamin Poulain  <benjamin@webkit.org>
     2
     3        Add the dynamic specificity of the selector list argument when matching :nth-child() and :nth-last-child()
     4        https://bugs.webkit.org/show_bug.cgi?id=139001
     5
     6        Reviewed by Andreas Kling.
     7
     8        When matching :nth-child(An+B of selector list) or :nth-last-child(An+B of selector list),
     9        we were previously ignoring the arguments.
     10
     11        That behavior seems to be confusing for users. We made the proposal to include the selector list
     12        like when using :matches():
     13            http://lists.w3.org/Archives/Public/www-style/2014Oct/0533.html
     14        David Baron also agrees with this behavior:
     15            http://lists.w3.org/Archives/Public/www-style/2014Oct/0534.html
     16
     17        This patch adds the specificity computation.
     18
     19        Tests: fast/css/nth-child-specificity-1.html
     20               fast/css/nth-child-specificity-2.html
     21               fast/css/nth-last-child-specificity-1.html
     22               fast/css/nth-last-child-specificity-2.html
     23
     24        * css/CSSSelector.cpp:
     25        (WebCore::simpleSelectorFunctionalPseudoClassStaticSpecificity):
     26        * css/SelectorChecker.cpp:
     27        (WebCore::SelectorChecker::checkOne):
     28        (WebCore::SelectorChecker::matchSelectorList):
     29        * css/SelectorChecker.h:
     30        * cssjit/SelectorCompiler.cpp:
     31        (WebCore::SelectorCompiler::addPseudoClassType):
     32
    1332014-12-01  Chris Dumez  <cdumez@apple.com>
    234
  • trunk/Source/WebCore/css/CSSSelector.cpp

    r176545 r176623  
    132132{
    133133    if (simpleSelector.match() == CSSSelector::PseudoClass) {
    134         if (simpleSelector.pseudoClassType() == CSSSelector::PseudoClassMatches) {
    135             const CSSSelectorList& selectorList = *simpleSelector.selectorList();
    136             const CSSSelector& firstSubselector = *selectorList.first();
     134        CSSSelector::PseudoClassType pseudoClassType = simpleSelector.pseudoClassType();
     135        if (pseudoClassType == CSSSelector::PseudoClassMatches || pseudoClassType == CSSSelector::PseudoClassNthChild || pseudoClassType == CSSSelector::PseudoClassNthLastChild) {
     136            const CSSSelectorList* selectorList = simpleSelector.selectorList();
     137            if (!selectorList) {
     138                ASSERT_WITH_MESSAGE(pseudoClassType != CSSSelector::PseudoClassMatches, ":matches() should never be created without a valid selector list.");
     139                return 0;
     140            }
     141
     142            const CSSSelector& firstSubselector = *selectorList->first();
    137143
    138144            unsigned initialSpecificity = staticSpecificityInternal(firstSubselector, ok);
  • trunk/Source/WebCore/css/SelectorChecker.cpp

    r176545 r176623  
    745745#if ENABLE(CSS_SELECTORS_LEVEL4)
    746746                if (const CSSSelectorList* selectorList = selector->selectorList()) {
    747                     if (!matchSelectorList(context, *element, *selectorList))
     747                    unsigned selectorListSpecificity;
     748                    if (matchSelectorList(context, *element, *selectorList, selectorListSpecificity))
     749                        specificity = CSSSelector::addSpecificities(specificity, selectorListSpecificity);
     750                    else
    748751                        return false;
    749752                }
     
    760763                            sibling->setAffectsNextSiblingElementStyle();
    761764
    762                         if (matchSelectorList(context, *sibling, *selectorList))
     765                        unsigned ignoredSpecificity;
     766                        if (matchSelectorList(context, *sibling, *selectorList, ignoredSpecificity))
    763767                            ++count;
    764768                    }
     
    797801#if ENABLE(CSS_SELECTORS_LEVEL4)
    798802                if (const CSSSelectorList* selectorList = selector->selectorList()) {
    799                     if (!matchSelectorList(context, *element, *selectorList))
     803                    unsigned selectorListSpecificity;
     804                    if (matchSelectorList(context, *element, *selectorList, selectorListSpecificity))
     805                        specificity = CSSSelector::addSpecificities(specificity, selectorListSpecificity);
     806                    else
    800807                        return false;
    801808
     
    813820                if (const CSSSelectorList* selectorList = selector->selectorList()) {
    814821                    for (Element* sibling = ElementTraversal::nextSibling(element); sibling; sibling = ElementTraversal::nextSibling(sibling)) {
    815                         if (matchSelectorList(context, *sibling, *selectorList))
     822                        unsigned ignoredSpecificity;
     823                        if (matchSelectorList(context, *sibling, *selectorList, ignoredSpecificity))
    816824                            ++count;
    817825                    }
     
    10301038}
    10311039
    1032 bool SelectorChecker::matchSelectorList(const CheckingContextWithStatus& baseContext, Element& element, const CSSSelectorList& selectorList) const
    1033 {
     1040bool SelectorChecker::matchSelectorList(const CheckingContextWithStatus& baseContext, Element& element, const CSSSelectorList& selectorList, unsigned& specificity) const
     1041{
     1042    specificity = 0;
     1043    bool hasMatchedAnything = false;
     1044
    10341045    for (const CSSSelector* subselector = selectorList.first(); subselector; subselector = CSSSelectorList::next(subselector)) {
    10351046        CheckingContextWithStatus subcontext(baseContext);
     
    10431054        if (matchRecursively(subcontext, ignoreDynamicPseudo, localSpecificity).match == Match::SelectorMatches) {
    10441055            ASSERT(!ignoreDynamicPseudo);
    1045             return true;
    1046         }
    1047     }
    1048     return false;
     1056
     1057            hasMatchedAnything = true;
     1058            specificity = std::max(specificity, localSpecificity);
     1059        }
     1060    }
     1061    return hasMatchedAnything;
    10491062}
    10501063
  • trunk/Source/WebCore/css/SelectorChecker.h

    r176152 r176623  
    110110    MatchResult matchRecursively(const CheckingContextWithStatus&, PseudoIdSet&, unsigned& specificity) const;
    111111    bool checkOne(const CheckingContextWithStatus&, PseudoIdSet&, MatchType&, unsigned& specificity) const;
    112     bool matchSelectorList(const CheckingContextWithStatus&, Element&, const CSSSelectorList&) const;
     112    bool matchSelectorList(const CheckingContextWithStatus&, Element&, const CSSSelectorList&, unsigned& specificity) const;
    113113
    114114    bool checkScrollbarPseudoClass(const CheckingContextWithStatus&, const CSSSelector*) const;
  • trunk/Source/WebCore/cssjit/SelectorCompiler.cpp

    r176545 r176623  
    637637                    globalFunctionType = FunctionType::SelectorCheckerWithCheckingContext;
    638638
     639                unsigned firstFragmentListSpecificity = 0;
     640                bool firstFragmentListSpecificitySet = false;
     641
    639642                for (const CSSSelector* subselector = selectorList->first(); subselector; subselector = CSSSelectorList::next(subselector)) {
    640643                    SelectorFragmentList selectorFragments;
     
    652655                        return FunctionType::CannotCompile;
    653656                    }
     657
     658                    if (firstFragmentListSpecificitySet) {
     659                        // The CSS JIT does not handle dynamic specificity yet.
     660                        if (selectorContext == SelectorContext::RuleCollector && selectorFragments.staticSpecificity != firstFragmentListSpecificity)
     661                            return FunctionType::CannotCompile;
     662                    } else {
     663                        firstFragmentListSpecificitySet = true;
     664                        firstFragmentListSpecificity = selectorFragments.staticSpecificity;
     665                    }
     666
    654667                    globalFunctionType = mostRestrictiveFunctionType(globalFunctionType, functionType);
    655668                }
     669                internalSpecificity = firstFragmentListSpecificity;
    656670                fragment.nthChildOfFilters.append(nthChildOfSelectorInfo);
    657671                return globalFunctionType;
Note: See TracChangeset for help on using the changeset viewer.