Reported testcase fails because it uses a child selector, and because revalidation does not set the scope root - So we need to make sure that `:scope` is "ignored" during revalidation matching. We do revalidate individual scope activations later, anyway (Which is separate because finding relevant scope roots exactly would involve running style matching from scratch). Differential Revision: https://phabricator.services.mozilla.com/D282011
343 lines
8.2 KiB
HTML
343 lines
8.2 KiB
HTML
<!DOCTYPE html>
|
|
<title>@scope - Cousin Style Sharing</title>
|
|
<link rel="help" href="https://drafts.csswg.org/css-cascade-6/#scope-atrule">
|
|
<script src="/resources/testharness.js"></script>
|
|
<script src="/resources/testharnessreport.js"></script>
|
|
<main id=main></main>
|
|
|
|
<template id=test_1>
|
|
<style>
|
|
@scope (.scope-start) to (:scope:last-of-type > .foo) {
|
|
.foo {
|
|
z-index: 1;
|
|
}
|
|
}
|
|
</style>
|
|
<div class="scope-start">
|
|
<div id="first" class="foo"></div>
|
|
</div>
|
|
<div class="scope-start">
|
|
<div id="second" class="foo"></div>
|
|
</div>
|
|
</template>
|
|
<script>
|
|
test((t) => {
|
|
t.add_cleanup(() => main.replaceChildren());
|
|
main.append(test_1.content.cloneNode(true));
|
|
|
|
assert_equals(getComputedStyle(first).zIndex, '1');
|
|
assert_equals(getComputedStyle(second).zIndex, 'auto');
|
|
}, '@scope with cousin style sharing, second sibling exits scope');
|
|
</script>
|
|
|
|
<template id=test_2>
|
|
<style>
|
|
@scope (.scope-start) to (:scope:first-of-type > .foo) {
|
|
.foo {
|
|
z-index: 1;
|
|
}
|
|
}
|
|
.scope-start:first-child {
|
|
color: green;
|
|
}
|
|
</style>
|
|
<div class="scope-start">
|
|
<div id="first" class="foo"></div>
|
|
</div>
|
|
<div class="scope-start">
|
|
<div id="second" class="foo"></div>
|
|
</div>
|
|
</template>
|
|
<script>
|
|
test((t) => {
|
|
t.add_cleanup(() => main.replaceChildren());
|
|
main.append(test_2.content.cloneNode(true));
|
|
|
|
assert_equals(getComputedStyle(first).zIndex, 'auto');
|
|
assert_equals(getComputedStyle(second).zIndex, '1');
|
|
}, '@scope with cousin style sharing, first sibling exits scope');
|
|
</script>
|
|
|
|
<template id=test_3>
|
|
<style>
|
|
@scope (.scope-start:first-of-type > .foo) {
|
|
:scope {
|
|
z-index: 1;
|
|
}
|
|
}
|
|
</style>
|
|
<div class="scope-start">
|
|
<div id="first" class="foo"></div>
|
|
</div>
|
|
<div class="scope-start">
|
|
<div id="second" class="foo"></div>
|
|
</div>
|
|
</template>
|
|
<script>
|
|
test((t) => {
|
|
t.add_cleanup(() => main.replaceChildren());
|
|
main.append(test_3.content.cloneNode(true));
|
|
|
|
assert_equals(getComputedStyle(first).zIndex, '1');
|
|
assert_equals(getComputedStyle(second).zIndex, 'auto');
|
|
}, '@scope with cousin style sharing, first sibling enters scope');
|
|
</script>
|
|
|
|
<template id=test_4>
|
|
<style>
|
|
@scope (.scope-start:last-of-type > .foo) {
|
|
:scope {
|
|
z-index: 1;
|
|
}
|
|
}
|
|
</style>
|
|
<div class="scope-start">
|
|
<div id="first" class="foo"></div>
|
|
</div>
|
|
<div class="scope-start">
|
|
<div id="second" class="foo"></div>
|
|
</div>
|
|
</template>
|
|
<script>
|
|
test((t) => {
|
|
t.add_cleanup(() => main.replaceChildren());
|
|
main.append(test_4.content.cloneNode(true));
|
|
|
|
assert_equals(getComputedStyle(first).zIndex, 'auto');
|
|
assert_equals(getComputedStyle(second).zIndex, '1');
|
|
}, '@scope with cousin style sharing, second sibling enters scope');
|
|
</script>
|
|
|
|
<template id=test_5>
|
|
<div class="scope-start">
|
|
<style>
|
|
@scope {
|
|
.foo {
|
|
z-index: 1;
|
|
}
|
|
}
|
|
</style>
|
|
<div id="first" class="foo"></div>
|
|
</div>
|
|
<div class="scope-start">
|
|
<div id="second" class="foo"></div>
|
|
</div>
|
|
</template>
|
|
<script>
|
|
test((t) => {
|
|
t.add_cleanup(() => main.replaceChildren());
|
|
main.append(test_5.content.cloneNode(true));
|
|
|
|
assert_equals(getComputedStyle(first).zIndex, '1');
|
|
assert_equals(getComputedStyle(second).zIndex, 'auto');
|
|
}, '@scope with cousin style sharing, second sibling parent does not have implicit scope');
|
|
</script>
|
|
|
|
<template id=test_6>
|
|
<div class="scope-start">
|
|
<div id="first" class="foo"></div>
|
|
</div>
|
|
<div class="scope-start">
|
|
<style>
|
|
@scope {
|
|
.foo {
|
|
z-index: 1;
|
|
}
|
|
}
|
|
</style>
|
|
<div id="second" class="foo"></div>
|
|
</div>
|
|
</template>
|
|
<script>
|
|
test((t) => {
|
|
t.add_cleanup(() => main.replaceChildren());
|
|
main.append(test_6.content.cloneNode(true));
|
|
|
|
assert_equals(getComputedStyle(first).zIndex, 'auto');
|
|
assert_equals(getComputedStyle(second).zIndex, '1');
|
|
}, '@scope with cousin style sharing, first sibling parent does not have implicit scope');
|
|
</script>
|
|
|
|
<template id=test_7>
|
|
<div class="scope-start">
|
|
<div id="first" class="foo">
|
|
<style>
|
|
@scope {
|
|
:scope {
|
|
z-index: 1;
|
|
}
|
|
}
|
|
</style>
|
|
</div>
|
|
</div>
|
|
<div class="scope-start">
|
|
<div id="second" class="foo">
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<script>
|
|
test((t) => {
|
|
t.add_cleanup(() => main.replaceChildren());
|
|
main.append(test_7.content.cloneNode(true));
|
|
|
|
assert_equals(getComputedStyle(first).zIndex, '1');
|
|
assert_equals(getComputedStyle(second).zIndex, 'auto');
|
|
}, '@scope with cousin style sharing, second sibling does not have implicit scope');
|
|
</script>
|
|
|
|
<template id=test_8>
|
|
<div class="scope-start">
|
|
<div id="first" class="foo">
|
|
</div>
|
|
</div>
|
|
<div class="scope-start">
|
|
<div id="second" class="foo">
|
|
<style>
|
|
@scope {
|
|
:scope {
|
|
z-index: 1;
|
|
}
|
|
}
|
|
</style>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<script>
|
|
test((t) => {
|
|
t.add_cleanup(() => main.replaceChildren());
|
|
main.append(test_8.content.cloneNode(true));
|
|
|
|
assert_equals(getComputedStyle(first).zIndex, 'auto');
|
|
assert_equals(getComputedStyle(second).zIndex, '1');
|
|
}, '@scope with cousin style sharing, first sibling does not have implicit scope');
|
|
</script>
|
|
|
|
<template id=test_9>
|
|
<style>
|
|
@scope (.scope-start:has(> .bar)) {
|
|
.foo {
|
|
z-index: 1;
|
|
}
|
|
}
|
|
</style>
|
|
<div class="scope-start">
|
|
<div id="first" class="foo"></div>
|
|
<div class="bar"></div>
|
|
</div>
|
|
<div class="scope-start">
|
|
<div id="second" class="foo"></div>
|
|
</div>
|
|
</template>
|
|
<script>
|
|
test((t) => {
|
|
t.add_cleanup(() => main.replaceChildren());
|
|
main.append(test_9.content.cloneNode(true));
|
|
|
|
assert_equals(getComputedStyle(first).zIndex, '1');
|
|
assert_equals(getComputedStyle(second).zIndex, 'auto');
|
|
}, '@scope with cousin style sharing, first sibling enters scope with :has');
|
|
</script>
|
|
|
|
<template id=test_10>
|
|
<style>
|
|
@scope (.scope-start:has(> .bar)) {
|
|
.foo {
|
|
z-index: 1;
|
|
}
|
|
}
|
|
</style>
|
|
<div class="scope-start">
|
|
<div id="first" class="foo"></div>
|
|
</div>
|
|
<div class="scope-start">
|
|
<div id="second" class="foo"></div>
|
|
<div class="bar"></div>
|
|
</div>
|
|
</template>
|
|
<script>
|
|
test((t) => {
|
|
t.add_cleanup(() => main.replaceChildren());
|
|
main.append(test_10.content.cloneNode(true));
|
|
|
|
assert_equals(getComputedStyle(first).zIndex, 'auto');
|
|
assert_equals(getComputedStyle(second).zIndex, '1');
|
|
}, '@scope with cousin style sharing, second sibling enters scope with :has');
|
|
</script>
|
|
|
|
<template id=test_11>
|
|
<style>
|
|
@scope (#first-parent) {
|
|
.foo {
|
|
z-index: 1;
|
|
}
|
|
}
|
|
</style>
|
|
<div id="first-parent">
|
|
<div id="first" class="foo"></div>
|
|
</div>
|
|
<div id="second-parent">
|
|
<div id="second" class="foo"></div>
|
|
</div>
|
|
</template>
|
|
<script>
|
|
test((t) => {
|
|
t.add_cleanup(() => main.replaceChildren());
|
|
main.append(test_11.content.cloneNode(true));
|
|
|
|
assert_equals(getComputedStyle(first).zIndex, '1');
|
|
assert_equals(getComputedStyle(second).zIndex, 'auto');
|
|
}, '@scope with cousin style sharing, first sibling enters scope ID selector');
|
|
</script>
|
|
|
|
<template id=test_12>
|
|
<style>
|
|
@scope (#second-parent) {
|
|
.foo {
|
|
z-index: 1;
|
|
}
|
|
}
|
|
</style>
|
|
<div id="first-parent">
|
|
<div id="first" class="foo"></div>
|
|
</div>
|
|
<div id="second-parent">
|
|
<div id="second" class="foo"></div>
|
|
</div>
|
|
</template>
|
|
<script>
|
|
test((t) => {
|
|
t.add_cleanup(() => main.replaceChildren());
|
|
main.append(test_12.content.cloneNode(true));
|
|
|
|
assert_equals(getComputedStyle(first).zIndex, 'auto');
|
|
assert_equals(getComputedStyle(second).zIndex, '1');
|
|
}, '@scope with cousin style sharing, second sibling enters scope ID selector');
|
|
</script>
|
|
|
|
<template id=test_13>
|
|
<style>
|
|
@scope (.root) {
|
|
> div:nth-of-type(2) > div {
|
|
z-index: 1;
|
|
}
|
|
}
|
|
</style>
|
|
<div class=root>
|
|
<div class=parent>
|
|
<div id="first"></div>
|
|
</div>
|
|
<div class=parent>
|
|
<div id="second"></div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<script>
|
|
test((t) => {
|
|
t.add_cleanup(() => main.replaceChildren());
|
|
main.append(test_13.content.cloneNode(true));
|
|
|
|
assert_equals(getComputedStyle(first).zIndex, 'auto');
|
|
assert_equals(getComputedStyle(second).zIndex, '1');
|
|
}, '@scope with cousin style sharing, with child relative implicit scope selector');
|
|
</script>
|