mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +01:00
auto merge of #880 : ILyoan/servo/appendChild, r=jdm
This commit is contained in:
commit
62f0d19fab
4 changed files with 94 additions and 11 deletions
|
@ -290,7 +290,8 @@ DOMInterfaces = {
|
||||||
'Node': {
|
'Node': {
|
||||||
'nativeType': 'AbstractNode<ScriptView>',
|
'nativeType': 'AbstractNode<ScriptView>',
|
||||||
'concreteType': 'Node<ScriptView>',
|
'concreteType': 'Node<ScriptView>',
|
||||||
'pointerType': ''
|
'pointerType': '',
|
||||||
|
'needsAbstract': ['appendChild', 'removeChild']
|
||||||
},
|
},
|
||||||
|
|
||||||
'NodeList': [
|
'NodeList': [
|
||||||
|
|
|
@ -795,7 +795,9 @@ impl DerivedWrapper for AbstractNode<ScriptView> {
|
||||||
|
|
||||||
#[deriving(ToStr)]
|
#[deriving(ToStr)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
FailureUnknown
|
FailureUnknown,
|
||||||
|
NotFound,
|
||||||
|
HierarchyRequest,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ErrorResult = Result<(), Error>;
|
pub type ErrorResult = Result<(), Error>;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//! The core DOM types. Defines the basic DOM hierarchy as well as all the HTML elements.
|
//! The core DOM types. Defines the basic DOM hierarchy as well as all the HTML elements.
|
||||||
|
|
||||||
use dom::bindings::node;
|
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::utils::{BindingObject, CacheableWrapper, rust_box};
|
||||||
use dom::bindings;
|
use dom::bindings;
|
||||||
use dom::characterdata::CharacterData;
|
use dom::characterdata::CharacterData;
|
||||||
|
@ -263,6 +263,10 @@ impl<'self, View> AbstractNode<View> {
|
||||||
self.transmute_mut(f)
|
self.transmute_mut(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_doctype(self) -> bool {
|
||||||
|
self.type_id() == DoctypeNodeTypeId
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_comment(self) -> bool {
|
pub fn is_comment(self) -> bool {
|
||||||
self.type_id() == CommentNodeTypeId
|
self.type_id() == CommentNodeTypeId
|
||||||
}
|
}
|
||||||
|
@ -499,19 +503,19 @@ impl Node<ScriptView> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn GetFirstChild(&self) -> Option<AbstractNode<ScriptView>> {
|
pub fn GetFirstChild(&self) -> Option<AbstractNode<ScriptView>> {
|
||||||
None
|
self.first_child
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn GetLastChild(&self) -> Option<AbstractNode<ScriptView>> {
|
pub fn GetLastChild(&self) -> Option<AbstractNode<ScriptView>> {
|
||||||
None
|
self.last_child
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn GetPreviousSibling(&self) -> Option<AbstractNode<ScriptView>> {
|
pub fn GetPreviousSibling(&self) -> Option<AbstractNode<ScriptView>> {
|
||||||
None
|
self.prev_sibling
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn GetNextSibling(&self) -> Option<AbstractNode<ScriptView>> {
|
pub fn GetNextSibling(&self) -> Option<AbstractNode<ScriptView>> {
|
||||||
None
|
self.next_sibling
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn GetNodeValue(&self) -> DOMString {
|
pub fn GetNodeValue(&self) -> DOMString {
|
||||||
|
@ -553,16 +557,68 @@ impl Node<ScriptView> {
|
||||||
fail!("stub")
|
fail!("stub")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn AppendChild(&mut self, _node: AbstractNode<ScriptView>, _rv: &mut ErrorResult) -> AbstractNode<ScriptView> {
|
pub fn AppendChild(&mut self,
|
||||||
fail!("stub")
|
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> {
|
pub fn ReplaceChild(&mut self, _node: AbstractNode<ScriptView>, _child: AbstractNode<ScriptView>, _rv: &mut ErrorResult) -> AbstractNode<ScriptView> {
|
||||||
fail!("stub")
|
fail!("stub")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn RemoveChild(&mut self, _node: AbstractNode<ScriptView>, _rv: &mut ErrorResult) -> AbstractNode<ScriptView> {
|
pub fn RemoveChild(&mut self,
|
||||||
fail!("stub")
|
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) {
|
pub fn Normalize(&mut self) {
|
||||||
|
|
|
@ -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.
|
// FIXME: Do this without precomputing a vector of refs.
|
||||||
// Easy for preorder; harder for postorder.
|
// Easy for preorder; harder for postorder.
|
||||||
pub struct TreeIterator<Ref> {
|
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.
|
/// Iterates over this node and all its descendants, in preorder.
|
||||||
fn traverse_preorder(&self) -> TreeIterator<Self> {
|
fn traverse_preorder(&self) -> TreeIterator<Self> {
|
||||||
self.traverse_preorder_prune(|_| false)
|
self.traverse_preorder_prune(|_| false)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue