Bug 1348490 - Part 1. Match both ::placehoder & ::moz-placeholder for placeholder pseudo-elements.
MozReview-Commit-ID: IDc7dI0m7Lw
--- a/servo/components/style/gecko/pseudo_element.rs
+++ b/servo/components/style/gecko/pseudo_element.rs
@@ -88,16 +88,26 @@ impl PseudoElement {
(self.flags() & structs::CSS_PSEUDO_ELEMENT_SUPPORTS_USER_ACTION_STATE) != 0
}
/// Whether this pseudo-element is precomputed.
#[inline]
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.
+ #[inline]
+ pub fn canonical(&self) -> PseudoElement {
+ return match *self {
+ PseudoElement::MozPlaceholder => PseudoElement::Placeholder,
+ _ => self.clone(),
+ };
+ }
}
impl ToCss for PseudoElement {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
dest.write_char(':')?;
dest.write_str(self.as_str())
}
}
--- a/servo/components/style/gecko/wrapper.rs
+++ b/servo/components/style/gecko/wrapper.rs
@@ -1363,17 +1363,17 @@ impl<'le> ::selectors::Element for Gecko
pseudo_element: &PseudoElement,
_context: &mut MatchingContext)
-> bool
{
// TODO(emilio): I believe we could assert we are a pseudo-element and
// 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,
}
}
fn get_id(&self) -> Option<Atom> {
if !self.has_id() {
return None;
}
--- a/servo/components/style/matching.rs
+++ b/servo/components/style/matching.rs
@@ -680,16 +680,18 @@ pub trait MatchMethods : TElement {
fn match_primary(&self,
context: &mut StyleContext<Self>,
data: &mut ElementData,
relations: &mut StyleRelations)
-> RulesMatchedResult
{
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.
let parent = self.parent_element().unwrap();
let parent_data = parent.borrow_data().unwrap();
let pseudo_style =
parent_data.styles().pseudos.get(&pseudo).unwrap();
let mut rules = pseudo_style.rules.clone();
--- a/servo/components/style/servo/selector_parser.rs
+++ b/servo/components/style/servo/selector_parser.rs
@@ -147,16 +147,23 @@ impl PseudoElement {
PseudoElement::ServoAnonymousTable |
PseudoElement::ServoAnonymousTableRow |
PseudoElement::ServoAnonymousTableCell |
PseudoElement::ServoAnonymousBlock |
PseudoElement::ServoInlineBlockWrapper |
PseudoElement::ServoInlineAbsolute => PseudoElementCascadeType::Precomputed,
}
}
+
+ /// Covert non-canonical pseudo-element to canonical one, and keep a
+ /// canonical one as it is.
+ #[inline]
+ pub fn canonical(&self) -> PseudoElement {
+ self.clone()
+ }
}
/// A non tree-structural pseudo-class.
/// See https://drafts.csswg.org/selectors-4/#structural-pseudos
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum NonTSPseudoClass {
--- a/servo/components/style/stylist.rs
+++ b/servo/components/style/stylist.rs
@@ -472,17 +472,17 @@ impl Stylist {
#[inline]
fn add_rule_to_map(&mut self,
selector: &Selector<SelectorImpl>,
rule: &Arc<Locked<StyleRule>>,
stylesheet: &Stylesheet)
{
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 {
self.element_map.borrow_for_origin(&stylesheet.origin)
};
map.insert(Rule::new(selector.clone(),
rule.clone(),
@@ -664,18 +664,19 @@ impl Stylist {
/// docs/components/style.md
pub fn lazy_pseudo_rules<E>(&self,
guards: &StylesheetGuards,
element: &E,
pseudo: &PseudoElement)
-> Option<StrongRuleNode>
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
}
// Apply the selector flags. We should be in sequential mode
// already, so we can directly apply the parent flags.
let mut set_selector_flags = |element: &E, flags: ElementSelectorFlags| {
if cfg!(feature = "servo") {
// Servo calls this function from the worker, but only for internal
@@ -697,17 +698,17 @@ impl Stylist {
}
}
};
let mut declarations = ApplicableDeclarationList::new();
let mut matching_context =
MatchingContext::new(MatchingMode::ForStatelessPseudoElement, None);
self.push_applicable_declarations(element,
- Some(pseudo),
+ Some(&pseudo),
None,
None,
AnimationRules(None, None),
&mut declarations,
&mut matching_context,
&mut set_selector_flags);
if declarations.is_empty() {
return None