| Differences between
and this patch
- a/LayoutTests/ChangeLog +40 lines
Lines 1-3 a/LayoutTests/ChangeLog_sec1
1
2020-04-13  Antti Koivisto  <antti@apple.com>
2
3
        [CSS Selectors] Remove dynamic specificity
4
        https://bugs.webkit.org/show_bug.cgi?id=210419
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        Update specificity tests for static behavior, trying to also keep them useful.
9
10
        * fast/css/is-specificity-10-expected.html:
11
        * fast/css/is-specificity-10.html:
12
        * fast/css/is-specificity-2-expected.html:
13
        * fast/css/is-specificity-2.html:
14
        * fast/css/is-specificity-3-expected.html:
15
        * fast/css/is-specificity-3.html:
16
        * fast/css/is-specificity-4-expected.html:
17
        * fast/css/is-specificity-4.html:
18
        * fast/css/is-specificity-5.html:
19
        * fast/css/matches-specificity-10-expected.html:
20
        * fast/css/matches-specificity-10.html:
21
        * fast/css/matches-specificity-2-expected.html:
22
        * fast/css/matches-specificity-2.html:
23
        * fast/css/matches-specificity-3-expected.html:
24
        * fast/css/matches-specificity-3.html:
25
        * fast/css/matches-specificity-4-expected.html:
26
        * fast/css/matches-specificity-4.html:
27
        * fast/css/matches-specificity-5.html:
28
        * fast/css/nth-child-specificity-2-expected.html:
29
        * fast/css/nth-child-specificity-2.html:
30
        * fast/css/nth-child-specificity-3-expected.html:
31
        * fast/css/nth-child-specificity-3.html:
32
        * fast/css/nth-child-specificity-4-expected.html:
33
        * fast/css/nth-child-specificity-4.html:
34
        * fast/css/nth-last-child-specificity-2-expected.html:
35
        * fast/css/nth-last-child-specificity-2.html:
36
        * fast/css/nth-last-child-specificity-3-expected.html:
37
        * fast/css/nth-last-child-specificity-3.html:
38
        * fast/css/nth-last-child-specificity-4-expected.html:
39
        * fast/css/nth-last-child-specificity-4.html:
40
1
2020-04-12  Lauro Moura  <lmoura@igalia.com>
41
2020-04-12  Lauro Moura  <lmoura@igalia.com>
2
42
3
        [WPE] Layout test gardening.
43
        [WPE] Layout test gardening.
- a/LayoutTests/fast/css/is-specificity-10-expected.html -2 lines
Lines 1-8 a/LayoutTests/fast/css/is-specificity-10-expected.html_sec1
1
<!doctype html>
1
<!doctype html>
2
<html>
2
<html>
3
<body>
3
<body>
4
    <p>This test the dynamic specificity of :is() with a simple descendant backtracking case. The test pass if each block has style matching its description. None of the result should have a border.</p>
5
6
    <foo id="b">
4
    <foo id="b">
7
        <foo id="c">
5
        <foo id="c">
8
            <e>
6
            <e>
- a/LayoutTests/fast/css/is-specificity-10.html -19 / +18 lines
Lines 2-9 a/LayoutTests/fast/css/is-specificity-10.html_sec1
2
<html>
2
<html>
3
<head>
3
<head>
4
<style>
4
<style>
5
    /* Specificity (2, 0, 2). */
5
    /* Specificity (3, 0, 2). */
6
    #f#f > padding > target {
6
    #f#f#f > padding > target {
7
        background-color: purple;
7
        background-color: purple;
8
    }
8
    }
9
9
Lines 23-43 a/LayoutTests/fast/css/is-specificity-10.html_sec2
23
        border: 5px blue solid;
23
        border: 5px blue solid;
24
    }
24
    }
25
25
26
    /* Specificity (3, 0, 1) */
26
    :is(aBlock, #b) > :is(#c, d) > :is(e, #f) target {
27
    :is(aBlock, #b) > :is(#c, d) > :is(e, #f) target {
27
        background-color: green;
28
        background-color: green;
28
        color: white;
29
        color: white;
29
        border: none;
30
        border: none;
30
    }
31
    }
32
33
    /* Specificity (3, 0, 2) */
34
    #c#c#c padding target {
35
        background-color: green;
36
    }
37
38
    /* Specificity (3, 0, 1) */
39
    #f#f#f target {
40
        background-color: green;
41
    }
42
43
    /* Specificity (3, 0, 2) */
44
    a #f#f#f target {
45
        color: green;
46
    }
31
</style>
47
</style>
32
</head>
48
</head>
33
<body>
49
<body>
34
    <p>This test the dynamic specificity of :is() with a simple descendant backtracking case. The test pass if each block has style matching its description. None of the result should have a border.</p>
35
36
    <!--
37
     This case should match ":is(a, #b) > :is(#c, d) > :is(e, #f) target"
38
     like "#a > #c > e target"
39
     with the specificity (2, 0, 2).
40
     -->
41
    <foo id="b">
50
    <foo id="b">
42
        <foo id="c">
51
        <foo id="c">
43
            <e> <!-- Success case from here. -->
52
            <e> <!-- Success case from here. -->
Lines 64-74 a/LayoutTests/fast/css/is-specificity-10.html_sec3
64
        </foo>
73
        </foo>
65
    </foo>
74
    </foo>
66
75
67
    <!--
68
     This case should match ":is(a, #b) > :is(#c, d) > :is(e, #f) target"
69
     like "#a > d > e target"
70
     with the specificity (1, 0, 3).
71
     -->
72
    <foo id="b">
76
    <foo id="b">
73
        <d>
77
        <d>
74
            <e> <!-- Success case from here. -->
78
            <e> <!-- Success case from here. -->
Lines 95-105 a/LayoutTests/fast/css/is-specificity-10.html_sec4
95
        </d>
99
        </d>
96
    </foo>
100
    </foo>
97
101
98
    <!--
99
     This case should match ":is(a, #b) > :is(#c, d) > :is(e, #f) target"
100
     like "a > d > e target"
101
     with the specificity (0, 0, 4).
102
     -->
103
    <aBlock>
102
    <aBlock>
104
        <d>
103
        <d>
105
            <e> <!-- Success case from here. -->
104
            <e> <!-- Success case from here. -->
- a/LayoutTests/fast/css/is-specificity-2-expected.html -2 / +1 lines
Lines 8-14 a/LayoutTests/fast/css/is-specificity-2-expected.html_sec1
8
</style>
8
</style>
9
</head>
9
</head>
10
<body>
10
<body>
11
    <p>This test the specificity of :is() with a dynamic specificity of zero. The test passes if the text "target" is displayed white on green background.</p>
11
    <target style="color: blue;">Target</target>
12
    <target style="background-color: green; color: white;">Target</target>
13
</body>
12
</body>
14
</html>
13
</html>
- a/LayoutTests/fast/css/is-specificity-2.html -6 / +1 lines
Lines 15-26 a/LayoutTests/fast/css/is-specificity-2.html_sec1
15
        background-color: green;
15
        background-color: green;
16
    }
16
    }
17
17
18
    /* The only dynamic selector that matches is "*". Every rules except the first one (* selector) should override the style defined here.
19
       Background-color is defined by the two tag selectors above.
20
       Color is defined below by the star rule. It has the same specificity but a higher position.
21
       Border overrides the black border defined in the first rule. */
22
    :is(#foo, .bar, target.notthere, *, foo>bar) {
18
    :is(#foo, .bar, target.notthere, *, foo>bar) {
23
        background-color: red;
19
        background-color: white;
24
        color: blue;
20
        color: blue;
25
        border: none;
21
        border: none;
26
    }
22
    }
Lines 30-36 a/LayoutTests/fast/css/is-specificity-2.html_sec2
30
</style>
26
</style>
31
</head>
27
</head>
32
<body>
28
<body>
33
    <p>This test the specificity of :is() with a dynamic specificity of zero. The test passes if the text "target" is displayed white on green background.</p>
34
    <target>Target</target>
29
    <target>Target</target>
35
</body>
30
</body>
36
</html>
31
</html>
- a/LayoutTests/fast/css/is-specificity-3-expected.html -18 / +8 lines
Lines 1-25 a/LayoutTests/fast/css/is-specificity-3-expected.html_sec1
1
<!doctype html>
1
<!doctype html>
2
<html>
2
<html>
3
<head>
3
<head>
4
<style>
5
    body > * {
6
        display: block;
7
    }
8
    html, body, p {
9
        background-color: white;
10
        color: black;
11
    }
12
</style>
13
</head>
4
</head>
14
<body>
5
<body>
15
    <p>This test checks the dynamic specificity of :is() changing the order in which rules are applied depending on the element. Each element should have the colors described in the text and no border.</p>
6
<div style="color: purple; background-color: blue;">Text</nottarget>
16
    <nottarget style="color: purple; background-color: red;">Purple text on red background.</nottarget>
7
<div style="color: purple; background-color: green;">Text</nottarget>
17
    <target style="color: white; background-color: green;">White text on green background.</target>
8
<div style="color: purple; background-color: blue;">Text</nottarget>
18
    <nottarget style="color: purple; background-color: red;">Purple text on red background.</nottarget>
9
<div style="color: purple; background-color: green;">Text</nottarget>
19
    <target style="color: purple; background-color: red;">Purple text on red background.</target>
10
<div style="color: purple; background-color: blue;">Text</nottarget>
20
    <nottarget style="color: purple; background-color: blue;">Purple text on blue background.</nottarget>
11
<div style="color: purple; background-color: blue;">Text</nottarget>
21
    <target style="color: purple; background-color: blue;">Purple text on blue background.</target>
12
<div style="color: purple; background-color: blue;">Text</nottarget>
22
    <nottarget style="color: purple; background-color: red;">Purple text on red background.</nottarget>
13
<div style="color: purple; background-color: blue;">Text</nottarget>
23
    <target style="color: purple; background-color: red;">Purple text on red background.</target>
24
</body>
14
</body>
25
</html>
15
</html>
- a/LayoutTests/fast/css/is-specificity-3.html -13 / +9 lines
Lines 8-17 a/LayoutTests/fast/css/is-specificity-3.html_sec1
8
        border: 5px solid black;
8
        border: 5px solid black;
9
    }
9
    }
10
10
11
    /* The following :is() gets a different class of specificity. Depending on what
11
    :is(.classB, target, *) {
12
       matches, the later rules may override this or not. */
13
    :is(.classB, target, #classA, *) {
14
        background-color: red;
15
        color: purple;
12
        color: purple;
16
        border: none;
13
        border: none;
17
    }
14
    }
Lines 33-46 a/LayoutTests/fast/css/is-specificity-3.html_sec2
33
</style>
30
</style>
34
</head>
31
</head>
35
<body>
32
<body>
36
    <p>This test checks the dynamic specificity of :is() changing the order in which rules are applied depending on the element. Each element should have the colors described in the text and no border.</p>
33
    <nottarget>Text</nottarget>
37
    <nottarget>Purple text on red background.</nottarget>
34
    <target>Text</target>
38
    <target>White text on green background.</target>
35
    <nottarget id="classA">Text</nottarget>
39
    <nottarget id="classA">Purple text on red background.</nottarget>
36
    <target id="classA">Text</target>
40
    <target id="classA">Purple text on red background.</target>
37
    <nottarget class="classB">Text</nottarget>
41
    <nottarget class="classB">Purple text on blue background.</nottarget>
38
    <target class="classB">Text</target>
42
    <target class="classB">Purple text on blue background.</target>
39
    <nottarget id="classA" class="classB">Text</nottarget>
43
    <nottarget id="classA" class="classB">Purple text on red background.</nottarget>
40
    <target id="classA" class="classB">Text</target>
44
    <target id="classA" class="classB">Purple text on red background.</target>
45
</body>
41
</body>
46
</html>
42
</html>
- a/LayoutTests/fast/css/is-specificity-4-expected.html -1 lines
Lines 1-7 a/LayoutTests/fast/css/is-specificity-4-expected.html_sec1
1
<!doctype html>
1
<!doctype html>
2
<html>
2
<html>
3
<body>
3
<body>
4
    <p>This test the dynamic specificity of :is() with a complex selector. The text succeed if the text "Target" shows up in white on green background.</p>
5
    <container>
4
    <container>
6
        <target style="background-color: green; color: white;">Target</target>
5
        <target style="background-color: green; color: white;">Target</target>
7
    </container>
6
    </container>
- a/LayoutTests/fast/css/is-specificity-4.html -8 / +1 lines
Lines 2-27 a/LayoutTests/fast/css/is-specificity-4.html_sec1
2
<html>
2
<html>
3
<head>
3
<head>
4
<style>
4
<style>
5
    /* The position of :is() should override this rule. */
6
    container > target {
5
    container > target {
7
        border: 5px solid black;
6
        border: 5px solid black;
8
        color: blue;
7
        color: blue;
9
    }
8
    }
10
9
11
    /* A class rule should supersede the following :is() because it has higher specificity. */
12
    .target {
10
    .target {
13
        color: white;
11
        color: white;
14
    }
12
    }
15
13
16
    /* The only subselector that matches is "container > target". It should override the simple "target"
14
    :is(foo, foo, container > target) {
17
       selector but be superseded by anything larger than two tagnames. */
18
    :is(foo.bar, bar.foo, container > target, foo#bar, bar#foo) {
19
        background-color: green;
15
        background-color: green;
20
        color: purple;
16
        color: purple;
21
        border: 25px solid red;
17
        border: 25px solid red;
22
    }
18
    }
23
19
24
    /* Those two rules only have score one tagname, they cannot take precedence over :is(). */
25
    target {
20
    target {
26
        background-color: red;
21
        background-color: red;
27
    }
22
    }
Lines 29-42 a/LayoutTests/fast/css/is-specificity-4.html_sec2
29
        color: black;
24
        color: black;
30
    }
25
    }
31
26
32
    /* This rule should have the same specificity as the :is() but higher position. */
33
    container > target {
27
    container > target {
34
        border: none;
28
        border: none;
35
    }
29
    }
36
</style>
30
</style>
37
</head>
31
</head>
38
<body>
32
<body>
39
    <p>This test the dynamic specificity of :is() with a complex selector. The text succeed if the text "Target" shows up in white on green background.</p>
40
    <container>
33
    <container>
41
        <target class="target">Target</target>
34
        <target class="target">Target</target>
42
    </container>
35
    </container>
- a/LayoutTests/fast/css/is-specificity-5.html -5 / +1 lines
Lines 6-17 a/LayoutTests/fast/css/is-specificity-5.html_sec1
6
        content: "Target";
6
        content: "Target";
7
    }
7
    }
8
8
9
    /* This rule has two .target, making it higher specificity than the rules below. */
10
    .target:is(*, target, .target, *, target)::before {
9
    .target:is(*, target, .target, *, target)::before {
11
        background-color: green;
10
        background-color: green;
12
    }
11
    }
13
12
14
    /* This rule has a tagname and a class name, making it higher specificity than ".target:is(*)::before". */
15
    target:is(*, target, .target, *, target)::before {
13
    target:is(*, target, .target, *, target)::before {
16
        color: white;
14
        color: white;
17
    }
15
    }
Lines 21-33 a/LayoutTests/fast/css/is-specificity-5.html_sec2
21
        color: blue;
19
        color: blue;
22
        border: none;
20
        border: none;
23
    }
21
    }
24
    /* This rule only has (0, 0, 3) and it superseded by the rule above. */
25
    target:is(*, target, *)::before {
22
    target:is(*, target, *)::before {
26
        border: 25px solid purple;
23
        border: 25px solid purple;
27
    }
24
    }
28
25
29
    /* This rule has lower specificity than all the rules above and its property never applies. */
26
    :is(foo, target)::before {
30
    :is(#target, target)::before {
31
        content: "Not Target";
27
        content: "Not Target";
32
    }
28
    }
33
</style>
29
</style>
- a/LayoutTests/fast/css/matches-specificity-10-expected.html -2 lines
Lines 1-8 a/LayoutTests/fast/css/matches-specificity-10-expected.html_sec1
1
<!doctype html>
1
<!doctype html>
2
<html>
2
<html>
3
<body>
3
<body>
4
    <p>This test the dynamic specificity of :matches() with a simple descendant backtracking case. The test pass if each block has style matching its description. None of the result should have a border.</p>
5
6
    <foo id="b">
4
    <foo id="b">
7
        <foo id="c">
5
        <foo id="c">
8
            <e>
6
            <e>
- a/LayoutTests/fast/css/matches-specificity-10.html -19 / +18 lines
Lines 2-9 a/LayoutTests/fast/css/matches-specificity-10.html_sec1
2
<html>
2
<html>
3
<head>
3
<head>
4
<style>
4
<style>
5
    /* Specificity (2, 0, 2). */
5
    /* Specificity (3, 0, 2). */
6
    #f#f > padding > target {
6
    #f#f#f > padding > target {
7
        background-color: purple;
7
        background-color: purple;
8
    }
8
    }
9
9
Lines 23-43 a/LayoutTests/fast/css/matches-specificity-10.html_sec2
23
        border: 5px blue solid;
23
        border: 5px blue solid;
24
    }
24
    }
25
25
26
    /* Specificity (3, 0, 1) */
26
    :matches(aBlock, #b) > :matches(#c, d) > :matches(e, #f) target {
27
    :matches(aBlock, #b) > :matches(#c, d) > :matches(e, #f) target {
27
        background-color: green;
28
        background-color: green;
28
        color: white;
29
        color: white;
29
        border: none;
30
        border: none;
30
    }
31
    }
32
33
    /* Specificity (3, 0, 2) */
34
    #c#c#c padding target {
35
        background-color: green;
36
    }
37
38
    /* Specificity (3, 0, 1) */
39
    #f#f#f target {
40
        background-color: green;
41
    }
42
43
    /* Specificity (3, 0, 2) */
44
    a #f#f#f target {
45
        color: green;
46
    }
31
</style>
47
</style>
32
</head>
48
</head>
33
<body>
49
<body>
34
    <p>This test the dynamic specificity of :matches() with a simple descendant backtracking case. The test pass if each block has style matching its description. None of the result should have a border.</p>
35
36
    <!--
37
     This case should match ":matches(a, #b) > :matches(#c, d) > matches(e, #f) target"
38
     like "#a > #c > e target"
39
     with the specificity (2, 0, 2).
40
     -->
41
    <foo id="b">
50
    <foo id="b">
42
        <foo id="c">
51
        <foo id="c">
43
            <e> <!-- Success case from here. -->
52
            <e> <!-- Success case from here. -->
Lines 64-74 a/LayoutTests/fast/css/matches-specificity-10.html_sec3
64
        </foo>
73
        </foo>
65
    </foo>
74
    </foo>
66
75
67
    <!--
68
     This case should match ":matches(a, #b) > :matches(#c, d) > matches(e, #f) target"
69
     like "#a > d > e target"
70
     with the specificity (1, 0, 3).
71
     -->
72
    <foo id="b">
76
    <foo id="b">
73
        <d>
77
        <d>
74
            <e> <!-- Success case from here. -->
78
            <e> <!-- Success case from here. -->
Lines 95-105 a/LayoutTests/fast/css/matches-specificity-10.html_sec4
95
        </d>
99
        </d>
96
    </foo>
100
    </foo>
