mirror of
https://github.com/servo/servo.git
synced 2025-06-25 17:44:33 +01:00
style: Make :host() and ::slotted() account for the inner selector's specificity.
As resolved in https://github.com/w3c/csswg-drafts/issues/1915. Bug: 1454165 Reviewed-by: xidorn Differential Revision: https://phabricator.services.mozilla.com/D1849
This commit is contained in:
parent
8688c53f07
commit
e6d62b685b
1 changed files with 37 additions and 12 deletions
|
@ -23,7 +23,7 @@ use sink::Push;
|
||||||
use smallvec::{self, SmallVec};
|
use smallvec::{self, SmallVec};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::ops::Add;
|
use std::ops::{AddAssign, Add};
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
|
||||||
|
@ -228,6 +228,16 @@ struct Specificity {
|
||||||
element_selectors: u32,
|
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 {
|
impl Add for Specificity {
|
||||||
type Output = Specificity;
|
type Output = Specificity;
|
||||||
|
|
||||||
|
@ -251,6 +261,7 @@ impl Default for Specificity {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<u32> for Specificity {
|
impl From<u32> for Specificity {
|
||||||
|
#[inline]
|
||||||
fn from(value: u32) -> Specificity {
|
fn from(value: u32) -> Specificity {
|
||||||
assert!(value <= MAX_10BIT << 20 | MAX_10BIT << 10 | MAX_10BIT);
|
assert!(value <= MAX_10BIT << 20 | MAX_10BIT << 10 | MAX_10BIT);
|
||||||
Specificity {
|
Specificity {
|
||||||
|
@ -262,6 +273,7 @@ impl From<u32> for Specificity {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Specificity> for u32 {
|
impl From<Specificity> for u32 {
|
||||||
|
#[inline]
|
||||||
fn from(specificity: Specificity) -> u32 {
|
fn from(specificity: Specificity) -> u32 {
|
||||||
cmp::min(specificity.id_selectors, MAX_10BIT) << 20 |
|
cmp::min(specificity.id_selectors, MAX_10BIT) << 20 |
|
||||||
cmp::min(specificity.class_like_selectors, MAX_10BIT) << 10 |
|
cmp::min(specificity.class_like_selectors, MAX_10BIT) << 10 |
|
||||||
|
@ -298,17 +310,29 @@ where
|
||||||
builder,
|
builder,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// FIXME(emilio): Spec doesn't define any particular specificity for
|
Component::PseudoElement(..) | Component::LocalName(..) => {
|
||||||
// ::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(..) => {
|
|
||||||
specificity.element_selectors += 1
|
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::Class(..) |
|
||||||
Component::AttributeInNoNamespace { .. } |
|
Component::AttributeInNoNamespace { .. } |
|
||||||
Component::AttributeInNoNamespaceExists { .. } |
|
Component::AttributeInNoNamespaceExists { .. } |
|
||||||
|
@ -319,7 +343,6 @@ where
|
||||||
Component::Root |
|
Component::Root |
|
||||||
Component::Empty |
|
Component::Empty |
|
||||||
Component::Scope |
|
Component::Scope |
|
||||||
Component::Host(..) |
|
|
||||||
Component::NthChild(..) |
|
Component::NthChild(..) |
|
||||||
Component::NthLastChild(..) |
|
Component::NthLastChild(..) |
|
||||||
Component::NthOfType(..) |
|
Component::NthOfType(..) |
|
||||||
|
@ -327,7 +350,9 @@ where
|
||||||
Component::FirstOfType |
|
Component::FirstOfType |
|
||||||
Component::LastOfType |
|
Component::LastOfType |
|
||||||
Component::OnlyOfType |
|
Component::OnlyOfType |
|
||||||
Component::NonTSPseudoClass(..) => specificity.class_like_selectors += 1,
|
Component::NonTSPseudoClass(..) => {
|
||||||
|
specificity.class_like_selectors += 1;
|
||||||
|
},
|
||||||
Component::ExplicitUniversalType |
|
Component::ExplicitUniversalType |
|
||||||
Component::ExplicitAnyNamespace |
|
Component::ExplicitAnyNamespace |
|
||||||
Component::ExplicitNoNamespace |
|
Component::ExplicitNoNamespace |
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue