aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/script/dom/node.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/script/dom/node.rs')
-rw-r--r--src/components/script/dom/node.rs338
1 files changed, 268 insertions, 70 deletions
diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs
index 712bdd4b00d..1e71b5c2fea 100644
--- a/src/components/script/dom/node.rs
+++ b/src/components/script/dom/node.rs
@@ -21,11 +21,11 @@ use dom::text::Text;
use js::jsapi::{JSObject, JSContext};
use servo_util::slot::{MutSlotRef, Slot, SlotRef};
-use servo_util::tree::{TreeNode, TreeNodeRef, TreeNodeRefAsElement};
use std::cast::transmute;
use std::cast;
use std::unstable::raw::Box;
use std::util;
+use style::TNode;
//
// The basic Node structure
@@ -210,59 +210,17 @@ impl<View> Clone for AbstractNode<View> {
}
}
-impl<View> TreeNodeRef<Node<View>> for AbstractNode<View> {
- fn node<'a>(&'a self) -> &'a Node<View> {
- unsafe {
- &(*self.obj).data
- }
- }
-
- fn mut_node<'a>(&'a self) -> &'a mut Node<View> {
- unsafe {
- &mut (*self.obj).data
- }
- }
-
- fn parent_node(node: &Node<View>) -> Option<AbstractNode<View>> {
- node.parent_node
- }
- fn first_child(node: &Node<View>) -> Option<AbstractNode<View>> {
- node.first_child
- }
- fn last_child(node: &Node<View>) -> Option<AbstractNode<View>> {
- node.last_child
- }
- fn prev_sibling(node: &Node<View>) -> Option<AbstractNode<View>> {
- node.prev_sibling
- }
- fn next_sibling(node: &Node<View>) -> Option<AbstractNode<View>> {
- node.next_sibling
+impl<View> TNode<Element> for AbstractNode<View> {
+ fn parent_node(&self) -> Option<AbstractNode<View>> {
+ self.node().parent_node
}
- fn set_parent_node(node: &mut Node<View>, new_parent_node: Option<AbstractNode<View>>) {
- let doc = node.owner_doc();
- doc.document().wait_until_safe_to_modify_dom();
- node.parent_node = new_parent_node
- }
- fn set_first_child(node: &mut Node<View>, new_first_child: Option<AbstractNode<View>>) {
- let doc = node.owner_doc();
- doc.document().wait_until_safe_to_modify_dom();
- node.first_child = new_first_child
- }
- fn set_last_child(node: &mut Node<View>, new_last_child: Option<AbstractNode<View>>) {
- let doc = node.owner_doc();
- doc.document().wait_until_safe_to_modify_dom();
- node.last_child = new_last_child
- }
- fn set_prev_sibling(node: &mut Node<View>, new_prev_sibling: Option<AbstractNode<View>>) {
- let doc = node.owner_doc();
- doc.document().wait_until_safe_to_modify_dom();
- node.prev_sibling = new_prev_sibling
+ fn prev_sibling(&self) -> Option<AbstractNode<View>> {
+ self.node().prev_sibling
}
- fn set_next_sibling(node: &mut Node<View>, new_next_sibling: Option<AbstractNode<View>>) {
- let doc = node.owner_doc();
- doc.document().wait_until_safe_to_modify_dom();
- node.next_sibling = new_next_sibling
+
+ fn next_sibling(&self) -> Option<AbstractNode<View>> {
+ self.node().next_sibling
}
fn is_element(&self) -> bool {
@@ -278,17 +236,34 @@ impl<View> TreeNodeRef<Node<View>> for AbstractNode<View> {
_ => false
}
}
-}
-impl<View> TreeNodeRefAsElement<Node<View>, Element> for AbstractNode<View> {
#[inline]
- fn with_imm_element_like<R>(&self, f: &fn(&Element) -> R) -> R {
+ fn with_element<R>(&self, f: &fn(&Element) -> R) -> R {
self.with_imm_element(f)
}
}
+impl<View> AbstractNode<View> {
+ pub fn node<'a>(&'a self) -> &'a Node<View> {
+ unsafe {
+ &(*self.obj).data
+ }
+ }
-impl<View> TreeNode<AbstractNode<View>> for Node<View> { }
+ pub fn mut_node<'a>(&'a self) -> &'a mut Node<View> {
+ unsafe {
+ &mut (*self.obj).data
+ }
+ }
+
+ pub fn first_child(&self) -> Option<AbstractNode<View>> {
+ self.node().first_child
+ }
+
+ pub fn last_child(&self) -> Option<AbstractNode<View>> {
+ self.node().last_child
+ }
+}
impl<'self, View> AbstractNode<View> {
// Unsafe accessors
@@ -335,21 +310,6 @@ impl<'self, View> AbstractNode<View> {
self.node().type_id
}
- /// Returns the parent node of this node. Fails if this node is borrowed mutably.
- pub fn parent_node(self) -> Option<AbstractNode<View>> {
- self.node().parent_node
- }
-
- /// Returns the first child of this node. Fails if this node is borrowed mutably.
- pub fn first_child(self) -> Option<AbstractNode<View>> {
- self.node().first_child
- }
-
- /// Returns the last child of this node. Fails if this node is borrowed mutably.
- pub fn last_child(self) -> Option<AbstractNode<View>> {
- self.node().last_child
- }
-
/// Returns the previous sibling of this node. Fails if this node is borrowed mutably.
pub fn prev_sibling(self) -> Option<AbstractNode<View>> {
self.node().prev_sibling
@@ -562,6 +522,14 @@ impl<'self, View> AbstractNode<View> {
format!("{:?}", self.type_id())
}
+ //
+ // Convenience accessors
+ //
+
+ fn is_leaf(&self) -> bool {
+ self.first_child().is_none()
+ }
+
pub fn children(&self) -> AbstractNodeChildrenIterator<View> {
self.node().children()
}
@@ -601,8 +569,123 @@ impl AbstractNode<ScriptView> {
document.document().content_changed();
}
+
+ //
+ // Pointer stitching
+ //
+
+ /// Adds a new child to the end of this node's list of children.
+ ///
+ /// Fails unless `new_child` is disconnected from the tree.
+ fn add_child(&self,
+ new_child: AbstractNode<ScriptView>,
+ before: Option<AbstractNode<ScriptView>>) {
+ let this_node = self.mut_node();
+ let new_child_node = new_child.mut_node();
+ assert!(new_child_node.parent_node.is_none());
+ assert!(new_child_node.prev_sibling.is_none());
+ assert!(new_child_node.next_sibling.is_none());
+ match before {
+ Some(before) => {
+ let before_node = before.mut_node();
+ // XXX Should assert that parent is self.
+ assert!(before_node.parent_node.is_some());
+ before_node.set_prev_sibling(Some(new_child.clone()));
+ new_child_node.set_next_sibling(Some(before.clone()));
+ match before_node.prev_sibling {
+ None => {
+ // XXX Should assert that before is the first child of
+ // self.
+ this_node.set_first_child(Some(new_child.clone()));
+ },
+ Some(prev_sibling) => {
+ let prev_sibling_node = prev_sibling.mut_node();
+ prev_sibling_node.set_next_sibling(Some(new_child.clone()));
+ new_child_node.set_prev_sibling(Some(prev_sibling.clone()));
+ },
+ }
+ },
+ None => {
+ match this_node.last_child {
+ None => this_node.set_first_child(Some(new_child.clone())),
+ Some(last_child) => {
+ let last_child_node = last_child.mut_node();
+ assert!(last_child_node.next_sibling.is_none());
+ last_child_node.set_next_sibling(Some(new_child.clone()));
+ new_child_node.set_prev_sibling(Some(last_child.clone()));
+ }
+ }
+
+ this_node.set_last_child(Some(new_child.clone()));
+ },
+ }
+
+ new_child_node.set_parent_node(Some((*self).clone()));
+ }
+
+ /// Removes the given child from this node's list of children.
+ ///
+ /// Fails unless `child` is a child of this node. (FIXME: This is not yet checked.)
+ fn remove_child(&self, child: AbstractNode<ScriptView>) {
+ let this_node = self.mut_node();
+ let child_node = child.mut_node();
+ assert!(child_node.parent_node.is_some());
+
+ match child_node.prev_sibling {
+ None => this_node.set_first_child(child_node.next_sibling),
+ Some(prev_sibling) => {
+ let prev_sibling_node = prev_sibling.mut_node();
+ prev_sibling_node.set_next_sibling(child_node.next_sibling);
+ }
+ }
+
+ match child_node.next_sibling {
+ None => this_node.set_last_child(child_node.prev_sibling),
+ Some(next_sibling) => {
+ let next_sibling_node = next_sibling.mut_node();
+ next_sibling_node.set_prev_sibling(child_node.prev_sibling);
+ }
+ }
+
+ child_node.set_prev_sibling(None);
+ child_node.set_next_sibling(None);
+ child_node.set_parent_node(None);
+ }
+
+ //
+ // Low-level pointer stitching wrappers
+ //
+
+ fn set_parent_node(&self, new_parent_node: Option<AbstractNode<ScriptView>>) {
+ let node = self.mut_node();
+ node.set_parent_node(new_parent_node)
+ }
+
+ fn set_first_child(&self, new_first_child: Option<AbstractNode<ScriptView>>) {
+ let node = self.mut_node();
+ node.set_first_child(new_first_child)
+ }
+
+ fn set_last_child(&self, new_last_child: Option<AbstractNode<ScriptView>>) {
+ let node = self.mut_node();
+ node.set_last_child(new_last_child)
+ }
+
+ fn set_prev_sibling(&self, new_prev_sibling: Option<AbstractNode<ScriptView>>) {
+ let node = self.mut_node();
+ node.set_prev_sibling(new_prev_sibling)
+ }
+
+ fn set_next_sibling(&self, new_next_sibling: Option<AbstractNode<ScriptView>>) {
+ let node = self.mut_node();
+ node.set_next_sibling(new_next_sibling)
+ }
}
+//
+// Iteration and traversal
+//
+
impl<View> Iterator<AbstractNode<View>> for AbstractNodeChildrenIterator<View> {
fn next(&mut self) -> Option<AbstractNode<View>> {
let node = self.current_node;
@@ -613,6 +696,86 @@ impl<View> Iterator<AbstractNode<View>> for AbstractNodeChildrenIterator<View> {
}
}
+pub struct AncestorIterator<View> {
+ priv current: Option<AbstractNode<View>>,
+}
+
+impl<View> Iterator<AbstractNode<View>> for AncestorIterator<View> {
+ fn next(&mut self) -> Option<AbstractNode<View>> {
+ if self.current.is_none() {
+ return None;
+ }
+
+ // FIXME: Do we need two clones here?
+ let x = self.current.get_ref().clone();
+ self.current = x.parent_node();
+ Some(x.clone())
+ }
+}
+
+// FIXME: Do this without precomputing a vector of refs.
+// Easy for preorder; harder for postorder.
+pub struct TreeIterator<View> {
+ priv nodes: ~[AbstractNode<View>],
+ priv index: uint,
+}
+
+impl<View> TreeIterator<View> {
+ fn new(nodes: ~[AbstractNode<View>]) -> TreeIterator<View> {
+ TreeIterator {
+ nodes: nodes,
+ index: 0,
+ }
+ }
+}
+
+impl<View> Iterator<AbstractNode<View>> for TreeIterator<View> {
+ fn next(&mut self) -> Option<AbstractNode<View>> {
+ if self.index >= self.nodes.len() {
+ None
+ } else {
+ let v = self.nodes[self.index].clone();
+ self.index += 1;
+ Some(v)
+ }
+ }
+}
+
+fn gather<View>(cur: &AbstractNode<View>, refs: &mut ~[AbstractNode<View>], postorder: bool) {
+ if !postorder {
+ refs.push(cur.clone());
+ }
+ for kid in cur.children() {
+ gather(&kid, refs, postorder)
+ }
+ if postorder {
+ refs.push(cur.clone());
+ }
+}
+
+impl<View> AbstractNode<View> {
+ /// Iterates over all ancestors of this node.
+ pub fn ancestors(&self) -> AncestorIterator<View> {
+ AncestorIterator {
+ current: self.parent_node(),
+ }
+ }
+
+ /// Iterates over this node and all its descendants, in preorder.
+ pub fn traverse_preorder(&self) -> TreeIterator<View> {
+ let mut nodes = ~[];
+ gather(self, &mut nodes, false);
+ TreeIterator::new(nodes)
+ }
+
+ /// Iterates over this node and all its descendants, in postorder.
+ pub fn sequential_traverse_postorder(&self) -> TreeIterator<View> {
+ let mut nodes = ~[];
+ gather(self, &mut nodes, true);
+ TreeIterator::new(nodes)
+ }
+}
+
impl<View> Node<View> {
pub fn owner_doc(&self) -> AbstractDocument {
self.owner_doc.unwrap()
@@ -1215,6 +1378,41 @@ impl Node<ScriptView> {
pub fn HasAttributes(&self) -> bool {
false
}
+
+
+ //
+ // Low-level pointer stitching
+ //
+
+ pub fn set_parent_node(&mut self, new_parent_node: Option<AbstractNode<ScriptView>>) {
+ let doc = self.owner_doc();
+ doc.document().wait_until_safe_to_modify_dom();
+ self.parent_node = new_parent_node
+ }
+
+ pub fn set_first_child(&mut self, new_first_child: Option<AbstractNode<ScriptView>>) {
+ let doc = self.owner_doc();
+ doc.document().wait_until_safe_to_modify_dom();
+ self.first_child = new_first_child
+ }
+
+ pub fn set_last_child(&mut self, new_last_child: Option<AbstractNode<ScriptView>>) {
+ let doc = self.owner_doc();
+ doc.document().wait_until_safe_to_modify_dom();
+ self.last_child = new_last_child
+ }
+
+ pub fn set_prev_sibling(&mut self, new_prev_sibling: Option<AbstractNode<ScriptView>>) {
+ let doc = self.owner_doc();
+ doc.document().wait_until_safe_to_modify_dom();
+ self.prev_sibling = new_prev_sibling
+ }
+
+ pub fn set_next_sibling(&mut self, new_next_sibling: Option<AbstractNode<ScriptView>>) {
+ let doc = self.owner_doc();
+ doc.document().wait_until_safe_to_modify_dom();
+ self.next_sibling = new_next_sibling
+ }
}
impl Reflectable for Node<ScriptView> {