diff options
Diffstat (limited to 'components/style/servo/selector_parser.rs')
-rw-r--r-- | components/style/servo/selector_parser.rs | 104 |
1 files changed, 61 insertions, 43 deletions
diff --git a/components/style/servo/selector_parser.rs b/components/style/servo/selector_parser.rs index e801738866c..fdc14b11e29 100644 --- a/components/style/servo/selector_parser.rs +++ b/components/style/servo/selector_parser.rs @@ -14,9 +14,10 @@ use element_state::ElementState; use fnv::FnvHashMap; use restyle_hints::ElementSnapshot; use selector_parser::{ElementExt, PseudoElementCascadeType, SelectorParser}; -use selectors::{Element, MatchAttrGeneric}; -use selectors::matching::StyleRelations; -use selectors::parser::{AttrSelector, SelectorMethods}; +use selectors::Element; +use selectors::attr::{AttrSelectorOperation, NamespaceConstraint}; +use selectors::matching::{MatchingContext, MatchingMode}; +use selectors::parser::SelectorMethods; use selectors::visitor::SelectorVisitor; use std::borrow::Cow; use std::fmt; @@ -51,6 +52,14 @@ pub enum PseudoElement { ServoInlineAbsolute, } +impl ::selectors::parser::PseudoElement for PseudoElement { + type Impl = SelectorImpl; + + fn supports_pseudo_class(&self, _: &NonTSPseudoClass) -> bool { + false + } +} + impl ToCss for PseudoElement { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { use self::PseudoElement::*; @@ -78,18 +87,6 @@ impl ToCss for PseudoElement { pub const EAGER_PSEUDO_COUNT: usize = 3; impl PseudoElement { - /// The pseudo-element, used for compatibility with Gecko's - /// `PseudoElementSelector`. - pub fn pseudo_element(&self) -> &Self { - self - } - - /// The pseudo-element selector's state, used for compatibility with Gecko's - /// `PseudoElementSelector`. - pub fn state(&self) -> ElementState { - ElementState::empty() - } - /// Gets the canonical index of this eagerly-cascaded pseudo-element. #[inline] pub fn eager_index(&self) -> usize { @@ -178,6 +175,7 @@ pub enum NonTSPseudoClass { ReadWrite, ReadOnly, ServoNonZeroBorder, + ServoCaseSensitiveTypeAttr(Atom), Target, Visited, } @@ -185,10 +183,18 @@ pub enum NonTSPseudoClass { impl ToCss for NonTSPseudoClass { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { use self::NonTSPseudoClass::*; - if let Lang(ref lang) = *self { - dest.write_str(":lang(")?; - serialize_identifier(lang, dest)?; - return dest.write_str(")"); + match *self { + Lang(ref lang) => { + dest.write_str(":lang(")?; + serialize_identifier(lang, dest)?; + return dest.write_str(")") + } + ServoCaseSensitiveTypeAttr(ref value) => { + dest.write_str(":-servo-case-sensitive-type-attr(")?; + serialize_identifier(value, dest)?; + return dest.write_str(")") + } + _ => {} } dest.write_str(match *self { @@ -201,7 +207,6 @@ impl ToCss for NonTSPseudoClass { Fullscreen => ":fullscreen", Hover => ":hover", Indeterminate => ":indeterminate", - Lang(_) => unreachable!(), Link => ":link", PlaceholderShown => ":placeholder-shown", ReadWrite => ":read-write", @@ -209,6 +214,8 @@ impl ToCss for NonTSPseudoClass { ServoNonZeroBorder => ":-servo-nonzero-border", Target => ":target", Visited => ":visited", + Lang(_) | + ServoCaseSensitiveTypeAttr(_) => unreachable!(), }) } } @@ -247,7 +254,8 @@ impl NonTSPseudoClass { Lang(_) | Link | Visited | - ServoNonZeroBorder => ElementState::empty(), + ServoNonZeroBorder | + ServoCaseSensitiveTypeAttr(_) => ElementState::empty(), } } @@ -264,7 +272,7 @@ impl NonTSPseudoClass { pub struct SelectorImpl; impl ::selectors::SelectorImpl for SelectorImpl { - type PseudoElementSelector = PseudoElement; + type PseudoElement = PseudoElement; type NonTSPseudoClass = NonTSPseudoClass; type AttrValue = String; @@ -316,16 +324,22 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> { -> Result<NonTSPseudoClass, ()> { use self::NonTSPseudoClass::*; let pseudo_class = match_ignore_ascii_case!{ &name, - "lang" => Lang(String::from(try!(parser.expect_ident_or_string())).into_boxed_str()), + "lang" => { + Lang(parser.expect_ident_or_string()?.into_owned().into_boxed_str()) + } + "-servo-case-sensitive-type-attr" => { + if !self.in_user_agent_stylesheet() { + return Err(()); + } + ServoCaseSensitiveTypeAttr(Atom::from(parser.expect_ident()?)) + } _ => return Err(()) }; Ok(pseudo_class) } - fn parse_pseudo_element(&self, - name: Cow<str>, - _input: &mut CssParser) + fn parse_pseudo_element(&self, name: Cow<str>) -> Result<PseudoElement, ()> { use self::PseudoElement::*; let pseudo_element = match_ignore_ascii_case! { &name, @@ -525,10 +539,10 @@ impl ServoElementSnapshot { .map(|&(_, ref v)| v) } - fn get_attr_ignore_ns(&self, name: &LocalName) -> Option<&AttrValue> { + fn any_attr_ignore_ns<F>(&self, name: &LocalName, mut f: F) -> bool + where F: FnMut(&AttrValue) -> bool { self.attrs.as_ref().unwrap().iter() - .find(|&&(ref ident, _)| ident.local_name == *name) - .map(|&(_, ref v)| v) + .any(|&(ref ident, ref v)| ident.local_name == *name && f(v)) } } @@ -561,26 +575,30 @@ impl ElementSnapshot for ServoElementSnapshot { } } -impl MatchAttrGeneric for ServoElementSnapshot { - type Impl = SelectorImpl; - - fn match_attr<F>(&self, attr: &AttrSelector<SelectorImpl>, test: F) -> bool - where F: Fn(&str) -> bool - { - use selectors::parser::NamespaceConstraint; - let html = self.is_html_element_in_html_document; - let local_name = if html { &attr.lower_name } else { &attr.name }; - match attr.namespace { - NamespaceConstraint::Specific(ref ns) => self.get_attr(&ns.url, local_name), - NamespaceConstraint::Any => self.get_attr_ignore_ns(local_name), - }.map_or(false, |v| test(v)) +impl ServoElementSnapshot { + /// selectors::Element::attr_matches + pub fn attr_matches(&self, + ns: &NamespaceConstraint<&Namespace>, + local_name: &LocalName, + operation: &AttrSelectorOperation<&String>) + -> bool { + match *ns { + NamespaceConstraint::Specific(ref ns) => { + self.get_attr(ns, local_name) + .map_or(false, |value| value.eval_selector(operation)) + } + NamespaceConstraint::Any => { + self.any_attr_ignore_ns(local_name, |value| value.eval_selector(operation)) + } + } } } impl<E: Element<Impl=SelectorImpl> + Debug> ElementExt for E { fn is_link(&self) -> bool { + let mut context = MatchingContext::new(MatchingMode::Normal, None); self.match_non_ts_pseudo_class(&NonTSPseudoClass::AnyLink, - &mut StyleRelations::empty(), + &mut context, &mut |_, _| {}) } |