Bug 1942695: Ensure that unknown match results don't get overwritten in selector lists. r=firefox-style-system-reviewers,emilio
Differential Revision: https://phabricator.services.mozilla.com/D235205
This commit is contained in:
@@ -36,24 +36,20 @@ impl KleeneValue {
|
||||
}
|
||||
}
|
||||
|
||||
/// Return true if any result of f() is true. Otherwise, return the strongest value seen.
|
||||
/// Return true if any result of f() is definitely true.
|
||||
/// Otherwise, return the `or` of all values.
|
||||
/// Returns false if empty, like that of `Iterator`.
|
||||
#[inline(always)]
|
||||
pub fn any<T>(
|
||||
iter: impl Iterator<Item = T>,
|
||||
f: impl FnMut(T) -> Self,
|
||||
) -> Self {
|
||||
Self::any_value(iter, Self::True, Self::False, f)
|
||||
pub fn any<T>(iter: impl Iterator<Item = T>, f: impl FnMut(T) -> Self) -> Self {
|
||||
Self::any_value(iter, Self::True, Self::False, |a, b| a | b, f)
|
||||
}
|
||||
|
||||
/// Return false if any results of f() is false. Otherwise, return the strongest value seen.
|
||||
/// Return false if any results of f() is definitely false.
|
||||
/// Otherwise, return the `and` of all values.
|
||||
/// Returns true if empty, opposite of `Iterator`.
|
||||
#[inline(always)]
|
||||
pub fn any_false<T>(
|
||||
iter: impl Iterator<Item = T>,
|
||||
f: impl FnMut(T) -> Self,
|
||||
) -> Self {
|
||||
Self::any_value(iter, Self::False, Self::True, f)
|
||||
pub fn any_false<T>(iter: impl Iterator<Item = T>, f: impl FnMut(T) -> Self) -> Self {
|
||||
Self::any_value(iter, Self::False, Self::True, |a, b| a & b, f)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -61,6 +57,7 @@ impl KleeneValue {
|
||||
iter: impl Iterator<Item = T>,
|
||||
value: Self,
|
||||
on_empty: Self,
|
||||
op: impl Fn(Self, Self) -> Self,
|
||||
mut f: impl FnMut(T) -> Self,
|
||||
) -> Self {
|
||||
let mut result = None;
|
||||
@@ -70,7 +67,7 @@ impl KleeneValue {
|
||||
return r;
|
||||
}
|
||||
if let Some(v) = result.as_mut() {
|
||||
*v = *v & r;
|
||||
*v = op(*v, r);
|
||||
} else {
|
||||
result = Some(r);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
<!DOCTYPE html>
|
||||
<title>CSS Selectors Invalidation: :is and :where selectors containing "hard" selectors and selectors that never match</title>
|
||||
<link rel="author" title="David Shin" href="dshin@mozilla.com">
|
||||
<link rel="help" href="https://drafts.csswg.org/selectors/#logical-combination">
|
||||
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1942695">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<style>
|
||||
.container {
|
||||
color: grey;
|
||||
}
|
||||
|
||||
#subject1:is(.container:has(.descendant):focus-within, .never-matches) {
|
||||
color: red;
|
||||
}
|
||||
|
||||
#subject2:where(.container:has(.descendant):focus-within, .never-matches) {
|
||||
color: orangered;
|
||||
}
|
||||
|
||||
#subject3:is(:nth-child(1 of .container):focus-within, .never-matches) {
|
||||
color: darkred;
|
||||
}
|
||||
|
||||
#subject4:where(:nth-child(1 of .container):focus-within, .never-matches) {
|
||||
color: pink;
|
||||
}
|
||||
</style>
|
||||
<div id="subject1" class="container">
|
||||
<div class="descendant"></div>
|
||||
<a id="anchor1" href="#">X</a>
|
||||
</div>
|
||||
<div id="subject2" class="container">
|
||||
<div class="descendant"></div>
|
||||
<a id="anchor2" href="#">X</a>
|
||||
</div>
|
||||
<div>
|
||||
<div id="subject3" class="container">
|
||||
<div class="descendant"></div>
|
||||
<a id="anchor3" href="#">x</a>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div id="subject4" class="container">
|
||||
<div class="descendant"></div>
|
||||
<a id="anchor4" href="#">x</a>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
const colors = {
|
||||
grey: "rgb(128, 128, 128)",
|
||||
red: "rgb(255, 0, 0)",
|
||||
orangered: "rgb(255, 69, 0)",
|
||||
darkred: "rgb(139, 0, 0)",
|
||||
pink: "rgb(255, 192, 203)",
|
||||
};
|
||||
|
||||
function run_test(subject, anchor, before, after) {
|
||||
const beforeColor = colors[before];
|
||||
test(() => {
|
||||
assert_equals(getComputedStyle(subject).color, beforeColor);
|
||||
}, subject.id + " initial color is " + before);
|
||||
|
||||
anchor.focus();
|
||||
const afterColor = colors[after];
|
||||
test(() => {
|
||||
assert_equals(getComputedStyle(subject).color, afterColor);
|
||||
}, subject.id + " color after focus is " + after);
|
||||
|
||||
anchor.blur();
|
||||
test(() => {
|
||||
assert_equals(getComputedStyle(subject).color, beforeColor);
|
||||
}, subject.id + " color after blur is " + before);
|
||||
}
|
||||
|
||||
run_test(subject1, anchor1, "grey", "red");
|
||||
run_test(subject2, anchor2, "grey", "orangered");
|
||||
run_test(subject3, anchor3, "grey", "darkred");
|
||||
run_test(subject4, anchor4, "grey", "pink");
|
||||
</script>
|
||||
Reference in New Issue
Block a user