From 6973317a58fdaabb4b1277694e432eba5b2c7c10 Mon Sep 17 00:00:00 2001 From: Cameron McCormack Date: Mon, 9 Dec 2019 03:16:03 +0000 Subject: [PATCH] style: Correctly style dark scrollbars in tree components. We need to ensure the rules that override all properties for scrollbar part elements only apply to those that are NAC (and so will be eligible for NAC style sharing). We have some uses of non-NAC elements that should continue to inherit properties from their parents. To avoid any changes in rule matching order that come with changing specificity, we add a new :-moz-native-anonymous-no-specificity pseudo-class. While we're here, we note :-moz-native-anonymous-no-specificity (and the regular :-moz-native-anonymous pseudo-class) as not needing style sharing cache revalidation, as we never share NAC styles. Differential Revision: https://phabricator.services.mozilla.com/D56154 --- components/selectors/builder.rs | 10 +++++++--- components/selectors/parser.rs | 8 ++++++++ components/style/gecko/non_ts_pseudo_class_list.rs | 1 + components/style/gecko/selector_parser.rs | 8 ++++++++ components/style/gecko/wrapper.rs | 3 ++- components/style/servo/selector_parser.rs | 5 +++++ 6 files changed, 31 insertions(+), 4 deletions(-) diff --git a/components/selectors/builder.rs b/components/selectors/builder.rs index 41b83b0c40e..352557735b3 100644 --- a/components/selectors/builder.rs +++ b/components/selectors/builder.rs @@ -17,7 +17,7 @@ //! is non-trivial. This module encapsulates those details and presents an //! easy-to-use API for the parser. -use crate::parser::{Combinator, Component, SelectorImpl}; +use crate::parser::{Combinator, Component, NonTSPseudoClass, SelectorImpl}; use crate::sink::Push; use servo_arc::{Arc, HeaderWithLength, ThinArc}; use smallvec::{self, SmallVec}; @@ -322,9 +322,13 @@ where Component::NthLastOfType(..) | Component::FirstOfType | Component::LastOfType | - Component::OnlyOfType | - Component::NonTSPseudoClass(..) => { + Component::OnlyOfType => { specificity.class_like_selectors += 1; + } + Component::NonTSPseudoClass(ref pseudo) => { + if !pseudo.has_zero_specificity() { + specificity.class_like_selectors += 1; + } }, Component::ExplicitUniversalType | Component::ExplicitAnyNamespace | diff --git a/components/selectors/parser.rs b/components/selectors/parser.rs index 507121bbf97..92a5b039b90 100644 --- a/components/selectors/parser.rs +++ b/components/selectors/parser.rs @@ -52,6 +52,9 @@ pub trait NonTSPseudoClass: Sized + ToCss { /// /// https://drafts.csswg.org/selectors-4/#useraction-pseudos fn is_user_action_state(&self) -> bool; + + /// Whether this pseudo-class has zero specificity. + fn has_zero_specificity(&self) -> bool; } /// Returns a Cow::Borrowed if `s` is already ASCII lowercase, and a @@ -2336,6 +2339,11 @@ pub mod tests { fn is_user_action_state(&self) -> bool { self.is_active_or_hover() } + + #[inline] + fn has_zero_specificity(&self) -> bool { + false + } } impl ToCss for PseudoClass { diff --git a/components/style/gecko/non_ts_pseudo_class_list.rs b/components/style/gecko/non_ts_pseudo_class_list.rs index f38757189d0..eca60fdc586 100644 --- a/components/style/gecko/non_ts_pseudo_class_list.rs +++ b/components/style/gecko/non_ts_pseudo_class_list.rs @@ -94,6 +94,7 @@ macro_rules! apply_non_ts_list { ("-moz-last-node", MozLastNode, lastNode, _, _), ("-moz-only-whitespace", MozOnlyWhitespace, mozOnlyWhitespace, _, _), ("-moz-native-anonymous", MozNativeAnonymous, mozNativeAnonymous, _, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS), + ("-moz-native-anonymous-no-specificity", MozNativeAnonymousNoSpecificity, mozNativeAnonymousNoSpecificity, _, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS), ("-moz-use-shadow-tree-root", MozUseShadowTreeRoot, mozUseShadowTreeRoot, _, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS), ("-moz-is-html", MozIsHTML, mozIsHTML, _, _), ("-moz-placeholder", MozPlaceholder, mozPlaceholder, _, _), diff --git a/components/style/gecko/selector_parser.rs b/components/style/gecko/selector_parser.rs index 2aad41adc9c..fec3c9247c3 100644 --- a/components/style/gecko/selector_parser.rs +++ b/components/style/gecko/selector_parser.rs @@ -233,6 +233,9 @@ impl NonTSPseudoClass { // across all the elements involved and the latter is already // checked for by our caching precondtions. NonTSPseudoClass::MozIsHTML | + // We prevent style sharing for NAC. + NonTSPseudoClass::MozNativeAnonymous | + NonTSPseudoClass::MozNativeAnonymousNoSpecificity | // :-moz-placeholder is parsed but never matches. NonTSPseudoClass::MozPlaceholder | // :-moz-locale-dir and :-moz-window-inactive depend only on @@ -275,6 +278,11 @@ impl ::selectors::parser::NonTSPseudoClass for NonTSPseudoClass { NonTSPseudoClass::Hover | NonTSPseudoClass::Active | NonTSPseudoClass::Focus ) } + + #[inline] + fn has_zero_specificity(&self) -> bool { + matches!(*self, NonTSPseudoClass::MozNativeAnonymousNoSpecificity) + } } /// The dummy struct we use to implement our selector parsing. diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index bf4da090646..e0079921072 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -2130,7 +2130,8 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { } true }, - NonTSPseudoClass::MozNativeAnonymous => self.is_in_native_anonymous_subtree(), + NonTSPseudoClass::MozNativeAnonymous | + NonTSPseudoClass::MozNativeAnonymousNoSpecificity => self.is_in_native_anonymous_subtree(), NonTSPseudoClass::MozUseShadowTreeRoot => self.is_root_of_use_element_shadow_tree(), NonTSPseudoClass::MozTableBorderNonzero => unsafe { bindings::Gecko_IsTableBorderNonzero(self.0) diff --git a/components/style/servo/selector_parser.rs b/components/style/servo/selector_parser.rs index 977a6c59a85..942dcdba1bb 100644 --- a/components/style/servo/selector_parser.rs +++ b/components/style/servo/selector_parser.rs @@ -309,6 +309,11 @@ impl ::selectors::parser::NonTSPseudoClass for NonTSPseudoClass { NonTSPseudoClass::Active | NonTSPseudoClass::Hover | NonTSPseudoClass::Focus ) } + + #[inline] + fn has_zero_specificity(&self) -> bool { + false + } } impl ToCss for NonTSPseudoClass {