diff --git a/components/style/gecko/pseudo_element.rs b/components/style/gecko/pseudo_element.rs index a501198f28e..888fdbdc33c 100644 --- a/components/style/gecko/pseudo_element.rs +++ b/components/style/gecko/pseudo_element.rs @@ -102,6 +102,15 @@ impl PseudoElement { pub fn is_precomputed(&self) -> bool { self.is_anon_box() } + + /// Covert non-canonical pseudo-element to canonical one, and keep a + /// canonical one as it is. + pub fn canonical(&self) -> PseudoElement { + match *self { + PseudoElement::MozPlaceholder => PseudoElement::Placeholder, + _ => self.clone(), + } + } } impl ToCss for PseudoElement { diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index 3732ea40051..638db04b580 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -1369,7 +1369,7 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { // match the proper pseudo-element, given how we rulehash the stuff // based on the pseudo. match self.implemented_pseudo_element() { - Some(ref pseudo) => pseudo == pseudo_element, + Some(ref pseudo) => *pseudo == pseudo_element.canonical(), None => false, } } diff --git a/components/style/matching.rs b/components/style/matching.rs index e0a8e4ec755..ecc62cf145b 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -684,6 +684,8 @@ pub trait MatchMethods : TElement { { let implemented_pseudo = self.implemented_pseudo_element(); if let Some(ref pseudo) = implemented_pseudo { + // We don't expect to match against a non-canonical pseudo-element. + debug_assert_eq!(*pseudo, pseudo.canonical()); if pseudo.is_eager() { // If it's an eager element-backed pseudo, just grab the matched // rules from the parent, and update animations. diff --git a/components/style/servo/selector_parser.rs b/components/style/servo/selector_parser.rs index fdc14b11e29..1cae314ddec 100644 --- a/components/style/servo/selector_parser.rs +++ b/components/style/servo/selector_parser.rs @@ -152,6 +152,12 @@ impl PseudoElement { PseudoElement::ServoInlineAbsolute => PseudoElementCascadeType::Precomputed, } } + + /// Covert non-canonical pseudo-element to canonical one, and keep a + /// canonical one as it is. + pub fn canonical(&self) -> PseudoElement { + self.clone() + } } /// A non tree-structural pseudo-class. diff --git a/components/style/stylist.rs b/components/style/stylist.rs index 7fb64c8acf5..906e4e56745 100644 --- a/components/style/stylist.rs +++ b/components/style/stylist.rs @@ -473,7 +473,7 @@ impl Stylist { { let map = if let Some(pseudo) = selector.pseudo_element() { self.pseudos_map - .entry(pseudo.clone()) + .entry(pseudo.canonical()) .or_insert_with(PerPseudoElementSelectorMap::new) .borrow_for_origin(&stylesheet.origin) } else { @@ -665,8 +665,9 @@ impl Stylist { -> Option where E: TElement { + let pseudo = pseudo.canonical(); debug_assert!(pseudo.is_lazy()); - if self.pseudos_map.get(pseudo).is_none() { + if self.pseudos_map.get(&pseudo).is_none() { return None } @@ -698,7 +699,7 @@ impl Stylist { let mut matching_context = MatchingContext::new(MatchingMode::ForStatelessPseudoElement, None); self.push_applicable_declarations(element, - Some(pseudo), + Some(&pseudo), None, None, AnimationRules(None, None),