mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
auto merge of #3623 : pcwalton/servo/use-atoms-2, r=jdm
75% improvement in style recalc for Guardians of the Galaxy.
This commit is contained in:
commit
8077edc062
31 changed files with 305 additions and 237 deletions
|
@ -35,3 +35,4 @@ git = "https://github.com/servo/string-cache"
|
|||
|
||||
[dependencies.string_cache_macros]
|
||||
git = "https://github.com/servo/string-cache"
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#![feature(phase)]
|
||||
#[phase(plugin, link)] extern crate log;
|
||||
#[phase(plugin)] extern crate string_cache_macros;
|
||||
|
||||
extern crate debug;
|
||||
extern crate collections;
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
use selectors::AttrSelector;
|
||||
use string_cache::{Atom, Namespace};
|
||||
|
||||
|
||||
pub trait TNode<'a, E: TElement<'a>> : Clone + Copy {
|
||||
fn parent_node(self) -> Option<Self>;
|
||||
fn first_child(self) -> Option<Self>;
|
||||
|
@ -28,8 +27,8 @@ pub trait TNode<'a, E: TElement<'a>> : Clone + Copy {
|
|||
}
|
||||
|
||||
pub trait TElement<'a> : Copy {
|
||||
fn get_attr(self, namespace: &Namespace, attr: &str) -> Option<&'a str>;
|
||||
fn get_attrs(self, attr: &str) -> Vec<&'a str>;
|
||||
fn get_attr(self, namespace: &Namespace, attr: &Atom) -> Option<&'a str>;
|
||||
fn get_attrs(self, attr: &Atom) -> Vec<&'a str>;
|
||||
fn get_link(self) -> Option<&'a str>;
|
||||
fn get_local_name(self) -> &'a Atom;
|
||||
fn get_namespace(self) -> &'a Namespace;
|
||||
|
@ -37,6 +36,13 @@ pub trait TElement<'a> : Copy {
|
|||
fn get_id(self) -> Option<Atom>;
|
||||
fn get_disabled_state(self) -> bool;
|
||||
fn get_enabled_state(self) -> bool;
|
||||
fn has_class(self, name: &str) -> bool;
|
||||
fn has_class(self, name: &Atom) -> bool;
|
||||
|
||||
// Ordinarily I wouldn't use callbacks like this, but the alternative is
|
||||
// really messy, since there is a `JSRef` and a `RefCell` involved. Maybe
|
||||
// in the future when we have associated types and/or a more convenient
|
||||
// JS GC story... --pcwalton
|
||||
fn each_class(self, callback: |&Atom|);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -108,20 +108,14 @@ impl SelectorMap {
|
|||
None => {}
|
||||
}
|
||||
|
||||
match element.get_attr(&ns!(""), "class") {
|
||||
Some(ref class_attr) => {
|
||||
// FIXME: Store classes pre-split as atoms to make the loop below faster.
|
||||
for class in class_attr.split(SELECTOR_WHITESPACE) {
|
||||
SelectorMap::get_matching_rules_from_hash(node,
|
||||
parent_bf,
|
||||
&self.class_hash,
|
||||
&Atom::from_slice(class),
|
||||
matching_rules_list,
|
||||
shareable);
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
element.each_class(|class| {
|
||||
SelectorMap::get_matching_rules_from_hash(node,
|
||||
parent_bf,
|
||||
&self.class_hash,
|
||||
class,
|
||||
matching_rules_list,
|
||||
shareable);
|
||||
});
|
||||
|
||||
let local_name_hash = if node.is_html_element_in_html_document() {
|
||||
&self.lower_local_name_hash
|
||||
|
@ -699,12 +693,12 @@ fn matches_compound_selector_internal<'a,
|
|||
/// will almost certainly break as nodes will start mistakenly sharing styles. (See the code in
|
||||
/// `main/css/matching.rs`.)
|
||||
#[inline]
|
||||
pub fn matches_simple_selector<'a, E:TElement<'a>,
|
||||
N:TNode<'a, E>>(
|
||||
selector: &SimpleSelector,
|
||||
element: &N,
|
||||
shareable: &mut bool)
|
||||
-> bool {
|
||||
pub fn matches_simple_selector<'a,E,N>(
|
||||
selector: &SimpleSelector,
|
||||
element: &N,
|
||||
shareable: &mut bool)
|
||||
-> bool
|
||||
where E:TElement<'a>, N:TNode<'a,E> {
|
||||
match *selector {
|
||||
LocalNameSelector(LocalName { ref name, ref lower_name }) => {
|
||||
let name = if element.is_html_element_in_html_document() { lower_name } else { name };
|
||||
|
@ -718,7 +712,6 @@ pub fn matches_simple_selector<'a, E:TElement<'a>,
|
|||
element.get_namespace() == namespace
|
||||
}
|
||||
// TODO: case-sensitivity depends on the document type and quirks mode
|
||||
// TODO: cache and intern IDs on elements.
|
||||
IDSelector(ref id) => {
|
||||
*shareable = false;
|
||||
let element = element.as_element();
|
||||
|
@ -726,10 +719,9 @@ pub fn matches_simple_selector<'a, E:TElement<'a>,
|
|||
attr == *id
|
||||
})
|
||||
}
|
||||
// TODO: cache and intern class names on elements.
|
||||
ClassSelector(ref class) => {
|
||||
let element = element.as_element();
|
||||
element.has_class(class.as_slice())
|
||||
element.has_class(class)
|
||||
}
|
||||
|
||||
AttrExists(ref attr) => {
|
||||
|
@ -876,6 +868,7 @@ pub fn matches_simple_selector<'a, E:TElement<'a>,
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn url_is_visited(_url: &str) -> bool {
|
||||
// FIXME: implement this.
|
||||
// This function will probably need to take a "session"
|
||||
|
@ -884,15 +877,14 @@ fn url_is_visited(_url: &str) -> bool {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn matches_generic_nth_child<'a,
|
||||
E:TElement<'a>,
|
||||
N:TNode<'a, E>>(
|
||||
fn matches_generic_nth_child<'a,E,N>(
|
||||
element: &N,
|
||||
a: i32,
|
||||
b: i32,
|
||||
is_of_type: bool,
|
||||
is_from_end: bool)
|
||||
-> bool {
|
||||
-> bool
|
||||
where E: TElement<'a>, N: TNode<'a,E> {
|
||||
let mut node = element.clone();
|
||||
// fail if we can't find a parent or if the node is the root element
|
||||
// of the document (Cf. Selectors Level 3)
|
||||
|
|
|
@ -106,8 +106,8 @@ pub struct LocalName {
|
|||
|
||||
#[deriving(Eq, PartialEq, Clone, Hash)]
|
||||
pub struct AttrSelector {
|
||||
pub name: String,
|
||||
pub lower_name: String,
|
||||
pub name: Atom,
|
||||
pub lower_name: Atom,
|
||||
pub namespace: NamespaceConstraint,
|
||||
}
|
||||
|
||||
|
@ -448,8 +448,8 @@ fn parse_attribute_selector(content: Vec<ComponentValue>, namespaces: &Namespace
|
|||
Some((_, None)) => fail!("Implementation error, this should not happen."),
|
||||
Some((namespace, Some(local_name))) => AttrSelector {
|
||||
namespace: namespace,
|
||||
lower_name: local_name.as_slice().to_ascii_lower(),
|
||||
name: local_name,
|
||||
lower_name: Atom::from_slice(local_name.as_slice().to_ascii_lower().as_slice()),
|
||||
name: Atom::from_slice(local_name.as_slice()),
|
||||
},
|
||||
};
|
||||
skip_whitespace(iter);
|
||||
|
@ -675,8 +675,8 @@ mod tests {
|
|||
assert!(parse_ns("[Foo]", &namespaces) == Ok(vec!(Selector {
|
||||
compound_selectors: Arc::new(CompoundSelector {
|
||||
simple_selectors: vec!(AttrExists(AttrSelector {
|
||||
name: String::from_str("Foo"),
|
||||
lower_name: String::from_str("foo"),
|
||||
name: Atom::from_slice("Foo"),
|
||||
lower_name: Atom::from_slice("foo"),
|
||||
namespace: SpecificNamespace(ns!("")),
|
||||
})),
|
||||
next: None,
|
||||
|
@ -690,8 +690,8 @@ mod tests {
|
|||
assert!(parse_ns("[Foo]", &namespaces) == Ok(vec!(Selector {
|
||||
compound_selectors: Arc::new(CompoundSelector {
|
||||
simple_selectors: vec!(AttrExists(AttrSelector {
|
||||
name: String::from_str("Foo"),
|
||||
lower_name: String::from_str("foo"),
|
||||
name: Atom::from_slice("Foo"),
|
||||
lower_name: Atom::from_slice("foo"),
|
||||
namespace: SpecificNamespace(ns!("")),
|
||||
})),
|
||||
next: None,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue