Cleanup Element iteration in dom/htmlcollection.rs

This commit is contained in:
Corey Farwell 2015-08-20 16:43:45 -04:00
parent c84b25cc99
commit 03f257697d

View file

@ -15,7 +15,6 @@ use dom::window::Window;
use util::str::{DOMString, split_html_space_chars}; use 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 {
@ -162,36 +161,47 @@ impl HTMLCollection {
HTMLCollection::create(window, root, box ElementChildFilter) HTMLCollection::create(window, root, box ElementChildFilter)
} }
fn traverse(root: &Node) fn elements_iter(&self) -> HTMLCollectionElementsIter {
-> FilterMap<Skip<TreeIterator>, let ref filter = self.collection.1;
fn(Root<Node>) -> Option<Root<Element>>> { let root = self.collection.0.root();
fn to_temporary(node: Root<Node>) -> Option<Root<Element>> { let mut node_iter = root.traverse_preorder();
ElementCast::to_root(node) let _ = node_iter.next(); // skip the root node
HTMLCollectionElementsIter {
node_iter: node_iter,
root: root,
filter: filter,
} }
root.traverse_preorder() }
.skip(1) }
.filter_map(to_temporary)
struct HTMLCollectionElementsIter<'a> {
node_iter: TreeIterator,
root: Root<Node>,
filter: &'a Box<CollectionFilter>,
}
impl<'a> Iterator for HTMLCollectionElementsIter<'a> {
type Item = Root<Element>;
fn next(&mut self) -> Option<Self::Item> {
let filter = self.filter;
let root = self.root.r();
self.node_iter.by_ref()
.filter_map(ElementCast::to_root)
.filter(|element| filter.filter(element.r(), root))
.next()
} }
} }
impl<'a> HTMLCollectionMethods for &'a HTMLCollection { impl<'a> HTMLCollectionMethods for &'a HTMLCollection {
// https://dom.spec.whatwg.org/#dom-htmlcollection-length // https://dom.spec.whatwg.org/#dom-htmlcollection-length
fn Length(self) -> u32 { fn Length(self) -> u32 {
let ref root = self.collection.0.root(); self.elements_iter().count() as u32
let ref filter = self.collection.1;
HTMLCollection::traverse(root.r())
.filter(|element| filter.filter(element.r(), root.r()))
.count() as u32
} }
// https://dom.spec.whatwg.org/#dom-htmlcollection-item // https://dom.spec.whatwg.org/#dom-htmlcollection-item
fn Item(self, index: u32) -> Option<Root<Element>> { fn Item(self, index: u32) -> Option<Root<Element>> {
let index = index as usize; self.elements_iter().nth(index as usize)
let ref root = self.collection.0.root();
let ref filter = self.collection.1;
HTMLCollection::traverse(root.r())
.filter(|element| filter.filter(element.r(), root.r()))
.nth(index)
} }
// https://dom.spec.whatwg.org/#dom-htmlcollection-nameditem // https://dom.spec.whatwg.org/#dom-htmlcollection-nameditem
@ -202,13 +212,10 @@ impl<'a> HTMLCollectionMethods for &'a HTMLCollection {
} }
// Step 2. // Step 2.
let ref root = self.collection.0.root(); self.elements_iter().find(|elem| {
let ref filter = self.collection.1; elem.r().get_string_attribute(&atom!("name")) == key ||
HTMLCollection::traverse(root.r()) elem.r().get_string_attribute(&atom!("id")) == key
.filter(|element| filter.filter(element.r(), root.r())) })
.find(|elem| {
elem.r().get_string_attribute(&atom!("name")) == key ||
elem.r().get_string_attribute(&atom!("id")) == key})
} }
// https://dom.spec.whatwg.org/#dom-htmlcollection-item // https://dom.spec.whatwg.org/#dom-htmlcollection-item
@ -231,10 +238,7 @@ impl<'a> HTMLCollectionMethods for &'a HTMLCollection {
let mut result = vec![]; let mut result = vec![];
// Step 2 // Step 2
let root = self.collection.0.root(); for elem in self.elements_iter() {
let ref filter = self.collection.1;
let elems = HTMLCollection::traverse(root.r()).filter(|element| filter.filter(element.r(), root.r()));
for elem in elems {
// Step 2.1 // Step 2.1
let id_attr = elem.get_string_attribute(&atom!("id")); let id_attr = elem.get_string_attribute(&atom!("id"));
if !id_attr.is_empty() && !result.contains(&id_attr) { if !id_attr.is_empty() && !result.contains(&id_attr) {