97
101
98
    <!--
99
     This case should match ":matches(a, #b) > :matches(#c, d) > matches(e, #f) target"
100
     like "a > d > e target"
101
     with the specificity (0, 0, 4).
102
     -->
103
    <aBlock>
102
    <aBlock>
104
        <d>
103
        <d>
105
            <e> <!-- Success case from here. -->
104
            <e> <!-- Success case from here. -->
- a/LayoutTests/fast/css/matches-specificity-2-expected.html -2 / +1 lines
Lines 8-14 a/LayoutTests/fast/css/matches-specificity-2-expected.html_sec1
8
</style>
8
</style>
9
</head>
9
</head>
10
<body>
10
<body>
11
    <p>This test the specificity of :matches() with a dynamic specificity of zero. The test passes if the text "target" is displayed white on green background.</p>
11
    <target style="color: blue;">Target</target>
12
    <target style="background-color: green; color: white;">Target</target>
13
</body>
12
</body>
14
</html>
13
</html>
- a/LayoutTests/fast/css/matches-specificity-2.html -6 / +1 lines
Lines 15-26 a/LayoutTests/fast/css/matches-specificity-2.html_sec1
15
        background-color: green;
15
        background-color: green;
16
    }
16
    }
17
17
18
    /* The only dynamic selector that matches is "*". Every rules except the first one (* selector) should override the style defined here.
19
       Background-color is defined by the two tag selectors above.
20
       Color is defined below by the star rule. It has the same specificity but a higher position.
21
       Border overrides the black border defined in the first rule. */
22
    :matches(#foo, .bar, target.notthere, *, foo>bar) {
18
    :matches(#foo, .bar, target.notthere, *, foo>bar) {
23
        background-color: red;
19
        background-color: white;
24
        color: blue;
20
        color: blue;
25
        border: none;
21
        border: none;
26
    }
22
    }
Lines 30-36 a/LayoutTests/fast/css/matches-specificity-2.html_sec2
30
</style>
26
</style>
31
</head>
27
</head>
32
<body>
28
<body>
33
    <p>This test the specificity of :matches() with a dynamic specificity of zero. The test passes if the text "target" is displayed white on green background.</p>
34
    <target>Target</target>
29
    <target>Target</target>
35
</body>
30
</body>
36
</html>
31
</html>
- a/LayoutTests/fast/css/matches-specificity-3-expected.html -18 / +8 lines
Lines 1-25 a/LayoutTests/fast/css/matches-specificity-3-expected.html_sec1
1
<!doctype html>
1
<!doctype html>
2
<html>
2
<html>
3
<head>
3
<head>
4
<style>
5
    body > * {
6
        display: block;
7
    }
8
    html, body, p {
9
        background-color: white;
10
        color: black;
11
    }
12
</style>
13
</head>
4
</head>
14
<body>
5
<body>
15
    <p>This test checks the dynamic specificity of matches changing the order in which rules are applied depending on the element. Each element should have the colors described in the text and no border.</p>
6
<div style="color: purple; background-color: blue;">Text</nottarget>
16
    <nottarget style="color: purple; background-color: red;">Purple text on red background.</nottarget>
7
<div style="color: purple; background-color: green;">Text</nottarget>
17
    <target style="color: white; background-color: green;">White text on green background.</target>
8
<div style="color: purple; background-color: blue;">Text</nottarget>
18
    <nottarget style="color: purple; background-color: red;">Purple text on red background.</nottarget>
9
<div style="color: purple; background-color: green;">Text</nottarget>
19
    <target style="color: purple; background-color: red;">Purple text on red background.</target>
10
<div style="color: purple; background-color: blue;">Text</nottarget>
20
    <nottarget style="color: purple; background-color: blue;">Purple text on blue background.</nottarget>
11
<div style="color: purple; background-color: blue;">Text</nottarget>
21
    <target style="color: purple; background-color: blue;">Purple text on blue background.</target>
12
<div style="color: purple; background-color: blue;">Text</nottarget>
22
    <nottarget style="color: purple; background-color: red;">Purple text on red background.</nottarget>
13
<div style="color: purple; background-color: blue;">Text</nottarget>
23
    <target style="color: purple; background-color: red;">Purple text on red background.</target>
24
</body>
14
</body>
25
</html>
15
</html>
- a/LayoutTests/fast/css/matches-specificity-3.html -13 / +9 lines
Lines 8-17 a/LayoutTests/fast/css/matches-specificity-3.html_sec1
8
        border: 5px solid black;
8
        border: 5px solid black;
9
    }
9
    }
10
10
11
    /* The following :matches() gets a different class of specificity. Depending on what
11
    :matches(.classB, target, *) {
12
       matches, the later rules may override this or not. */
13
    :matches(.classB, target, #classA, *) {
14
        background-color: red;
15
        color: purple;
12
        color: purple;
16
        border: none;
13
        border: none;
17
    }
14
    }
Lines 33-46 a/LayoutTests/fast/css/matches-specificity-3.html_sec2
33
</style>
30
</style>
34
</head>
31
</head>
35
<body>
32
<body>
36
    <p>This test checks the dynamic specificity of matches changing the order in which rules are applied depending on the element. Each element should have the colors described in the text and no border.</p>
33
    <nottarget>Text</nottarget>
37
    <nottarget>Purple text on red background.</nottarget>
34
    <target>Text</target>
38
    <target>White text on green background.</target>
35
    <nottarget id="classA">Text</nottarget>
39
    <nottarget id="classA">Purple text on red background.</nottarget>
36
    <target id="classA">Text</target>
40
    <target id="classA">Purple text on red background.</target>
37
    <nottarget class="classB">Text</nottarget>
41
    <nottarget class="classB">Purple text on blue background.</nottarget>
38
    <target class="classB">Text</target>
42
    <target class="classB">Purple text on blue background.</target>
39
    <nottarget id="classA" class="classB">Text</nottarget>
43
    <nottarget id="classA" class="classB">Purple text on red background.</nottarget>
40
    <target id="classA" class="classB">Text</target>
44
    <target id="classA" class="classB">Purple text on red background.</target>
45
</body>
41
</body>
46
</html>
42
</html>
- a/LayoutTests/fast/css/matches-specificity-4-expected.html -1 lines
Lines 1-7 a/LayoutTests/fast/css/matches-specificity-4-expected.html_sec1
1
<!doctype html>
1
<!doctype html>
2
<html>
2
<html>
3
<body>
3
<body>
4
    <p>This test the dynamic specificity of :matches() with a complex selector. The text succeed if the text "Target" shows up in white on green background.</p>
5
    <container>
4
    <container>
6
        <target style="background-color: green; color: white;">Target</target>
5
        <target style="background-color: green; color: white;">Target</target>
7
    </container>
6
    </container>
- a/LayoutTests/fast/css/matches-specificity-4.html -8 / +1 lines
Lines 2-27 a/LayoutTests/fast/css/matches-specificity-4.html_sec1
2
<html>
2
<html>
3
<head>
3
<head>
4
<style>
4
<style>
5
    /* The position of :matches() should override this rule. */
6
    container > target {
5
    container > target {
7
        border: 5px solid black;
6
        border: 5px solid black;
8
        color: blue;
7
        color: blue;
9
    }
8
    }
10
9
11
    /* A class rule should supersede the following :matches() because it has higher specificity. */
12
    .target {
10
    .target {
13
        color: white;
11
        color: white;
14
    }
12
    }
15
13
16
    /* The only subselector that matches is "container > target". It should override the simple "target"
14
    :matches(foo, foo, container > target) {
17
       selector but be superseded by anything larger than two tagnames. */
18
    :matches(foo.bar, bar.foo, container > target, foo#bar, bar#foo) {
19
        background-color: green;
15
        background-color: green;
20
        color: purple;
16
        color: purple;
21
        border: 25px solid red;
17
        border: 25px solid red;
22
    }
18
    }
23
19
24
    /* Those two rules only have score one tagname, they cannot take precedence over :matches(). */
25
    target {
20
    target {
26
        background-color: red;
21
        background-color: red;
27
    }
22
    }
Lines 29-42 a/LayoutTests/fast/css/matches-specificity-4.html_sec2
29
        color: black;
24
        color: black;
30
    }
25
    }
31
26
32
    /* This rule should have the same specificity as the :matches() but higher position. */
33
    container > target {
27
    container > target {
34
        border: none;
28
        border: none;
35
    }
29
    }
36
</style>
30
</style>
37
</head>
31
</head>
38
<body>
32
<body>
39
    <p>This test the dynamic specificity of :matches() with a complex selector. The text succeed if the text "Target" shows up in white on green background.</p>
40
    <container>
33
    <container>
41
        <target class="target">Target</target>
34
        <target class="target">Target</target>
42
    </container>
35
    </container>
- a/LayoutTests/fast/css/matches-specificity-5.html -5 / +1 lines
Lines 6-17 a/LayoutTests/fast/css/matches-specificity-5.html_sec1
6
        content: "Target";
6
        content: "Target";
7
    }
7
    }
8
8
9
    /* This rule has two .target, making it higher specificity than the rules below. */
10
    .target:matches(*, target, .target, *, target)::before {
9
    .target:matches(*, target, .target, *, target)::before {
11
        background-color: green;
10
        background-color: green;
12
    }
11
    }
13
12
14
    /* This rule has a tagname and a class name, making it higher specificity than ".target:matches(*)::before". */
15
    target:matches(*, target, .target, *, target)::before {
13
    target:matches(*, target, .target, *, target)::before {
16
        color: white;
14
        color: white;
17
    }
15
    }
Lines 21-33 a/LayoutTests/fast/css/matches-specificity-5.html_sec2
21
        color: blue;
19
        color: blue;
22
        border: none;
20
        border: none;
23
    }
21
    }
24
    /* This rule only has (0, 0, 3) and it superseded by the rule above. */
25
    target:matches(*, target, *)::before {
22
    target:matches(*, target, *)::before {
26
        border: 25px solid purple;
23
        border: 25px solid purple;
27
    }
24
    }
28
25
29
    /* This rule has lower specificity than all the rules above and its property never applies. */
26
    :matches(foo, target)::before {
30
    :matches(#target, target)::before {
31
        content: "Not Target";
27
        content: "Not Target";
32
    }
28
    }
33
</style>
29
</style>
- a/LayoutTests/fast/css/nth-child-specificity-2-expected.html -3 / +2 lines
Lines 9-24 a/LayoutTests/fast/css/nth-child-specificity-2-expected.html_sec1
9
</style>
9
</style>
10
</head>
10
</head>
11
<body>
11
<body>
12
    <p>This test the specificity of :nth-child() with dynamic specificity. If the test pass, the style of each line should match its text description.</p>
13
    <div>
12
    <div>
14
        <target style="background-color: white; color: black; border: none;">Black text on white background.</target>
13
        <target style="background-color: white; color: black; border: none;">Black text on white background.</target>
15
        <target style="background-color: red; color: white; border: 5px solid purple;">White text on red background with a purple border.</target>
14
        <target style="background-color: red; color: white; border: 5px solid purple;">White text on red background with a purple border.</target>
16
        <target style="background-color: green; color: red; border: none;">Red text on green background.</target>
15
        <target style="background-color: green; color: red; border: none;">Red text on green background.</target>
17
        <target style="background-color: green; color: white; border: 5px solid purple;">White text on green background with a purple border.</target>
16
        <target style="background-color: red; color: white; border: 5px solid purple;">White text on red background with a purple border.</target>
18
        <target style="background-color: white; color: black; border: 5px solid blue;">Black text on white background with a blue border.</target>
17
        <target style="background-color: white; color: black; border: 5px solid blue;">Black text on white background with a blue border.</target>
19
        <target style="background-color: red; color: white; border: 5px solid purple;">White text on red background with a purple border.</target>
18
        <target style="background-color: red; color: white; border: 5px solid purple;">White text on red background with a purple border.</target>
20
        <target style="background-color: green; color: red; border: 5px solid blue;">Red text on green background with a blue border.</target>
19
        <target style="background-color: green; color: red; border: 5px solid blue;">Red text on green background with a blue border.</target>
21
        <target style="background-color: red; color: white; border: 5px solid purple;">White text on red background with a purple border.</target>
20
        <target style="background-color: red; color: white; border: 5px solid purple;">White text on red background with a purple border.</target>
22
    </div>
21
    </div>
23
</body>
22
</body>
24
</html>
23
</html>
- a/LayoutTests/fast/css/nth-child-specificity-2.html -4 / +3 lines
Lines 2-8 a/LayoutTests/fast/css/nth-child-specificity-2.html_sec1
2
<html>
2
<html>
3
<head>
3
<head>
4
<style>
4
<style>
5
    /* The specifity varies with the element being matched. */
5
    /* (1, 1, 0) */
