aboutsummaryrefslogtreecommitdiffstats
path: root/components/style/servo_selector_impl.rs
diff options
context:
space:
mode:
authorEmilio Cobos Álvarez <ecoal95@gmail.com>2016-07-15 16:31:20 -0700
committerEmilio Cobos Álvarez <ecoal95@gmail.com>2016-07-21 14:24:04 -0700
commit611e611215a2826677b2fa255a166ce65fc221e4 (patch)
tree016db21394f13a21e453bd84f73ab0f2b63fcf30 /components/style/servo_selector_impl.rs
parentca9bc23b391b92d1a6e16f565b531a7fac68852c (diff)
downloadservo-611e611215a2826677b2fa255a166ce65fc221e4.tar.gz
servo-611e611215a2826677b2fa255a166ce65fc221e4.zip
style: Rewrite the restyle hints code to allow different kinds of element snapshots, and use it for Gecko.
This is a rewrite for how style interfaces with its consumers in order to allow different representations for an element snapshot. This also changes the requirements of an element snapshot, requiring them to only implement MatchAttr, instead of MatchAttrGeneric. This is important for stylo since implementing MatchAttrGeneric is way more difficult for us given the atom limitations. This also allows for more performant implementations in the Gecko side of things.
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)
}