Bug 2066283 - Fix handling of passed_rightmost_selector. r=firefox-style-system-reviewers,dshin
This was uncovered by the discussion in D317358. The fact that we reset this flag for nested lists to false is wrong. E.g. we end up treating for `:is(#foo) span` differently to `#foo span`: the first one would end up with "foo" in mapped_ids, while the second wouldn't (and would end up being a revalidation selector instead). I think the `:is(#foo)` behavior ends up being better (it avoids sharing between two elements with the same id if that id is referenced from selectors, but in exchange it does a lot less revalidation of children). This matches how we treat classes, for that matter. We could remove the flag in this patch, but since we want to use it in D321095, I'm keeping it. Luckily it seems rustc isn't smart enough to -Werror about it. Differential Revision: https://phabricator.services.mozilla.com/D321094
This commit is contained in:
committed by
ealvarez@mozilla.com
parent
79a6c4aa9f
commit
5666c13937
@@ -2566,8 +2566,7 @@ struct StylistSelectorVisitor<'a> {
|
||||
/// inside of, if any
|
||||
in_selector_list_of: SelectorListKind,
|
||||
|
||||
/// The filter with all the id's getting referenced from rightmost
|
||||
/// selectors.
|
||||
/// The filter with all the id's getting referenced from selectors.
|
||||
mapped_ids: &'a mut PrecomputedHashSet<Atom>,
|
||||
|
||||
/// The filter with the IDs getting referenced from the selector list of
|
||||
@@ -2602,19 +2601,8 @@ struct StylistSelectorVisitor<'a> {
|
||||
document_state_dependencies: &'a mut DocumentState,
|
||||
}
|
||||
|
||||
fn component_needs_revalidation(
|
||||
c: &Component<SelectorImpl>,
|
||||
passed_rightmost_selector: bool,
|
||||
) -> bool {
|
||||
fn component_needs_revalidation(c: &Component<SelectorImpl>) -> bool {
|
||||
match *c {
|
||||
Component::ID(_) => {
|
||||
// TODO(emilio): This could also check that the ID is not already in
|
||||
// the rule hash. In that case, we could avoid making this a
|
||||
// revalidation selector too.
|
||||
//
|
||||
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1369611
|
||||
passed_rightmost_selector
|
||||
},
|
||||
Component::AttributeInNoNamespaceExists { .. }
|
||||
| Component::AttributeInNoNamespace { .. }
|
||||
| Component::AttributeOther(_)
|
||||
@@ -2636,7 +2624,7 @@ impl<'a> StylistSelectorVisitor<'a> {
|
||||
let old_passed_rightmost_selector = self.passed_rightmost_selector;
|
||||
let old_in_selector_list_of = self.in_selector_list_of;
|
||||
|
||||
self.passed_rightmost_selector = false;
|
||||
// NOTE: Not resetting passed_rightmost_selector, intentionally.
|
||||
self.in_selector_list_of = in_selector_list_of;
|
||||
let _ret = selector.visit(self);
|
||||
debug_assert!(_ret, "We never return false");
|
||||
@@ -2708,8 +2696,7 @@ impl<'a> SelectorVisitor for StylistSelectorVisitor<'a> {
|
||||
}
|
||||
|
||||
fn visit_simple_selector(&mut self, s: &Component<SelectorImpl>) -> bool {
|
||||
*self.needs_revalidation = *self.needs_revalidation
|
||||
|| component_needs_revalidation(s, self.passed_rightmost_selector);
|
||||
*self.needs_revalidation = *self.needs_revalidation || component_needs_revalidation(s);
|
||||
|
||||
match *s {
|
||||
Component::NonTSPseudoClass(NonTSPseudoClass::CustomState(ref name)) => {
|
||||
@@ -2732,21 +2719,7 @@ impl<'a> SelectorVisitor for StylistSelectorVisitor<'a> {
|
||||
}
|
||||
},
|
||||
Component::ID(ref id) => {
|
||||
// We want to stop storing mapped ids as soon as we've moved off
|
||||
// the rightmost ComplexSelector that is not a pseudo-element.
|
||||
//
|
||||
// That can be detected by a visit_complex_selector call with a
|
||||
// combinator other than None and PseudoElement.
|
||||
//
|
||||
// Importantly, this call happens before we visit any of the
|
||||
// simple selectors in that ComplexSelector.
|
||||
//
|
||||
// NOTE(emilio): See the comment regarding on when this may
|
||||
// break in visit_complex_selector.
|
||||
if !self.passed_rightmost_selector {
|
||||
self.mapped_ids.insert(id.0.clone());
|
||||
}
|
||||
|
||||
self.mapped_ids.insert(id.0.clone());
|
||||
if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
|
||||
self.nth_of_mapped_ids.insert(id.0.clone());
|
||||
}
|
||||
@@ -3937,8 +3910,8 @@ impl CascadeData {
|
||||
)?;
|
||||
let mut needs_revalidation = false;
|
||||
let mut visitor = StylistSelectorVisitor {
|
||||
needs_revalidation: &mut needs_revalidation,
|
||||
passed_rightmost_selector: false,
|
||||
needs_revalidation: &mut needs_revalidation,
|
||||
in_selector_list_of: SelectorListKind::default(),
|
||||
mapped_ids: &mut self.mapped_ids,
|
||||
nth_of_mapped_ids: &mut self.nth_of_mapped_ids,
|
||||
@@ -4475,8 +4448,8 @@ impl CascadeData {
|
||||
if let Some(cond) = cur_scope.condition.as_ref() {
|
||||
let mut _unused = false;
|
||||
let visitor = StylistSelectorVisitor {
|
||||
needs_revalidation: &mut _unused,
|
||||
passed_rightmost_selector: true,
|
||||
needs_revalidation: &mut _unused,
|
||||
in_selector_list_of: SelectorListKind::default(),
|
||||
mapped_ids: &mut self.mapped_ids,
|
||||
nth_of_mapped_ids: &mut self.nth_of_mapped_ids,
|
||||
|
||||
Reference in New Issue
Block a user