6
    :nth-child(even of .foo, #bar, target) {
6
    :nth-child(even of .foo, #bar, target) {
7
        background-color: red;
7
        background-color: red;
8
        color: white;
8
        color: white;
Lines 30-45 a/LayoutTests/fast/css/nth-child-specificity-2.html_sec2
30
</style>
30
</style>
31
</head>
31
</head>
32
<body>
32
<body>
33
    <p>This test the specificity of :nth-child() with dynamic specificity. If the test pass, the style of each line should match its text description.</p>
34
    <div>
33
    <div>
35
        <target>Black text on white background.</target>
34
        <target>Black text on white background.</target>
36
        <target>White text on red background with a purple border.</target>
35
        <target>White text on red background with a purple border.</target>
37
        <target class="foo">Red text on green background.</target>
36
        <target class="foo">Red text on green background.</target>
38
        <target class="foo">White text on green background with a purple border.</target>
37
        <target class="foo">White text on red background with a purple border.</target>
39
        <target id="bar">Black text on white background with a blue border.</target>
38
        <target id="bar">Black text on white background with a blue border.</target>
40
        <target id="bar">White text on red background with a purple border.</target>
39
        <target id="bar">White text on red background with a purple border.</target>
41
        <target class="foo" id="bar">Red text on green background with a blue border.</target>
40
        <target class="foo" id="bar">Red text on green background with a blue border.</target>
42
        <target class="foo" id="bar">White text on red background with a purple border.</target>
41
        <target class="foo" id="bar">White text on red background with a purple border.</target>
43
    </div>
42
    </div>
44
</body>
43
</body>
45
</html>
44
</html>
- a/LayoutTests/fast/css/nth-child-specificity-3-expected.html -3 / +2 lines
Lines 9-24 a/LayoutTests/fast/css/nth-child-specificity-3-expected.html_sec1
9
</style>
9
</style>
10
</head>
10
</head>
11
<body>
11
<body>
12
    <p>This test the specificity of :nth-child() with dynamic specificity of compound selectors. If the test pass, the style of each line should match its text description.</p>
13
    <div>
12
    <div>
14
        <target>Black text.</target>
13
        <target>Black text.</target>
15
        <target>Black text.</target>
14
        <target>Black text.</target>
16
        <target style="color:red; border: 5px solid black;">Red text with black border.</target>
15
        <target style="color:red; border: 5px solid black;">Red text with black border.</target>
17
        <target style="color:white; background-color:red; border: 5px solid black;">White text on red background with black border.</target>
16
        <target style="color:white; background-color:red; border: 5px solid purple;">White text on red background with purple border.</target>
18
        <target style="border: 5px solid blue;">Black text with blue border.</target>
17
        <target style="border: 5px solid blue;">Black text with blue border.</target>
19
        <target style="color:white; background-color:red; border: 5px solid purple;">White text on red background with purple border.</target>
18
        <target style="color:white; background-color:red; border: 5px solid purple;">White text on red background with purple border.</target>
20
        <target style="color:red; background-color:green; border: 5px solid blue;">Red text on green background with blue border.</target>
19
        <target style="color:red; background-color:green; border: 5px solid blue;">Red text on green background with blue border.</target>
21
        <target style="color:white; background-color:red; border: 5px solid purple;">White text on red background with purple border.</target>
20
        <target style="color:white; background-color:red; border: 5px solid purple;">White text on red background with purple border.</target>
22
    </div>
21
    </div>
23
</body>
22
</body>
24
</html>
23
</html>
- a/LayoutTests/fast/css/nth-child-specificity-3.html -4 / +3 lines
Lines 2-8 a/LayoutTests/fast/css/nth-child-specificity-3.html_sec1
2
<html>
2
<html>
3
<head>
3
<head>
4
<style>
4
<style>
5
    /* The specifity varies with the element being matched. */
5
    /* (1, 2, 1) */
6
    :nth-child(even of target.foo, .foo#bar, target.foo#bar, target#bar) {
6
    :nth-child(even of target.foo, .foo#bar, target.foo#bar, target#bar) {
7
        background-color: red;
7
        background-color: red;
8
        color: white;
8
        color: white;
Lines 34-49 a/LayoutTests/fast/css/nth-child-specificity-3.html_sec2
34
</style>
34
</style>
35
</head>
35
</head>
36
<body>
36
<body>
37
    <p>This test the specificity of :nth-child() with dynamic specificity of compound selectors. If the test pass, the style of each line should match its text description.</p>
38
    <div>
37
    <div>
39
        <target>Black text.</target>
38
        <target>Black text.</target>
40
        <target>Black text.</target>
39
        <target>Black text.</target>
41
        <target class="foo">Red text with black border.</target>
40
        <target class="foo">Red text with black border.</target>
42
        <target class="foo">White text on red background with black border.</target>
41
        <target class="foo">White text on red background with purple border.</target>
43
        <target id="bar">Black text with blue border.</target>
42
        <target id="bar">Black text with blue border.</target>
44
        <target id="bar">White text on red background with purple border.</target>
43
        <target id="bar">White text on red background with purple border.</target>
45
        <target class="foo" id="bar">Red text on green background with blue border.</target>
44
        <target class="foo" id="bar">Red text on green background with blue border.</target>
46
        <target class="foo" id="bar">White text on red background with purple border.</target>
45
        <target class="foo" id="bar">White text on red background with purple border.</target>
47
    </div>
46
    </div>
48
</body>
47
</body>
49
</html>
48
</html>
- a/LayoutTests/fast/css/nth-child-specificity-4-expected.html -3 / +2 lines
Lines 9-24 a/LayoutTests/fast/css/nth-child-specificity-4-expected.html_sec1
9
</style>
9
</style>
10
</head>
10
</head>
11
<body>
11
<body>
12
    <p>This test the specificity of :nth-child() with dynamic specificity of compound selectors. In this case, we verify the matching of siblings does not affect the specificity of the current element. If the test pass, the style of each line should match its text description.</p>
13
    <div>
12
    <div>
14
        <target>Black text.</target>
13
        <target>Black text.</target>
15
        <target>Black text.</target>
14
        <target>Black text.</target>
16
        <target style="border: 5px solid blue;">Black text with blue border.</target>
15
        <target style="border: 5px solid blue;">Black text with blue border.</target>
17
        <target style="color:white; background-color:red; border: 5px solid black;">White text on red background with black border.</target>
16
        <target style="color:white; background-color:red; border: 5px solid purple;">White text on red background with purple border.</target>
18
        <target style="color:red; background-color:green; border: 5px solid blue;">Red text on green background with blue border.</target>
17
        <target style="color:red; background-color:green; border: 5px solid blue;">Red text on green background with blue border.</target>
19
        <target style="color:white; background-color:red; border: 5px solid purple;">White text on red background with purple border.</target>
18
        <target style="color:white; background-color:red; border: 5px solid purple;">White text on red background with purple border.</target>
20
        <target style="color:red; border: 5px solid black;">Red text with black border.</target>
19
        <target style="color:red; border: 5px solid black;">Red text with black border.</target>
21
        <target style="color:white; background-color:red; border: 5px solid purple;">White text on red background with purple border.</target>
20
        <target style="color:white; background-color:red; border: 5px solid purple;">White text on red background with purple border.</target>
22
    </div>
21
    </div>
23
</body>
22
</body>
24
</html>
23
</html>
- a/LayoutTests/fast/css/nth-child-specificity-4.html -4 / +3 lines
Lines 2-8 a/LayoutTests/fast/css/nth-child-specificity-4.html_sec1
2
<html>
2
<html>
3
<head>
3
<head>
4
<style>
4
<style>
5
    /* The specifity varies with the element being matched. */
5
    /* (1, 2, 1) */
6
    :nth-child(even of target.foo, .foo#bar, target.foo#bar, target#bar) {
6
    :nth-child(even of target.foo, .foo#bar, target.foo#bar, target#bar) {
7
        background-color: red;
7
        background-color: red;
8
        color: white;
8
        color: white;
Lines 34-49 a/LayoutTests/fast/css/nth-child-specificity-4.html_sec2
34
</style>
34
</style>
35
</head>
35
</head>
36
<body>
36
<body>
37
    <p>This test the specificity of :nth-child() with dynamic specificity of compound selectors. In this case, we verify the matching of siblings does not affect the specificity of the current element. If the test pass, the style of each line should match its text description.</p>
38
    <div>
37
    <div>
39
        <target>Black text.</target>
38
        <target>Black text.</target>
40
        <target>Black text.</target>
39
        <target>Black text.</target>
41
        <target id="bar">Black text with blue border.</target>
40
        <target id="bar">Black text with blue border.</target>
42
        <target class="foo">White text on red background with black border.</target>
41
        <target class="foo">White text on red background with purple border.</target>
43
        <target class="foo" id="bar">Red text on green background with blue border.</target>
42
        <target class="foo" id="bar">Red text on green background with blue border.</target>
44
        <target id="bar">White text on red background with purple border.</target>
43
        <target id="bar">White text on red background with purple border.</target>
45
        <target class="foo">Red text with black border.</target>
44
        <target class="foo">Red text with black border.</target>
46
        <target class="foo" id="bar">White text on red background with purple border.</target>
45
        <target class="foo" id="bar">White text on red background with purple border.</target>
47
    </div>
46
    </div>
48
</body>
47
</body>
49
</html>
48
</html>
- a/LayoutTests/fast/css/nth-last-child-specificity-2-expected.html -3 / +2 lines
Lines 9-19 a/LayoutTests/fast/css/nth-last-child-specificity-2-expected.html_sec1
9
</style>
9
</style>
10
</head>
10
</head>
11
<body>
11
<body>
12
    <p>This test the specificity of :nth-last-child() with dynamic specificity. If the test pass, the style of each line should match its text description.</p>
13
    <div>
12
    <div>
14
        <target style="background-color: red; color: white; border: 5px solid purple;">White text on red background with a purple border.</target>
13
        <target style="background-color: red; color: white; border: 5px solid purple;">White text on red background with a purple border.</target>
15
        <target style="background-color: white; color: black; border: none;">Black text on white background.</target>
14
        <target style="background-color: white; color: black; border: none;">Black text on white background.</target>
16
        <target style="background-color: green; color: white; border: 5px solid purple;">White text on green background with a purple border.</target>
15
        <target style="background-color: red; color: white; border: 5px solid purple;">White text on red background with a purple border.</target>
17
        <target style="background-color: green; color: red; border: none;">Red text on green background.</target>
16
        <target style="background-color: green; color: red; border: none;">Red text on green background.</target>
18
        <target style="background-color: red; color: white; border: 5px solid purple;">White text on red background with a purple border.</target>
17
        <target style="background-color: red; color: white; border: 5px solid purple;">White text on red background with a purple border.</target>
19
        <target style="background-color: white; color: black; border: 5px solid blue;">Black text on white background with a blue border.</target>
18
        <target style="background-color: white; color: black; border: 5px solid blue;">Black text on white background with a blue border.</target>
Lines 21-24 a/LayoutTests/fast/css/nth-last-child-specificity-2-expected.html_sec2
21
        <target style="background-color: green; color: red; border: 5px solid blue;">Red text on green background with a blue border.</target>
20
        <target style="background-color: green; color: red; border: 5px solid blue;">Red text on green background with a blue border.</target>
22
    </div>
21
    </div>
23
</body>
22
</body>
24
</html>
23
</html>
- a/LayoutTests/fast/css/nth-last-child-specificity-2.html -4 / +3 lines
Lines 2-8 a/LayoutTests/fast/css/nth-last-child-specificity-2.html_sec1
2
<html>
2
<html>
3
<head>
3
<head>
4
<style>
4
<style>
5
    /* The specifity varies with the element being matched. */
5
    /* (1, 1, 0) */
6
    :nth-last-child(even of .foo, #bar, target) {
6
    :nth-last-child(even of .foo, #bar, target) {
7
        background-color: red;
7
        background-color: red;
8
        color: white;
8
        color: white;
Lines 30-40 a/LayoutTests/fast/css/nth-last-child-specificity-2.html_sec2
30
</style>
30
</style>
31
</head>
31
</head>
32
<body>
32
<body>
33
    <p>This test the specificity of :nth-last-child() with dynamic specificity. If the test pass, the style of each line should match its text description.</p>
34
    <div>
33
    <div>
35
        <target>White text on red background with a purple border.</target>
34
        <target>White text on red background with a purple border.</target>
36
        <target>Black text on white background.</target>
35
        <target>Black text on white background.</target>
37
        <target class="foo">White text on green background with a purple border.</target>
36
        <target class="foo">White text on red background with a purple border.</target>
38
        <target class="foo">Red text on green background.</target>
37
        <target class="foo">Red text on green background.</target>
39
        <target id="bar">White text on red background with a purple border.</target>
38
        <target id="bar">White text on red background with a purple border.</target>
40
        <target id="bar">Black text on white background with a blue border.</target>
39
        <target id="bar">Black text on white background with a blue border.</target>
Lines 42-45 a/LayoutTests/fast/css/nth-last-child-specificity-2.html_sec3
42
        <target class="foo" id="bar">Red text on green background with a blue border.</target>
41
        <target class="foo" id="bar">Red text on green background with a blue border.</target>
43
    </div>
42
    </div>
44
</body>
43
</body>
45
</html>
44
</html>
- a/LayoutTests/fast/css/nth-last-child-specificity-3-expected.html -3 / +2 lines
Lines 9-19 a/LayoutTests/fast/css/nth-last-child-specificity-3-expected.html_sec1
9
</style>
9
</style>
10
</head>
10
</head>
11
<body>
11
<body>
12
    <p>This test the specificity of :nth-last-child() with dynamic specificity of compound selectors. If the test pass, the style of each line should match its text description.</p>
13
    <div>
12
    <div>
14
        <target>Black text.</target>
13
        <target>Black text.</target>
15
        <target>Black text.</target>
14
        <target>Black text.</target>
16
        <target style="color:white; background-color:red; border: 5px solid black;">White text on red background with black border.</target>
15
        <target style="color:white; background-color:red; border: 5px solid purple;">White text on red background with purple border.</target>
17
        <target style="color:red; border: 5px solid black;">Red text with black border.</target>
16
        <target style="color:red; border: 5px solid black;">Red text with black border.</target>
18
        <target style="color:white; background-color:red; border: 5px solid purple;">White text on red background with purple border.</target>
17
        <target style="color:white; background-color:red; border: 5px solid purple;">White text on red background with purple border.</target>
19
        <target style="border: 5px solid blue;">Black text with blue border.</target>
18
        <target style="border: 5px solid blue;">Black text with blue border.</target>
Lines 21-24 a/LayoutTests/fast/css/nth-last-child-specificity-3-expected.html_sec2
21
        <target style="color:red; background-color:green; border: 5px solid blue;">Red text on green background with blue border.</target>
20
        <target style="color:red; background-color:green; border: 5px solid blue;">Red text on green background with blue border.</target>
22
    </div>
21
    </div>
23
</body>
22
</body>
24
</html>
23
</html>
- a/LayoutTests/fast/css/nth-last-child-specificity-3.html -4 / +3 lines
Lines 2-8 a/LayoutTests/fast/css/nth-last-child-specificity-3.html_sec1
2
<html>
2
<html>
3
<head>
3
<head>
4
<style>
4
<style>
5
    /* The specifity varies with the element being matched. */
5
    /* (1, 2, 1) */
6
    :nth-last-child(even of target.foo, .foo#bar, target.foo#bar, target#bar) {
6
    :nth-last-child(even of target.foo, .foo#bar, target.foo#bar, target#bar) {
7
        background-color: red;
7
        background-color: red;
8
        color: white;
8
        color: white;
Lines 34-44 a/LayoutTests/fast/css/nth-last-child-specificity-3.html_sec2
34
</style>
34
</style>
35
</head>
35
</head>
36
<body>
36
<body>
37
    <p>This test the specificity of :nth-last-child() with dynamic specificity of compound selectors. If the test pass, the style of each line should match its text description.</p>
38
    <div>
37
    <div>
39
        <target>Black text.</target>
38
        <target>Black text.</target>
40
        <target>Black text.</target>
39
        <target>Black text.</target>
41
        <target class="foo">White text on red background with black border.</target>
40
        <target class="foo">White text on red background with purple border.</target>
42
        <target class="foo">Red text with black border.</target>
41
        <target class="foo">Red text with black border.</target>
43
        <target id="bar">White text on red background with purple border.</target>
42
        <target id="bar">White text on red background with purple border.</target>
44
        <target id="bar">Black text with blue border.</target>
43
        <target id="bar">Black text with blue border.</target>
Lines 46-49 a/LayoutTests/fast/css/nth-last-child-specificity-3.html_sec3
46
        <target class="foo" id="bar">Red text on green background with blue border.</target>
45
        <target class="foo" id="bar">Red text on green background with blue border.</target>
47
    </div>
46
    </div>
48
</body>
47
</body>
49
</html>
48
</html>
- a/LayoutTests/fast/css/nth-last-child-specificity-4-expected.html -3 / +2 lines
Lines 9-19 a/LayoutTests/fast/css/nth-last-child-specificity-4-expected.html_sec1
9
</style>
9
</style>
10
</head>
10
</head>
11
<body>
11
<body>
12
    <p>This test the specificity of :nth-last-child() with dynamic specificity of compound selectors. In this case, we verify the matching of siblings does not affect the specificity of the current element. If the test pass, the style of each line should match its text description.</p>
13
    <div>
12
    <div>
14
        <target>Black text.</target>
13
        <target>Black text.</target>
15
        <target>Black text.</target>
14
        <target>Black text.</target>
16
        <target style="color:white; background-color:red; border: 5px solid black;">White text on red background with black border.</target>
15
        <target style="color:white; background-color:red; border: 5px solid purple;">White text on red background with purple border.</target>
17
        <target style="border: 5px solid blue;">Black text with blue border.</target>
16
        <target style="border: 5px solid blue;">Black text with blue border.</target>
18
        <target style="color:white; background-color:red; border: 5px solid purple;">White text on red background with purple border.</target>
17
        <target style="color:white; background-color:red; border: 5px solid purple;">White text on red background with purple border.</target>
19
        <target style="color:red; background-color:green; border: 5px solid blue;">Red text on green background with blue border.</target>
18
        <target style="color:red; background-color:green; border: 5px solid blue;">Red text on green background with blue border.</target>
Lines 21-24 a/LayoutTests/fast/css/nth-last-child-specificity-4-expected.html_sec2
21
        <target style="color:red; border: 5px solid black;">Red text with black border.</target>
20
        <target style="color:red; border: 5px solid black;">Red text with black border.</target>
22
    </div>
21
    </div>
23
</body>
22
</body>
24
</html>
23
</html>
- a/LayoutTests/fast/css/nth-last-child-specificity-4.html -4 / +3 lines
Lines 2-8 a/LayoutTests/fast/css/nth-last-child-specificity-4.html_sec1
2
<html>
2
<html>
3
<head>
3
<head>
4
<style>
4
<style>
5
    /* The specifity varies with the element being matched. */
5
    /* (1, 2, 1) */
6
    :nth-last-child(even of target.foo, .foo#bar, target.foo#bar, target#bar) {
6
    :nth-last-child(even of target.foo, .foo#bar, target.foo#bar, target#bar) {
7
        background-color: red;
7
        background-color: red;
8
        color: white;
8
        color: white;
Lines 34-44 a/LayoutTests/fast/css/nth-last-child-specificity-4.html_sec2
34
</style>
34
</style>
35
</head>
35
</head>
36
<body>
36
<body>
37
    <p>This test the specificity of :nth-last-child() with dynamic specificity of compound selectors. In this case, we verify the matching of siblings does not affect the specificity of the current element. If the test pass, the style of each line should match its text description.</p>
38
    <div>
37
    <div>
39
        <target>Black text.</target>
38
        <target>Black text.</target>
40
        <target>Black text.</target>
39
        <target>Black text.</target>
41
        <target class="foo">White text on red background with black border.</target>
40
        <target class="foo">White text on red background with purple border.</target>
42
        <target id="bar">Black text with blue border.</target>
41
        <target id="bar">Black text with blue border.</target>
43
        <target id="bar">White text on red background with purple border.</target>
42
        <target id="bar">White text on red background with purple border.</target>
44
        <target class="foo" id="bar">Red text on green background with blue border.</target>
43
        <target class="foo" id="bar">Red text on green background with blue border.</target>
Lines 46-49 a/LayoutTests/fast/css/nth-last-child-specificity-4.html_sec3
46
        <target class="foo">Red text with black border.</target>
45
        <target class="foo">Red text with black border.</target>
47
    </div>
46
    </div>
48
</body>
47
</body>
49
</html>
48
</html>
- a/LayoutTests/imported/w3c/ChangeLog +9 lines
Lines 1-3 a/LayoutTests/imported/w3c/ChangeLog_sec1
1
2020-04-13  Antti Koivisto  <antti@apple.com>
2
3
        [CSS Selectors] Remove dynamic specificity
4
        https://bugs.webkit.org/show_bug.cgi?id=210419
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        * web-platform-tests/css/selectors/invalidation/is-expected.txt:
9
1
2020-04-12  Antti Koivisto  <antti@apple.com>
10
2020-04-12  Antti Koivisto  <antti@apple.com>
2
11
3
        Update imported/w3c/web-platform-tests/css/selectors/invalidation/is.html
12
        Update imported/w3c/web-platform-tests/css/selectors/invalidation/is.html
- a/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/is-expected.txt -1 / +1 lines
Lines 13-17 PASS Invalidate :is() for simple selector arguments. a/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/is-expected.txt_sec1
13
PASS Invalidate :is() for compound selector arguments. 
13
PASS Invalidate :is() for compound selector arguments. 
14
PASS Invalidate :is() for complex selector arguments. 
14
PASS Invalidate :is() for complex selector arguments. 
15
PASS Invalidate nested :is(). 
15
PASS Invalidate nested :is(). 
16
FAIL Test specificity of :is(). assert_equals: expected "rgb(0, 0, 255)" but got "rgb(0, 0, 0)"
16
PASS Test specificity of :is(). 
17
17
- a/Source/WebCore/ChangeLog +84 lines
Lines 1-3 a/Source/WebCore/ChangeLog_sec1
1
2020-04-13  Antti Koivisto  <antti@apple.com>
2
3
        [CSS Selectors] Remove dynamic specificity
4
        https://bugs.webkit.org/show_bug.cgi?id=210419
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        CSS selector specification drafts at some point had a concept of "dynamic specificity" where
9
        the specificity of a selector depended on the element it matched. It was only ever used with
10
        :matches and :nth-child pseudo classes and has subsequently been removed. Selector specificity
11
        can now always be computed statically.
12
13
        There is a ton of code to support this obsolete feature. Remove it.
14
15
        * css/CSSSelector.cpp:
16
        (WebCore::selectorSpecificity):
17
        (WebCore::maxSpecificity):
18
        (WebCore::simpleSelectorSpecificityInternal):
19
        (WebCore::CSSSelector::simpleSelectorSpecificity const):
20
21
        Also handle nth here.
22
23
        (WebCore::CSSSelector::specificity const):
24
        (WebCore::simpleSelectorFunctionalPseudoClassStaticSpecificity): Deleted.
25
        (WebCore::functionalPseudoClassStaticSpecificity): Deleted.
26
        (WebCore::staticSpecificityInternal): Deleted.
27
        (WebCore::CSSSelector::staticSpecificity const): Deleted.
28
29
        Rename to just specificity(), there is no other kind than static.
30
31
        * css/CSSSelector.h:
32
        * css/SelectorChecker.cpp:
33
        (WebCore::SelectorChecker::match const):
34
        (WebCore::SelectorChecker::matchHostPseudoClass const):
35
        (WebCore::SelectorChecker::matchRecursively const):
36
        (WebCore::SelectorChecker::checkOne const):
37
        (WebCore::SelectorChecker::matchSelectorList const):
38
39
        SelectorChecker doesn't need to deal with specificity anymore.
40
41
        * css/SelectorChecker.h:
42
        * cssjit/SelectorCompiler.cpp:
43
        (WebCore::SelectorCompiler::addNthChildType):
44
        (WebCore::SelectorCompiler::addPseudoClassType):
45
        (WebCore::SelectorCompiler::constructFragmentsInternal):
46
        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateSelectorChecker):
47
        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementAttributeFunctionCallValueMatching):
48
49
        Neither does SelectorCompiler.
50
51
        * cssjit/SelectorCompiler.h:
52
        * dom/SelectorQuery.cpp:
53
        (WebCore::SelectorDataList::selectorMatches const):
54
        (WebCore::SelectorDataList::selectorClosest const):
55
        * inspector/InspectorStyleSheet.cpp:
56
        (WebCore::buildObjectForSelectorHelper):
57
        (WebCore::selectorsFromSource):
58
        (WebCore::InspectorStyleSheet::buildObjectForSelector):
59
        (WebCore::InspectorStyleSheet::buildObjectForSelectorList):
60
        (WebCore::InspectorStyleSheet::buildObjectForRule):
61
        (WebCore::InspectorStyleSheet::buildArrayForRuleList):
62
        (WebCore::hasDynamicSpecificity): Deleted.
63
        * inspector/InspectorStyleSheet.h:
64
        * inspector/agents/InspectorCSSAgent.cpp:
65
        (WebCore::InspectorCSSAgent::setRuleSelector):
66
        (WebCore::InspectorCSSAgent::addRule):
67
        (WebCore::InspectorCSSAgent::buildObjectForRule):
68
        (WebCore::InspectorCSSAgent::buildArrayForMatchedRuleList):
69
        * inspector/agents/InspectorDOMAgent.cpp:
70
        (WebCore::InspectorDOMAgent::highlightSelector):
71
        * style/ElementRuleCollector.cpp:
72
        (WebCore::Style::ElementRuleCollector::ruleMatches):
73
        (WebCore::Style::ElementRuleCollector::collectMatchingRulesForList):
74
        * style/ElementRuleCollector.h:
75
        * style/RuleData.cpp:
76
        (WebCore::Style::computeMatchesBasedOnRuleHash):
77
        (WebCore::Style::RuleData::RuleData):
78
        (WebCore::Style::computeMatchBasedOnRuleHash): Deleted.
79
        * style/RuleData.h:
80
        (WebCore::Style::RuleData::matchesBasedOnRuleHash const):
81
        (WebCore::Style::RuleData::matchBasedOnRuleHash const): Deleted.
82
83
        This can be a bit instead of an enum since there is no need to communicate specificity.
84
1
2020-04-13  Rob Buis  <rbuis@igalia.com>
85
2020-04-13  Rob Buis  <rbuis@igalia.com>
2
86
3
        Remove return parameter from FrameLoader::closeURL
87
        Remove return parameter from FrameLoader::closeURL
- a/Source/WebCore/css/CSSSelector.cpp -72 / +20 lines
Lines 90-103 void CSSSelector::createRareData() a/Source/WebCore/css/CSSSelector.cpp_sec1
90
    m_hasRareData = true;
90
    m_hasRareData = true;
91
}
91
}
92
92
93
static unsigned simpleSelectorSpecificityInternal(const CSSSelector& simpleSelector, bool isComputingMaximumSpecificity);
93
static unsigned simpleSelectorSpecificityInternal(const CSSSelector& simpleSelector);
94
94
95
static unsigned selectorSpecificity(const CSSSelector& firstSimpleSelector, bool isComputingMaximumSpecificity)
95
static unsigned selectorSpecificity(const CSSSelector& firstSimpleSelector)
96
{
96
{
97
    unsigned total = simpleSelectorSpecificityInternal(firstSimpleSelector, isComputingMaximumSpecificity);
97
    unsigned total = 0;
98
98
    for (const CSSSelector* selector = &firstSimpleSelector; selector; selector = selector->tagHistory())
99
    for (const CSSSelector* selector = firstSimpleSelector.tagHistory(); selector; selector = selector->tagHistory())
99
        total = CSSSelector::addSpecificities(total, simpleSelectorSpecificityInternal(*selector));
100
        total = CSSSelector::addSpecificities(total, simpleSelectorSpecificityInternal(*selector, isComputingMaximumSpecificity));
101
    return total;
100
    return total;
102
}
101
}
103
102
Lines 105-115 static unsigned maxSpecificity(const CSSSelectorList& selectorList) a/Source/WebCore/css/CSSSelector.cpp_sec2
105
{
104
{
106
    unsigned maxSpecificity = 0;
105
    unsigned maxSpecificity = 0;
107
    for (const CSSSelector* subSelector = selectorList.first(); subSelector; subSelector = CSSSelectorList::next(subSelector))
106
    for (const CSSSelector* subSelector = selectorList.first(); subSelector; subSelector = CSSSelectorList::next(subSelector))
108
        maxSpecificity = std::max(maxSpecificity, selectorSpecificity(*subSelector, true));
107
        maxSpecificity = std::max(maxSpecificity, selectorSpecificity(*subSelector));
109
    return maxSpecificity;
108
    return maxSpecificity;
110
}
109
}
111
110
112
static unsigned simpleSelectorSpecificityInternal(const CSSSelector& simpleSelector, bool isComputingMaximumSpecificity)
111
static unsigned simpleSelectorSpecificityInternal(const CSSSelector& simpleSelector)
113
{
112
{
114
    ASSERT_WITH_MESSAGE(!simpleSelector.isForPage(), "At the time of this writing, page selectors are not treated as real selectors that are matched. The value computed here only account for real selectors.");
113
    ASSERT_WITH_MESSAGE(!simpleSelector.isForPage(), "At the time of this writing, page selectors are not treated as real selectors that are matched. The value computed here only account for real selectors.");
115
114
Lines 120-137 static unsigned simpleSelectorSpecificityInternal(const CSSSelector& simpleSelec a/Source/WebCore/css/CSSSelector.cpp_sec3
120
    case CSSSelector::PagePseudoClass:
119
    case CSSSelector::PagePseudoClass:
121
        break;
120
        break;
122
    case CSSSelector::PseudoClass:
121
    case CSSSelector::PseudoClass:
123
        if (simpleSelector.pseudoClassType() == CSSSelector::PseudoClassIs || simpleSelector.pseudoClassType() == CSSSelector::PseudoClassMatches) {
122
        switch (simpleSelector.pseudoClassType()) {
124
            ASSERT_WITH_MESSAGE(simpleSelector.selectorList() && simpleSelector.selectorList()->first(), "The parser should never generate a valid selector for an empty :is()/:matches().");
123
        case CSSSelector::PseudoClassIs:
125
            if (!isComputingMaximumSpecificity)
124
        case CSSSelector::PseudoClassMatches:
126
                return 0;
125
        case CSSSelector::PseudoClassNot:
127
            return maxSpecificity(*simpleSelector.selectorList());
128
        }
129
130
        if (simpleSelector.pseudoClassType() == CSSSelector::PseudoClassNot) {
131
            ASSERT_WITH_MESSAGE(simpleSelector.selectorList() && simpleSelector.selectorList()->first(), "The parser should never generate a valid selector for an empty :not().");
132
            return maxSpecificity(*simpleSelector.selectorList());
126
            return maxSpecificity(*simpleSelector.selectorList());
127
        case CSSSelector::PseudoClassNthChild:
128
        case CSSSelector::PseudoClassNthLastChild:
129
            return CSSSelector::addSpecificities(static_cast<unsigned>(SelectorSpecificityIncrement::ClassB), simpleSelector.selectorList() ? maxSpecificity(*simpleSelector.selectorList()) : 0);
130
        default:
131
            break;
133
        }
132
        }
134
        FALLTHROUGH;
133
        return static_cast<unsigned>(SelectorSpecificityIncrement::ClassB);
135
    case CSSSelector::Exact:
134
    case CSSSelector::Exact:
136
    case CSSSelector::Class:
135
    case CSSSelector::Class:
137
    case CSSSelector::Set:
136
    case CSSSelector::Set:
Lines 154-216 static unsigned simpleSelectorSpecificityInternal(const CSSSelector& simpleSelec a/Source/WebCore/css/CSSSelector.cpp_sec4
154
153
155
unsigned CSSSelector::simpleSelectorSpecificity() const
154
unsigned CSSSelector::simpleSelectorSpecificity() const
156
{
155
{
157
    return simpleSelectorSpecificityInternal(*this, false);
156
    return simpleSelectorSpecificityInternal(*this);
158
}
159
160
static unsigned staticSpecificityInternal(const CSSSelector& firstSimpleSelector, bool& ok);
161
162
static unsigned simpleSelectorFunctionalPseudoClassStaticSpecificity(const CSSSelector& simpleSelector, bool& ok)
163
{
164
    if (simpleSelector.match() == CSSSelector::PseudoClass) {
165
        CSSSelector::PseudoClassType pseudoClassType = simpleSelector.pseudoClassType();
166
        if (pseudoClassType == CSSSelector::PseudoClassIs || pseudoClassType == CSSSelector::PseudoClassMatches || pseudoClassType == CSSSelector::PseudoClassNthChild || pseudoClassType == CSSSelector::PseudoClassNthLastChild) {
167
            const CSSSelectorList* selectorList = simpleSelector.selectorList();
168
            if (!selectorList) {
169
                ASSERT_WITH_MESSAGE(pseudoClassType != CSSSelector::PseudoClassIs && pseudoClassType != CSSSelector::PseudoClassMatches, ":is()/:matches() should never be created without a valid selector list.");
170
                return 0;
171
            }
172
173
            const CSSSelector& firstSubselector = *selectorList->first();
174
175
            unsigned initialSpecificity = staticSpecificityInternal(firstSubselector, ok);
176
            if (!ok)
177
                return 0;
178
179
            const CSSSelector* subselector = &firstSubselector;
180
            while ((subselector = CSSSelectorList::next(subselector))) {
181
                unsigned subSelectorSpecificity = staticSpecificityInternal(*subselector, ok);
182
                if (initialSpecificity != subSelectorSpecificity)
183
                    ok = false;
184
                if (!ok)
185
                    return 0;
186
            }
187
            return initialSpecificity;
188
        }
189
    }
190
    return 0;
191
}
192
193
static unsigned functionalPseudoClassStaticSpecificity(const CSSSelector& firstSimpleSelector, bool& ok)
194
{
195
    unsigned total = 0;
196
    for (const CSSSelector* selector = &firstSimpleSelector; selector; selector = selector->tagHistory()) {
197
        total = CSSSelector::addSpecificities(total, simpleSelectorFunctionalPseudoClassStaticSpecificity(*selector, ok));
198
        if (!ok)
199
            return 0;
200
    }
201
    return total;
202
}
203
204
static unsigned staticSpecificityInternal(const CSSSelector& firstSimpleSelector, bool& ok)
205
{
206
    unsigned staticSpecificity = selectorSpecificity(firstSimpleSelector, false);
207
    return CSSSelector::addSpecificities(staticSpecificity, functionalPseudoClassStaticSpecificity(firstSimpleSelector, ok));
208
}
157
}
209
158
210
unsigned CSSSelector::staticSpecificity(bool &ok) const
159
unsigned CSSSelector::specificity() const
211
{
160
{
212
    ok = true;
161
    return selectorSpecificity(*this);
213
    return staticSpecificityInternal(*this, ok);
214
}
162
}
215
163
216
unsigned CSSSelector::addSpecificities(unsigned a, unsigned b)
164
unsigned CSSSelector::addSpecificities(unsigned a, unsigned b)
- a/Source/WebCore/css/CSSSelector.h -1 / +1 lines
Lines 57-63 namespace WebCore { a/Source/WebCore/css/CSSSelector.h_sec1
57
        static const unsigned classMask = 0xff00;
57
        static const unsigned classMask = 0xff00;
58
        static const unsigned elementMask = 0xff;
58
        static const unsigned elementMask = 0xff;
59
59
60
        unsigned staticSpecificity(bool& ok) const;
60
        unsigned specificity() const;
61
        unsigned specificityForPage() const;
61
        unsigned specificityForPage() const;
62
        unsigned simpleSelectorSpecificity() const;
62
        unsigned simpleSelectorSpecificity() const;
63
        static unsigned addSpecificities(unsigned, unsigned);
63
        static unsigned addSpecificities(unsigned, unsigned);
- a/Source/WebCore/css/SelectorChecker.cpp -79 / +25 lines
Lines 170-179 SelectorChecker::SelectorChecker(Document& document) a/Source/WebCore/css/SelectorChecker.cpp_sec1
170
{
170
{
171
}
171
}
172
172
173
bool SelectorChecker::match(const CSSSelector& selector, const Element& element, CheckingContext& checkingContext, unsigned& specificity) const
173
bool SelectorChecker::match(const CSSSelector& selector, const Element& element, CheckingContext& checkingContext) const
174
{
174
{
175
    specificity = 0;
176
177
    LocalContext context(selector, element, checkingContext.resolvingMode == SelectorChecker::Mode::QueryingRules ? VisitedMatchType::Disabled : VisitedMatchType::Enabled, checkingContext.pseudoId);
175
    LocalContext context(selector, element, checkingContext.resolvingMode == SelectorChecker::Mode::QueryingRules ? VisitedMatchType::Disabled : VisitedMatchType::Enabled, checkingContext.pseudoId);
178
176
179
    if (checkingContext.isMatchingHostPseudoClass) {
177
    if (checkingContext.isMatchingHostPseudoClass) {
Lines 182-188 bool SelectorChecker::match(const CSSSelector& selector, const Element& element, a/Source/WebCore/css/SelectorChecker.cpp_sec2
182
    }
180
    }
183
181
184
    PseudoIdSet pseudoIdSet;
182
    PseudoIdSet pseudoIdSet;
185
    MatchResult result = matchRecursively(checkingContext, context, pseudoIdSet, specificity);
183
    MatchResult result = matchRecursively(checkingContext, context, pseudoIdSet);
186
    if (result.match != Match::SelectorMatches)
184
    if (result.match != Match::SelectorMatches)
187
        return false;
185
        return false;
188
    if (checkingContext.pseudoId != PseudoId::None && !pseudoIdSet.has(checkingContext.pseudoId))
186
    if (checkingContext.pseudoId != PseudoId::None && !pseudoIdSet.has(checkingContext.pseudoId))
Lines 200-221 bool SelectorChecker::match(const CSSSelector& selector, const Element& element, a/Source/WebCore/css/SelectorChecker.cpp_sec3
200
    return true;
198
    return true;
201
}
199
}
202
200
203
bool SelectorChecker::matchHostPseudoClass(const CSSSelector& selector, const Element& element, CheckingContext& checkingContext, unsigned& specificity) const
201
bool SelectorChecker::matchHostPseudoClass(const CSSSelector& selector, const Element& element, CheckingContext& checkingContext) const
204
{
202
{
205
    ASSERT(element.shadowRoot());
203
    ASSERT(element.shadowRoot());
206
    ASSERT(selector.match() == CSSSelector::PseudoClass && selector.pseudoClassType() == CSSSelector::PseudoClassHost);
204
    ASSERT(selector.match() == CSSSelector::PseudoClass && selector.pseudoClassType() == CSSSelector::PseudoClassHost);
207
205
208
    specificity = selector.simpleSelectorSpecificity();
209
210
    if (auto* selectorList = selector.selectorList()) {
206
    if (auto* selectorList = selector.selectorList()) {
211
        LocalContext context(*selectorList->first(), element, VisitedMatchType::Enabled, PseudoId::None);
207
        LocalContext context(*selectorList->first(), element, VisitedMatchType::Enabled, PseudoId::None);
212
        context.inFunctionalPseudoClass = true;
208
        context.inFunctionalPseudoClass = true;
213
        context.pseudoElementEffective = false;
209
        context.pseudoElementEffective = false;
214
        PseudoIdSet ignoreDynamicPseudo;
210
        PseudoIdSet ignoreDynamicPseudo;
215
        unsigned subselectorSpecificity = 0;
211
        if (matchRecursively(checkingContext, context, ignoreDynamicPseudo).match != Match::SelectorMatches)
216
        if (matchRecursively(checkingContext, context, ignoreDynamicPseudo, subselectorSpecificity).match != Match::SelectorMatches)
217
            return false;
212
            return false;
218
        specificity = CSSSelector::addSpecificities(specificity, subselectorSpecificity);
219
    }
213
    }
220
    return true;
214
    return true;
221
}
215
}
Lines 263-274 static SelectorChecker::LocalContext localContextForParent(const SelectorChecker a/Source/WebCore/css/SelectorChecker.cpp_sec4
263
// * SelectorFailsLocally     - the selector fails for the element e
257
// * SelectorFailsLocally     - the selector fails for the element e
264
// * SelectorFailsAllSiblings - the selector fails for e and any sibling of e
258
// * SelectorFailsAllSiblings - the selector fails for e and any sibling of e
265
// * SelectorFailsCompletely  - the selector fails for e and any sibling or ancestor of e
259
// * SelectorFailsCompletely  - the selector fails for e and any sibling or ancestor of e
266
SelectorChecker::MatchResult SelectorChecker::matchRecursively(CheckingContext& checkingContext, const LocalContext& context, PseudoIdSet& dynamicPseudoIdSet, unsigned& specificity) const
260
SelectorChecker::MatchResult SelectorChecker::matchRecursively(CheckingContext& checkingContext, const LocalContext& context, PseudoIdSet& dynamicPseudoIdSet) const
267
{
261
{
268
    MatchType matchType = MatchType::Element;
262
    MatchType matchType = MatchType::Element;
269
263
270
    // The first selector has to match.
264
    // The first selector has to match.
271
    if (!checkOne(checkingContext, context, matchType, specificity))
265
    if (!checkOne(checkingContext, context, matchType))
272
        return MatchResult::fails(Match::SelectorFailsLocally);
266
        return MatchResult::fails(Match::SelectorFailsLocally);
273
267
274
    if (context.selector->match() == CSSSelector::PseudoElement) {
268
    if (context.selector->match() == CSSSelector::PseudoElement) {
Lines 336-348 SelectorChecker::MatchResult SelectorChecker::matchRecursively(CheckingContext& a/Source/WebCore/css/SelectorChecker.cpp_sec5
336
        nextContext.firstSelectorOfTheFragment = nextContext.selector;
330
        nextContext.firstSelectorOfTheFragment = nextContext.selector;
337
        for (; nextContext.element; nextContext = localContextForParent(nextContext)) {
331
        for (; nextContext.element; nextContext = localContextForParent(nextContext)) {
338
            PseudoIdSet ignoreDynamicPseudo;
332
            PseudoIdSet ignoreDynamicPseudo;
339
            unsigned descendantsSpecificity = 0;
333
            MatchResult result = matchRecursively(checkingContext, nextContext, ignoreDynamicPseudo);
340
            MatchResult result = matchRecursively(checkingContext, nextContext, ignoreDynamicPseudo, descendantsSpecificity);
341
            ASSERT(!nextContext.pseudoElementEffective && !ignoreDynamicPseudo);
334
            ASSERT(!nextContext.pseudoElementEffective && !ignoreDynamicPseudo);
342
335
343
            if (result.match == Match::SelectorMatches)
344
                specificity = CSSSelector::addSpecificities(specificity, descendantsSpecificity);
345
346
            if (result.match == Match::SelectorMatches || result.match == Match::SelectorFailsCompletely)
336
            if (result.match == Match::SelectorMatches || result.match == Match::SelectorFailsCompletely)
347
                return MatchResult::updateWithMatchType(result, matchType);
337
                return MatchResult::updateWithMatchType(result, matchType);
348
        }
338
        }
Lines 355-367 SelectorChecker::MatchResult SelectorChecker::matchRecursively(CheckingContext& a/Source/WebCore/css/SelectorChecker.cpp_sec6
355
                return MatchResult::fails(Match::SelectorFailsCompletely);
345
                return MatchResult::fails(Match::SelectorFailsCompletely);
356
            nextContext.firstSelectorOfTheFragment = nextContext.selector;
346
            nextContext.firstSelectorOfTheFragment = nextContext.selector;
357
            PseudoIdSet ignoreDynamicPseudo;
347
            PseudoIdSet ignoreDynamicPseudo;
358
            unsigned childSpecificity = 0;
348
            MatchResult result = matchRecursively(checkingContext, nextContext, ignoreDynamicPseudo);
359
            MatchResult result = matchRecursively(checkingContext, nextContext, ignoreDynamicPseudo, childSpecificity);
360
            ASSERT(!nextContext.pseudoElementEffective && !ignoreDynamicPseudo);
349
            ASSERT(!nextContext.pseudoElementEffective && !ignoreDynamicPseudo);
361
350
362
            if (result.match == Match::SelectorMatches)
363
                specificity = CSSSelector::addSpecificities(specificity, childSpecificity);
364
365
            if (result.match == Match::SelectorMatches || result.match == Match::SelectorFailsCompletely)
351
            if (result.match == Match::SelectorMatches || result.match == Match::SelectorFailsCompletely)
366
                return MatchResult::updateWithMatchType(result, matchType);
352
                return MatchResult::updateWithMatchType(result, matchType);
367
            return MatchResult::fails(Match::SelectorFailsAllSiblings);
353
            return MatchResult::fails(Match::SelectorFailsAllSiblings);
Lines 381-393 SelectorChecker::MatchResult SelectorChecker::matchRecursively(CheckingContext& a/Source/WebCore/css/SelectorChecker.cpp_sec7
381
            nextContext.element = previousElement;
367
            nextContext.element = previousElement;
382
            nextContext.firstSelectorOfTheFragment = nextContext.selector;
368
            nextContext.firstSelectorOfTheFragment = nextContext.selector;
383
            PseudoIdSet ignoreDynamicPseudo;
369
            PseudoIdSet ignoreDynamicPseudo;
384
            unsigned adjacentSpecificity = 0;
370
            MatchResult result = matchRecursively(checkingContext, nextContext, ignoreDynamicPseudo);
385
            MatchResult result = matchRecursively(checkingContext, nextContext, ignoreDynamicPseudo, adjacentSpecificity);
386
            ASSERT(!nextContext.pseudoElementEffective && !ignoreDynamicPseudo);
371
            ASSERT(!nextContext.pseudoElementEffective && !ignoreDynamicPseudo);
387
372
388
            if (result.match == Match::SelectorMatches)
389
                specificity = CSSSelector::addSpecificities(specificity, adjacentSpecificity);
390
391
            return MatchResult::updateWithMatchType(result, matchType);
373
            return MatchResult::updateWithMatchType(result, matchType);
392
        }
374
        }
393
    case CSSSelector::IndirectAdjacent: {
375
    case CSSSelector::IndirectAdjacent: {
Lines 400-412 SelectorChecker::MatchResult SelectorChecker::matchRecursively(CheckingContext& a/Source/WebCore/css/SelectorChecker.cpp_sec8
400
            addStyleRelation(checkingContext, *nextContext.element, Style::Relation::AffectsNextSibling);
382
            addStyleRelation(checkingContext, *nextContext.element, Style::Relation::AffectsNextSibling);
401
383
402
            PseudoIdSet ignoreDynamicPseudo;
384
            PseudoIdSet ignoreDynamicPseudo;
403
            unsigned indirectAdjacentSpecificity = 0;
385
            MatchResult result = matchRecursively(checkingContext, nextContext, ignoreDynamicPseudo);
404
            MatchResult result = matchRecursively(checkingContext, nextContext, ignoreDynamicPseudo, indirectAdjacentSpecificity);
405
            ASSERT(!nextContext.pseudoElementEffective && !ignoreDynamicPseudo);
386
            ASSERT(!nextContext.pseudoElementEffective && !ignoreDynamicPseudo);
406
387
407
            if (result.match == Match::SelectorMatches)
408
                specificity = CSSSelector::addSpecificities(specificity, indirectAdjacentSpecificity);
409
410
            if (result.match == Match::SelectorMatches || result.match == Match::SelectorFailsAllSiblings || result.match == Match::SelectorFailsCompletely)
388
            if (result.match == Match::SelectorMatches || result.match == Match::SelectorFailsAllSiblings || result.match == Match::SelectorFailsCompletely)
411
                return MatchResult::updateWithMatchType(result, matchType);
389
                return MatchResult::updateWithMatchType(result, matchType);
412
        };
390
        };
Lines 424-434 SelectorChecker::MatchResult SelectorChecker::matchRecursively(CheckingContext& a/Source/WebCore/css/SelectorChecker.cpp_sec9
424
                && !(nextContext.hasScrollbarPseudo && nextContext.selector->match() == CSSSelector::PseudoClass))
402
                && !(nextContext.hasScrollbarPseudo && nextContext.selector->match() == CSSSelector::PseudoClass))
425
                return MatchResult::fails(Match::SelectorFailsCompletely);
403
                return MatchResult::fails(Match::SelectorFailsCompletely);
426
404
427
            unsigned subselectorSpecificity = 0;
405
            MatchResult result = matchRecursively(checkingContext, nextContext, dynamicPseudoIdSet);
428
            MatchResult result = matchRecursively(checkingContext, nextContext, dynamicPseudoIdSet, subselectorSpecificity);
429
430
            if (result.match == Match::SelectorMatches)
431
                specificity = CSSSelector::addSpecificities(specificity, subselectorSpecificity);
432
406
433
            return MatchResult::updateWithMatchType(result, matchType);
407
            return MatchResult::updateWithMatchType(result, matchType);
434
        }
408
        }
Lines 443-453 SelectorChecker::MatchResult SelectorChecker::matchRecursively(CheckingContext& a/Source/WebCore/css/SelectorChecker.cpp_sec10
443
            nextContext.firstSelectorOfTheFragment = nextContext.selector;
417
            nextContext.firstSelectorOfTheFragment = nextContext.selector;
444
            nextContext.isSubjectOrAdjacentElement = false;
418
            nextContext.isSubjectOrAdjacentElement = false;
445
            PseudoIdSet ignoreDynamicPseudo;
419
            PseudoIdSet ignoreDynamicPseudo;
446
            unsigned shadowDescendantSpecificity = 0;
420
            MatchResult result = matchRecursively(checkingContext, nextContext, ignoreDynamicPseudo);
447
            MatchResult result = matchRecursively(checkingContext, nextContext, ignoreDynamicPseudo, shadowDescendantSpecificity);
448
449
            if (result.match == Match::SelectorMatches)
450
                specificity = CSSSelector::addSpecificities(specificity, shadowDescendantSpecificity);
451
421
452
            return MatchResult::updateWithMatchType(result, matchType);
422
            return MatchResult::updateWithMatchType(result, matchType);
453
        }
423
        }
Lines 651-663 static inline bool tagMatches(const Element& element, const CSSSelector& simpleS a/Source/WebCore/css/SelectorChecker.cpp_sec11
651
    return namespaceURI == starAtom() || namespaceURI == element.namespaceURI();
621
    return namespaceURI == starAtom() || namespaceURI == element.namespaceURI();
652
}
622
}
653
623
654
bool SelectorChecker::checkOne(CheckingContext& checkingContext, const LocalContext& context, MatchType& matchType, unsigned& specificity) const
624
bool SelectorChecker::checkOne(CheckingContext& checkingContext, const LocalContext& context, MatchType& matchType) const
655
{
625
{
656
    const Element& element = *context.element;
626
    const Element& element = *context.element;
657
    const CSSSelector& selector = *context.selector;
627
    const CSSSelector& selector = *context.selector;
658
628
659
    specificity = CSSSelector::addSpecificities(specificity, selector.simpleSelectorSpecificity());
660
661
    if (context.mayMatchHostPseudoClass) {
629
    if (context.mayMatchHostPseudoClass) {
662
        // :host doesn't combine with anything except pseudo elements.
630
        // :host doesn't combine with anything except pseudo elements.
663
        bool isHostPseudoClass = selector.match() == CSSSelector::PseudoClass && selector.pseudoClassType() == CSSSelector::PseudoClassHost;
631
        bool isHostPseudoClass = selector.match() == CSSSelector::PseudoClass && selector.pseudoClassType() == CSSSelector::PseudoClassHost;
Lines 704-711 bool SelectorChecker::checkOne(CheckingContext& checkingContext, const LocalCont a/Source/WebCore/css/SelectorChecker.cpp_sec12
704
                subcontext.firstSelectorOfTheFragment = selectorList->first();
672
                subcontext.firstSelectorOfTheFragment = selectorList->first();
705
                PseudoIdSet ignoreDynamicPseudo;
673
                PseudoIdSet ignoreDynamicPseudo;
706
674
707
                unsigned ignoredSpecificity;
675
                if (matchRecursively(checkingContext, subcontext, ignoreDynamicPseudo).match == Match::SelectorMatches) {
708
                if (matchRecursively(checkingContext, subcontext, ignoreDynamicPseudo, ignoredSpecificity).match == Match::SelectorMatches) {
709
                    ASSERT(!ignoreDynamicPseudo);
676
                    ASSERT(!ignoreDynamicPseudo);
710
                    return false;
677
                    return false;
711
                }
678
                }
Lines 833-839 bool SelectorChecker::checkOne(CheckingContext& checkingContext, const LocalCont a/Source/WebCore/css/SelectorChecker.cpp_sec13
833
        case CSSSelector::PseudoClassMatches:
800
        case CSSSelector::PseudoClassMatches:
834
            {
801
            {
835
                bool hasMatchedAnything = false;
802
                bool hasMatchedAnything = false;
836
                unsigned maxSpecificity = 0;
837
803
838
                MatchType localMatchType = MatchType::VirtualPseudoElementOnly;
804
                MatchType localMatchType = MatchType::VirtualPseudoElementOnly;
839
                for (const CSSSelector* subselector = selector.selectorList()->first(); subselector; subselector = CSSSelectorList::next(subselector)) {
805
                for (const CSSSelector* subselector = selector.selectorList()->first(); subselector; subselector = CSSSelectorList::next(subselector)) {
Lines 844-869 bool SelectorChecker::checkOne(CheckingContext& checkingContext, const LocalCont a/Source/WebCore/css/SelectorChecker.cpp_sec14
844
                    subcontext.firstSelectorOfTheFragment = subselector;
810
                    subcontext.firstSelectorOfTheFragment = subselector;
845
                    subcontext.pseudoId = PseudoId::None;
811
                    subcontext.pseudoId = PseudoId::None;
846
                    PseudoIdSet localDynamicPseudoIdSet;
812
                    PseudoIdSet localDynamicPseudoIdSet;
847
                    unsigned localSpecificity = 0;
813
                    MatchResult result = matchRecursively(checkingContext, subcontext, localDynamicPseudoIdSet);
848
                    MatchResult result = matchRecursively(checkingContext, subcontext, localDynamicPseudoIdSet, localSpecificity);
849
814
850
                    // Pseudo elements are not valid inside :is()/:matches()
815
                    // Pseudo elements are not valid inside :is()/:matches()
851
                    if (localDynamicPseudoIdSet)
816
                    if (localDynamicPseudoIdSet)
852
                        continue;
817
                        continue;
853
818
854
                    if (result.match == Match::SelectorMatches) {
819
                    if (result.match == Match::SelectorMatches) {
855
                        maxSpecificity = std::max(maxSpecificity, localSpecificity);
856
857
                        if (result.matchType == MatchType::Element)
820
                        if (result.matchType == MatchType::Element)
858
                            localMatchType = MatchType::Element;
821
                            localMatchType = MatchType::Element;
859
822
860
                        hasMatchedAnything = true;
823
                        hasMatchedAnything = true;
861
                    }
824
                    }
862
                }
825
                }
863
                if (hasMatchedAnything) {
826
                if (hasMatchedAnything)
864
                    matchType = localMatchType;
827
                    matchType = localMatchType;
865
                    specificity = CSSSelector::addSpecificities(specificity, maxSpecificity);
866
                }
867
                return hasMatchedAnything;
828
                return hasMatchedAnything;
868
            }
829
            }
869
        case CSSSelector::PseudoClassPlaceholderShown:
830
        case CSSSelector::PseudoClassPlaceholderShown:
Lines 881-897 bool SelectorChecker::checkOne(CheckingContext& checkingContext, const LocalCont a/Source/WebCore/css/SelectorChecker.cpp_sec15
881
                break; // FIXME: Add the support for specifying relations on ShadowRoot.
842
                break; // FIXME: Add the support for specifying relations on ShadowRoot.
882
843
883
            if (const CSSSelectorList* selectorList = selector.selectorList()) {
844
            if (const CSSSelectorList* selectorList = selector.selectorList()) {
884
                unsigned selectorListSpecificity;
845
                if (!matchSelectorList(checkingContext, context, element, *selectorList))
885
                if (!matchSelectorList(checkingContext, context, element, *selectorList, selectorListSpecificity))
886
                    return false;
846
                    return false;
887
                specificity = CSSSelector::addSpecificities(specificity, selectorListSpecificity);
888
            }
847
            }
889
848
890
            int count = 1;
849
            int count = 1;
891
            if (const CSSSelectorList* selectorList = selector.selectorList()) {
850
            if (const CSSSelectorList* selectorList = selector.selectorList()) {
892
                for (Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(*sibling)) {
851
                for (Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(*sibling)) {
893
                    unsigned ignoredSpecificity;
852
                    if (matchSelectorList(checkingContext, context, *sibling, *selectorList))
894
                    if (matchSelectorList(checkingContext, context, *sibling, *selectorList, ignoredSpecificity))
895
                        ++count;
853
                        ++count;
896
                }
854
                }
897
            } else {
855
            } else {
Lines 921-930 bool SelectorChecker::checkOne(CheckingContext& checkingContext, const LocalCont a/Source/WebCore/css/SelectorChecker.cpp_sec16
921
            if (is<Element>(parent)) {
879
            if (is<Element>(parent)) {
922
                auto& parentElement = downcast<Element>(*parent);
880
                auto& parentElement = downcast<Element>(*parent);
923
                if (const CSSSelectorList* selectorList = selector.selectorList()) {
881
                if (const CSSSelectorList* selectorList = selector.selectorList()) {
924
                    unsigned selectorListSpecificity;
882
                    if (!matchSelectorList(checkingContext, context, element, *selectorList))
925
                    if (!matchSelectorList(checkingContext, context, element, *selectorList, selectorListSpecificity))
926
                        return false;
883
                        return false;
927
                    specificity = CSSSelector::addSpecificities(specificity, selectorListSpecificity);
928
884
929
                    addStyleRelation(checkingContext, parentElement, Style::Relation::ChildrenAffectedByPropertyBasedBackwardPositionalRules);
885
                    addStyleRelation(checkingContext, parentElement, Style::Relation::ChildrenAffectedByPropertyBasedBackwardPositionalRules);
930
                } else {
886
                } else {
Lines 939-946 bool SelectorChecker::checkOne(CheckingContext& checkingContext, const LocalCont a/Source/WebCore/css/SelectorChecker.cpp_sec17
939
            int count = 1;
895
            int count = 1;
940
            if (const CSSSelectorList* selectorList = selector.selectorList()) {
896
            if (const CSSSelectorList* selectorList = selector.selectorList()) {
941
                for (Element* sibling = ElementTraversal::nextSibling(element); sibling; sibling = ElementTraversal::nextSibling(*sibling)) {
897
                for (Element* sibling = ElementTraversal::nextSibling(element); sibling; sibling = ElementTraversal::nextSibling(*sibling)) {
942
                    unsigned ignoredSpecificity;
898
                    if (matchSelectorList(checkingContext, context, *sibling, *selectorList))
943
                    if (matchSelectorList(checkingContext, context, *sibling, *selectorList, ignoredSpecificity))
944
                        ++count;
899
                        ++count;
945
                }
900
                }
946
            } else
901
            } else
Lines 974-981 bool SelectorChecker::checkOne(CheckingContext& checkingContext, const LocalCont a/Source/WebCore/css/SelectorChecker.cpp_sec18
974
                for (subcontext.selector = selector.selectorList()->first(); subcontext.selector; subcontext.selector = CSSSelectorList::next(subcontext.selector)) {
929
                for (subcontext.selector = selector.selectorList()->first(); subcontext.selector; subcontext.selector = CSSSelectorList::next(subcontext.selector)) {
975
                    subcontext.firstSelectorOfTheFragment = subcontext.selector;
930
                    subcontext.firstSelectorOfTheFragment = subcontext.selector;
976
                    PseudoIdSet ignoreDynamicPseudo;
931
                    PseudoIdSet ignoreDynamicPseudo;
977
                    unsigned ingoredSpecificity = 0;
932
                    if (matchRecursively(checkingContext, subcontext, ignoreDynamicPseudo).match == Match::SelectorMatches)
978
                    if (matchRecursively(checkingContext, subcontext, ignoreDynamicPseudo, ingoredSpecificity).match == Match::SelectorMatches)
979
                        return true;
933
                        return true;
980
                }
934
                }
981
            }
935
            }
Lines 1090-1100 bool SelectorChecker::checkOne(CheckingContext& checkingContext, const LocalCont a/Source/WebCore/css/SelectorChecker.cpp_sec19
1090
        case CSSSelector::PseudoClassHost: {
1044
        case CSSSelector::PseudoClassHost: {
1091
            if (!context.mayMatchHostPseudoClass)
1045
            if (!context.mayMatchHostPseudoClass)
1092
                return false;
1046
                return false;
1093
            unsigned hostSpecificity;
1047
            return matchHostPseudoClass(selector, element, checkingContext);
1094
            if (!matchHostPseudoClass(selector, element, checkingContext, hostSpecificity))
1095
                return false;
1096
            specificity = CSSSelector::addSpecificities(specificity, hostSpecificity);
1097
            return true;
1098
        }
1048
        }
1099
        case CSSSelector::PseudoClassDefined:
1049
        case CSSSelector::PseudoClassDefined:
1100
            return isDefinedElement(element);
1050
            return isDefinedElement(element);
Lines 1147-1154 bool SelectorChecker::checkOne(CheckingContext& checkingContext, const LocalCont a/Source/WebCore/css/SelectorChecker.cpp_sec20
1147
                subcontext.inFunctionalPseudoClass = true;
1097
                subcontext.inFunctionalPseudoClass = true;
1148
                subcontext.pseudoElementEffective = false;
1098
                subcontext.pseudoElementEffective = false;
1149
                PseudoIdSet ignoredDynamicPseudo;
1099
                PseudoIdSet ignoredDynamicPseudo;
1150
                unsigned ignoredSpecificity = 0;
1100
                if (matchRecursively(checkingContext, subcontext, ignoredDynamicPseudo).match == Match::SelectorMatches)
1151
                if (matchRecursively(checkingContext, subcontext, ignoredDynamicPseudo, ignoredSpecificity).match == Match::SelectorMatches)
1152
                    return true;
1101
                    return true;
1153
            }
1102
            }
1154
            return false;
1103
            return false;
Lines 1204-1212 bool SelectorChecker::checkOne(CheckingContext& checkingContext, const LocalCont a/Source/WebCore/css/SelectorChecker.cpp_sec21
1204
    return true;
1153
    return true;
1205
}
1154
}
1206
1155
1207
bool SelectorChecker::matchSelectorList(CheckingContext& checkingContext, const LocalContext& context, const Element& element, const CSSSelectorList& selectorList, unsigned& specificity) const
1156
bool SelectorChecker::matchSelectorList(CheckingContext& checkingContext, const LocalContext& context, const Element& element, const CSSSelectorList& selectorList) const
1208
{
1157
{
1209
    specificity = 0;
1210
    bool hasMatchedAnything = false;
1158
    bool hasMatchedAnything = false;
1211
1159
1212
    for (const CSSSelector* subselector = selectorList.first(); subselector; subselector = CSSSelectorList::next(subselector)) {
1160
    for (const CSSSelector* subselector = selectorList.first(); subselector; subselector = CSSSelectorList::next(subselector)) {
Lines 1217-1228 bool SelectorChecker::matchSelectorList(CheckingContext& checkingContext, const a/Source/WebCore/css/SelectorChecker.cpp_sec22
1217
        subcontext.pseudoElementEffective = false;
1165
        subcontext.pseudoElementEffective = false;
1218
        subcontext.firstSelectorOfTheFragment = subselector;
1166
        subcontext.firstSelectorOfTheFragment = subselector;
1219
        PseudoIdSet ignoreDynamicPseudo;
1167
        PseudoIdSet ignoreDynamicPseudo;
1220
        unsigned localSpecificity = 0;
1168
        if (matchRecursively(checkingContext, subcontext, ignoreDynamicPseudo).match == Match::SelectorMatches) {
1221
        if (matchRecursively(checkingContext, subcontext, ignoreDynamicPseudo, localSpecificity).match == Match::SelectorMatches) {
1222
            ASSERT(!ignoreDynamicPseudo);
1169
            ASSERT(!ignoreDynamicPseudo);
1223
1170
1224
            hasMatchedAnything = true;
1171
            hasMatchedAnything = true;
1225
            specificity = std::max(specificity, localSpecificity);
1226
        }
1172
        }
1227
    }
1173
    }
1228
    return hasMatchedAnything;
1174
    return hasMatchedAnything;
- a/Source/WebCore/css/SelectorChecker.h -5 / +5 lines
Lines 101-109 public: a/Source/WebCore/css/SelectorChecker.h_sec1
101
        PseudoIdSet pseudoIDSet;
101
        PseudoIdSet pseudoIDSet;
102
    };
102
    };
103
103
104
    bool match(const CSSSelector&, const Element&, CheckingContext&, unsigned& specificity) const;
104
    bool match(const CSSSelector&, const Element&, CheckingContext&) const;
105
105
106
    bool matchHostPseudoClass(const CSSSelector&, const Element&, CheckingContext&, unsigned& specificity) const;
106
    bool matchHostPseudoClass(const CSSSelector&, const Element&, CheckingContext&) const;
107
107
108
    static bool isCommonPseudoClassSelector(const CSSSelector*);
108
    static bool isCommonPseudoClassSelector(const CSSSelector*);
109
    static bool matchesFocusPseudoClass(const Element&);
109
    static bool matchesFocusPseudoClass(const Element&);
Lines 116-124 public: a/Source/WebCore/css/SelectorChecker.h_sec2
116
    struct LocalContext;
116
    struct LocalContext;
117
    
117
    
118
private:
118
private:
119
    MatchResult matchRecursively(CheckingContext&, const LocalContext&, PseudoIdSet&, unsigned& specificity) const;
119
    MatchResult matchRecursively(CheckingContext&, const LocalContext&, PseudoIdSet&) const;
120
    bool checkOne(CheckingContext&, const LocalContext&, MatchType&, unsigned& specificity) const;
120
    bool checkOne(CheckingContext&, const LocalContext&, MatchType&) const;
121
    bool matchSelectorList(CheckingContext&, const LocalContext&, const Element&, const CSSSelectorList&, unsigned& specificity) const;
121
    bool matchSelectorList(CheckingContext&, const LocalContext&, const Element&, const CSSSelectorList&) const;
122
122
123
    bool checkScrollbarPseudoClass(const CheckingContext&, const Element&, const CSSSelector&) const;
123
    bool checkScrollbarPseudoClass(const CheckingContext&, const Element&, const CSSSelector&) const;
124
124
- a/Source/WebCore/cssjit/SelectorCompiler.cpp -48 / +5 lines
Lines 231-237 class SelectorFragmentList : public Vector<SelectorFragment, 4> { a/Source/WebCore/cssjit/SelectorCompiler.cpp_sec1
231
public:
231
public:
232
    unsigned registerRequirements = std::numeric_limits<unsigned>::max();
232
    unsigned registerRequirements = std::numeric_limits<unsigned>::max();
233
    unsigned stackRequirements = std::numeric_limits<unsigned>::max();
233
    unsigned stackRequirements = std::numeric_limits<unsigned>::max();
234
    unsigned staticSpecificity = 0;
235
    bool clobberElementAddressRegister = true;
234
    bool clobberElementAddressRegister = true;
236
};
235
};
237
236
Lines 464-470 static inline FunctionType addScrollbarPseudoClassType(const CSSSelector&, Selec a/Source/WebCore/cssjit/SelectorCompiler.cpp_sec2
464
}
463
}
465
464
466
// Handle the forward :nth-child() and backward :nth-last-child().
465
// Handle the forward :nth-child() and backward :nth-last-child().
467
static FunctionType addNthChildType(const CSSSelector& selector, SelectorContext selectorContext, FragmentPositionInRootFragments positionInRootFragments, CSSSelector::PseudoClassType firstMatchAlternative, bool visitedMatchEnabled, Vector<std::pair<int, int>, 2>& simpleCases, Vector<NthChildOfSelectorInfo>& filteredCases, HashSet<unsigned>& pseudoClasses, unsigned& internalSpecificity)
466
static FunctionType addNthChildType(const CSSSelector& selector, SelectorContext selectorContext, FragmentPositionInRootFragments positionInRootFragments, CSSSelector::PseudoClassType firstMatchAlternative, bool visitedMatchEnabled, Vector<std::pair<int, int>, 2>& simpleCases, Vector<NthChildOfSelectorInfo>& filteredCases, HashSet<unsigned>& pseudoClasses)
468
{
467
{
469
    int a = selector.nthA();
468
    int a = selector.nthA();
470
    int b = selector.nthB();
469
    int b = selector.nthB();
Lines 482-490 static FunctionType addNthChildType(const CSSSelector& selector, SelectorContext a/Source/WebCore/cssjit/SelectorCompiler.cpp_sec3
482
        if (selectorContext != SelectorContext::QuerySelector)
481
        if (selectorContext != SelectorContext::QuerySelector)
483
            globalFunctionType = FunctionType::SelectorCheckerWithCheckingContext;
482
            globalFunctionType = FunctionType::SelectorCheckerWithCheckingContext;
484
483
485
        unsigned firstFragmentListSpecificity = 0;
486
        bool firstFragmentListSpecificitySet = false;
487
488
        SelectorFragmentList* selectorFragments = nullptr;
484
        SelectorFragmentList* selectorFragments = nullptr;
489
        for (const CSSSelector* subselector = selectorList->first(); subselector; subselector = CSSSelectorList::next(subselector)) {
485
        for (const CSSSelector* subselector = selectorList->first(); subselector; subselector = CSSSelectorList::next(subselector)) {
490
            if (!selectorFragments) {
486
            if (!selectorFragments) {
Lines 505-519 static FunctionType addNthChildType(const CSSSelector& selector, SelectorContext a/Source/WebCore/cssjit/SelectorCompiler.cpp_sec4
505
                return FunctionType::CannotCompile;
501
                return FunctionType::CannotCompile;
506
            }
502
            }
507
503
508
            if (firstFragmentListSpecificitySet) {
509
                // The CSS JIT does not handle dynamic specificity yet.
510
                if (selectorContext == SelectorContext::RuleCollector && selectorFragments->staticSpecificity != firstFragmentListSpecificity)
511
                    return FunctionType::CannotCompile;
512
            } else {
513
                firstFragmentListSpecificitySet = true;
514
                firstFragmentListSpecificity = selectorFragments->staticSpecificity;
515
            }
516
517
            globalFunctionType = mostRestrictiveFunctionType(globalFunctionType, functionType);
504
            globalFunctionType = mostRestrictiveFunctionType(globalFunctionType, functionType);
518
            selectorFragments = nullptr;
505
            selectorFragments = nullptr;
519
        }
506
        }
Lines 526-532 static FunctionType addNthChildType(const CSSSelector& selector, SelectorContext a/Source/WebCore/cssjit/SelectorCompiler.cpp_sec5
526
        if (nthChildOfSelectorInfo.selectorList.isEmpty())
513
        if (nthChildOfSelectorInfo.selectorList.isEmpty())
527
            return FunctionType::CannotMatchAnything;
514
            return FunctionType::CannotMatchAnything;
528
515
529
        internalSpecificity = firstFragmentListSpecificity;
530
        filteredCases.append(nthChildOfSelectorInfo);
516
        filteredCases.append(nthChildOfSelectorInfo);
531
        return globalFunctionType;
517
        return globalFunctionType;
532
    }
518
    }
Lines 540-546 static FunctionType addNthChildType(const CSSSelector& selector, SelectorContext a/Source/WebCore/cssjit/SelectorCompiler.cpp_sec6
540
    return FunctionType::SelectorCheckerWithCheckingContext;
526
    return FunctionType::SelectorCheckerWithCheckingContext;
541
}
527
}
542
528
543
static inline FunctionType addPseudoClassType(const CSSSelector& selector, SelectorFragment& fragment, unsigned& internalSpecificity, SelectorContext selectorContext, FragmentsLevel fragmentLevel, FragmentPositionInRootFragments positionInRootFragments, bool visitedMatchEnabled, VisitedMode& visitedMode, PseudoElementMatchingBehavior pseudoElementMatchingBehavior)
529
static inline FunctionType addPseudoClassType(const CSSSelector& selector, SelectorFragment& fragment, SelectorContext selectorContext, FragmentsLevel fragmentLevel, FragmentPositionInRootFragments positionInRootFragments, bool visitedMatchEnabled, VisitedMode& visitedMode, PseudoElementMatchingBehavior pseudoElementMatchingBehavior)
544
{
530
{
545
    CSSSelector::PseudoClassType type = selector.pseudoClassType();
531
    CSSSelector::PseudoClassType type = selector.pseudoClassType();
546
    switch (type) {
532
    switch (type) {
Lines 722-731 static inline FunctionType addPseudoClassType(const CSSSelector& selector, Selec a/Source/WebCore/cssjit/SelectorCompiler.cpp_sec7
722
        return FunctionType::SelectorCheckerWithCheckingContext;
708
        return FunctionType::SelectorCheckerWithCheckingContext;
723
709
724
    case CSSSelector::PseudoClassNthChild:
710
    case CSSSelector::PseudoClassNthChild:
725
        return addNthChildType(selector, selectorContext, positionInRootFragments, CSSSelector::PseudoClassFirstChild, visitedMatchEnabled, fragment.nthChildFilters, fragment.nthChildOfFilters, fragment.pseudoClasses, internalSpecificity);
711
        return addNthChildType(selector, selectorContext, positionInRootFragments, CSSSelector::PseudoClassFirstChild, visitedMatchEnabled, fragment.nthChildFilters, fragment.nthChildOfFilters, fragment.pseudoClasses);
726
712
727
    case CSSSelector::PseudoClassNthLastChild:
713
    case CSSSelector::PseudoClassNthLastChild:
728
        return addNthChildType(selector, selectorContext, positionInRootFragments, CSSSelector::PseudoClassLastChild, visitedMatchEnabled, fragment.nthLastChildFilters, fragment.nthLastChildOfFilters, fragment.pseudoClasses, internalSpecificity);
714
        return addNthChildType(selector, selectorContext, positionInRootFragments, CSSSelector::PseudoClassLastChild, visitedMatchEnabled, fragment.nthLastChildFilters, fragment.nthLastChildOfFilters, fragment.pseudoClasses);
729
715
730
    case CSSSelector::PseudoClassNot:
716
    case CSSSelector::PseudoClassNot:
731
        {
717
        {
Lines 817-824 static inline FunctionType addPseudoClassType(const CSSSelector& selector, Selec a/Source/WebCore/cssjit/SelectorCompiler.cpp_sec8
817
            SelectorList matchesList;
803
            SelectorList matchesList;
818
            const CSSSelectorList* selectorList = selector.selectorList();
804
            const CSSSelectorList* selectorList = selector.selectorList();
819
            FunctionType functionType = FunctionType::SimpleSelectorChecker;
805
            FunctionType functionType = FunctionType::SimpleSelectorChecker;
820
            unsigned firstFragmentListSpecificity = 0;
821
            bool firstFragmentListSpecificitySet = false;
822
            SelectorFragmentList* selectorFragments = nullptr;
806
            SelectorFragmentList* selectorFragments = nullptr;
823
            for (const CSSSelector* subselector = selectorList->first(); subselector; subselector = CSSSelectorList::next(subselector)) {
807
            for (const CSSSelector* subselector = selectorList->first(); subselector; subselector = CSSSelectorList::next(subselector)) {
824
                if (!selectorFragments) {
808
                if (!selectorFragments) {
Lines 841-855 static inline FunctionType addPseudoClassType(const CSSSelector& selector, Selec a/Source/WebCore/cssjit/SelectorCompiler.cpp_sec9
841
                if (selectorFragments->first().pseudoElementSelector)
825
                if (selectorFragments->first().pseudoElementSelector)
842
                    return FunctionType::CannotCompile;
826
                    return FunctionType::CannotCompile;
843
827
844
                if (firstFragmentListSpecificitySet) {
845
                    // The CSS JIT does not handle dynamic specificity yet.
846
                    if (selectorContext == SelectorContext::RuleCollector && selectorFragments->staticSpecificity != firstFragmentListSpecificity)
847
                        return FunctionType::CannotCompile;
848
                } else {
849
                    firstFragmentListSpecificitySet = true;
850
                    firstFragmentListSpecificity = selectorFragments->staticSpecificity;
851
                }
852
853
                functionType = mostRestrictiveFunctionType(functionType, localFunctionType);
828
                functionType = mostRestrictiveFunctionType(functionType, localFunctionType);
854
                selectorFragments = nullptr;
829
                selectorFragments = nullptr;
855
            }
830
            }
Lines 863-870 static inline FunctionType addPseudoClassType(const CSSSelector& selector, Selec a/Source/WebCore/cssjit/SelectorCompiler.cpp_sec10
863
            if (matchesList.isEmpty())
838
            if (matchesList.isEmpty())
864
                return FunctionType::CannotMatchAnything;
839
                return FunctionType::CannotMatchAnything;
865
840
866
            internalSpecificity = firstFragmentListSpecificity;
867
868
            fragment.matchesFilters.append(matchesList);
841
            fragment.matchesFilters.append(matchesList);
869
842
870
            return functionType;
843
            return functionType;
Lines 919-933 static FunctionType constructFragmentsInternal(const CSSSelector* rootSelector, a/Source/WebCore/cssjit/SelectorCompiler.cpp_sec11
919
    bool isRightmostOrAdjacent = positionInRootFragments != FragmentPositionInRootFragments::Other;
892
    bool isRightmostOrAdjacent = positionInRootFragments != FragmentPositionInRootFragments::Other;
920
    FunctionType functionType = FunctionType::SimpleSelectorChecker;
893
    FunctionType functionType = FunctionType::SimpleSelectorChecker;
921
    SelectorFragment* fragment = nullptr;
894
    SelectorFragment* fragment = nullptr;
922
    unsigned specificity = 0;
923
    for (const CSSSelector* selector = rootSelector; selector; selector = selector->tagHistory()) {
895
    for (const CSSSelector* selector = rootSelector; selector; selector = selector->tagHistory()) {
924
        if (!fragment) {
896
        if (!fragment) {
925
            selectorFragments.append(SelectorFragment());
897
            selectorFragments.append(SelectorFragment());
926
            fragment = &selectorFragments.last();
898
            fragment = &selectorFragments.last();
927
        }
899
        }
928
900
929
        specificity = CSSSelector::addSpecificities(specificity, selector->simpleSelectorSpecificity());
930
931
        // A selector is invalid if something follows a pseudo-element.
901
        // A selector is invalid if something follows a pseudo-element.
932
        // We make an exception for scrollbar pseudo elements and allow a set of pseudo classes (but nothing else)
902
        // We make an exception for scrollbar pseudo elements and allow a set of pseudo classes (but nothing else)
933
        // to follow the pseudo elements.
903
        // to follow the pseudo elements.
Lines 962-970 static FunctionType constructFragmentsInternal(const CSSSelector* rootSelector, a/Source/WebCore/cssjit/SelectorCompiler.cpp_sec12
962
            if (fragment->pseudoElementSelector && isScrollbarPseudoElement(fragment->pseudoElementSelector->pseudoElementType()))
932
            if (fragment->pseudoElementSelector && isScrollbarPseudoElement(fragment->pseudoElementSelector->pseudoElementType()))
963
                functionType = mostRestrictiveFunctionType(functionType, addScrollbarPseudoClassType(*selector, *fragment));
933
                functionType = mostRestrictiveFunctionType(functionType, addScrollbarPseudoClassType(*selector, *fragment));
964
            else {
934
            else {
965
                unsigned internalSpecificity = 0;
935
                functionType = mostRestrictiveFunctionType(functionType, addPseudoClassType(*selector, *fragment, selectorContext, fragmentLevel, subPosition, visitedMatchEnabled, visitedMode, pseudoElementMatchingBehavior));
966
                functionType = mostRestrictiveFunctionType(functionType, addPseudoClassType(*selector, *fragment, internalSpecificity, selectorContext, fragmentLevel, subPosition, visitedMatchEnabled, visitedMode, pseudoElementMatchingBehavior));
967
                specificity = CSSSelector::addSpecificities(specificity, internalSpecificity);
968
            }
936
            }
969
            if (!pseudoClassOnlyMatchesLinksInQuirksMode(*selector))
937
            if (!pseudoClassOnlyMatchesLinksInQuirksMode(*selector))
970
                fragment->onlyMatchesLinksInQuirksMode = false;
938
                fragment->onlyMatchesLinksInQuirksMode = false;
Lines 1073-1080 static FunctionType constructFragmentsInternal(const CSSSelector* rootSelector, a/Source/WebCore/cssjit/SelectorCompiler.cpp_sec13
1073
1041
1074
    ASSERT(!fragment);
1042
    ASSERT(!fragment);
1075
1043
1076
    selectorFragments.staticSpecificity = specificity;
1077
1078
    return functionType;
1044
    return functionType;
1079
}
1045
}
1080
1046
Lines 1784-1797 void SelectorCodeGenerator::generateSelectorChecker() a/Source/WebCore/cssjit/SelectorCompiler.cpp_sec14
1784
        generateRequestedPseudoElementEqualsToSelectorPseudoElement(failureOnFunctionEntry, m_selectorFragments.first(), checkingContextRegister);
1750
        generateRequestedPseudoElementEqualsToSelectorPseudoElement(failureOnFunctionEntry, m_selectorFragments.first(), checkingContextRegister);
1785
    }
1751
    }
1786
1752
1787
    if (m_selectorContext == SelectorContext::RuleCollector) {
1788
        unsigned specificity = m_selectorFragments.staticSpecificity;
1789
        if (m_functionType == FunctionType::SelectorCheckerWithCheckingContext)
1790
            m_assembler.store32(Assembler::TrustedImm32(specificity), JSC::GPRInfo::argumentGPR2);
1791
        else
1792
            m_assembler.store32(Assembler::TrustedImm32(specificity), JSC::GPRInfo::argumentGPR1);
1793
    }
1794
1795
    computeBacktrackingMemoryRequirements(m_selectorFragments);
1753
    computeBacktrackingMemoryRequirements(m_selectorFragments);
1796
    unsigned availableRegisterCount = m_registerAllocator.reserveCallerSavedRegisters(m_selectorFragments.registerRequirements);
1754
    unsigned availableRegisterCount = m_registerAllocator.reserveCallerSavedRegisters(m_selectorFragments.registerRequirements);
1797
1755
Lines 3077-3083 void SelectorCodeGenerator::generateElementAttributeFunctionCallValueMatching(As a/Source/WebCore/cssjit/SelectorCompiler.cpp_sec15
3077
    LocalRegisterWithPreference expectedValueRegister(m_registerAllocator, JSC::GPRInfo::argumentGPR1);
3035
    LocalRegisterWithPreference expectedValueRegister(m_registerAllocator, JSC::GPRInfo::argumentGPR1);
3078
    m_assembler.move(Assembler::TrustedImmPtr(expectedValue.impl()), expectedValueRegister);
3036
    m_assembler.move(Assembler::TrustedImmPtr(expectedValue.impl()), expectedValueRegister);
3079
3037
3080
3081
    switch (valueCaseSensitivity) {
3038
    switch (valueCaseSensitivity) {
3082
    case AttributeCaseSensitivity::CaseSensitive: {
3039
    case AttributeCaseSensitivity::CaseSensitive: {
3083
        FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
3040
        FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
- a/Source/WebCore/cssjit/SelectorCompiler.h -2 / +2 lines
Lines 45-54 enum class SelectorContext { a/Source/WebCore/cssjit/SelectorCompiler.h_sec1
45
    QuerySelector
45
    QuerySelector
46
};
46
};
47
47
48
typedef unsigned (*RuleCollectorSimpleSelectorChecker)(const Element*, unsigned*);
48
typedef unsigned (*RuleCollectorSimpleSelectorChecker)(const Element*);
49
typedef unsigned (*QuerySelectorSimpleSelectorChecker)(const Element*);
49
typedef unsigned (*QuerySelectorSimpleSelectorChecker)(const Element*);
50
50
51
typedef unsigned (*RuleCollectorSelectorCheckerWithCheckingContext)(const Element*, SelectorChecker::CheckingContext*, unsigned*);
51
typedef unsigned (*RuleCollectorSelectorCheckerWithCheckingContext)(const Element*, SelectorChecker::CheckingContext*);
52
typedef unsigned (*QuerySelectorSelectorCheckerWithCheckingContext)(const Element*, const SelectorChecker::CheckingContext*);
52
typedef unsigned (*QuerySelectorSelectorCheckerWithCheckingContext)(const Element*, const SelectorChecker::CheckingContext*);
53
53
54
void compileSelector(CompiledSelector&, const CSSSelector*, SelectorContext);
54
void compileSelector(CompiledSelector&, const CSSSelector*, SelectorContext);
- a/Source/WebCore/dom/SelectorQuery.cpp -4 / +2 lines
Lines 124-131 inline bool SelectorDataList::selectorMatches(const SelectorData& selectorData, a/Source/WebCore/dom/SelectorQuery.cpp_sec1
124
    SelectorChecker selectorChecker(element.document());
124
    SelectorChecker selectorChecker(element.document());
125
    SelectorChecker::CheckingContext selectorCheckingContext(SelectorChecker::Mode::QueryingRules);
125
    SelectorChecker::CheckingContext selectorCheckingContext(SelectorChecker::Mode::QueryingRules);
126
    selectorCheckingContext.scope = rootNode.isDocumentNode() ? nullptr : &rootNode;
126
    selectorCheckingContext.scope = rootNode.isDocumentNode() ? nullptr : &rootNode;
127
    unsigned ignoredSpecificity;
127
    return selectorChecker.match(*selectorData.selector, element, selectorCheckingContext);
128
    return selectorChecker.match(*selectorData.selector, element, selectorCheckingContext, ignoredSpecificity);
129
}
128
}
130
129
131
inline Element* SelectorDataList::selectorClosest(const SelectorData& selectorData, Element& element, const ContainerNode& rootNode) const
130
inline Element* SelectorDataList::selectorClosest(const SelectorData& selectorData, Element& element, const ContainerNode& rootNode) const
Lines 133-140 inline Element* SelectorDataList::selectorClosest(const SelectorData& selectorDa a/Source/WebCore/dom/SelectorQuery.cpp_sec2
133
    SelectorChecker selectorChecker(element.document());
132
    SelectorChecker selectorChecker(element.document());
134
    SelectorChecker::CheckingContext selectorCheckingContext(SelectorChecker::Mode::QueryingRules);
133
    SelectorChecker::CheckingContext selectorCheckingContext(SelectorChecker::Mode::QueryingRules);
135
    selectorCheckingContext.scope = rootNode.isDocumentNode() ? nullptr : &rootNode;
134
    selectorCheckingContext.scope = rootNode.isDocumentNode() ? nullptr : &rootNode;
136
    unsigned ignoredSpecificity;
135
    if (!selectorChecker.match(*selectorData.selector, element, selectorCheckingContext))
137
    if (!selectorChecker.match(*selectorData.selector, element, selectorCheckingContext, ignoredSpecificity))
138
        return nullptr;
136
        return nullptr;
139
    return &element;
137
    return &element;
140
}
138
}
- a/Source/WebCore/inspector/InspectorStyleSheet.cpp -52 / +18 lines
Lines 1047-1104 RefPtr<Inspector::Protocol::CSS::CSSStyleSheetHeader> InspectorStyleSheet::build a/Source/WebCore/inspector/InspectorStyleSheet.cpp_sec1
1047
        .release();
1047
        .release();
1048
}
1048
}
1049
1049
1050
static bool hasDynamicSpecificity(const CSSSelector& simpleSelector)
1050
static Ref<Inspector::Protocol::CSS::CSSSelector> buildObjectForSelectorHelper(const String& selectorText, const CSSSelector& selector)
1051
{
1052
    // It is possible that these can have a static specificity if each selector in the list has
1053
    // equal specificity, but lets always report that they can be dynamic.
1054
    for (const CSSSelector* selector = &simpleSelector; selector; selector = selector->tagHistory()) {
1055
        if (selector->match() == CSSSelector::PseudoClass) {
1056
            CSSSelector::PseudoClassType pseudoClassType = selector->pseudoClassType();
1057
            if (pseudoClassType == CSSSelector::PseudoClassIs || pseudoClassType == CSSSelector::PseudoClassMatches)
1058
                return true;
1059
            if (pseudoClassType == CSSSelector::PseudoClassNthChild || pseudoClassType == CSSSelector::PseudoClassNthLastChild) {
1060
                if (selector->selectorList())
1061
                    return true;
1062
                return false;
1063
            }
1064
        }
1065
    }
1066
1067
    return false;
1068
}
1069
1070
static Ref<Inspector::Protocol::CSS::CSSSelector> buildObjectForSelectorHelper(const String& selectorText, const CSSSelector& selector, Element* element)
1071
{
1051
{
1072
    auto inspectorSelector = Inspector::Protocol::CSS::CSSSelector::create()
1052
    auto inspectorSelector = Inspector::Protocol::CSS::CSSSelector::create()
1073
        .setText(selectorText)
1053
        .setText(selectorText)
1074
        .release();
1054
        .release();
1075
1055
1076
    if (element) {
1056
    auto specificity = selector.specificity();
1077
        bool dynamic = hasDynamicSpecificity(selector);
1057
1078
        if (dynamic)
1058
    auto tuple = JSON::ArrayOf<int>::create();
1079
            inspectorSelector->setDynamic(true);
1059
    tuple->addItem(static_cast<int>((specificity & CSSSelector::idMask) >> 16));
1080
1060
    tuple->addItem(static_cast<int>((specificity & CSSSelector::classMask) >> 8));
1081
        SelectorChecker::CheckingContext context(SelectorChecker::Mode::CollectingRules);
1061
    tuple->addItem(static_cast<int>(specificity & CSSSelector::elementMask));
1082
        SelectorChecker selectorChecker(element->document());
1062
    inspectorSelector->setSpecificity(WTFMove(tuple));
1083
1084
        unsigned specificity;
1085
        bool okay = selectorChecker.match(selector, *element, context, specificity);
1086
        if (!okay)
1087
            specificity = selector.staticSpecificity(okay);
1088
1089
        if (okay) {
1090
            auto tuple = JSON::ArrayOf<int>::create();
1091
            tuple->addItem(static_cast<int>((specificity & CSSSelector::idMask) >> 16));
1092
            tuple->addItem(static_cast<int>((specificity & CSSSelector::classMask) >> 8));
1093
            tuple->addItem(static_cast<int>(specificity & CSSSelector::elementMask));
1094
            inspectorSelector->setSpecificity(WTFMove(tuple));
1095
        }
1096
    }
1097
1063
1098
    return inspectorSelector;
1064
    return inspectorSelector;
1099
}
1065
}
1100
1066
1101
static Ref<JSON::ArrayOf<Inspector::Protocol::CSS::CSSSelector>> selectorsFromSource(const CSSRuleSourceData* sourceData, const String& sheetText, const CSSSelectorList& selectorList, Element* element)
1067
static Ref<JSON::ArrayOf<Inspector::Protocol::CSS::CSSSelector>> selectorsFromSource(const CSSRuleSourceData* sourceData, const String& sheetText, const CSSSelectorList& selectorList)
1102
{
1068
{
1103
    static NeverDestroyed<JSC::Yarr::RegularExpression> comment("/\\*[^]*?\\*/", JSC::Yarr::TextCaseSensitive, JSC::Yarr::MultilineEnabled);
1069
    static NeverDestroyed<JSC::Yarr::RegularExpression> comment("/\\*[^]*?\\*/", JSC::Yarr::TextCaseSensitive, JSC::Yarr::MultilineEnabled);
1104
1070
Lines 1115-1133 static Ref<JSON::ArrayOf<Inspector::Protocol::CSS::CSSSelector>> selectorsFromSo a/Source/WebCore/inspector/InspectorStyleSheet.cpp_sec2
1115
1081
1116
        // We don't want to see any comments in the selector components, only the meaningful parts.
1082
        // We don't want to see any comments in the selector components, only the meaningful parts.
1117
        replace(selectorText, comment, String());
1083
        replace(selectorText, comment, String());
1118
        result->addItem(buildObjectForSelectorHelper(selectorText.stripWhiteSpace(), *selector, element));
1084
        result->addItem(buildObjectForSelectorHelper(selectorText.stripWhiteSpace(), *selector));
1119
1085
1120
        selector = CSSSelectorList::next(selector);
1086
        selector = CSSSelectorList::next(selector);
1121
    }
1087
    }
1122
    return result;
1088
    return result;
1123
}
1089
}
1124
1090
1125
Ref<Inspector::Protocol::CSS::CSSSelector> InspectorStyleSheet::buildObjectForSelector(const CSSSelector* selector, Element* element)
1091
Ref<Inspector::Protocol::CSS::CSSSelector> InspectorStyleSheet::buildObjectForSelector(const CSSSelector* selector)
1126
{
1092
{
1127
    return buildObjectForSelectorHelper(selector->selectorText(), *selector, element);
1093
    return buildObjectForSelectorHelper(selector->selectorText(), *selector);
1128
}
1094
}
1129
1095
1130
Ref<Inspector::Protocol::CSS::SelectorList> InspectorStyleSheet::buildObjectForSelectorList(CSSStyleRule* rule, Element* element, int& endingLine)
1096
Ref<Inspector::Protocol::CSS::SelectorList> InspectorStyleSheet::buildObjectForSelectorList(CSSStyleRule* rule, int& endingLine)
1131
{
1097
{
1132
    RefPtr<CSSRuleSourceData> sourceData;
1098
    RefPtr<CSSRuleSourceData> sourceData;
1133
    if (ensureParsedDataReady())
1099
    if (ensureParsedDataReady())
Lines 1138-1149 Ref<Inspector::Protocol::CSS::SelectorList> InspectorStyleSheet::buildObjectForS a/Source/WebCore/inspector/InspectorStyleSheet.cpp_sec3
1138
    String selectorText = rule->selectorText();
1104
    String selectorText = rule->selectorText();
1139
1105
1140
    if (sourceData)
1106
    if (sourceData)
1141
        selectors = selectorsFromSource(sourceData.get(), m_parsedStyleSheet->text(), rule->styleRule().selectorList(), element);
1107
        selectors = selectorsFromSource(sourceData.get(), m_parsedStyleSheet->text(), rule->styleRule().selectorList());
1142
    else {
1108
    else {
1143
        selectors = JSON::ArrayOf<Inspector::Protocol::CSS::CSSSelector>::create();
1109
        selectors = JSON::ArrayOf<Inspector::Protocol::CSS::CSSSelector>::create();
1144
        const CSSSelectorList& selectorList = rule->styleRule().selectorList();
1110
        const CSSSelectorList& selectorList = rule->styleRule().selectorList();
1145
        for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector))
1111
        for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector))
1146
            selectors->addItem(buildObjectForSelector(selector, element));
1112
            selectors->addItem(buildObjectForSelector(selector));
1147
    }
1113
    }
1148
    auto result = Inspector::Protocol::CSS::SelectorList::create()
1114
    auto result = Inspector::Protocol::CSS::SelectorList::create()
1149
        .setSelectors(WTFMove(selectors))
1115
        .setSelectors(WTFMove(selectors))
Lines 1154-1160 Ref<Inspector::Protocol::CSS::SelectorList> InspectorStyleSheet::buildObjectForS a/Source/WebCore/inspector/InspectorStyleSheet.cpp_sec4
1154
    return result;
1120
    return result;
1155
}
1121
}
1156
1122
1157
RefPtr<Inspector::Protocol::CSS::CSSRule> InspectorStyleSheet::buildObjectForRule(CSSStyleRule* rule, Element* element)
1123
RefPtr<Inspector::Protocol::CSS::CSSRule> InspectorStyleSheet::buildObjectForRule(CSSStyleRule* rule)
1158
{
1124
{
1159
    CSSStyleSheet* styleSheet = pageStyleSheet();
1125
    CSSStyleSheet* styleSheet = pageStyleSheet();
1160
    if (!styleSheet)
1126
    if (!styleSheet)
Lines 1162-1168 RefPtr<Inspector::Protocol::CSS::CSSRule> InspectorStyleSheet::buildObjectForRul a/Source/WebCore/inspector/InspectorStyleSheet.cpp_sec5
1162
1128
1163
    int endingLine = 0;
1129
    int endingLine = 0;
1164
    auto result = Inspector::Protocol::CSS::CSSRule::create()
1130
    auto result = Inspector::Protocol::CSS::CSSRule::create()
1165
        .setSelectorList(buildObjectForSelectorList(rule, element, endingLine))
1131
        .setSelectorList(buildObjectForSelectorList(rule, endingLine))
1166
        .setSourceLine(endingLine)
1132
        .setSourceLine(endingLine)
1167
        .setOrigin(m_origin)
1133
        .setOrigin(m_origin)
1168
        .setStyle(buildObjectForStyle(&rule->style()))
1134
        .setStyle(buildObjectForStyle(&rule->style()))
Lines 1458-1464 Ref<JSON::ArrayOf<Inspector::Protocol::CSS::CSSRule>> InspectorStyleSheet::build a/Source/WebCore/inspector/InspectorStyleSheet.cpp_sec6
1458
    collectFlatRules(WTFMove(refRuleList), &rules);
1424
    collectFlatRules(WTFMove(refRuleList), &rules);
1459
1425
1460
    for (auto& rule : rules)
1426
    for (auto& rule : rules)
1461
        result->addItem(buildObjectForRule(rule.get(), nullptr));
1427
        result->addItem(buildObjectForRule(rule.get()));
1462
1428
1463
    return result;
1429
    return result;
1464
}
1430
}
- a/Source/WebCore/inspector/InspectorStyleSheet.h -3 / +3 lines
Lines 174-180 public: a/Source/WebCore/inspector/InspectorStyleSheet.h_sec1
174
    CSSStyleRule* ruleForId(const InspectorCSSId&) const;
174
    CSSStyleRule* ruleForId(const InspectorCSSId&) const;
175
    RefPtr<Inspector::Protocol::CSS::CSSStyleSheetBody> buildObjectForStyleSheet();
175
    RefPtr<Inspector::Protocol::CSS::CSSStyleSheetBody> buildObjectForStyleSheet();
176
    RefPtr<Inspector::Protocol::CSS::CSSStyleSheetHeader> buildObjectForStyleSheetInfo();
176
    RefPtr<Inspector::Protocol::CSS::CSSStyleSheetHeader> buildObjectForStyleSheetInfo();
177
    RefPtr<Inspector::Protocol::CSS::CSSRule> buildObjectForRule(CSSStyleRule*, Element*);
177
    RefPtr<Inspector::Protocol::CSS::CSSRule> buildObjectForRule(CSSStyleRule*);
178
    RefPtr<Inspector::Protocol::CSS::CSSStyle> buildObjectForStyle(CSSStyleDeclaration*);
178
    RefPtr<Inspector::Protocol::CSS::CSSStyle> buildObjectForStyle(CSSStyleDeclaration*);
179
    ExceptionOr<void> setStyleText(const InspectorCSSId&, const String& text, String* oldText);
179
    ExceptionOr<void> setStyleText(const InspectorCSSId&, const String& text, String* oldText);
180
180
Lines 215-222 private: a/Source/WebCore/inspector/InspectorStyleSheet.h_sec2
215
    bool inlineStyleSheetText(String* result) const;
215
    bool inlineStyleSheetText(String* result) const;
216
    bool extensionStyleSheetText(String* result) const;
216
    bool extensionStyleSheetText(String* result) const;
217
    Ref<JSON::ArrayOf<Inspector::Protocol::CSS::CSSRule>> buildArrayForRuleList(CSSRuleList*);
217
    Ref<JSON::ArrayOf<Inspector::Protocol::CSS::CSSRule>> buildArrayForRuleList(CSSRuleList*);
218
    Ref<Inspector::Protocol::CSS::CSSSelector> buildObjectForSelector(const CSSSelector*, Element*);
218
    Ref<Inspector::Protocol::CSS::CSSSelector> buildObjectForSelector(const CSSSelector*);
219
    Ref<Inspector::Protocol::CSS::SelectorList> buildObjectForSelectorList(CSSStyleRule*, Element*, int& endingLine);
219
    Ref<Inspector::Protocol::CSS::SelectorList> buildObjectForSelectorList(CSSStyleRule*, int& endingLine);
220
220
221
    InspectorPageAgent* m_pageAgent;
221
    InspectorPageAgent* m_pageAgent;
222
    String m_id;
222
    String m_id;
- a/Source/WebCore/inspector/agents/InspectorCSSAgent.cpp -6 / +5 lines
Lines 679-685 void InspectorCSSAgent::setRuleSelector(ErrorString& errorString, const JSON::Ob a/Source/WebCore/inspector/agents/InspectorCSSAgent.cpp_sec1
679
        return;
679
        return;
680
    }
680
    }
681
681
682
    result = inspectorStyleSheet->buildObjectForRule(inspectorStyleSheet->ruleForId(compoundId), nullptr);
682
    result = inspectorStyleSheet->buildObjectForRule(inspectorStyleSheet->ruleForId(compoundId));
683
}
683
}
684
684
685
void InspectorCSSAgent::createStyleSheet(ErrorString& errorString, const String& frameId, String* styleSheetId)
685
void InspectorCSSAgent::createStyleSheet(ErrorString& errorString, const String& frameId, String* styleSheetId)
Lines 772-778 void InspectorCSSAgent::addRule(ErrorString& errorString, const String& styleShe a/Source/WebCore/inspector/agents/InspectorCSSAgent.cpp_sec2
772
772
773
    InspectorCSSId ruleId = rawAction.newRuleId();
773
    InspectorCSSId ruleId = rawAction.newRuleId();
774
    CSSStyleRule* rule = inspectorStyleSheet->ruleForId(ruleId);
774
    CSSStyleRule* rule = inspectorStyleSheet->ruleForId(ruleId);
775
    result = inspectorStyleSheet->buildObjectForRule(rule, nullptr);
775
    result = inspectorStyleSheet->buildObjectForRule(rule);
776
}
776
}
777
777
778
void InspectorCSSAgent::getSupportedCSSProperties(ErrorString&, RefPtr<JSON::ArrayOf<Inspector::Protocol::CSS::CSSPropertyInfo>>& cssProperties)
778
void InspectorCSSAgent::getSupportedCSSProperties(ErrorString&, RefPtr<JSON::ArrayOf<Inspector::Protocol::CSS::CSSPropertyInfo>>& cssProperties)
Lines 963-969 RefPtr<Inspector::Protocol::CSS::CSSRule> InspectorCSSAgent::buildObjectForRule( a/Source/WebCore/inspector/agents/InspectorCSSAgent.cpp_sec3
963
        return nullptr;
963
        return nullptr;
964
964
965
    InspectorStyleSheet* inspectorStyleSheet = bindStyleSheet(cssomWrapper->parentStyleSheet());
965
    InspectorStyleSheet* inspectorStyleSheet = bindStyleSheet(cssomWrapper->parentStyleSheet());
966
    return inspectorStyleSheet ? inspectorStyleSheet->buildObjectForRule(cssomWrapper, &element) : nullptr;
966
    return inspectorStyleSheet ? inspectorStyleSheet->buildObjectForRule(cssomWrapper) : nullptr;
967
}
967
}
968
968
969
RefPtr<Inspector::Protocol::CSS::CSSRule> InspectorCSSAgent::buildObjectForRule(CSSStyleRule* rule)
969
RefPtr<Inspector::Protocol::CSS::CSSRule> InspectorCSSAgent::buildObjectForRule(CSSStyleRule* rule)
Lines 973-979 RefPtr<Inspector::Protocol::CSS::CSSRule> InspectorCSSAgent::buildObjectForRule( a/Source/WebCore/inspector/agents/InspectorCSSAgent.cpp_sec4
973
973
974
    ASSERT(rule->parentStyleSheet());
974
    ASSERT(rule->parentStyleSheet());
975
    InspectorStyleSheet* inspectorStyleSheet = bindStyleSheet(rule->parentStyleSheet());
975
    InspectorStyleSheet* inspectorStyleSheet = bindStyleSheet(rule->parentStyleSheet());
976
    return inspectorStyleSheet ? inspectorStyleSheet->buildObjectForRule(rule, nullptr) : nullptr;
976
    return inspectorStyleSheet ? inspectorStyleSheet->buildObjectForRule(rule) : nullptr;
977
}
977
}
978
978
979
RefPtr<JSON::ArrayOf<Inspector::Protocol::CSS::RuleMatch>> InspectorCSSAgent::buildArrayForMatchedRuleList(const Vector<RefPtr<const StyleRule>>& matchedRules, Style::Resolver& styleResolver, Element& element, PseudoId pseudoId)
979
RefPtr<JSON::ArrayOf<Inspector::Protocol::CSS::RuleMatch>> InspectorCSSAgent::buildArrayForMatchedRuleList(const Vector<RefPtr<const StyleRule>>& matchedRules, Style::Resolver& styleResolver, Element& element, PseudoId pseudoId)
Lines 993-1000 RefPtr<JSON::ArrayOf<Inspector::Protocol::CSS::RuleMatch>> InspectorCSSAgent::bu a/Source/WebCore/inspector/agents/InspectorCSSAgent.cpp_sec5
993
        const CSSSelectorList& selectorList = matchedRule->selectorList();
993
        const CSSSelectorList& selectorList = matchedRule->selectorList();
994
        int index = 0;
994
        int index = 0;
995
        for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector)) {
995
        for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector)) {
996
            unsigned ignoredSpecificity;
996
            bool matched = selectorChecker.match(*selector, element, context);
997
            bool matched = selectorChecker.match(*selector, element, context, ignoredSpecificity);
998
            if (matched)
997
            if (matched)
999
                matchingSelectors->addItem(index);
998
                matchingSelectors->addItem(index);
1000
            ++index;
999
            ++index;
- a/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp -2 / +1 lines
Lines 1291-1298 void InspectorDOMAgent::highlightSelector(ErrorString& errorString, const JSON:: a/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp_sec1
1291
            SelectorChecker::CheckingContext context(SelectorChecker::Mode::ResolvingStyle);
1291
            SelectorChecker::CheckingContext context(SelectorChecker::Mode::ResolvingStyle);
1292
            context.pseudoId = pseudoId;
1292
            context.pseudoId = pseudoId;
1293
1293
1294
            unsigned ignoredSpecificity;
1294
            if (selectorChecker.match(*selector, descendantElement, context)) {
1295
            if (selectorChecker.match(*selector, descendantElement, context, ignoredSpecificity)) {
1296
                if (seenNodes.add(&descendantElement))
1295
                if (seenNodes.add(&descendantElement))
1297
                    nodeList.append(descendantElement);
1296
                    nodeList.append(descendantElement);
1298
            }
1297
            }
- a/Source/WebCore/style/ElementRuleCollector.cpp -29 / +9 lines
Lines 419-449 static const CSSSelector* findSlottedPseudoElementSelector(const CSSSelector* se a/Source/WebCore/style/ElementRuleCollector.cpp_sec1
419
    return nullptr;
419
    return nullptr;
420
}
420
}
421
421
422
inline bool ElementRuleCollector::ruleMatches(const RuleData& ruleData, unsigned& specificity)
422
inline bool ElementRuleCollector::ruleMatches(const RuleData& ruleData)
423
{
423
{
424
    // We know a sufficiently simple single part selector matches simply because we found it from the rule hash when filtering the RuleSet.
424
    // We know a sufficiently simple single part selector matches simply because we found it from the rule hash when filtering the RuleSet.
425
    // This is limited to HTML only so we don't need to check the namespace (because of tag name match).
425
    // This is limited to HTML only so we don't need to check the namespace (because of tag name match).
426
    auto matchBasedOnRuleHash = ruleData.matchBasedOnRuleHash();
426
    auto matchesBasedOnRuleHash = ruleData.matchesBasedOnRuleHash();
427
    if (matchBasedOnRuleHash != MatchBasedOnRuleHash::None && element().isHTMLElement()) {
427
    if (matchesBasedOnRuleHash && element().isHTMLElement()) {
428
        ASSERT_WITH_MESSAGE(m_pseudoElementRequest.pseudoId == PseudoId::None, "If we match based on the rule hash while collecting for a particular pseudo element ID, we would add incorrect rules for that pseudo element ID. We should never end in ruleMatches() with a pseudo element if the ruleData cannot match any pseudo element.");
428
        ASSERT_WITH_MESSAGE(m_pseudoElementRequest.pseudoId == PseudoId::None, "If we match based on the rule hash while collecting for a particular pseudo element ID, we would add incorrect rules for that pseudo element ID. We should never end in ruleMatches() with a pseudo element if the ruleData cannot match any pseudo element.");
429
430
        switch (matchBasedOnRuleHash) {
431
        case MatchBasedOnRuleHash::None:
432
            ASSERT_NOT_REACHED();
433
            break;
434
        case MatchBasedOnRuleHash::Universal:
435
            specificity = 0;
436
            break;
437
        case MatchBasedOnRuleHash::ClassA:
438
            specificity = static_cast<unsigned>(SelectorSpecificityIncrement::ClassA);
439
            break;
440
        case MatchBasedOnRuleHash::ClassB:
441
            specificity = static_cast<unsigned>(SelectorSpecificityIncrement::ClassB);
442
            break;
443
        case MatchBasedOnRuleHash::ClassC:
444
            specificity = static_cast<unsigned>(SelectorSpecificityIncrement::ClassC);
445
            break;
446
        }
447
        return true;
429
        return true;
448
    }
430
    }
449
431
Lines 458-467 inline bool ElementRuleCollector::ruleMatches(const RuleData& ruleData, unsigned a/Source/WebCore/style/ElementRuleCollector.cpp_sec2
458
440
459
        auto selectorChecker = SelectorCompiler::ruleCollectorSimpleSelectorCheckerFunction(compiledSelector);
441
        auto selectorChecker = SelectorCompiler::ruleCollectorSimpleSelectorCheckerFunction(compiledSelector);
460
#if !ASSERT_MSG_DISABLED
442
#if !ASSERT_MSG_DISABLED
461
        unsigned ignoreSpecificity;
443
        ASSERT_WITH_MESSAGE(!selectorChecker(&element()) || m_pseudoElementRequest.pseudoId == PseudoId::None, "When matching pseudo elements, we should never compile a selector checker without context unless it cannot match anything.");
462
        ASSERT_WITH_MESSAGE(!selectorChecker(&element(), &ignoreSpecificity) || m_pseudoElementRequest.pseudoId == PseudoId::None, "When matching pseudo elements, we should never compile a selector checker without context unless it cannot match anything.");
463
#endif
444
#endif
464
        bool selectorMatches = selectorChecker(&element(), &specificity);
445
        bool selectorMatches = selectorChecker(&element());
465
446
466
        if (selectorMatches && ruleData.containsUncommonAttributeSelector())
447
        if (selectorMatches && ruleData.containsUncommonAttributeSelector())
467
            m_didMatchUncommonAttributeSelector = true;
448
            m_didMatchUncommonAttributeSelector = true;
Lines 483-489 inline bool ElementRuleCollector::ruleMatches(const RuleData& ruleData, unsigned a/Source/WebCore/style/ElementRuleCollector.cpp_sec3
483
        compiledSelector.wasUsed();
464
        compiledSelector.wasUsed();
484
465
485
        auto selectorChecker = SelectorCompiler::ruleCollectorSelectorCheckerFunctionWithCheckingContext(compiledSelector);
466
        auto selectorChecker = SelectorCompiler::ruleCollectorSelectorCheckerFunctionWithCheckingContext(compiledSelector);
486
        selectorMatches = selectorChecker(&element(), &context, &specificity);
467
        selectorMatches = selectorChecker(&element(), &context);
487
    } else
468
    } else
488
#endif // ENABLE(CSS_SELECTOR_JIT)
469
#endif // ENABLE(CSS_SELECTOR_JIT)
489
    {
470
    {
Lines 495-501 inline bool ElementRuleCollector::ruleMatches(const RuleData& ruleData, unsigned a/Source/WebCore/style/ElementRuleCollector.cpp_sec4
495
        }
476
        }
496
        // Slow path.
477
        // Slow path.
497
        SelectorChecker selectorChecker(element().document());
478
        SelectorChecker selectorChecker(element().document());
498
        selectorMatches = selectorChecker.match(*selector, element(), context, specificity);
479
        selectorMatches = selectorChecker.match(*selector, element(), context);
499
    }
480
    }
500
481
501
    if (ruleData.containsUncommonAttributeSelector()) {
482
    if (ruleData.containsUncommonAttributeSelector()) {
Lines 534-542 void ElementRuleCollector::collectMatchingRulesForList(const RuleSet::RuleDataVe a/Source/WebCore/style/ElementRuleCollector.cpp_sec5
534
        if (properties && properties->isEmpty() && !m_shouldIncludeEmptyRules)
515
        if (properties && properties->isEmpty() && !m_shouldIncludeEmptyRules)
535
            continue;
516
            continue;
536
517
537
        unsigned specificity;
518
        if (ruleMatches(ruleData))
538
        if (ruleMatches(ruleData, specificity))
519
            addMatchedRule(ruleData, ruleData.selector()->specificity(), matchRequest.styleScopeOrdinal);
539
            addMatchedRule(ruleData, specificity, matchRequest.styleScopeOrdinal);
540
    }
520
    }
541
}
521
}
542
522
- a/Source/WebCore/style/ElementRuleCollector.h -1 / +1 lines
Lines 137-143 private: a/Source/WebCore/style/ElementRuleCollector.h_sec1
137
137
138
    void collectMatchingRules(const MatchRequest&);
138
    void collectMatchingRules(const MatchRequest&);
139
    void collectMatchingRulesForList(const RuleSet::RuleDataVector*, const MatchRequest&);
139
    void collectMatchingRulesForList(const RuleSet::RuleDataVector*, const MatchRequest&);
140
    bool ruleMatches(const RuleData&, unsigned &specificity);
140
    bool ruleMatches(const RuleData&);
141
141
142
    void sortMatchedRules();
142
    void sortMatchedRules();
143
143
- a/Source/WebCore/style/RuleData.cpp -13 / +8 lines
Lines 61-88 struct SameSizeAsRuleData { a/Source/WebCore/style/RuleData.cpp_sec1
61
61
62
COMPILE_ASSERT(sizeof(RuleData) == sizeof(SameSizeAsRuleData), RuleData_should_stay_small);
62
COMPILE_ASSERT(sizeof(RuleData) == sizeof(SameSizeAsRuleData), RuleData_should_stay_small);
63
63
64
static inline MatchBasedOnRuleHash computeMatchBasedOnRuleHash(const CSSSelector& selector)
64
static inline bool computeMatchesBasedOnRuleHash(const CSSSelector& selector)
65
{
65
{
66
    if (selector.tagHistory())
66
    if (selector.tagHistory())
67
        return MatchBasedOnRuleHash::None;
67
        return false;
68
68
69
    if (selector.match() == CSSSelector::Tag) {
69
    if (selector.match() == CSSSelector::Tag) {
70
        const QualifiedName& tagQualifiedName = selector.tagQName();
70
        const QualifiedName& tagQualifiedName = selector.tagQName();
71
        const AtomString& selectorNamespace = tagQualifiedName.namespaceURI();
71
        const AtomString& selectorNamespace = tagQualifiedName.namespaceURI();
72
        if (selectorNamespace == starAtom() || selectorNamespace == xhtmlNamespaceURI) {
72
        return selectorNamespace == starAtom() || selectorNamespace == xhtmlNamespaceURI;
73
            if (tagQualifiedName == anyQName())
74
                return MatchBasedOnRuleHash::Universal;
75
            return MatchBasedOnRuleHash::ClassC;
76
        }
77
        return MatchBasedOnRuleHash::None;
78
    }
73
    }
79
    if (SelectorChecker::isCommonPseudoClassSelector(&selector))
74
    if (SelectorChecker::isCommonPseudoClassSelector(&selector))
80
        return MatchBasedOnRuleHash::ClassB;
75
        return true;
81
    if (selector.match() == CSSSelector::Id)
76
    if (selector.match() == CSSSelector::Id)
82
        return MatchBasedOnRuleHash::ClassA;
77
        return true;
83
    if (selector.match() == CSSSelector::Class)
78
    if (selector.match() == CSSSelector::Class)
84
        return MatchBasedOnRuleHash::ClassB;
79
        return true;
85
    return MatchBasedOnRuleHash::None;
80
    return false;
86
}
81
}
87
82
88
static bool selectorCanMatchPseudoElement(const CSSSelector& rootSelector)
83
static bool selectorCanMatchPseudoElement(const CSSSelector& rootSelector)
Lines 163-169 RuleData::RuleData(const StyleRule& styleRule, unsigned selectorIndex, unsigned a/Source/WebCore/style/RuleData.cpp_sec2
163
    , m_selectorIndex(selectorIndex)
158
    , m_selectorIndex(selectorIndex)
164
    , m_selectorListIndex(selectorListIndex)
159
    , m_selectorListIndex(selectorListIndex)
165
    , m_position(position)
160
    , m_position(position)
166
    , m_matchBasedOnRuleHash(static_cast<unsigned>(computeMatchBasedOnRuleHash(*selector())))
161
    , m_matchesBasedOnRuleHash(computeMatchesBasedOnRuleHash(*selector()))
167
    , m_canMatchPseudoElement(selectorCanMatchPseudoElement(*selector()))
162
    , m_canMatchPseudoElement(selectorCanMatchPseudoElement(*selector()))
168
    , m_containsUncommonAttributeSelector(computeContainsUncommonAttributeSelector(*selector()))
163
    , m_containsUncommonAttributeSelector(computeContainsUncommonAttributeSelector(*selector()))
169
    , m_linkMatchType(SelectorChecker::determineLinkMatchType(selector()))
164
    , m_linkMatchType(SelectorChecker::determineLinkMatchType(selector()))
- a/Source/WebCore/style/RuleData.h -10 / +2 lines
Lines 35-48 enum PropertyWhitelistType { a/Source/WebCore/style/RuleData.h_sec1
35
#endif
35
#endif
36
};
36
};
37
37
38
enum class MatchBasedOnRuleHash : unsigned {
39
    None,
40
    Universal,
41
    ClassA,
42
    ClassB,
43
    ClassC
44
};
45
46
class RuleData {
38
class RuleData {
47
public:
39
public:
48
    static const unsigned maximumSelectorComponentCount = 8192;
40
    static const unsigned maximumSelectorComponentCount = 8192;
Lines 62-68 public: a/Source/WebCore/style/RuleData.h_sec2
62
    unsigned selectorListIndex() const { return m_selectorListIndex; }
54
    unsigned selectorListIndex() const { return m_selectorListIndex; }
63
55
64
    bool canMatchPseudoElement() const { return m_canMatchPseudoElement; }
56
    bool canMatchPseudoElement() const { return m_canMatchPseudoElement; }
65
    MatchBasedOnRuleHash matchBasedOnRuleHash() const { return static_cast<MatchBasedOnRuleHash>(m_matchBasedOnRuleHash); }
57
    bool matchesBasedOnRuleHash() const { return m_matchesBasedOnRuleHash; }
66
    bool containsUncommonAttributeSelector() const { return m_containsUncommonAttributeSelector; }
58
    bool containsUncommonAttributeSelector() const { return m_containsUncommonAttributeSelector; }
67
    unsigned linkMatchType() const { return m_linkMatchType; }
59
    unsigned linkMatchType() const { return m_linkMatchType; }
68
    PropertyWhitelistType propertyWhitelistType() const { return static_cast<PropertyWhitelistType>(m_propertyWhitelistType); }
60
    PropertyWhitelistType propertyWhitelistType() const { return static_cast<PropertyWhitelistType>(m_propertyWhitelistType); }
Lines 80-86 private: a/Source/WebCore/style/RuleData.h_sec3
80
    unsigned m_selectorListIndex : 16;
72
    unsigned m_selectorListIndex : 16;
81
    // If we have more rules than 2^bitcount here we'll get confused about rule order.
73
    // If we have more rules than 2^bitcount here we'll get confused about rule order.
82
    unsigned m_position : 22;
74
    unsigned m_position : 22;
83
    unsigned m_matchBasedOnRuleHash : 3;
75
    unsigned m_matchesBasedOnRuleHash : 1;
84
    unsigned m_canMatchPseudoElement : 1;
76
    unsigned m_canMatchPseudoElement : 1;
85
    unsigned m_containsUncommonAttributeSelector : 1;
77
    unsigned m_containsUncommonAttributeSelector : 1;
86
    unsigned m_linkMatchType : 2; //  SelectorChecker::LinkMatchMask
78
    unsigned m_linkMatchType : 2; //  SelectorChecker::LinkMatchMask

Return to Bug 210419