diff options
Diffstat (limited to 'components/style/servo_selector_impl.rs')
-rw-r--r-- | components/style/servo_selector_impl.rs | 84 |
1 files changed, 82 insertions, 2 deletions
diff --git a/components/style/servo_selector_impl.rs b/components/style/servo_selector_impl.rs index d1fdaf0336c..cee046e62f3 100644 --- a/components/style/servo_selector_impl.rs +++ b/components/style/servo_selector_impl.rs @@ -2,13 +2,16 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use attr::{AttrIdentifier, AttrValue}; use element_state::ElementState; use error_reporting::StdoutErrorReporter; use parser::ParserContextExtraData; +use restyle_hints::ElementSnapshot; use selector_impl::{SelectorImplExt, ElementExt, PseudoElementCascadeType, TheSelectorImpl}; -use selectors::Element; -use selectors::parser::{ParserContext, SelectorImpl}; +use selectors::parser::{AttrSelector, ParserContext, SelectorImpl}; +use selectors::{Element, MatchAttrGeneric}; use std::process; +use string_cache::{Atom, Namespace}; use stylesheets::{Stylesheet, Origin}; use url::Url; use util::opts; @@ -189,7 +192,84 @@ impl SelectorImplExt for ServoSelectorImpl { } } +/// Servo's version of an element snapshot. +#[derive(Debug)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +pub struct ServoElementSnapshot { + pub state: Option<ElementState>, + pub attrs: Option<Vec<(AttrIdentifier, AttrValue)>>, + pub is_html_element_in_html_document: bool, +} + +impl ServoElementSnapshot { + pub fn new(is_html_element_in_html_document: bool) -> Self { + ServoElementSnapshot { + state: None, + attrs: None, + is_html_element_in_html_document: is_html_element_in_html_document, + } + } + + fn get_attr(&self, namespace: &Namespace, name: &Atom) -> Option<&AttrValue> { + self.attrs.as_ref().unwrap().iter() + .find(|&&(ref ident, _)| ident.local_name == *name && + ident.namespace == *namespace) + .map(|&(_, ref v)| v) + } + + fn get_attr_ignore_ns(&self, name: &Atom) -> Option<&AttrValue> { + self.attrs.as_ref().unwrap().iter() + .find(|&&(ref ident, _)| ident.local_name == *name) + .map(|&(_, ref v)| v) + } +} + +impl ElementSnapshot for ServoElementSnapshot { + fn state(&self) -> Option<ElementState> { + self.state.clone() + } + + fn has_attrs(&self) -> bool { + self.attrs.is_some() + } + + fn id_attr(&self) -> Option<Atom> { + self.get_attr(&ns!(), &atom!("id")).map(|v| v.as_atom().clone()) + } + + fn has_class(&self, name: &Atom) -> bool { + self.get_attr(&ns!(), &atom!("class")) + .map_or(false, |v| v.as_tokens().iter().any(|atom| atom == name)) + } + + fn each_class<F>(&self, mut callback: F) + where F: FnMut(&Atom) + { + if let Some(v) = self.get_attr(&ns!(), &atom!("class")) { + for class in v.as_tokens() { + callback(class); + } + } + } +} + +impl MatchAttrGeneric for ServoElementSnapshot { + fn match_attr<F>(&self, attr: &AttrSelector, 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, local_name), + NamespaceConstraint::Any => self.get_attr_ignore_ns(local_name), + }.map_or(false, |v| test(v)) + } +} + impl<E: Element<Impl=TheSelectorImpl, AttrString=String>> ElementExt for E { + type Snapshot = ServoElementSnapshot; + fn is_link(&self) -> bool { self.match_non_ts_pseudo_class(NonTSPseudoClass::AnyLink) } |