aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/main/css/matching.rs4
-rw-r--r--src/components/main/css/node_util.rs3
-rw-r--r--src/components/main/layout/box.rs3
-rw-r--r--src/components/main/layout/construct.rs1
-rw-r--r--src/components/main/layout/extra.rs1
-rw-r--r--src/components/main/layout/inline.rs3
-rw-r--r--src/components/main/layout/layout_task.rs5
-rw-r--r--src/components/main/layout/util.rs1
-rw-r--r--src/components/script/dom/bindings/node.rs1
-rw-r--r--src/components/script/dom/document.rs9
-rw-r--r--src/components/script/dom/element.rs4
-rw-r--r--src/components/script/dom/eventdispatcher.rs1
-rw-r--r--src/components/script/dom/htmldocument.rs4
-rw-r--r--src/components/script/dom/htmlimageelement.rs2
-rw-r--r--src/components/script/dom/htmlscriptelement.rs2
-rw-r--r--src/components/script/dom/node.rs338
-rw-r--r--src/components/script/html/hubbub_html_parser.rs3
-rw-r--r--src/components/script/script_task.rs2
-rw-r--r--src/components/style/node.rs28
-rw-r--r--src/components/style/selector_matching.rs131
-rw-r--r--src/components/style/style.rc2
-rw-r--r--src/components/util/tree.rs354
-rw-r--r--src/components/util/util.rc1
23 files changed, 381 insertions, 522 deletions
diff --git a/src/components/main/css/matching.rs b/src/components/main/css/matching.rs
index cbe11e00010..78537d9be7a 100644
--- a/src/components/main/css/matching.rs
+++ b/src/components/main/css/matching.rs
@@ -15,9 +15,7 @@ use layout::incremental;
use layout::util::LayoutDataAccess;
use script::dom::node::{AbstractNode, LayoutView};
-use style::Stylist;
-use style::cascade;
-use servo_util::tree::TreeNodeRef;
+use style::{TNode, Stylist, cascade};
pub trait MatchMethods {
fn match_node(&self, stylist: &Stylist);
diff --git a/src/components/main/css/node_util.rs b/src/components/main/css/node_util.rs
index 84b7c6098d1..b5d8e790c00 100644
--- a/src/components/main/css/node_util.rs
+++ b/src/components/main/css/node_util.rs
@@ -7,9 +7,8 @@ use layout::util::LayoutDataAccess;
use extra::arc::Arc;
use std::cast;
-use style::ComputedValues;
+use style::{ComputedValues, TNode};
use script::dom::node::{AbstractNode, LayoutView};
-use servo_util::tree::TreeNodeRef;
pub trait NodeUtil {
fn get_css_select_results<'a>(&'a self) -> &'a Arc<ComputedValues>;
diff --git a/src/components/main/layout/box.rs b/src/components/main/layout/box.rs
index 0479892f280..9c341f12028 100644
--- a/src/components/main/layout/box.rs
+++ b/src/components/main/layout/box.rs
@@ -23,12 +23,11 @@ use servo_util::geometry::Au;
use servo_util::geometry;
use servo_util::range::*;
use servo_util::slot::Slot;
-use servo_util::tree::{TreeNodeRef, ElementLike};
use std::cast;
use std::cell::Cell;
use std::cmp::ApproxEq;
use std::num::Zero;
-use style::ComputedValues;
+use style::{ComputedValues, TElement, TNode};
use style::computed_values::{LengthOrPercentage, overflow};
use style::computed_values::{border_style, clear, font_family, font_style, line_height};
use style::computed_values::{text_align, text_decoration, vertical_align, visibility};
diff --git a/src/components/main/layout/construct.rs b/src/components/main/layout/construct.rs
index 03ab5f4033f..42764b9fe60 100644
--- a/src/components/main/layout/construct.rs
+++ b/src/components/main/layout/construct.rs
@@ -36,7 +36,6 @@ use script::dom::node::{AbstractNode, CommentNodeTypeId, DoctypeNodeTypeId};
use script::dom::node::{DocumentFragmentNodeTypeId, DocumentNodeTypeId, ElementNodeTypeId};
use script::dom::node::{LayoutView, PostorderNodeMutTraversal, TextNodeTypeId};
use servo_util::slot::Slot;
-use servo_util::tree::TreeNodeRef;
use std::util;
use style::computed_values::{display, float};
diff --git a/src/components/main/layout/extra.rs b/src/components/main/layout/extra.rs
index 57d77f1e3fa..8b6a8c46478 100644
--- a/src/components/main/layout/extra.rs
+++ b/src/components/main/layout/extra.rs
@@ -7,7 +7,6 @@
use layout::util::{LayoutData, LayoutDataAccess};
use script::dom::node::{AbstractNode, LayoutView};
-use servo_util::tree::TreeNodeRef;
/// Functionality useful for querying the layout-specific data on DOM nodes.
pub trait LayoutAuxMethods {
diff --git a/src/components/main/layout/inline.rs b/src/components/main/layout/inline.rs
index 2f2eea797ff..c270d90df60 100644
--- a/src/components/main/layout/inline.rs
+++ b/src/components/main/layout/inline.rs
@@ -22,8 +22,7 @@ use servo_util::range::Range;
use std::cell::Cell;
use std::u16;
use std::util;
-use style::computed_values::text_align;
-use style::computed_values::vertical_align;
+use style::computed_values::{text_align, vertical_align};
/// Lineboxes are represented as offsets into the child list, rather than
/// as an object that "owns" boxes. Choosing a different set of line
diff --git a/src/components/main/layout/layout_task.rs b/src/components/main/layout/layout_task.rs
index 6d177ec34dd..74070b6a6f8 100644
--- a/src/components/main/layout/layout_task.rs
+++ b/src/components/main/layout/layout_task.rs
@@ -43,16 +43,13 @@ use servo_net::local_image_cache::{ImageResponder, LocalImageCache};
use servo_util::geometry::Au;
use servo_util::time::{ProfilerChan, profile};
use servo_util::time;
-use servo_util::tree::TreeNodeRef;
use std::cast::transmute;
use std::cast;
use std::cell::Cell;
use std::comm::Port;
use std::task;
use std::util;
-use style::AuthorOrigin;
-use style::Stylesheet;
-use style::Stylist;
+use style::{AuthorOrigin, Stylesheet, Stylist};
/// Information needed by the layout task.
struct LayoutTask {
diff --git a/src/components/main/layout/util.rs b/src/components/main/layout/util.rs
index 22763308da6..66681135b52 100644
--- a/src/components/main/layout/util.rs
+++ b/src/components/main/layout/util.rs
@@ -9,7 +9,6 @@ use extra::arc::Arc;
use script::dom::node::{AbstractNode, LayoutView};
use servo_util::range::Range;
use servo_util::slot::{MutSlotRef, SlotRef};
-use servo_util::tree::TreeNodeRef;
use std::cast;
use std::iter::Enumerate;
use std::libc::uintptr_t;
diff --git a/src/components/script/dom/bindings/node.rs b/src/components/script/dom/bindings/node.rs
index 561e22cc637..6a009a9bac4 100644
--- a/src/components/script/dom/bindings/node.rs
+++ b/src/components/script/dom/bindings/node.rs
@@ -10,7 +10,6 @@ use std::cast;
use std::libc;
use std::ptr;
use js::jsapi::{JSTracer, JSTRACE_OBJECT, JS_CallTracer};
-use servo_util::tree::TreeNodeRef;
impl Reflectable for AbstractNode<ScriptView> {
fn reflector<'a>(&'a self) -> &'a Reflector {
diff --git a/src/components/script/dom/document.rs b/src/components/script/dom/document.rs
index e86e7465ec3..cd3bb578507 100644
--- a/src/components/script/dom/document.rs
+++ b/src/components/script/dom/document.rs
@@ -21,16 +21,15 @@ use dom::uievent::UIEvent;
use dom::window::Window;
use dom::htmltitleelement::HTMLTitleElement;
use html::hubbub_html_parser::build_element_from_tag;
-use js::jsapi::{JSObject, JSContext, JSTracer};
-use servo_util::tree::{TreeNodeRef, ElementLike};
use layout_interface::{DocumentDamageLevel, ContentChangedDocumentDamage};
-use std::hashmap::HashMap;
-
+use js::jsapi::{JSObject, JSContext, JSTracer};
+use std::ascii::StrAsciiExt;
use std::cast;
+use std::hashmap::HashMap;
use std::str::eq_slice;
-use std::ascii::StrAsciiExt;
use std::unstable::raw::Box;
+use style::{TElement, TNode};
#[deriving(Eq)]
pub enum DocumentTypeId {
diff --git a/src/components/script/dom/element.rs b/src/components/script/dom/element.rs
index e8acb68f731..001cd3e34f9 100644
--- a/src/components/script/dom/element.rs
+++ b/src/components/script/dom/element.rs
@@ -20,8 +20,8 @@ use dom::namespace::Namespace;
use layout_interface::{ContentBoxQuery, ContentBoxResponse, ContentBoxesQuery};
use layout_interface::{ContentBoxesResponse, ContentChangedDocumentDamage};
use layout_interface::{MatchSelectorsDocumentDamage};
+use style::{TElement, TNode};
use style;
-use servo_util::tree::{TreeNodeRef, ElementLike};
use std::comm;
use std::hashmap::HashMap;
@@ -125,7 +125,7 @@ pub enum ElementTypeId {
// Element methods
//
-impl ElementLike for Element {
+impl TElement for Element {
fn get_local_name<'a>(&'a self) -> &'a str {
self.tag_name.as_slice()
}
diff --git a/src/components/script/dom/eventdispatcher.rs b/src/components/script/dom/eventdispatcher.rs
index 7edc4f5df1d..5a1c09ce9f6 100644
--- a/src/components/script/dom/eventdispatcher.rs
+++ b/src/components/script/dom/eventdispatcher.rs
@@ -6,7 +6,6 @@ use dom::bindings::callback::eReportExceptions;
use dom::eventtarget::{AbstractEventTarget, Capturing, Bubbling};
use dom::event::{AbstractEvent, Phase_At_Target, Phase_None, Phase_Bubbling, Phase_Capturing};
use dom::node::AbstractNode;
-use servo_util::tree::{TreeNodeRef};
// See http://dom.spec.whatwg.org/#concept-event-dispatch for the full dispatch algorithm
pub fn dispatch_event(target: AbstractEventTarget,
diff --git a/src/components/script/dom/htmldocument.rs b/src/components/script/dom/htmldocument.rs
index cbc937afa84..16bf7f8b569 100644
--- a/src/components/script/dom/htmldocument.rs
+++ b/src/components/script/dom/htmldocument.rs
@@ -11,10 +11,8 @@ use dom::node::{AbstractNode, ScriptView, ElementNodeTypeId};
use dom::window::Window;
use js::jsapi::JSTracer;
-
-use servo_util::tree::{TreeNodeRef, ElementLike};
-
use std::str::eq_slice;
+use style::TElement;
pub struct HTMLDocument {
parent: Document
diff --git a/src/components/script/dom/htmlimageelement.rs b/src/components/script/dom/htmlimageelement.rs
index 2a90a71886d..6e8192a2349 100644
--- a/src/components/script/dom/htmlimageelement.rs
+++ b/src/components/script/dom/htmlimageelement.rs
@@ -14,7 +14,7 @@ use layout_interface::{ContentBoxQuery, ContentBoxResponse};
use servo_net::image_cache_task;
use servo_net::image_cache_task::ImageCacheTask;
use servo_util::url::make_url;
-use servo_util::tree::ElementLike;
+use style::TElement;
pub struct HTMLImageElement {
htmlelement: HTMLElement,
diff --git a/src/components/script/dom/htmlscriptelement.rs b/src/components/script/dom/htmlscriptelement.rs
index 1ced40c2e66..37b49fbd1ac 100644
--- a/src/components/script/dom/htmlscriptelement.rs
+++ b/src/components/script/dom/htmlscriptelement.rs
@@ -8,7 +8,7 @@ use dom::document::AbstractDocument;
use dom::element::HTMLScriptElementTypeId;
use dom::htmlelement::HTMLElement;
use dom::node::{AbstractNode, Node, ScriptView};
-use servo_util::tree::ElementLike;
+use style::TElement;
pub struct HTMLScriptElement {
htmlelement: HTMLElement,
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> {
diff --git a/src/components/script/html/hubbub_html_parser.rs b/src/components/script/html/hubbub_html_parser.rs
index 6ca31770032..f854a546371 100644
--- a/src/components/script/html/hubbub_html_parser.rs
+++ b/src/components/script/html/hubbub_html_parser.rs
@@ -20,7 +20,6 @@ use js::jsapi::JSContext;
use servo_msg::constellation_msg::SubpageId;
use servo_net::image_cache_task::ImageCacheTask;
use servo_net::resource_task::{Load, Payload, Done, ResourceTask, load_whole_resource};
-use servo_util::tree::{TreeNodeRef, ElementLike};
use servo_util::url::make_url;
use std::cast;
use std::cell::Cell;
@@ -29,7 +28,7 @@ use std::comm;
use std::from_str::FromStr;
use std::str::eq_slice;
use std::str;
-use style::Stylesheet;
+use style::{Stylesheet, TElement};
macro_rules! handle_element(
($document: expr,
diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs
index 226a5af6305..746b7afa03f 100644
--- a/src/components/script/script_task.rs
+++ b/src/components/script/script_task.rs
@@ -45,7 +45,6 @@ use servo_msg::constellation_msg;
use servo_net::image_cache_task::ImageCacheTask;
use servo_net::resource_task::ResourceTask;
use servo_util::geometry::to_frac_px;
-use servo_util::tree::{TreeNode, TreeNodeRef, ElementLike};
use servo_util::url::make_url;
use std::cell::Cell;
use std::comm::{Port, SharedChan};
@@ -54,6 +53,7 @@ use std::ptr;
use std::str::eq_slice;
use std::task::{spawn_sched, SingleThreaded};
use std::util::replace;
+use style::{TElement, TNode};
/// Messages used to control the script task.
pub enum ScriptMsg {
diff --git a/src/components/style/node.rs b/src/components/style/node.rs
new file mode 100644
index 00000000000..f585ff86e9b
--- /dev/null
+++ b/src/components/style/node.rs
@@ -0,0 +1,28 @@
+/* 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/. */
+
+//! Traits that nodes must implement. Breaks the otherwise-cyclic dependency between script and
+//! style.
+
+/// FIXME(pcwalton): Should not require `Clone` and should instead return references. When this
+/// happens this will need to only be implemented for `AbstractNode<LayoutView>`.
+pub trait TNode<E:TElement> : Clone {
+ fn parent_node(&self) -> Option<Self>;
+ fn prev_sibling(&self) -> Option<Self>;
+ fn next_sibling(&self) -> Option<Self>;
+
+ fn is_document(&self) -> bool;
+ fn is_element(&self) -> bool;
+
+ /// FIXME(pcwalton): This should not use the `with` pattern.
+ fn with_element<R>(&self, f: &fn(&E) -> R) -> R;
+}
+
+pub trait TElement {
+ fn get_attr(&self, namespace: Option<~str>, attr: &str) -> Option<~str>;
+ fn get_link(&self) -> Option<~str>;
+ fn get_local_name<'a>(&'a self) -> &'a str;
+ fn get_namespace_url<'a>(&'a self) -> &'a str;
+}
+
diff --git a/src/components/style/selector_matching.rs b/src/components/style/selector_matching.rs
index 6fc2c03214e..b897888d810 100644
--- a/src/components/style/selector_matching.rs
+++ b/src/components/style/selector_matching.rs
@@ -2,18 +2,17 @@
* 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/. */
-use std::ascii::StrAsciiExt;
-use std::hashmap::HashMap;
use extra::arc::Arc;
use extra::sort::tim_sort;
+use std::ascii::StrAsciiExt;
+use std::hashmap::HashMap;
+use std::str;
-use selectors::*;
-use stylesheets::{Stylesheet, iter_style_rules};
use media_queries::{Device, Screen};
+use node::{TElement, TNode};
use properties::{PropertyDeclaration, PropertyDeclarationBlock};
-use servo_util::tree::{TreeNodeRefAsElement, TreeNode, ElementLike};
-
-use std::str;
+use selectors::*;
+use stylesheets::{Stylesheet, iter_style_rules};
pub enum StylesheetOrigin {
UserAgentOrigin,
@@ -67,16 +66,15 @@ impl SelectorMap {
///
/// Extract matching rules as per node's ID, classes, tag name, etc..
/// Sort the Rules at the end to maintain cascading order.
- fn get_all_matching_rules<N:TreeNode<T>,
- T:TreeNodeRefAsElement<N,E>,
- E:ElementLike>(
+ fn get_all_matching_rules<E:TElement,
+ N:TNode<E>>(
&self,
- node: &T,
+ node: &N,
pseudo_element: Option<PseudoElement>,
matching_rules_list: &mut ~[Rule]) {
// At the end, we're going to sort the rules that we added, so remember where we began.
let init_len = matching_rules_list.len();
- node.with_imm_element_like(|element: &E| {
+ node.with_element(|element: &E| {
match element.get_attr(None, "id") {
Some(id) => {
SelectorMap::get_matching_rules_from_hash(node,
@@ -118,10 +116,9 @@ impl SelectorMap {
tim_sort(matching_rules_list.mut_slice_from(init_len));
}
- fn get_matching_rules_from_hash<N:TreeNode<T>,
- T:TreeNodeRefAsElement<N,E>,
- E:ElementLike>(
- node: &T,
+ fn get_matching_rules_from_hash<E:TElement,
+ N:TNode<E>>(
+ node: &N,
pseudo_element: Option<PseudoElement>,
hash: &HashMap<~str,~[Rule]>,
key: &str,
@@ -135,10 +132,9 @@ impl SelectorMap {
}
/// Adds rules in `rules` that match `node` to the `matching_rules` list.
- fn get_matching_rules<N:TreeNode<T>,
- T:TreeNodeRefAsElement<N,E>,
- E:ElementLike>(
- node: &T,
+ fn get_matching_rules<E:TElement,
+ N:TNode<E>>(
+ node: &N,
pseudo_element: Option<PseudoElement>,
rules: &[Rule],
matching_rules: &mut ~[Rule]) {
@@ -301,11 +297,10 @@ impl Stylist {
/// Returns the applicable CSS declarations for the given element. This corresponds to
/// `ElementRuleCollector` in WebKit.
- pub fn get_applicable_declarations<N:TreeNode<T>,
- T:TreeNodeRefAsElement<N,E>,
- E:ElementLike>(
+ pub fn get_applicable_declarations<E:TElement,
+ N:TNode<E>>(
&self,
- element: &T,
+ element: &N,
style_attribute: Option<&PropertyDeclarationBlock>,
pseudo_element: Option<PseudoElement>)
-> ~[Arc<~[PropertyDeclaration]>] {
@@ -421,7 +416,6 @@ struct Rule {
stylesheet_index: uint,
}
-
impl Ord for Rule {
#[inline]
fn lt(&self, other: &Rule) -> bool {
@@ -431,16 +425,19 @@ impl Ord for Rule {
}
}
-
#[inline]
-fn matches_selector<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: ElementLike>(
- selector: &Selector, element: &T, pseudo_element: Option<PseudoElement>) -> bool {
+fn matches_selector<E:TElement,
+ N:TNode<E>>(
+ selector: &Selector,
+ element: &N,
+ pseudo_element: Option<PseudoElement>)
+ -> bool {
selector.pseudo_element == pseudo_element &&
- matches_compound_selector::<N, T, E>(&selector.compound_selectors, element)
+ matches_compound_selector::<E,N>(&selector.compound_selectors, element)
}
-fn matches_compound_selector<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: ElementLike>(
- selector: &CompoundSelector, element: &T) -> bool {
+fn matches_compound_selector<E:TElement,N:TNode<E>>(selector: &CompoundSelector, element: &N)
+ -> bool {
if !do selector.simple_selectors.iter().all |simple_selector| {
matches_simple_selector(simple_selector, element)
} {
@@ -455,12 +452,12 @@ fn matches_compound_selector<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: E
NextSibling => (true, true),
LaterSibling => (true, false),
};
- let mut node = element.clone();
+ let mut node = (*element).clone();
loop {
let next_node = if siblings {
- node.node().prev_sibling()
+ node.prev_sibling()
} else {
- node.node().parent_node()
+ node.parent_node()
};
match next_node {
None => return false,
@@ -479,25 +476,24 @@ fn matches_compound_selector<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: E
}
#[inline]
-fn matches_simple_selector<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: ElementLike>(
- selector: &SimpleSelector, element: &T) -> bool {
+fn matches_simple_selector<E:TElement,N:TNode<E>>(selector: &SimpleSelector, element: &N) -> bool {
match *selector {
// TODO: case-sensitivity depends on the document type
// TODO: intern element names
LocalNameSelector(ref name) => {
- do element.with_imm_element_like |element: &E| {
+ do element.with_element |element: &E| {
element.get_local_name().eq_ignore_ascii_case(name.as_slice())
}
}
NamespaceSelector(ref url) => {
- do element.with_imm_element_like |element: &E| {
+ do element.with_element |element: &E| {
element.get_namespace_url() == url.as_slice()
}
}
// TODO: case-sensitivity depends on the document type and quirks mode
// TODO: cache and intern IDs on elements.
IDSelector(ref id) => {
- do element.with_imm_element_like |element: &E| {
+ do element.with_element |element: &E| {
match element.get_attr(None, "id") {
Some(attr) => str::eq_slice(attr, *id),
None => false
@@ -506,7 +502,7 @@ fn matches_simple_selector<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: Ele
}
// TODO: cache and intern classe names on elements.
ClassSelector(ref class) => {
- do element.with_imm_element_like |element: &E| {
+ do element.with_element |element: &E| {
match element.get_attr(None, "class") {
None => false,
// TODO: case-sensitivity depends on the document type and quirks mode
@@ -537,12 +533,12 @@ fn matches_simple_selector<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: Ele
AnyLink => {
- do element.with_imm_element_like |element: &E| {
+ do element.with_element |element: &E| {
element.get_link().is_some()
}
}
Link => {
- do element.with_imm_element_like |element: &E| {
+ do element.with_element |element: &E| {
match element.get_link() {
Some(url) => !url_is_visited(url),
None => false,
@@ -550,7 +546,7 @@ fn matches_simple_selector<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: Ele
}
}
Visited => {
- do element.with_imm_element_like |element: &E| {
+ do element.with_element |element: &E| {
match element.get_link() {
Some(url) => url_is_visited(url),
None => false,
@@ -589,12 +585,18 @@ fn url_is_visited(_url: &str) -> bool {
}
#[inline]
-fn matches_generic_nth_child<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: ElementLike>(
- element: &T, a: i32, b: i32, is_of_type: bool, is_from_end: bool) -> bool {
+fn matches_generic_nth_child<E:TElement,
+ N:TNode<E>>(
+ element: &N,
+ a: i32,
+ b: i32,
+ is_of_type: bool,
+ is_from_end: bool)
+ -> bool {
let mut node = element.clone();
// fail if we can't find a parent or if the node is the root element
// of the document (Cf. Selectors Level 3)
- match node.node().parent_node() {
+ match node.parent_node() {
Some(parent) => if parent.is_document() {
return false;
},
@@ -604,7 +606,7 @@ fn matches_generic_nth_child<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: E
let mut element_local_name = "";
let mut element_namespace = "";
if is_of_type {
- do element.with_imm_element_like |element: &E| {
+ do element.with_element |element: &E| {
element_local_name = element.get_local_name();
element_namespace = element.get_namespace_url();
}
@@ -613,12 +615,12 @@ fn matches_generic_nth_child<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: E
let mut index = 1;
loop {
if is_from_end {
- match node.node().next_sibling() {
+ match node.next_sibling() {
None => break,
Some(next_sibling) => node = next_sibling
}
} else {
- match node.node().prev_sibling() {
+ match node.prev_sibling() {
None => break,
Some(prev_sibling) => node = prev_sibling
}
@@ -626,7 +628,7 @@ fn matches_generic_nth_child<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: E
if node.is_element() {
if is_of_type {
- do node.with_imm_element_like |node: &E| {
+ do node.with_element |node: &E| {
if element_local_name == node.get_local_name() &&
element_namespace == node.get_namespace_url() {
index += 1;
@@ -648,27 +650,25 @@ fn matches_generic_nth_child<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: E
}
#[inline]
-fn matches_root<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: ElementLike>(
- element: &T) -> bool {
- match element.node().parent_node() {
+fn matches_root<E:TElement,N:TNode<E>>(element: &N) -> bool {
+ match element.parent_node() {
Some(parent) => parent.is_document(),
None => false
}
}
#[inline]
-fn matches_first_child<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: ElementLike>(
- element: &T) -> bool {
+fn matches_first_child<E:TElement,N:TNode<E>>(element: &N) -> bool {
let mut node = element.clone();
loop {
- match node.node().prev_sibling() {
+ match node.prev_sibling() {
Some(prev_sibling) => {
node = prev_sibling;
if node.is_element() {
return false
}
},
- None => match node.node().parent_node() {
+ None => match node.parent_node() {
// Selectors level 3 says :first-child does not match the
// root of the document; Warning, level 4 says, for the time
// being, the contrary...
@@ -680,18 +680,17 @@ fn matches_first_child<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: Element
}
#[inline]
-fn matches_last_child<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: ElementLike>(
- element: &T) -> bool {
+fn matches_last_child<E:TElement,N:TNode<E>>(element: &N) -> bool {
let mut node = element.clone();
loop {
- match node.node().next_sibling() {
+ match node.next_sibling() {
Some(next_sibling) => {
node = next_sibling;
if node.is_element() {
return false
}
},
- None => match node.node().parent_node() {
+ None => match node.parent_node() {
// Selectors level 3 says :last-child does not match the
// root of the document; Warning, level 4 says, for the time
// being, the contrary...
@@ -703,9 +702,13 @@ fn matches_last_child<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: ElementL
}
#[inline]
-fn match_attribute<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: ElementLike>(
- attr: &AttrSelector, element: &T, f: &fn(&str)-> bool) -> bool {
- do element.with_imm_element_like |element: &E| {
+fn match_attribute<E:TElement,
+ N:TNode<E>>(
+ attr: &AttrSelector,
+ element: &N,
+ f: &fn(&str) -> bool)
+ -> bool {
+ do element.with_element |element: &E| {
// FIXME: avoid .clone() here? See #1367
match element.get_attr(attr.namespace.clone(), attr.name) {
None => false,
diff --git a/src/components/style/style.rc b/src/components/style/style.rc
index 00c891fd739..3868e39fb70 100644
--- a/src/components/style/style.rc
+++ b/src/components/style/style.rc
@@ -25,6 +25,7 @@ pub use selector_matching::{Stylist, StylesheetOrigin, UserAgentOrigin, AuthorOr
pub use properties::{cascade, PropertyDeclaration, ComputedValues, computed_values};
pub use properties::{PropertyDeclarationBlock, parse_style_attribute}; // Style attributes
pub use errors::with_errors_silenced;
+pub use node::{TElement, TNode};
mod stylesheets;
mod errors;
@@ -32,5 +33,6 @@ mod selectors;
mod selector_matching;
mod properties;
mod namespaces;
+mod node;
mod media_queries;
mod parsing_utils;
diff --git a/src/components/util/tree.rs b/src/components/util/tree.rs
deleted file mode 100644
index 64c26a2d4ea..00000000000
--- a/src/components/util/tree.rs
+++ /dev/null
@@ -1,354 +0,0 @@
-/* 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/. */
-
-//! Helper functions for garbage collected doubly-linked trees.
-
-// Macros to make add_child etc. less painful to write.
-// Code outside this module should instead implement TreeNode
-// and use its default methods.
-macro_rules! get(
- ($node:expr, $fun:ident) => (
- {
- let val: Option<Self> = TreeNodeRef::<Node>::$fun($node);
- val
- }
- )
-)
-
-macro_rules! set(
- ($node:expr, $fun:ident, $val:expr) => (
- {
- let val: Option<Self> = $val;
- TreeNodeRef::<Node>::$fun($node, val)
- }
- )
-)
-
-pub struct ChildIterator<Ref> {
- priv current: Option<Ref>,
-}
-
-impl<Node, Ref: TreeNodeRef<Node>> Iterator<Ref> for ChildIterator<Ref> {
- fn next(&mut self) -> Option<Ref> {
- if self.current.is_none() {
- return None;
- }
-
- // FIXME: Do we need two clones here?
- let x = self.current.get_ref().clone();
- self.current = TreeNodeRef::<Node>::next_sibling(x.node());
- Some(x.clone())
- }
-}
-
-pub struct AncestorIterator<Ref> {
- priv current: Option<Ref>,
-}
-
-impl<Node, Ref: TreeNodeRef<Node>> Iterator<Ref> for AncestorIterator<Ref> {
- fn next(&mut self) -> Option<Ref> {
- if self.current.is_none() {
- return None;
- }
-
- // FIXME: Do we need two clones here?
- let x = self.current.get_ref().clone();
- self.current = TreeNodeRef::<Node>::parent_node(x.node());
- Some(x.clone())
- }
-}
-
-// FIXME: Do this without precomputing a vector of refs.
-// Easy for preorder; harder for postorder.
-pub struct TreeIterator<Ref> {
- priv nodes: ~[Ref],
- priv index: uint,
-}
-
-impl<Ref> TreeIterator<Ref> {
- fn new(nodes: ~[Ref]) -> TreeIterator<Ref> {
- TreeIterator {
- nodes: nodes,
- index: 0,
- }
- }
-}
-
-impl<Ref: Clone> Iterator<Ref> for TreeIterator<Ref> {
- fn next(&mut self) -> Option<Ref> {
- if self.index >= self.nodes.len() {
- None
- } else {
- let v = self.nodes[self.index].clone();
- self.index += 1;
- Some(v)
- }
- }
-}
-
-/// A type implementing TreeNodeRef<Node> is a clonable reference to an underlying
-/// node type Node.
-///
-/// We have to define both ref and node operations in the same trait, which makes
-/// the latter more annoying to call (as static methods). But we provide non-static
-/// proxies in trait TreeNode below.
-pub trait TreeNodeRef<Node>: Clone {
-
- // Fundamental operations on refs.
-
- /// Borrows this node as immutable.
- fn node<'a>(&'a self) -> &'a Node;
- /// Borrows this node as mutable.
- fn mut_node<'a>(&'a self) -> &'a mut Node;
-
- // Fundamental operations on nodes.
-
- /// Returns the parent of this node.
- fn parent_node(node: &Node) -> Option<Self>;
-
- /// Returns the first child of this node.
- fn first_child(node: &Node) -> Option<Self>;
-
- /// Returns the last child of this node.
- fn last_child(node: &Node) -> Option<Self>;
-
- /// Returns the previous sibling of this node.
- fn prev_sibling(node: &Node) -> Option<Self>;
-
- /// Returns the next sibling of this node.
- fn next_sibling(node: &Node) -> Option<Self>;
-
- /// Sets the parent of this node.
- fn set_parent_node(node: &mut Node, new_parent: Option<Self>);
-
- /// Sets the first child of this node.
- fn set_first_child(node: &mut Node, new_first_child: Option<Self>);
-
- /// Sets the last child of this node.
- fn set_last_child(node: &mut Node, new_last_child: Option<Self>);
-
- /// Sets the previous sibling of this node.
- fn set_prev_sibling(node: &mut Node, new_prev_sibling: Option<Self>);
-
- /// Sets the next sibling of this node.
- fn set_next_sibling(node: &mut Node, new_next_sibling: Option<Self>);
-
-
- // The tree utilities, operating on refs mostly.
-
- /// Returns true if this node is disconnected from the tree or has no children.
- fn is_leaf(&self) -> bool {
- (get!(self.node(), first_child)).is_none()
- }
-
- /// 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: Self, before: Option<Self>) {
- let this_node = self.mut_node();
- let new_child_node = new_child.mut_node();
- assert!((get!(new_child_node, parent_node)).is_none());
- assert!((get!(new_child_node, prev_sibling)).is_none());
- assert!((get!(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!((get!(before_node, parent_node)).is_some());
- set!(before_node, set_prev_sibling, Some(new_child.clone()));
- set!(new_child_node, set_next_sibling, Some(before.clone()));
- match get!(before_node, prev_sibling) {
- None => {
- // XXX Should assert that before is the first child of
- // self.
- set!(this_node, set_first_child, Some(new_child.clone()));
- },
- Some(prev_sibling) => {
- let prev_sibling_node = prev_sibling.mut_node();
- set!(prev_sibling_node, set_next_sibling, Some(new_child.clone()));
- set!(new_child_node, set_prev_sibling, Some(prev_sibling.clone()));
- },
- }
- },
- None => {
- match get!(this_node, last_child) {
- None => set!(this_node, set_first_child, Some(new_child.clone())),
- Some(last_child) => {
- let last_child_node = last_child.mut_node();
- assert!((get!(last_child_node, next_sibling)).is_none());
- set!(last_child_node, set_next_sibling, Some(new_child.clone()));
- set!(new_child_node, set_prev_sibling, Some(last_child.clone()));
- }
- }
-
- set!(this_node, set_last_child, Some(new_child.clone()));
- },
- }
-
- set!(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: Self) {
- let this_node = self.mut_node();
- let child_node = child.mut_node();
- assert!((get!(child_node, parent_node)).is_some());
-
- match get!(child_node, prev_sibling) {
- None => set!(this_node, set_first_child, get!(child_node, next_sibling)),
- Some(prev_sibling) => {
- let prev_sibling_node = prev_sibling.mut_node();
- set!(prev_sibling_node, set_next_sibling, get!(child_node, next_sibling));
- }
- }
-
- match get!(child_node, next_sibling) {
- None => set!(this_node, set_last_child, get!(child_node, prev_sibling)),
- Some(next_sibling) => {
- let next_sibling_node = next_sibling.mut_node();
- set!(next_sibling_node, set_prev_sibling, get!(child_node, prev_sibling));
- }
- }
-
- set!(child_node, set_prev_sibling, None);
- set!(child_node, set_next_sibling, None);
- set!(child_node, set_parent_node, None);
- }
-
- /// Iterates over all children of this node.
- fn children(&self) -> ChildIterator<Self> {
- ChildIterator {
- current: get!(self.node(), first_child),
- }
- }
-
- /// Iterates over all ancestors of this node.
- fn ancestors(&self) -> AncestorIterator<Self> {
- AncestorIterator {
- current: get!(self.node(), parent_node),
- }
- }
-
- /// Iterates over this node and all its descendants, in preorder.
- fn traverse_preorder(&self) -> TreeIterator<Self> {
- self.traverse_preorder_prune(|_| false)
- }
-
- /// Iterates over this node and all its descendants, in postorder.
- fn traverse_postorder(&self) -> TreeIterator<Self> {
- self.traverse_postorder_prune(|_| false)
- }
-
- /// Like traverse_preorder but calls 'prune' first on each node. If it returns true then we
- /// skip the whole subtree but continue iterating.
- fn traverse_preorder_prune(&self, prune: &fn(&Self) -> bool) -> TreeIterator<Self> {
- let mut nodes = ~[];
- gather(self, &mut nodes, false, prune);
- TreeIterator::new(nodes)
- }
-
- /// Like traverse_postorder but calls 'prune' first on each node. If it returns true then we
- /// skip the whole subtree but continue iterating.
- ///
- /// NB: 'prune' is called *before* traversing children, even though this is a
- /// postorder traversal.
- fn traverse_postorder_prune(&self, prune: &fn(&Self) -> bool) -> TreeIterator<Self> {
- let mut nodes = ~[];
- gather(self, &mut nodes, true, prune);
- TreeIterator::new(nodes)
- }
-
- fn is_element(&self) -> bool;
-
- fn is_document(&self) -> bool;
-}
-
-pub trait TreeNodeRefAsElement<Node, E: ElementLike>: TreeNodeRef<Node> {
- fn with_imm_element_like<R>(&self, f: &fn(&E) -> R) -> R;
-}
-
-fn gather<Node, Ref: TreeNodeRef<Node>>(cur: &Ref, refs: &mut ~[Ref],
- postorder: bool, prune: &fn(&Ref) -> bool) {
- // prune shouldn't mutate, so don't clone
- if prune(cur) {
- return;
- }
-
- if !postorder {
- refs.push(cur.clone());
- }
- for kid in cur.children() {
- // FIXME: Work around rust#2202. We should be able to pass the callback directly.
- gather(&kid, refs, postorder, |a| prune(a))
- }
- if postorder {
- refs.push(cur.clone());
- }
-}
-
-
-/// Access the fields of a node without a static TreeNodeRef method call.
-/// If you make an impl TreeNodeRef<Node> for Ref then you should also make
-/// impl TreeNode<Ref> for Node with an empty body.
-pub trait TreeNode<Ref: TreeNodeRef<Self>> {
- /// Returns the parent of this node.
- fn parent_node(&self) -> Option<Ref> {
- TreeNodeRef::<Self>::parent_node(self)
- }
-
- /// Returns the first child of this node.
- fn first_child(&self) -> Option<Ref> {
- TreeNodeRef::<Self>::first_child(self)
- }
-
- /// Returns the last child of this node.
- fn last_child(&self) -> Option<Ref> {
- TreeNodeRef::<Self>::last_child(self)
- }
-
- /// Returns the previous sibling of this node.
- fn prev_sibling(&self) -> Option<Ref> {
- TreeNodeRef::<Self>::prev_sibling(self)
- }
-
- /// Returns the next sibling of this node.
- fn next_sibling(&self) -> Option<Ref> {
- TreeNodeRef::<Self>::next_sibling(self)
- }
-
- /// Sets the parent of this node.
- fn set_parent_node(&mut self, new_parent: Option<Ref>) {
- TreeNodeRef::<Self>::set_parent_node(self, new_parent)
- }
-
- /// Sets the first child of this node.
- fn set_first_child(&mut self, new_first_child: Option<Ref>) {
- TreeNodeRef::<Self>::set_first_child(self, new_first_child)
- }
-
- /// Sets the last child of this node.
- fn set_last_child(&mut self, new_last_child: Option<Ref>) {
- TreeNodeRef::<Self>::set_last_child(self, new_last_child)
- }
-
- /// Sets the previous sibling of this node.
- fn set_prev_sibling(&mut self, new_prev_sibling: Option<Ref>) {
- TreeNodeRef::<Self>::set_prev_sibling(self, new_prev_sibling)
- }
-
- /// Sets the next sibling of this node.
- fn set_next_sibling(&mut self, new_next_sibling: Option<Ref>) {
- TreeNodeRef::<Self>::set_next_sibling(self, new_next_sibling)
- }
-}
-
-
-pub trait ElementLike {
- fn get_local_name<'a>(&'a self) -> &'a str;
- fn get_namespace_url<'a>(&'a self) -> &'a str;
- fn get_attr(&self, ns_url: Option<~str>, name: &str) -> Option<~str>;
- fn get_link(&self) -> Option<~str>;
-}
diff --git a/src/components/util/util.rc b/src/components/util/util.rc
index 5a7fddbb51f..d4b6b63483f 100644
--- a/src/components/util/util.rc
+++ b/src/components/util/util.rc
@@ -18,7 +18,6 @@ pub mod geometry;
pub mod range;
pub mod slot;
pub mod time;
-pub mod tree;
pub mod url;
pub mod vec;
pub mod debug;