aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorbors-servo <release+servo@mozilla.com>2013-09-09 22:09:44 -0700
committerbors-servo <release+servo@mozilla.com>2013-09-09 22:09:44 -0700
commit62f0d19fabe218cbd720892283de2122820ea01e (patch)
tree812f63f0f59a18096dcbabe9985b9ea3a7f90366 /src
parentae0d531dd6857d62777190bd91248600c21c9900 (diff)
parent0d4cfd0eb93456d9ead4fa77fcc5990511745240 (diff)
downloadservo-62f0d19fabe218cbd720892283de2122820ea01e.tar.gz
servo-62f0d19fabe218cbd720892283de2122820ea01e.zip
auto merge of #880 : ILyoan/servo/appendChild, r=jdm
Diffstat (limited to 'src')
-rw-r--r--src/components/script/dom/bindings/codegen/Bindings.conf3
-rw-r--r--src/components/script/dom/bindings/utils.rs4
-rw-r--r--src/components/script/dom/node.rs74
-rw-r--r--src/components/util/tree.rs24
4 files changed, 94 insertions, 11 deletions
diff --git a/src/components/script/dom/bindings/codegen/Bindings.conf b/src/components/script/dom/bindings/codegen/Bindings.conf
index 5f6ed7de836..0ef1d9d502a 100644
--- a/src/components/script/dom/bindings/codegen/Bindings.conf
+++ b/src/components/script/dom/bindings/codegen/Bindings.conf
@@ -290,7 +290,8 @@ DOMInterfaces = {
'Node': {
'nativeType': 'AbstractNode<ScriptView>',
'concreteType': 'Node<ScriptView>',
- 'pointerType': ''
+ 'pointerType': '',
+ 'needsAbstract': ['appendChild', 'removeChild']
},
'NodeList': [
diff --git a/src/components/script/dom/bindings/utils.rs b/src/components/script/dom/bindings/utils.rs
index 3ea5eda38c7..547405e13a2 100644
--- a/src/components/script/dom/bindings/utils.rs
+++ b/src/components/script/dom/bindings/utils.rs
@@ -795,7 +795,9 @@ impl DerivedWrapper for AbstractNode<ScriptView> {
#[deriving(ToStr)]
pub enum Error {
- FailureUnknown
+ FailureUnknown,
+ NotFound,
+ HierarchyRequest,
}
pub type ErrorResult = Result<(), Error>;
diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs
index 6ed81517567..e137d4c31d0 100644
--- a/src/components/script/dom/node.rs
+++ b/src/components/script/dom/node.rs
@@ -5,7 +5,7 @@
//! The core DOM types. Defines the basic DOM hierarchy as well as all the HTML elements.
use dom::bindings::node;
-use dom::bindings::utils::{WrapperCache, DOMString, null_string, str, ErrorResult};
+use dom::bindings::utils::{WrapperCache, DOMString, null_string, str, ErrorResult, NotFound, HierarchyRequest};
use dom::bindings::utils::{BindingObject, CacheableWrapper, rust_box};
use dom::bindings;
use dom::characterdata::CharacterData;
@@ -263,6 +263,10 @@ impl<'self, View> AbstractNode<View> {
self.transmute_mut(f)
}
+ pub fn is_doctype(self) -> bool {
+ self.type_id() == DoctypeNodeTypeId
+ }
+
pub fn is_comment(self) -> bool {
self.type_id() == CommentNodeTypeId
}
@@ -499,19 +503,19 @@ impl Node<ScriptView> {
}
pub fn GetFirstChild(&self) -> Option<AbstractNode<ScriptView>> {
- None
+ self.first_child
}
pub fn GetLastChild(&self) -> Option<AbstractNode<ScriptView>> {
- None
+ self.last_child
}
pub fn GetPreviousSibling(&self) -> Option<AbstractNode<ScriptView>> {
- None
+ self.prev_sibling
}
pub fn GetNextSibling(&self) -> Option<AbstractNode<ScriptView>> {
- None
+ self.next_sibling
}
pub fn GetNodeValue(&self) -> DOMString {
@@ -553,16 +557,68 @@ impl Node<ScriptView> {
fail!("stub")
}
- pub fn AppendChild(&mut self, _node: AbstractNode<ScriptView>, _rv: &mut ErrorResult) -> AbstractNode<ScriptView> {
- fail!("stub")
+ pub fn AppendChild(&mut self,
+ abstract_self: AbstractNode<ScriptView>,
+ node: AbstractNode<ScriptView>,
+ rv: &mut ErrorResult) -> AbstractNode<ScriptView> {
+ fn is_hierarchy_request_err(this_node: AbstractNode<ScriptView>,
+ new_child: AbstractNode<ScriptView>) -> bool {
+ if new_child.is_doctype() {
+ return true;
+ }
+ if !this_node.is_element() {
+ // FIXME: This should also work for Document and DocumentFragments when they inherit from node.
+ // per jgraham
+ return true;
+ }
+ if this_node == new_child {
+ return true;
+ }
+ for ancestor in this_node.ancestors() {
+ if ancestor == new_child {
+ return true;
+ }
+ }
+ false
+ }
+
+ if is_hierarchy_request_err(abstract_self, node) {
+ *rv = Err(HierarchyRequest);
+ }
+
+ // TODO: Should we handle WRONG_DOCUMENT_ERR here?
+
+ if rv.is_ok() {
+ // If the node already exists it is removed from current parent node.
+ node.parent_node().map(|parent| parent.remove_child(node));
+ abstract_self.add_child(node);
+ }
+ node
}
pub fn ReplaceChild(&mut self, _node: AbstractNode<ScriptView>, _child: AbstractNode<ScriptView>, _rv: &mut ErrorResult) -> AbstractNode<ScriptView> {
fail!("stub")
}
- pub fn RemoveChild(&mut self, _node: AbstractNode<ScriptView>, _rv: &mut ErrorResult) -> AbstractNode<ScriptView> {
- fail!("stub")
+ pub fn RemoveChild(&mut self,
+ abstract_self: AbstractNode<ScriptView>,
+ node: AbstractNode<ScriptView>,
+ rv: &mut ErrorResult) -> AbstractNode<ScriptView> {
+ fn is_not_found_err(this_node: AbstractNode<ScriptView>,
+ old_child: AbstractNode<ScriptView>) -> bool {
+ match old_child.parent_node() {
+ Some(parent) if parent == this_node => false,
+ _ => true
+ }
+ }
+
+ if is_not_found_err(abstract_self, node) {
+ *rv = Err(NotFound);
+ }
+ if rv.is_ok() {
+ abstract_self.remove_child(node);
+ }
+ node
}
pub fn Normalize(&mut self) {
diff --git a/src/components/util/tree.rs b/src/components/util/tree.rs
index d38d4a7f5da..2b3b467ac45 100644
--- a/src/components/util/tree.rs
+++ b/src/components/util/tree.rs
@@ -42,6 +42,23 @@ impl<Node, Ref: TreeNodeRef<Node>> Iterator<Ref> for ChildIterator<Ref> {
}
}
+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 = x.with_base(|n| TreeNodeRef::<Node>::parent_node(n));
+ Some(x.clone())
+ }
+}
+
// FIXME: Do this without precomputing a vector of refs.
// Easy for preorder; harder for postorder.
pub struct TreeIterator<Ref> {
@@ -196,6 +213,13 @@ pub trait TreeNodeRef<Node>: Clone {
}
}
+ /// Iterates over all ancestors of this node.
+ fn ancestors(&self) -> AncestorIterator<Self> {
+ AncestorIterator {
+ current: self.with_base(|n| get!(n, parent_node)),
+ }
+ }
+
/// Iterates over this node and all its descendants, in preorder.
fn traverse_preorder(&self) -> TreeIterator<Self> {
self.traverse_preorder_prune(|_| false)