зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1739391 [wpt PR 31504] - Support style invalidation of ':has()' in rightmost compound, a=testonly
Automatic update from web-platform-tests Support style invalidation of ':has()' in rightmost compound This is the initial CL of supporting style invalidation with ':has()'. To minimize complexity, we will focus on the following limited usage. - Supports ':has()' in a rightmost, top-level compound - Supports ':has()' argument starts with child or descendant combinator - Only allow attribute or elemental selectors in argument So the following will be ignored for now. - Ignore ':has()' in a non-rightmost compound - Ignore ':has()' in a logical combinations - Ignore ':has()' argument starts with '~' or '+' - Ignore all pseudos in ':has()' argument To support this case, for a change on an element, we need to invalidate ancestors. Invalidate every ancestors for every mutations on every element is very bad for performance. So we need a way to skip these. - irrelevant element - irrelevant ancestor - irrelevant mutation To skip the 'irrelevant element' and 'irrelevant ancestor', this CL introduces two flags in the ComputedStyle. - AncestorsAffectedByHas : Indicate that the element has an ancestor affected by ':has()' state change - AffectedByHas : Indicate that the element can be affected by ':has()' state change During style recalculation, 'AffectedByHas' and 'AncestorAffectedByHas' flag will be set when SelectorChecker tries to match any ':has()' selector on an element. The 'AncestorAffectedByHas' flag is inherited by children of the element. <style> .a:has(.b) { color: red }</style> <div> <div class="a"> <!-- AffectedByHas, AncestorAffectedByHas --> <div> <!-- AncestorAffectedByHas --> <div> <!-- AncestorAffectedByHas --> </div> </div> </div> <div> <div> </div> </div> </div> Only for a mutation on the element with 'AncestorAffectedByHas', style engine will walk up ancestors. And it invalidates style only when an ancestor is 'AffectedByHas'. Still we have invalidation for irrelevant mutation and invalidation on irrelevant ancestors. We will handle those by separate CLs. Bug: 669058 Change-Id: Ia7e607e01f9a070c0d69d89679b99efa0a104797 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3260677 Commit-Queue: Byungwoo Lee <blee@igalia.com> Reviewed-by: Rune Lillesveen <futhark@chromium.org> Cr-Commit-Position: refs/heads/main@{#940274} -- wpt-commits: e29b779bac49b4976b7fad8c10b8c9e762018cf1 wpt-pr: 31504
This commit is contained in:
Родитель
5756622db3
Коммит
e8b96dbbd6
|
@ -0,0 +1,84 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Selectors Invalidation: :has() invalidation basic</title>
|
||||
<link rel="author" title="Byungwoo Lee" href="mailto:blee@igalia.com">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
|
||||
<style>
|
||||
div, main { color: grey }
|
||||
.subject:has(> .child) { color: red }
|
||||
.subject:has(.descendant) { color: green }
|
||||
.subject:has([attrname=descendant]) { color: blue }
|
||||
.subject:has(#div_descendant) { color: yellow }
|
||||
.subject:has(descendant) { color: yellowgreen }
|
||||
</style>
|
||||
<main id=main>
|
||||
<div id=div_subject class="subject">
|
||||
<div id=div_child>
|
||||
<div id=div_grandchild></div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<script>
|
||||
let grey = 'rgb(128, 128, 128)';
|
||||
let red = 'rgb(255, 0, 0)';
|
||||
let green = 'rgb(0, 128, 0)';
|
||||
let blue = 'rgb(0, 0, 255)';
|
||||
let yellow = 'rgb(255, 255, 0)';
|
||||
let yellowgreen = 'rgb(154, 205, 50)';
|
||||
|
||||
function test_div(test_name, el, color) {
|
||||
test(function() {
|
||||
assert_equals(getComputedStyle(el).color, color);
|
||||
}, test_name + ': div#' + el.id + '.color');
|
||||
}
|
||||
|
||||
test_div('initial_color', div_subject, grey);
|
||||
test_div('initial_color', div_child, grey);
|
||||
test_div('initial_color', div_grandchild, grey);
|
||||
|
||||
div_child.classList.add('child');
|
||||
test_div('add .child to #div_child', div_subject, red);
|
||||
div_child.classList.remove('child');
|
||||
test_div('remove .child from #div_child', div_subject, grey);
|
||||
|
||||
div_grandchild.classList.add('child');
|
||||
test_div('add .child to #div_grandchild', div_subject, grey);
|
||||
div_grandchild.classList.remove('child');
|
||||
test_div('remove .child from #div_grandchild', div_subject, grey);
|
||||
|
||||
div_child.classList.add('descendant');
|
||||
test_div('add .descendant to #div_child', div_subject, green);
|
||||
div_child.classList.remove('descendant');
|
||||
test_div('remove .descendant from #div_child', div_subject, grey);
|
||||
|
||||
div_grandchild.classList.add('descendant');
|
||||
test_div('add .descendant to #div_grandchild', div_subject, green);
|
||||
div_grandchild.classList.remove('descendant');
|
||||
test_div('remove .descendant from #div_grandchild', div_subject, grey);
|
||||
|
||||
div_grandchild.setAttribute('attrname', 'descendant');
|
||||
test_div('set descendant to #div_grandchild[attrname]', div_subject, blue);
|
||||
div_grandchild.setAttribute('attrname', '');
|
||||
test_div('clear #div_grandchild[attrname]', div_subject, grey);
|
||||
|
||||
div_grandchild.id = 'div_descendant';
|
||||
test_div('change #div_grandchild to #div_descendant', div_subject, yellow);
|
||||
div_descendant.id = 'div_grandchild';
|
||||
test_div('change #div_descendant to #div_grandchild', div_subject, grey);
|
||||
|
||||
descendant = document.createElement('descendant');
|
||||
div_subject.appendChild(descendant);
|
||||
test_div('add descendant to #div_subject', div_subject, yellowgreen);
|
||||
div_subject.removeChild(descendant);
|
||||
test_div('remove descendant from #div_subject', div_subject, grey);
|
||||
|
||||
div = document.createElement('div');
|
||||
div.appendChild(descendant);
|
||||
div_subject.appendChild(div);
|
||||
test_div('add "div > descendant" to #div_subject', div_subject, yellowgreen);
|
||||
div_subject.removeChild(div);
|
||||
test_div('remove "div > descendant" from #div_subject', div_subject, grey);
|
||||
|
||||
</script>
|
Загрузка…
Ссылка в новой задаче