aboutsummaryrefslogtreecommitdiffstats
path: root/components/style/servo_selector_impl.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/style/servo_selector_impl.rs')
-rw-r--r--components/style/servo_selector_impl.rs84
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)
}