From 995e4fdd112b46dd4558e458b3f0e9c319386f52 Mon Sep 17 00:00:00 2001 From: Ilyong Cho Date: Thu, 5 Sep 2013 12:36:29 +0900 Subject: [PATCH 1/4] Add some dom node tree implementations --- src/components/script/dom/node.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs index 6ed81517567..2eedaa8bbe8 100644 --- a/src/components/script/dom/node.rs +++ b/src/components/script/dom/node.rs @@ -499,19 +499,19 @@ impl Node { } pub fn GetFirstChild(&self) -> Option> { - None + self.first_child } pub fn GetLastChild(&self) -> Option> { - None + self.last_child } pub fn GetPreviousSibling(&self) -> Option> { - None + self.prev_sibling } pub fn GetNextSibling(&self) -> Option> { - None + self.next_sibling } pub fn GetNodeValue(&self) -> DOMString { From bcd7c0b8c6a3fd4ed1839a9a3e781eb77a954922 Mon Sep 17 00:00:00 2001 From: Ilyong Cho Date: Thu, 5 Sep 2013 12:49:10 +0900 Subject: [PATCH 2/4] Add node.removeChild --- .../script/dom/bindings/codegen/Bindings.conf | 3 ++- src/components/script/dom/bindings/utils.rs | 3 ++- src/components/script/dom/node.rs | 23 ++++++++++++++++--- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/components/script/dom/bindings/codegen/Bindings.conf b/src/components/script/dom/bindings/codegen/Bindings.conf index 5f6ed7de836..5ec918b6b2c 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', 'concreteType': 'Node', - 'pointerType': '' + 'pointerType': '', + 'needsAbstract': ['removeChild'] }, 'NodeList': [ diff --git a/src/components/script/dom/bindings/utils.rs b/src/components/script/dom/bindings/utils.rs index 3ea5eda38c7..9dfc4e965d0 100644 --- a/src/components/script/dom/bindings/utils.rs +++ b/src/components/script/dom/bindings/utils.rs @@ -795,7 +795,8 @@ impl DerivedWrapper for AbstractNode { #[deriving(ToStr)] pub enum Error { - FailureUnknown + FailureUnknown, + NotFound, } pub type ErrorResult = Result<(), Error>; diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs index 2eedaa8bbe8..5aeab579f54 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}; use dom::bindings::utils::{BindingObject, CacheableWrapper, rust_box}; use dom::bindings; use dom::characterdata::CharacterData; @@ -561,8 +561,25 @@ impl Node { fail!("stub") } - pub fn RemoveChild(&mut self, _node: AbstractNode, _rv: &mut ErrorResult) -> AbstractNode { - fail!("stub") + pub fn RemoveChild(&mut self, + abstract_self: AbstractNode, + node: AbstractNode, + rv: &mut ErrorResult) -> AbstractNode { + fn is_not_found_err(this_node: AbstractNode, + old_child: AbstractNode) -> 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) { From 47c5279e3145cf47d2d61da7b98c1d7b112fde81 Mon Sep 17 00:00:00 2001 From: Ilyong Cho Date: Mon, 9 Sep 2013 15:32:07 +0900 Subject: [PATCH 3/4] Add AncestorIterator by jgraham --- src/components/util/tree.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) 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> Iterator for ChildIterator { } } +pub struct AncestorIterator { + priv current: Option, +} + +impl> Iterator for AncestorIterator { + fn next(&mut self) -> Option { + 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::::parent_node(n)); + Some(x.clone()) + } +} + // FIXME: Do this without precomputing a vector of refs. // Easy for preorder; harder for postorder. pub struct TreeIterator { @@ -196,6 +213,13 @@ pub trait TreeNodeRef: Clone { } } + /// Iterates over all ancestors of this node. + fn ancestors(&self) -> AncestorIterator { + 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.traverse_preorder_prune(|_| false) From 0d4cfd0eb93456d9ead4fa77fcc5990511745240 Mon Sep 17 00:00:00 2001 From: Ilyong Cho Date: Thu, 5 Sep 2013 13:02:52 +0900 Subject: [PATCH 4/4] Add node.appendChild --- .../script/dom/bindings/codegen/Bindings.conf | 2 +- src/components/script/dom/bindings/utils.rs | 1 + src/components/script/dom/node.rs | 45 +++++++++++++++++-- 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/components/script/dom/bindings/codegen/Bindings.conf b/src/components/script/dom/bindings/codegen/Bindings.conf index 5ec918b6b2c..0ef1d9d502a 100644 --- a/src/components/script/dom/bindings/codegen/Bindings.conf +++ b/src/components/script/dom/bindings/codegen/Bindings.conf @@ -291,7 +291,7 @@ DOMInterfaces = { 'nativeType': 'AbstractNode', 'concreteType': 'Node', 'pointerType': '', - 'needsAbstract': ['removeChild'] + 'needsAbstract': ['appendChild', 'removeChild'] }, 'NodeList': [ diff --git a/src/components/script/dom/bindings/utils.rs b/src/components/script/dom/bindings/utils.rs index 9dfc4e965d0..547405e13a2 100644 --- a/src/components/script/dom/bindings/utils.rs +++ b/src/components/script/dom/bindings/utils.rs @@ -797,6 +797,7 @@ impl DerivedWrapper for AbstractNode { pub enum Error { 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 5aeab579f54..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, NotFound}; +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 { self.transmute_mut(f) } + pub fn is_doctype(self) -> bool { + self.type_id() == DoctypeNodeTypeId + } + pub fn is_comment(self) -> bool { self.type_id() == CommentNodeTypeId } @@ -553,8 +557,43 @@ impl Node { fail!("stub") } - pub fn AppendChild(&mut self, _node: AbstractNode, _rv: &mut ErrorResult) -> AbstractNode { - fail!("stub") + pub fn AppendChild(&mut self, + abstract_self: AbstractNode, + node: AbstractNode, + rv: &mut ErrorResult) -> AbstractNode { + fn is_hierarchy_request_err(this_node: AbstractNode, + new_child: AbstractNode) -> 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, _child: AbstractNode, _rv: &mut ErrorResult) -> AbstractNode {