Skip the root node in live HTMLCollections.

The root node is never included in the collection, and omitting it here
simplifies and speeds up the filter implementations.
This commit is contained in:
Ms2ger 2014-12-13 10:38:17 +01:00
parent 4a2c4b65cc
commit 14e1455119
2 changed files with 11 additions and 20 deletions

View file

@ -16,7 +16,7 @@ use servo_util::namespace;
use servo_util::str::{DOMString, split_html_space_chars}; use servo_util::str::{DOMString, split_html_space_chars};
use std::ascii::AsciiExt; use std::ascii::AsciiExt;
use std::iter::FilterMap; use std::iter::{FilterMap, Skip};
use string_cache::{Atom, Namespace}; use string_cache::{Atom, Namespace};
pub trait CollectionFilter : JSTraceable { pub trait CollectionFilter : JSTraceable {
@ -63,10 +63,7 @@ impl HTMLCollection {
namespace_filter: Option<Namespace> namespace_filter: Option<Namespace>
} }
impl CollectionFilter for AllElementFilter { impl CollectionFilter for AllElementFilter {
fn filter(&self, elem: JSRef<Element>, root: JSRef<Node>) -> bool { fn filter(&self, elem: JSRef<Element>, _root: JSRef<Node>) -> bool {
if NodeCast::from_ref(elem) == root {
return false
}
match self.namespace_filter { match self.namespace_filter {
None => true, None => true,
Some(ref namespace) => *elem.namespace() == *namespace Some(ref namespace) => *elem.namespace() == *namespace
@ -89,10 +86,7 @@ impl HTMLCollection {
ascii_lower_tag: Atom, ascii_lower_tag: Atom,
} }
impl CollectionFilter for TagNameFilter { impl CollectionFilter for TagNameFilter {
fn filter(&self, elem: JSRef<Element>, root: JSRef<Node>) -> bool { fn filter(&self, elem: JSRef<Element>, _root: JSRef<Node>) -> bool {
if NodeCast::from_ref(elem) == root {
return false
}
if elem.html_element_in_html_document() { if elem.html_element_in_html_document() {
*elem.local_name() == self.ascii_lower_tag *elem.local_name() == self.ascii_lower_tag
} else { } else {
@ -123,10 +117,7 @@ impl HTMLCollection {
namespace_filter: Option<Namespace> namespace_filter: Option<Namespace>
} }
impl CollectionFilter for TagNameNSFilter { impl CollectionFilter for TagNameNSFilter {
fn filter(&self, elem: JSRef<Element>, root: JSRef<Node>) -> bool { fn filter(&self, elem: JSRef<Element>, _root: JSRef<Node>) -> bool {
if NodeCast::from_ref(elem) == root {
return false
}
let ns_match = match self.namespace_filter { let ns_match = match self.namespace_filter {
Some(ref namespace) => { Some(ref namespace) => {
*elem.namespace() == *namespace *elem.namespace() == *namespace
@ -150,8 +141,8 @@ impl HTMLCollection {
classes: Vec<Atom> classes: Vec<Atom>
} }
impl CollectionFilter for ClassNameFilter { impl CollectionFilter for ClassNameFilter {
fn filter(&self, elem: JSRef<Element>, root: JSRef<Node>) -> bool { fn filter(&self, elem: JSRef<Element>, _root: JSRef<Node>) -> bool {
(NodeCast::from_ref(elem) != root) && self.classes.iter().all(|class| elem.has_class(class)) self.classes.iter().all(|class| elem.has_class(class))
} }
} }
let filter = ClassNameFilter { let filter = ClassNameFilter {
@ -176,8 +167,9 @@ impl HTMLCollection {
fn traverse<'a>(root: JSRef<'a, Node>) fn traverse<'a>(root: JSRef<'a, Node>)
-> FilterMap<'a, JSRef<'a, Node>, -> FilterMap<'a, JSRef<'a, Node>,
JSRef<'a, Element>, JSRef<'a, Element>,
TreeIterator<'a>> { Skip<TreeIterator<'a>>> {
root.traverse_preorder() root.traverse_preorder()
.skip(1)
.filter_map(ElementCast::to_ref) .filter_map(ElementCast::to_ref)
} }
} }

View file

@ -6,7 +6,7 @@ use dom::attr::Attr;
use dom::attr::AttrHelpers; use dom::attr::AttrHelpers;
use dom::bindings::codegen::Bindings::HTMLFieldSetElementBinding; use dom::bindings::codegen::Bindings::HTMLFieldSetElementBinding;
use dom::bindings::codegen::Bindings::HTMLFieldSetElementBinding::HTMLFieldSetElementMethods; use dom::bindings::codegen::Bindings::HTMLFieldSetElementBinding::HTMLFieldSetElementMethods;
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLFieldSetElementDerived, NodeCast}; use dom::bindings::codegen::InheritTypes::{HTMLFieldSetElementDerived, NodeCast};
use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLLegendElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLLegendElementDerived};
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::utils::{Reflectable, Reflector}; use dom::bindings::utils::{Reflectable, Reflector};
@ -54,11 +54,10 @@ impl<'a> HTMLFieldSetElementMethods for JSRef<'a, HTMLFieldSetElement> {
#[jstraceable] #[jstraceable]
struct ElementsFilter; struct ElementsFilter;
impl CollectionFilter for ElementsFilter { impl CollectionFilter for ElementsFilter {
fn filter<'a>(&self, elem: JSRef<'a, Element>, root: JSRef<'a, Node>) -> bool { fn filter<'a>(&self, elem: JSRef<'a, Element>, _root: JSRef<'a, Node>) -> bool {
static TAG_NAMES: StaticStringVec = &["button", "fieldset", "input", static TAG_NAMES: StaticStringVec = &["button", "fieldset", "input",
"keygen", "object", "output", "select", "textarea"]; "keygen", "object", "output", "select", "textarea"];
let root: JSRef<Element> = ElementCast::to_ref(root).unwrap(); TAG_NAMES.iter().any(|&tag_name| tag_name == elem.local_name().as_slice())
elem != root && TAG_NAMES.iter().any(|&tag_name| tag_name == elem.local_name().as_slice())
} }
} }
let node: JSRef<Node> = NodeCast::from_ref(self); let node: JSRef<Node> = NodeCast::from_ref(self);