aboutsummaryrefslogtreecommitdiffstats
path: root/components/style/servo/selector_parser.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/style/servo/selector_parser.rs')
-rw-r--r--components/style/servo/selector_parser.rs104
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 |_, _| {})
}