tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit bb3e3ab5e511ddd9e4718c1445a6a6710281e955
parent 33f299d69f9b260232493c7fc76621625e535d63
Author: David Shin <dshin@mozilla.com>
Date:   Wed,  8 Oct 2025 20:19:22 +0000

Bug 1993226: Do not coerce non-subject unknown results. r=firefox-style-system-reviewers,emilio

This optimization is not sound. See bugs 1874042 and 1964575.

Differential Revision: https://phabricator.services.mozilla.com/D268012

Diffstat:
Mservo/components/selectors/matching.rs | 20++------------------
Atesting/web-platform/tests/css/selectors/invalidation/negated-first-of-type-in-nonsubject-position.html | 30++++++++++++++++++++++++++++++
Atesting/web-platform/tests/css/selectors/invalidation/negated-has-in-nonsubject-position.html | 31+++++++++++++++++++++++++++++++
3 files changed, 63 insertions(+), 18 deletions(-)

diff --git a/servo/components/selectors/matching.rs b/servo/components/selectors/matching.rs @@ -826,24 +826,8 @@ where selector_iter, element ); - let matches_compound_selector = { - let result = matches_compound_selector(&mut selector_iter, element, context, rightmost); - // We only care for unknown match in the first subject in compound - in the context of comparison - // invalidation, ancestors/previous sibling being an unknown match doesn't matter - we must - // invalidate to guarantee correctness. - if result == KleeneValue::Unknown && first_subject_compound == SubjectOrPseudoElement::No { - debug_assert!( - context - .matching_for_invalidation_comparison() - .unwrap_or(false), - "How did we return unknown?" - ); - // Coerce the result to matched. - KleeneValue::from(!context.in_negation()) - } else { - result - } - }; + let matches_compound_selector = + matches_compound_selector(&mut selector_iter, element, context, rightmost); let Some(combinator) = selector_iter.next_sequence() else { return match matches_compound_selector { diff --git a/testing/web-platform/tests/css/selectors/invalidation/negated-first-of-type-in-nonsubject-position.html b/testing/web-platform/tests/css/selectors/invalidation/negated-first-of-type-in-nonsubject-position.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<!doctype html> +<meta charset="utf-8"> +<html class="reftest-wait"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1993226"> +<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com"> +<link rel="match" href="../../reference/ref-filled-green-100px-square.xht"> +<style> +.c { + width: 100px; + height: 100px; + background: green; +} +.b:not(.ancestor:first-of-type .a) .c { + background: red; +} +</style> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div class=ancestor> + <div id=dut class=b> + <div class=c></div> + </div> +</div> +<script> +onload = () => { + dut.classList.toggle('a'); + dut.getBoundingClientRect(); // Ensure layout flush. + document.documentElement.classList.remove('reftest-wait'); +}; +</script> diff --git a/testing/web-platform/tests/css/selectors/invalidation/negated-has-in-nonsubject-position.html b/testing/web-platform/tests/css/selectors/invalidation/negated-has-in-nonsubject-position.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<!doctype html> +<meta charset="utf-8"> +<html class="reftest-wait"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1993226"> +<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com"> +<link rel="match" href="../../reference/ref-filled-green-100px-square.xht"> +<style> +.c { + width: 100px; + height: 100px; + background: green; +} +.b:not(.ancestor:has(+ .sibling) .a) .c { + background: red; +} +</style> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div class=ancestor> + <div id=dut class=b> + <div class=c></div> + </div> +</div> +<div class=sibling></div> +<script> +onload = () => { + dut.classList.toggle('a'); + dut.getBoundingClientRect(); // Ensure layout flush. + document.documentElement.classList.remove('reftest-wait'); +}; +</script>