⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 167585 in webkit


Ignore:
Timestamp:
Apr 20, 2014, 11:26:20 PM (12 years ago)
Author:
benjamin@webkit.org
Message:

Compile the :root pseudo class and fix a related issue with :nth-child()
https://bugs.webkit.org/show_bug.cgi?id=131926

Reviewed by Andreas Kling.

Source/WebCore:
Add the :root pseudo class. This is another trivial selector, we just need to compare
the element pointer with the documentElement.

I discovered some issues with :nth-child(n) through the layout tests for ":root".
When the pseudo class nth-child could match anything, no code was generated. That decision
was taken when generating the fragments.

The specification of :nth-child() has two tests: the parent test and the counter test.
Since some fragments would not generate any code for :nth-child(n), they would succeed on the root,
which is incorrect since the root should fail the parent test.

This was fixed by moving the filtering of non-counting :nth-child() after we generate the parent
check.
We still don't generate any counter test unless required.

Test: fast/selectors/nth-child-on-root.html

  • cssjit/SelectorCompiler.cpp:

(WebCore::SelectorCompiler::addPseudoClassType):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementMatching):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsNthChild):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsRoot):

  • dom/Document.h:

(WebCore::Document::documentElementMemoryOffset):

LayoutTests:
Add more test coverage that would have caught the bug with :nth-child(n).

  • fast/selectors/nth-child-on-root-expected.txt: Added.
  • fast/selectors/nth-child-on-root.html: Added.
Location:
trunk
Files:
2 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r167584 r167585  
     12014-04-20  Benjamin Poulain  <benjamin@webkit.org>
     2
     3        Compile the :root pseudo class and fix a related issue with :nth-child()
     4        https://bugs.webkit.org/show_bug.cgi?id=131926
     5
     6        Reviewed by Andreas Kling.
     7
     8        Add more test coverage that would have caught the bug with :nth-child(n).
     9
     10        * fast/selectors/nth-child-on-root-expected.txt: Added.
     11        * fast/selectors/nth-child-on-root.html: Added.
     12
    1132014-04-20  Benjamin Poulain  <benjamin@webkit.org>
    214
  • trunk/Source/WebCore/ChangeLog

    r167584 r167585  
     12014-04-20  Benjamin Poulain  <benjamin@webkit.org>
     2
     3        Compile the :root pseudo class and fix a related issue with :nth-child()
     4        https://bugs.webkit.org/show_bug.cgi?id=131926
     5
     6        Reviewed by Andreas Kling.
     7
     8        Add the :root pseudo class. This is another trivial selector, we just need to compare
     9        the element pointer with the documentElement.
     10
     11        I discovered some issues with :nth-child(n) through the layout tests for ":root".
     12        When the pseudo class nth-child could match anything, no code was generated. That decision
     13        was taken when generating the fragments.
     14
     15        The specification of :nth-child() has two tests: the parent test and the counter test.
     16        Since some fragments would not generate any code for :nth-child(n), they would succeed on the root,
     17        which is incorrect since the root should fail the parent test.
     18
     19        This was fixed by moving the filtering of non-counting :nth-child() after we generate the parent
     20        check.
     21        We still don't generate any counter test unless required.
     22
     23        Test: fast/selectors/nth-child-on-root.html
     24
     25        * cssjit/SelectorCompiler.cpp:
     26        (WebCore::SelectorCompiler::addPseudoClassType):
     27        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementMatching):
     28        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsNthChild):
     29        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsRoot):
     30        * dom/Document.h:
     31        (WebCore::Document::documentElementMemoryOffset):
     32
    1332014-04-20  Benjamin Poulain  <benjamin@webkit.org>
    234
  • trunk/Source/WebCore/cssjit/SelectorCompiler.cpp

    r167575 r167585  
    191191    void generateElementIsLink(Assembler::JumpList& failureCases);
    192192    void generateElementIsNthChild(Assembler::JumpList& failureCases, const SelectorFragment&);
     193    void generateElementIsRoot(Assembler::JumpList& failureCases);
    193194    void generateElementIsTarget(Assembler::JumpList& failureCases);
    194195
     
    320321
    321322    case CSSSelector::PseudoClassLink:
     323    case CSSSelector::PseudoClassRoot:
    322324    case CSSSelector::PseudoClassTarget:
    323325        fragment.pseudoClasses.add(type);
     
    343345            if (a <= 0 && b < 1)
    344346                return FunctionType::CannotMatchAnything;
    345 
    346             // Anything modulo 1 is zero. Unless b restrict the range, this does not filter anything out.
    347             if (a == 1 && (!b || (b == 1)))
    348                 return FunctionType::SimpleSelectorChecker;
    349347
    350348            fragment.nthChildfilters.append(std::pair<int, int>(a, b));
     
    11691167        generateElementIsLink(failureCases);
    11701168
     1169    if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassRoot))
     1170        generateElementIsRoot(failureCases);
     1171
    11711172    if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassTarget))
    11721173        generateElementIsTarget(failureCases);
     
    19431944    generateWalkToParentElement(failureCases, parentElement);
    19441945
     1946    Vector<std::pair<int, int>> validSubsetFilters;
     1947    validSubsetFilters.reserveInitialCapacity(fragment.nthChildfilters.size());
     1948    for (const auto& slot : fragment.nthChildfilters) {
     1949        int a = slot.first;
     1950        int b = slot.second;
     1951
     1952        // Anything modulo 1 is zero. Unless b restricts the range, this does not filter anything out.
     1953        if (a == 1 && (!b || (b == 1)))
     1954            continue;
     1955        validSubsetFilters.uncheckedAppend(slot);
     1956    }
     1957    if (validSubsetFilters.isEmpty())
     1958        return;
     1959
    19451960    // Setup the counter at 1.
    19461961    LocalRegister elementCounter(m_registerAllocator);
     
    20192034
    20202035    // Test every the nth-child filter.
    2021     for (const auto& slot : fragment.nthChildfilters) {
     2036    for (const auto& slot : validSubsetFilters) {
    20222037        int a = slot.first;
    20232038        int b = slot.second;
     
    20442059}
    20452060
     2061void SelectorCodeGenerator::generateElementIsRoot(Assembler::JumpList& failureCases)
     2062{
     2063    LocalRegister document(m_registerAllocator);
     2064    getDocument(m_assembler, elementAddressRegister, document);
     2065    failureCases.append(m_assembler.branchPtr(Assembler::NotEqual, Assembler::Address(document, Document::documentElementMemoryOffset()), elementAddressRegister));
     2066}
     2067
    20462068void SelectorCodeGenerator::generateElementIsTarget(Assembler::JumpList& failureCases)
    20472069{
  • trunk/Source/WebCore/dom/Document.h

    r167574 r167585  
    407407        return m_documentElement.get();
    408408    }
     409    static ptrdiff_t documentElementMemoryOffset() { return OBJECT_OFFSETOF(Document, m_documentElement); }
    409410
    410411    Element* activeElement();
Note: See TracChangeset for help on using the changeset viewer.