diff options
Diffstat (limited to 'components/selectors/builder.rs')
-rw-r--r-- | components/selectors/builder.rs | 49 |
1 files changed, 37 insertions, 12 deletions
diff --git a/components/selectors/builder.rs b/components/selectors/builder.rs index 0be3eb90e0c..29ac822fa03 100644 --- a/components/selectors/builder.rs +++ b/components/selectors/builder.rs @@ -23,7 +23,7 @@ use sink::Push; use smallvec::{self, SmallVec}; use std::cmp; use std::iter; -use std::ops::Add; +use std::ops::{AddAssign, Add}; use std::ptr; use std::slice; @@ -228,6 +228,16 @@ struct Specificity { element_selectors: u32, } + +impl AddAssign for Specificity { + #[inline] + fn add_assign(&mut self, rhs: Self) { + self.id_selectors += rhs.id_selectors; + self.class_like_selectors += rhs.class_like_selectors; + self.element_selectors += rhs.element_selectors; + } +} + impl Add for Specificity { type Output = Specificity; @@ -251,6 +261,7 @@ impl Default for Specificity { } impl From<u32> for Specificity { + #[inline] fn from(value: u32) -> Specificity { assert!(value <= MAX_10BIT << 20 | MAX_10BIT << 10 | MAX_10BIT); Specificity { @@ -262,6 +273,7 @@ impl From<u32> for Specificity { } impl From<Specificity> for u32 { + #[inline] fn from(specificity: Specificity) -> u32 { cmp::min(specificity.id_selectors, MAX_10BIT) << 20 | cmp::min(specificity.class_like_selectors, MAX_10BIT) << 10 | @@ -298,17 +310,29 @@ where builder, ); } - // FIXME(emilio): Spec doesn't define any particular specificity for - // ::slotted(), so apply the general rule for pseudos per: - // - // https://github.com/w3c/csswg-drafts/issues/1915 - // - // Though other engines compute it dynamically, so maybe we should - // do that instead, eventually. - Component::Slotted(..) | Component::PseudoElement(..) | Component::LocalName(..) => { + Component::PseudoElement(..) | Component::LocalName(..) => { specificity.element_selectors += 1 }, - Component::ID(..) => specificity.id_selectors += 1, + Component::Slotted(ref selector) => { + specificity.element_selectors += 1; + // Note that due to the way ::slotted works we only compete with + // other ::slotted rules, so the above rule doesn't really + // matter, but we do it still for consistency with other + // pseudo-elements. + // + // See: https://github.com/w3c/csswg-drafts/issues/1915 + *specificity += Specificity::from(selector.specificity()); + }, + Component::Host(ref selector) => { + specificity.class_like_selectors += 1; + if let Some(ref selector) = *selector { + // See: https://github.com/w3c/csswg-drafts/issues/1915 + *specificity += Specificity::from(selector.specificity()); + } + } + Component::ID(..) => { + specificity.id_selectors += 1; + }, Component::Class(..) | Component::AttributeInNoNamespace { .. } | Component::AttributeInNoNamespaceExists { .. } | @@ -319,7 +343,6 @@ where Component::Root | Component::Empty | Component::Scope | - Component::Host(..) | Component::NthChild(..) | Component::NthLastChild(..) | Component::NthOfType(..) | @@ -327,7 +350,9 @@ where Component::FirstOfType | Component::LastOfType | Component::OnlyOfType | - Component::NonTSPseudoClass(..) => specificity.class_like_selectors += 1, + Component::NonTSPseudoClass(..) => { + specificity.class_like_selectors += 1; + }, Component::ExplicitUniversalType | Component::ExplicitAnyNamespace | Component::ExplicitNoNamespace | |