aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/treewalker.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/treewalker.rs')
-rw-r--r--components/script/dom/treewalker.rs286
1 files changed, 148 insertions, 138 deletions
diff --git a/components/script/dom/treewalker.rs b/components/script/dom/treewalker.rs
index 2409d65af4f..86aa97466a7 100644
--- a/components/script/dom/treewalker.rs
+++ b/components/script/dom/treewalker.rs
@@ -1,62 +1,66 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
-use dom::bindings::callback::ExceptionHandling::Rethrow;
-use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
-use dom::bindings::codegen::Bindings::NodeFilterBinding::NodeFilter;
-use dom::bindings::codegen::Bindings::NodeFilterBinding::NodeFilterConstants;
-use dom::bindings::codegen::Bindings::TreeWalkerBinding;
-use dom::bindings::codegen::Bindings::TreeWalkerBinding::TreeWalkerMethods;
-use dom::bindings::error::Fallible;
-use dom::bindings::js::{JS, MutJS};
-use dom::bindings::js::Root;
-use dom::bindings::reflector::{Reflector, reflect_dom_object};
-use dom::document::Document;
-use dom::node::Node;
+use crate::dom::bindings::callback::ExceptionHandling::Rethrow;
+use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
+use crate::dom::bindings::codegen::Bindings::NodeFilterBinding::NodeFilter;
+use crate::dom::bindings::codegen::Bindings::NodeFilterBinding::NodeFilterConstants;
+use crate::dom::bindings::codegen::Bindings::TreeWalkerBinding::TreeWalkerMethods;
+use crate::dom::bindings::error::{Error, Fallible};
+use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
+use crate::dom::bindings::root::{Dom, DomRoot, MutDom};
+use crate::dom::document::Document;
+use crate::dom::node::Node;
use dom_struct::dom_struct;
+use std::cell::Cell;
use std::rc::Rc;
// https://dom.spec.whatwg.org/#interface-treewalker
#[dom_struct]
pub struct TreeWalker {
reflector_: Reflector,
- root_node: JS<Node>,
- current_node: MutJS<Node>,
+ root_node: Dom<Node>,
+ current_node: MutDom<Node>,
what_to_show: u32,
- #[ignore_heap_size_of = "function pointers and Rc<T> are hard"]
- filter: Filter
+ #[ignore_malloc_size_of = "function pointers and Rc<T> are hard"]
+ filter: Filter,
+ active: Cell<bool>,
}
impl TreeWalker {
- fn new_inherited(root_node: &Node,
- what_to_show: u32,
- filter: Filter) -> TreeWalker {
+ fn new_inherited(root_node: &Node, what_to_show: u32, filter: Filter) -> TreeWalker {
TreeWalker {
reflector_: Reflector::new(),
- root_node: JS::from_ref(root_node),
- current_node: MutJS::new(root_node),
+ root_node: Dom::from_ref(root_node),
+ current_node: MutDom::new(root_node),
what_to_show: what_to_show,
- filter: filter
+ filter: filter,
+ active: Cell::new(false),
}
}
- pub fn new_with_filter(document: &Document,
- root_node: &Node,
- what_to_show: u32,
- filter: Filter) -> Root<TreeWalker> {
- reflect_dom_object(box TreeWalker::new_inherited(root_node, what_to_show, filter),
- document.window(),
- TreeWalkerBinding::Wrap)
+ pub fn new_with_filter(
+ document: &Document,
+ root_node: &Node,
+ what_to_show: u32,
+ filter: Filter,
+ ) -> DomRoot<TreeWalker> {
+ reflect_dom_object(
+ Box::new(TreeWalker::new_inherited(root_node, what_to_show, filter)),
+ document.window(),
+ )
}
- pub fn new(document: &Document,
- root_node: &Node,
- what_to_show: u32,
- node_filter: Option<Rc<NodeFilter>>) -> Root<TreeWalker> {
+ pub fn new(
+ document: &Document,
+ root_node: &Node,
+ what_to_show: u32,
+ node_filter: Option<Rc<NodeFilter>>,
+ ) -> DomRoot<TreeWalker> {
let filter = match node_filter {
None => Filter::None,
- Some(jsfilter) => Filter::JS(jsfilter)
+ Some(jsfilter) => Filter::Dom(jsfilter),
};
TreeWalker::new_with_filter(document, root_node, what_to_show, filter)
}
@@ -64,8 +68,8 @@ impl TreeWalker {
impl TreeWalkerMethods for TreeWalker {
// https://dom.spec.whatwg.org/#dom-treewalker-root
- fn Root(&self) -> Root<Node> {
- Root::from_ref(&*self.root_node)
+ fn Root(&self) -> DomRoot<Node> {
+ DomRoot::from_ref(&*self.root_node)
}
// https://dom.spec.whatwg.org/#dom-treewalker-whattoshow
@@ -77,13 +81,12 @@ impl TreeWalkerMethods for TreeWalker {
fn GetFilter(&self) -> Option<Rc<NodeFilter>> {
match self.filter {
Filter::None => None,
- Filter::JS(ref nf) => Some(nf.clone()),
- Filter::Native(_) => panic!("Cannot convert native node filter to DOM NodeFilter")
+ Filter::Dom(ref nf) => Some(nf.clone()),
}
}
// https://dom.spec.whatwg.org/#dom-treewalker-currentnode
- fn CurrentNode(&self) -> Root<Node> {
+ fn CurrentNode(&self) -> DomRoot<Node> {
self.current_node.get()
}
@@ -93,7 +96,7 @@ impl TreeWalkerMethods for TreeWalker {
}
// https://dom.spec.whatwg.org/#dom-treewalker-parentnode
- fn ParentNode(&self) -> Fallible<Option<Root<Node>>> {
+ fn ParentNode(&self) -> Fallible<Option<DomRoot<Node>>> {
// "1. Let node be the value of the currentNode attribute."
let mut node = self.current_node.get();
// "2. While node is not null and is not root, run these substeps:"
@@ -104,9 +107,9 @@ impl TreeWalkerMethods for TreeWalker {
node = n;
// "2. If node is not null and filtering node returns FILTER_ACCEPT,
// then set the currentNode attribute to node, return node."
- if NodeFilterConstants::FILTER_ACCEPT == try!(self.accept_node(&node)) {
+ if NodeFilterConstants::FILTER_ACCEPT == self.accept_node(&node)? {
self.current_node.set(&node);
- return Ok(Some(node))
+ return Ok(Some(node));
}
},
None => break,
@@ -117,35 +120,31 @@ impl TreeWalkerMethods for TreeWalker {
}
// https://dom.spec.whatwg.org/#dom-treewalker-firstchild
- fn FirstChild(&self) -> Fallible<Option<Root<Node>>> {
+ fn FirstChild(&self) -> Fallible<Option<DomRoot<Node>>> {
// "The firstChild() method must traverse children of type first."
- self.traverse_children(|node| node.GetFirstChild(),
- |node| node.GetNextSibling())
+ self.traverse_children(|node| node.GetFirstChild(), |node| node.GetNextSibling())
}
// https://dom.spec.whatwg.org/#dom-treewalker-lastchild
- fn LastChild(&self) -> Fallible<Option<Root<Node>>> {
+ fn LastChild(&self) -> Fallible<Option<DomRoot<Node>>> {
// "The lastChild() method must traverse children of type last."
- self.traverse_children(|node| node.GetLastChild(),
- |node| node.GetPreviousSibling())
+ self.traverse_children(|node| node.GetLastChild(), |node| node.GetPreviousSibling())
}
// https://dom.spec.whatwg.org/#dom-treewalker-previoussibling
- fn PreviousSibling(&self) -> Fallible<Option<Root<Node>>> {
+ fn PreviousSibling(&self) -> Fallible<Option<DomRoot<Node>>> {
// "The nextSibling() method must traverse siblings of type next."
- self.traverse_siblings(|node| node.GetLastChild(),
- |node| node.GetPreviousSibling())
+ self.traverse_siblings(|node| node.GetLastChild(), |node| node.GetPreviousSibling())
}
// https://dom.spec.whatwg.org/#dom-treewalker-nextsibling
- fn NextSibling(&self) -> Fallible<Option<Root<Node>>> {
+ fn NextSibling(&self) -> Fallible<Option<DomRoot<Node>>> {
// "The previousSibling() method must traverse siblings of type previous."
- self.traverse_siblings(|node| node.GetFirstChild(),
- |node| node.GetNextSibling())
+ self.traverse_siblings(|node| node.GetFirstChild(), |node| node.GetNextSibling())
}
// https://dom.spec.whatwg.org/#dom-treewalker-previousnode
- fn PreviousNode(&self) -> Fallible<Option<Root<Node>>> {
+ fn PreviousNode(&self) -> Fallible<Option<DomRoot<Node>>> {
// "1. Let node be the value of the currentNode attribute."
let mut node = self.current_node.get();
// "2. While node is not root, run these substeps:"
@@ -163,16 +162,15 @@ impl TreeWalkerMethods for TreeWalker {
// "4. If result is FILTER_ACCEPT, then
// set the currentNode attribute to node and return node."
loop {
- let result = try!(self.accept_node(&node));
+ let result = self.accept_node(&node)?;
match result {
NodeFilterConstants::FILTER_REJECT => break,
- _ if node.GetFirstChild().is_some() =>
- node = node.GetLastChild().unwrap(),
+ _ if node.GetFirstChild().is_some() => node = node.GetLastChild().unwrap(),
NodeFilterConstants::FILTER_ACCEPT => {
self.current_node.set(&node);
- return Ok(Some(node))
+ return Ok(Some(node));
},
- _ => break
+ _ => break,
}
}
// "5. Set sibling to the previous sibling of node."
@@ -180,21 +178,23 @@ impl TreeWalkerMethods for TreeWalker {
}
// "3. If node is root or node's parent is null, return null."
if self.is_root_node(&node) || node.GetParentNode().is_none() {
- return Ok(None)
+ return Ok(None);
}
// "4. Set node to its parent."
match node.GetParentNode() {
None =>
- // This can happen if the user set the current node to somewhere
- // outside of the tree rooted at the original root.
- return Ok(None),
- Some(n) => node = n
+ // This can happen if the user set the current node to somewhere
+ // outside of the tree rooted at the original root.
+ {
+ return Ok(None);
+ }
+ Some(n) => node = n,
}
// "5. Filter node and if the return value is FILTER_ACCEPT, then
// set the currentNode attribute to node and return node."
- if NodeFilterConstants::FILTER_ACCEPT == try!(self.accept_node(&node)) {
+ if NodeFilterConstants::FILTER_ACCEPT == self.accept_node(&node)? {
self.current_node.set(&node);
- return Ok(Some(node))
+ return Ok(Some(node));
}
}
// "6. Return null."
@@ -202,7 +202,7 @@ impl TreeWalkerMethods for TreeWalker {
}
// https://dom.spec.whatwg.org/#dom-treewalker-nextnode
- fn NextNode(&self) -> Fallible<Option<Root<Node>>> {
+ fn NextNode(&self) -> Fallible<Option<DomRoot<Node>>> {
// "1. Let node be the value of the currentNode attribute."
let mut node = self.current_node.get();
// "2. Let result be FILTER_ACCEPT."
@@ -220,14 +220,14 @@ impl TreeWalkerMethods for TreeWalker {
// "1. Set node to its first child."
node = child;
// "2. Filter node and set result to the return value."
- result = try!(self.accept_node(&node));
+ result = self.accept_node(&node)?;
// "3. If result is FILTER_ACCEPT, then
// set the currentNode attribute to node and return node."
if NodeFilterConstants::FILTER_ACCEPT == result {
self.current_node.set(&node);
- return Ok(Some(node))
+ return Ok(Some(node));
}
- }
+ },
}
}
// "2. If a node is following node and is not following root,
@@ -238,14 +238,14 @@ impl TreeWalkerMethods for TreeWalker {
Some(n) => {
node = n;
// "3. Filter node and set result to the return value."
- result = try!(self.accept_node(&node));
+ result = self.accept_node(&node)?;
// "4. If result is FILTER_ACCEPT, then
// set the currentNode attribute to node and return node."
if NodeFilterConstants::FILTER_ACCEPT == result {
self.current_node.set(&node);
- return Ok(Some(node))
+ return Ok(Some(node));
}
- }
+ },
}
// "5. Run these substeps again."
}
@@ -254,12 +254,14 @@ impl TreeWalkerMethods for TreeWalker {
impl TreeWalker {
// https://dom.spec.whatwg.org/#concept-traverse-children
- fn traverse_children<F, G>(&self,
- next_child: F,
- next_sibling: G)
- -> Fallible<Option<Root<Node>>>
- where F: Fn(&Node) -> Option<Root<Node>>,
- G: Fn(&Node) -> Option<Root<Node>>
+ fn traverse_children<F, G>(
+ &self,
+ next_child: F,
+ next_sibling: G,
+ ) -> Fallible<Option<DomRoot<Node>>>
+ where
+ F: Fn(&Node) -> Option<DomRoot<Node>>,
+ G: Fn(&Node) -> Option<DomRoot<Node>>,
{
// "To **traverse children** of type *type*, run these steps:"
// "1. Let node be the value of the currentNode attribute."
@@ -275,13 +277,13 @@ impl TreeWalker {
// 4. Main: Repeat these substeps:
'main: loop {
// "1. Filter node and let result be the return value."
- let result = try!(self.accept_node(&node));
+ let result = self.accept_node(&node)?;
match result {
// "2. If result is FILTER_ACCEPT, then set the currentNode
// attribute to node and return node."
NodeFilterConstants::FILTER_ACCEPT => {
self.current_node.set(&node);
- return Ok(Some(Root::from_ref(&node)))
+ return Ok(Some(DomRoot::from_ref(&node)));
},
// "3. If result is FILTER_SKIP, run these subsubsteps:"
NodeFilterConstants::FILTER_SKIP => {
@@ -290,10 +292,10 @@ impl TreeWalker {
if let Some(child) = next_child(&node) {
// "2. If child is not null, set node to child and goto Main."
node = child;
- continue 'main
+ continue 'main;
}
},
- _ => {}
+ _ => {},
}
// "4. Repeat these subsubsteps:"
loop {
@@ -304,7 +306,7 @@ impl TreeWalker {
// set node to sibling and goto Main."
Some(sibling) => {
node = sibling;
- continue 'main
+ continue 'main;
},
None => {
// "3. Let parent be node's parent."
@@ -313,32 +315,36 @@ impl TreeWalker {
// or parent is currentNode attribute's value,
// return null."
None => return Ok(None),
- Some(ref parent) if self.is_root_node(&parent)
- || self.is_current_node(&parent) =>
- return Ok(None),
+ Some(ref parent)
+ if self.is_root_node(&parent) || self.is_current_node(&parent) =>
+ {
+ return Ok(None);
+ }
// "5. Otherwise, set node to parent."
- Some(parent) => node = parent
+ Some(parent) => node = parent,
}
- }
+ },
}
}
}
}
// https://dom.spec.whatwg.org/#concept-traverse-siblings
- fn traverse_siblings<F, G>(&self,
- next_child: F,
- next_sibling: G)
- -> Fallible<Option<Root<Node>>>
- where F: Fn(&Node) -> Option<Root<Node>>,
- G: Fn(&Node) -> Option<Root<Node>>
+ fn traverse_siblings<F, G>(
+ &self,
+ next_child: F,
+ next_sibling: G,
+ ) -> Fallible<Option<DomRoot<Node>>>
+ where
+ F: Fn(&Node) -> Option<DomRoot<Node>>,
+ G: Fn(&Node) -> Option<DomRoot<Node>>,
{
// "To **traverse siblings** of type *type* run these steps:"
// "1. Let node be the value of the currentNode attribute."
let mut node = self.current_node.get();
// "2. If node is root, return null."
if self.is_root_node(&node) {
- return Ok(None)
+ return Ok(None);
}
// "3. Run these substeps:"
loop {
@@ -350,12 +356,12 @@ impl TreeWalker {
// "1. Set node to sibling."
node = sibling_op.unwrap();
// "2. Filter node and let result be the return value."
- let result = try!(self.accept_node(&node));
+ let result = self.accept_node(&node)?;
// "3. If result is FILTER_ACCEPT, then set the currentNode
// attribute to node and return node."
if NodeFilterConstants::FILTER_ACCEPT == result {
self.current_node.set(&node);
- return Ok(Some(node))
+ return Ok(Some(node));
}
// "4. Set sibling to node's first child if type is next,
@@ -365,9 +371,10 @@ impl TreeWalker {
// then set sibling to node's next sibling if type is next,
// and node's previous sibling if type is previous."
match (result, &sibling_op) {
- (NodeFilterConstants::FILTER_REJECT, _)
- | (_, &None) => sibling_op = next_sibling(&node),
- _ => {}
+ (NodeFilterConstants::FILTER_REJECT, _) | (_, &None) => {
+ sibling_op = next_sibling(&node)
+ },
+ _ => {},
}
}
// "3. Set node to its parent."
@@ -378,31 +385,26 @@ impl TreeWalker {
// "5. Filter node and if the return value is FILTER_ACCEPT, then return null."
Some(n) => {
node = n;
- if NodeFilterConstants::FILTER_ACCEPT == try!(self.accept_node(&node)) {
- return Ok(None)
+ if NodeFilterConstants::FILTER_ACCEPT == self.accept_node(&node)? {
+ return Ok(None);
}
- }
+ },
}
// "6. Run these substeps again."
}
}
// https://dom.spec.whatwg.org/#concept-tree-following
- fn first_following_node_not_following_root(&self, node: &Node)
- -> Option<Root<Node>> {
+ fn first_following_node_not_following_root(&self, node: &Node) -> Option<DomRoot<Node>> {
// "An object A is following an object B if A and B are in the same tree
// and A comes after B in tree order."
match node.GetNextSibling() {
None => {
- let mut candidate = Root::from_ref(node);
+ let mut candidate = DomRoot::from_ref(node);
while !self.is_root_node(&candidate) && candidate.GetNextSibling().is_none() {
- match candidate.GetParentNode() {
- None =>
- // This can happen if the user set the current node to somewhere
- // outside of the tree rooted at the original root.
- return None,
- Some(n) => candidate = n
- }
+ // This can return None if the user set the current node to somewhere
+ // outside of the tree rooted at the original root.
+ candidate = candidate.GetParentNode()?;
}
if self.is_root_node(&candidate) {
None
@@ -410,33 +412,40 @@ impl TreeWalker {
candidate.GetNextSibling()
}
},
- it => it
+ it => it,
}
}
// https://dom.spec.whatwg.org/#concept-node-filter
fn accept_node(&self, node: &Node) -> Fallible<u16> {
- // "To filter node run these steps:"
- // "1. Let n be node's nodeType attribute value minus 1."
+ // Step 1.
+ if self.active.get() {
+ return Err(Error::InvalidState);
+ }
+ // Step 2.
let n = node.NodeType() - 1;
- // "2. If the nth bit (where 0 is the least significant bit) of whatToShow is not set,
- // return FILTER_SKIP."
+ // Step 3.
if (self.what_to_show & (1 << n)) == 0 {
- return Ok(NodeFilterConstants::FILTER_SKIP)
+ return Ok(NodeFilterConstants::FILTER_SKIP);
}
- // "3. If filter is null, return FILTER_ACCEPT."
- // "4. Let result be the return value of invoking filter."
- // "5. If an exception was thrown, re-throw the exception."
- // "6. Return result."
match self.filter {
+ // Step 4.
Filter::None => Ok(NodeFilterConstants::FILTER_ACCEPT),
- Filter::Native(f) => Ok((f)(node)),
- Filter::JS(ref callback) => callback.AcceptNode_(self, node, Rethrow)
+ Filter::Dom(ref callback) => {
+ // Step 5.
+ self.active.set(true);
+ // Step 6.
+ let result = callback.AcceptNode_(self, node, Rethrow);
+ // Step 7.
+ self.active.set(false);
+ // Step 8.
+ result
+ },
}
}
fn is_root_node(&self, node: &Node) -> bool {
- JS::from_ref(node) == self.root_node
+ Dom::from_ref(node) == self.root_node
}
fn is_current_node(&self, node: &Node) -> bool {
@@ -445,18 +454,20 @@ impl TreeWalker {
}
impl<'a> Iterator for &'a TreeWalker {
- type Item = Root<Node>;
+ type Item = DomRoot<Node>;
- fn next(&mut self) -> Option<Root<Node>> {
+ fn next(&mut self) -> Option<DomRoot<Node>> {
match self.NextNode() {
Ok(node) => node,
Err(_) =>
- // The Err path happens only when a JavaScript
- // NodeFilter throws an exception. This iterator
- // is meant for internal use from Rust code, which
- // will probably be using a native Rust filter,
- // which cannot produce an Err result.
+ // The Err path happens only when a JavaScript
+ // NodeFilter throws an exception. This iterator
+ // is meant for internal use from Rust code, which
+ // will probably be using a native Rust filter,
+ // which cannot produce an Err result.
+ {
unreachable!()
+ }
}
}
}
@@ -464,6 +475,5 @@ impl<'a> Iterator for &'a TreeWalker {
#[derive(JSTraceable)]
pub enum Filter {
None,
- Native(fn (node: &Node) -> u16),
- JS(Rc<NodeFilter>)
+ Dom(Rc<NodeFilter>),
}