auto merge of #4363 : Ms2ger/servo/collectionfilter, r=Manishearth

This commit is contained in:
bors-servo 2014-12-13 10:15:45 -07:00
commit 29c9975a83
2 changed files with 28 additions and 42 deletions

View file

@ -10,12 +10,13 @@ use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::trace::JSTraceable; use dom::bindings::trace::JSTraceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::element::{Element, AttributeHandlers, ElementHelpers}; use dom::element::{Element, AttributeHandlers, ElementHelpers};
use dom::node::{Node, NodeHelpers}; use dom::node::{Node, NodeHelpers, TreeIterator};
use dom::window::Window; use dom::window::Window;
use servo_util::namespace; 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, Skip};
use string_cache::{Atom, Namespace}; use string_cache::{Atom, Namespace};
pub trait CollectionFilter : JSTraceable { pub trait CollectionFilter : JSTraceable {
@ -62,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
@ -88,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 {
@ -122,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
@ -149,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 {
@ -171,6 +163,15 @@ impl HTMLCollection {
} }
HTMLCollection::create(window, root, box ElementChildFilter) HTMLCollection::create(window, root, box ElementChildFilter)
} }
fn traverse<'a>(root: JSRef<'a, Node>)
-> FilterMap<'a, JSRef<'a, Node>,
JSRef<'a, Element>,
Skip<TreeIterator<'a>>> {
root.traverse_preorder()
.skip(1)
.filter_map(ElementCast::to_ref)
}
} }
impl<'a> HTMLCollectionMethods for JSRef<'a, HTMLCollection> { impl<'a> HTMLCollectionMethods for JSRef<'a, HTMLCollection> {
@ -180,11 +181,9 @@ impl<'a> HTMLCollectionMethods for JSRef<'a, HTMLCollection> {
Static(ref elems) => elems.len() as u32, Static(ref elems) => elems.len() as u32,
Live(ref root, ref filter) => { Live(ref root, ref filter) => {
let root = root.root(); let root = root.root();
root.traverse_preorder() HTMLCollection::traverse(*root)
.filter(|&child| { .filter(|element| filter.filter(*element, *root))
let elem: Option<JSRef<Element>> = ElementCast::to_ref(child); .count() as u32
elem.map_or(false, |elem| filter.filter(elem, *root))
}).count() as u32
} }
} }
} }
@ -198,17 +197,11 @@ impl<'a> HTMLCollectionMethods for JSRef<'a, HTMLCollection> {
.map(|elem| Temporary::new(elem.clone())), .map(|elem| Temporary::new(elem.clone())),
Live(ref root, ref filter) => { Live(ref root, ref filter) => {
let root = root.root(); let root = root.root();
root.traverse_preorder() HTMLCollection::traverse(*root)
.filter_map(|node| { .filter(|element| filter.filter(*element, *root))
let elem: Option<JSRef<Element>> = ElementCast::to_ref(node);
match elem {
Some(ref elem) if filter.filter(*elem, *root) => Some(elem.clone()),
_ => None
}
})
.nth(index as uint) .nth(index as uint)
.clone() .clone()
.map(|elem| Temporary::from_rooted(elem)) .map(Temporary::from_rooted)
} }
} }
} }
@ -230,18 +223,12 @@ impl<'a> HTMLCollectionMethods for JSRef<'a, HTMLCollection> {
.map(|maybe_elem| Temporary::from_rooted(*maybe_elem)), .map(|maybe_elem| Temporary::from_rooted(*maybe_elem)),
Live(ref root, ref filter) => { Live(ref root, ref filter) => {
let root = root.root(); let root = root.root();
root.traverse_preorder() HTMLCollection::traverse(*root)
.filter_map(|node| { .filter(|element| filter.filter(*element, *root))
let elem: Option<JSRef<Element>> = ElementCast::to_ref(node);
match elem {
Some(ref elem) if filter.filter(*elem, *root) => Some(elem.clone()),
_ => None
}
})
.find(|elem| { .find(|elem| {
elem.get_string_attribute(&atom!("name")) == key || elem.get_string_attribute(&atom!("name")) == key ||
elem.get_string_attribute(&atom!("id")) == key }) elem.get_string_attribute(&atom!("id")) == key })
.map(|maybe_elem| Temporary::from_rooted(maybe_elem)) .map(Temporary::from_rooted)
} }
} }
} }

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);