style: Make pseudo-elements work with :host.

Imported WebKit's test as a WPT.

Bug: 1465291
Reviewed-by: xidorn
MozReview-Commit-ID: 19ZThuoqKLW
This commit is contained in:
Emilio Cobos Álvarez 2018-06-04 16:27:00 +02:00
parent 8d069d127a
commit 8821ad72f4
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
2 changed files with 35 additions and 28 deletions

View file

@ -544,10 +544,26 @@ impl<Impl: SelectorImpl> Selector<Impl> {
} }
/// Whether this selector is a featureless :host selector, with no /// Whether this selector is a featureless :host selector, with no
/// combinators to the left. /// combinators to the left, and optionally has a pseudo-element to the
/// right.
#[inline] #[inline]
pub fn is_featureless_host_selector(&self) -> bool { pub fn is_featureless_host_selector_or_pseudo_element(&self) -> bool {
self.iter().is_featureless_host_selector() let mut iter = self.iter();
if !self.has_pseudo_element() {
return iter.is_featureless_host_selector();
}
// Skip the pseudo-element.
for _ in &mut iter { }
match iter.next_sequence() {
None => return false,
Some(combinator) => {
debug_assert_eq!(combinator, Combinator::PseudoElement);
}
}
iter.is_featureless_host_selector()
} }
/// Returns an iterator over this selector in matching order (right-to-left), /// Returns an iterator over this selector in matching order (right-to-left),

View file

@ -1951,14 +1951,9 @@ pub struct CascadeData {
/// cascade level. /// cascade level.
normal_rules: ElementAndPseudoRules, normal_rules: ElementAndPseudoRules,
/// The `:host` pseudo rules that are the rightmost selector. /// The `:host` pseudo rules that are the rightmost selector (without
/// /// accounting for pseudo-elements).
/// Note that as of right now these can't affect invalidation in any way, host_rules: Option<Box<ElementAndPseudoRules>>,
/// until we support the :host(<selector>) notation.
///
/// Also, note that other engines don't accept stuff like :host::before /
/// :host::after, so we don't need to store pseudo rules at all.
host_rules: Option<Box<SelectorMap<Rule>>>,
/// The data coming from ::slotted() pseudo-element rules. /// The data coming from ::slotted() pseudo-element rules.
/// ///
@ -2122,11 +2117,7 @@ impl CascadeData {
#[inline] #[inline]
fn host_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> { fn host_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> {
if pseudo.is_some() { self.host_rules.as_ref().and_then(|d| d.rules(pseudo))
return None;
}
self.host_rules.as_ref().map(|rules| &**rules)
} }
#[inline] #[inline]
@ -2258,20 +2249,20 @@ impl CascadeData {
} }
} }
if selector.is_featureless_host_selector() { // NOTE(emilio): It's fine to look at :host and then at
let host_rules = self.host_rules // ::slotted(..), since :host::slotted(..) could never
.get_or_insert_with(|| Box::new(Default::default())); // possibly match, as <slot> is not a valid shadow host.
host_rules.insert(rule, quirks_mode)?; let rules = if selector.is_featureless_host_selector_or_pseudo_element() {
self.host_rules
.get_or_insert_with(|| Box::new(Default::default()))
} else if selector.is_slotted() {
self.slotted_rules
.get_or_insert_with(|| Box::new(Default::default()))
} else { } else {
let rules = if selector.is_slotted() { &mut self.normal_rules
self.slotted_rules };
.get_or_insert_with(|| Box::new(Default::default()))
} else {
&mut self.normal_rules
};
rules.insert(rule, pseudo_element, quirks_mode)?; rules.insert(rule, pseudo_element, quirks_mode)?;
}
} }
self.rules_source_order += 1; self.rules_source_order += 1;
}, },