diff options
Diffstat (limited to 'src/components/script/dom/node.rs')
-rw-r--r-- | src/components/script/dom/node.rs | 1152 |
1 files changed, 488 insertions, 664 deletions
diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs index 3f0649fbdac..4526b45dd8b 100644 --- a/src/components/script/dom/node.rs +++ b/src/components/script/dom/node.rs @@ -4,22 +4,23 @@ //! The core DOM types. Defines the basic DOM hierarchy as well as all the HTML elements. +use dom::bindings::codegen::InheritTypes::{DocumentTypeCast, ElementCast, TextCast, NodeCast}; +use dom::bindings::codegen::InheritTypes::{CharacterDataCast, NodeBase, NodeDerived}; +use dom::bindings::codegen::InheritTypes::ProcessingInstructionCast; +use dom::bindings::js::JS; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{ErrorResult, Fallible, NotFound, HierarchyRequest}; use dom::bindings::utils; use dom::characterdata::CharacterData; -use dom::document::{AbstractDocument, DocumentTypeId}; +use dom::document::{Document, DocumentTypeId}; use dom::documenttype::DocumentType; -use dom::element::{Element, ElementTypeId, HTMLImageElementTypeId, HTMLIframeElementTypeId, HTMLObjectElementTypeId}; -use dom::element::{HTMLAnchorElementTypeId, HTMLStyleElementTypeId}; -use dom::eventtarget::{AbstractEventTarget, EventTarget, NodeTypeId}; -use dom::htmliframeelement::HTMLIFrameElement; -use dom::htmlimageelement::HTMLImageElement; -use dom::htmlobjectelement::HTMLObjectElement; +use dom::element::{Element, ElementTypeId, HTMLAnchorElementTypeId}; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::nodelist::{NodeList}; use dom::text::Text; use dom::processinginstruction::ProcessingInstruction; use layout_interface::{LayoutChan, ReapLayoutDataMsg, UntrustedNodeAddress}; +use layout_interface::TrustedNodeAddress; use servo_util::str::{DOMString, null_str_as_empty}; use js::jsapi::{JSContext, JSObject, JSRuntime}; @@ -27,25 +28,19 @@ use js::jsfriendapi; use std::cast::transmute; use std::cast; use std::cell::{RefCell, Ref, RefMut}; -use std::iter::Filter; +use std::iter::{Map, Filter}; use std::libc::uintptr_t; -use std::util; use std::unstable::raw::Box; +use std::util; + +use extra::serialize::{Encoder, Encodable}; // // The basic Node structure // -/// This is what a Node looks like if you do not know what kind of node it is. To unpack it, use -/// downcast(). -/// -/// FIXME: This should be replaced with a trait once they can inherit from structs. -#[deriving(Eq)] -pub struct AbstractNode { - priv obj: *mut (), -} - /// An HTML node. +#[deriving(Encodable)] pub struct Node { /// The JavaScript reflector for this node. eventtarget: EventTarget, @@ -53,28 +48,26 @@ pub struct Node { /// The type of node that this is. type_id: NodeTypeId, - abstract: Option<AbstractNode>, - /// The parent of this node. - parent_node: Option<AbstractNode>, + parent_node: Option<JS<Node>>, /// The first child of this node. - first_child: Option<AbstractNode>, + first_child: Option<JS<Node>>, /// The last child of this node. - last_child: Option<AbstractNode>, + last_child: Option<JS<Node>>, /// The next sibling of this node. - next_sibling: Option<AbstractNode>, + next_sibling: Option<JS<Node>>, /// The previous sibling of this node. - prev_sibling: Option<AbstractNode>, + prev_sibling: Option<JS<Node>>, /// The document that this node belongs to. - priv owner_doc: Option<AbstractDocument>, + priv owner_doc: Option<JS<Document>>, /// The live list of children return by .childNodes. - child_list: Option<@mut NodeList>, + child_list: Option<JS<NodeList>>, /// A bitfield of flags for node items. priv flags: NodeFlags, @@ -86,7 +79,22 @@ pub struct Node { layout_data: LayoutDataRef, } +impl<S: Encoder> Encodable<S> for LayoutDataRef { + fn encode(&self, _s: &mut S) { + } +} + +impl NodeDerived for EventTarget { + fn is_node(&self) -> bool { + match self.type_id { + NodeTargetTypeId(_) => true, + _ => false + } + } +} + /// Flags for node items. +#[deriving(Encodable)] pub struct NodeFlags(u8); impl NodeFlags { @@ -195,7 +203,7 @@ impl LayoutDataRef { pub trait TLayoutData {} /// The different types of nodes. -#[deriving(Eq)] +#[deriving(Eq,Encodable)] pub enum NodeTypeId { DoctypeNodeTypeId, DocumentFragmentNodeTypeId, @@ -206,413 +214,209 @@ pub enum NodeTypeId { ProcessingInstructionNodeTypeId, } -impl Clone for AbstractNode { - fn clone(&self) -> AbstractNode { - *self - } +pub trait INode { + fn AppendChild(&mut self, node: &mut JS<Node>) -> Fallible<JS<Node>>; + fn ReplaceChild(&mut self, node: &mut JS<Node>, child: &mut JS<Node>) -> Fallible<JS<Node>>; + fn RemoveChild(&mut self, node: &mut JS<Node>) -> Fallible<JS<Node>>; } -impl AbstractNode { - #[inline] - pub fn node<'a>(&'a self) -> &'a Node { - unsafe { - let box_: *mut Box<Node> = cast::transmute(self.obj); - &(*box_).data - } - } - - #[inline] - pub fn mut_node<'a>(&'a self) -> &'a mut Node { - unsafe { - let box_: *mut Box<Node> = cast::transmute(self.obj); - &mut (*box_).data - } - } - - #[inline] - pub fn parent_node(&self) -> Option<AbstractNode> { - self.node().parent_node - } - - #[inline] - pub fn first_child(&self) -> Option<AbstractNode> { - self.node().first_child - } - - #[inline] - pub fn last_child(&self) -> Option<AbstractNode> { - self.node().last_child - } - - pub fn is_element(&self) -> bool { - match self.type_id() { - ElementNodeTypeId(..) => true, - _ => false - } - } - - pub fn is_document(&self) -> bool { - match self.type_id() { - DocumentNodeTypeId(..) => true, - _ => false - } - } - - /// If the given untrusted node address represents a valid DOM node in the given runtime, - /// returns it. - pub fn from_untrusted_node_address(runtime: *JSRuntime, candidate: UntrustedNodeAddress) - -> AbstractNode { - unsafe { - let candidate: uintptr_t = cast::transmute(candidate); - let object: *JSObject = jsfriendapi::bindgen::JS_GetAddressableObject(runtime, - candidate); - if object.is_null() { - fail!("Attempted to create an `AbstractNode` from an invalid pointer!") - } - let boxed_node: *mut Box<Node> = utils::unwrap(object); - AbstractNode::from_box(boxed_node) - } +impl INode for JS<Node> { + fn AppendChild(&mut self, node: &mut JS<Node>) -> Fallible<JS<Node>> { + let mut self_node = self.clone(); + self.get_mut().AppendChild(&mut self_node, node) } - pub fn is_inclusive_ancestor_of(&self, parent: AbstractNode) -> bool { - *self == parent || parent.ancestors().any(|ancestor| ancestor == *self) + fn ReplaceChild(&mut self, node: &mut JS<Node>, child: &mut JS<Node>) -> Fallible<JS<Node>> { + let mut self_node = self.clone(); + self.get_mut().ReplaceChild(&mut self_node, node, child) } - pub fn is_parent_of(&self, child: AbstractNode) -> bool { - child.parent_node() == Some(*self) + fn RemoveChild(&mut self, node: &mut JS<Node>) -> Fallible<JS<Node>> { + let mut self_node = self.clone(); + self.get_mut().RemoveChild(&mut self_node, node) } } -impl<'a> AbstractNode { - // Unsafe accessors +pub trait NodeHelpers { + fn ancestors(&self) -> AncestorIterator; + fn children(&self) -> AbstractNodeChildrenIterator; + fn child_elements(&self) -> ChildElementIterator; + fn following_siblings(&self) -> AbstractNodeChildrenIterator; + fn is_in_doc(&self) -> bool; + fn is_inclusive_ancestor_of(&self, parent: &JS<Node>) -> bool; + fn is_parent_of(&self, child: &JS<Node>) -> bool; + + fn type_id(&self) -> NodeTypeId; + + fn parent_node(&self) -> Option<JS<Node>>; + fn first_child(&self) -> Option<JS<Node>>; + fn last_child(&self) -> Option<JS<Node>>; + fn prev_sibling(&self) -> Option<JS<Node>>; + fn next_sibling(&self) -> Option<JS<Node>>; + + fn is_element(&self) -> bool; + fn is_document(&self) -> bool; + fn is_doctype(&self) -> bool; + fn is_text(&self) -> bool; + fn is_anchor_element(&self) -> bool; + + fn node_inserted(&self); + fn node_removed(&self); + fn add_child(&mut self, new_child: &mut JS<Node>, before: Option<JS<Node>>); + fn remove_child(&mut self, child: &mut JS<Node>); + + fn get_hover_state(&self) -> bool; + fn set_hover_state(&mut self, state: bool); + + fn dump(&self); + fn dump_indent(&self, indent: uint); + fn debug_str(&self) -> ~str; + + fn traverse_preorder(&self) -> TreeIterator; + fn sequential_traverse_postorder(&self) -> TreeIterator; + fn inclusively_following_siblings(&self) -> AbstractNodeChildrenIterator; + + fn from_untrusted_node_address(runtime: *JSRuntime, candidate: UntrustedNodeAddress) -> Self; + fn to_trusted_node_address(&self) -> TrustedNodeAddress; +} - pub unsafe fn as_cacheable_wrapper(&self) -> @mut Reflectable { - match self.type_id() { - TextNodeTypeId => { - let node: @mut Text = cast::transmute(self.obj); - node as @mut Reflectable - } - _ => { - fail!("unsupported node type") - } - } +impl NodeHelpers for JS<Node> { + /// Dumps the subtree rooted at this node, for debugging. + fn dump(&self) { + self.dump_indent(0); } - /// Allow consumers to recreate an AbstractNode from the raw boxed type. - /// Must only be used in situations where the boxed type is in the inheritance - /// chain for nodes. - /// - /// FIXME(pcwalton): Mark unsafe? - pub fn from_box<T>(ptr: *mut Box<T>) -> AbstractNode { - AbstractNode { - obj: ptr as *mut () + /// Dumps the node tree, for debugging, with indentation. + fn dump_indent(&self, indent: uint) { + let mut s = ~""; + for _ in range(0, indent) { + s.push_str(" "); } - } - /// Allow consumers to upcast from derived classes. - pub fn from_document(doc: AbstractDocument) -> AbstractNode { - unsafe { - cast::transmute(doc) - } - } + s.push_str(self.debug_str()); + debug!("{:s}", s); - pub fn from_eventtarget(target: AbstractEventTarget) -> AbstractNode { - assert!(target.is_node()); - unsafe { - cast::transmute(target) + // FIXME: this should have a pure version? + for kid in self.children() { + kid.dump_indent(indent + 1u) } } - // Convenience accessors - - /// Returns the type ID of this node. Fails if this node is borrowed mutably. - #[inline] - pub fn type_id(self) -> NodeTypeId { - self.node().type_id + /// Returns a string that describes this node. + fn debug_str(&self) -> ~str { + format!("{:?}", self.type_id()) } - /// Returns the previous sibling of this node. Fails if this node is borrowed mutably. - pub fn prev_sibling(self) -> Option<AbstractNode> { - self.node().prev_sibling + /// Iterates over all ancestors of this node. + fn ancestors(&self) -> AncestorIterator { + self.get().ancestors() } - /// Returns the next sibling of this node. Fails if this node is borrowed mutably. - pub fn next_sibling(self) -> Option<AbstractNode> { - self.node().next_sibling + fn children(&self) -> AbstractNodeChildrenIterator { + self.get().children() } - // - // Downcasting borrows - // - - pub fn transmute<'a, T, R>(self, f: |&'a T| -> R) -> R { - unsafe { - let node_box: *mut Box<Node> = transmute(self.obj); - let node = &mut (*node_box).data; - let old = node.abstract; - node.abstract = Some(self); - let box_: *Box<T> = transmute(self.obj); - let rv = f(&(*box_).data); - node.abstract = old; - rv - } + fn child_elements(&self) -> ChildElementIterator { + self.get().child_elements() } - pub fn transmute_mut<T, R>(self, f: |&mut T| -> R) -> R { - unsafe { - let node_box: *mut Box<Node> = transmute(self.obj); - let node = &mut (*node_box).data; - let old = node.abstract; - node.abstract = Some(self); - let box_: *Box<T> = transmute(self.obj); - let rv = f(cast::transmute(&(*box_).data)); - node.abstract = old; - rv - } + fn is_in_doc(&self) -> bool { + self.get().flags.is_in_doc() } - // FIXME: This should be doing dynamic borrow checking for safety. - pub fn is_characterdata(self) -> bool { - self.is_text() || self.is_comment() || self.is_processing_instruction() + /// Returns the type ID of this node. Fails if this node is borrowed mutably. + fn type_id(&self) -> NodeTypeId { + self.get().type_id } - pub fn with_imm_characterdata<R>(self, f: |&CharacterData| -> R) -> R { - if !self.is_characterdata() { - fail!(~"node is not characterdata"); - } - self.transmute(f) + fn parent_node(&self) -> Option<JS<Node>> { + self.get().parent_node.clone() } - pub fn with_mut_characterdata<R>(self, f: |&mut CharacterData| -> R) -> R { - if !self.is_characterdata() { - fail!(~"node is not characterdata"); - } - self.transmute_mut(f) + fn first_child(&self) -> Option<JS<Node>> { + self.get().first_child.clone() } - pub fn is_doctype(self) -> bool { - self.type_id() == DoctypeNodeTypeId + fn last_child(&self) -> Option<JS<Node>> { + self.get().last_child.clone() } - pub fn with_imm_doctype<R>(self, f: |&DocumentType| -> R) -> R { - if !self.is_doctype() { - fail!(~"node is not doctype"); - } - self.transmute(f) + /// Returns the previous sibling of this node. Fails if this node is borrowed mutably. + fn prev_sibling(&self) -> Option<JS<Node>> { + self.get().prev_sibling.clone() } - pub fn with_mut_doctype<R>(self, f: |&mut DocumentType| -> R) -> R { - if !self.is_doctype() { - fail!(~"node is not doctype"); - } - self.transmute_mut(f) + /// Returns the next sibling of this node. Fails if this node is borrowed mutably. + fn next_sibling(&self) -> Option<JS<Node>> { + self.get().next_sibling.clone() } #[inline] - pub fn is_comment(self) -> bool { - // FIXME(pcwalton): Temporary workaround for the lack of inlining of autogenerated `Eq` - // implementations in Rust. + fn is_element(&self) -> bool { match self.type_id() { - CommentNodeTypeId => true, - _ => false, + ElementNodeTypeId(..) => true, + _ => false } } #[inline] - pub fn is_text(self) -> bool { - // FIXME(pcwalton): Temporary workaround for the lack of inlining of autogenerated `Eq` - // implementations in Rust. + fn is_document(&self) -> bool { match self.type_id() { - TextNodeTypeId => true, - _ => false, - } - } - - pub fn with_imm_text<R>(self, f: |&Text| -> R) -> R { - if !self.is_text() { - fail!(~"node is not text"); - } - self.transmute(f) - } - - pub fn with_mut_text<R>(self, f: |&mut Text| -> R) -> R { - if !self.is_text() { - fail!(~"node is not text"); + DocumentNodeTypeId(..) => true, + _ => false } - self.transmute_mut(f) } #[inline] - pub fn is_processing_instruction(self) -> bool { - self.type_id() == ProcessingInstructionNodeTypeId - } - - pub fn with_imm_processing_instruction<R>(self, f: |&ProcessingInstruction| -> R) -> R { - if !self.is_processing_instruction() { - fail!("node is not processing instruction"); - } - self.transmute(f) - } - - // FIXME: This should be doing dynamic borrow checking for safety. - pub fn with_imm_element<R>(self, f: |&Element| -> R) -> R { - if !self.is_element() { - fail!(~"node is not an element"); - } - self.transmute(f) - } - - // FIXME: This should be doing dynamic borrow checking for safety. - pub fn as_mut_element<R>(self, f: |&mut Element| -> R) -> R { - if !self.is_element() { - fail!(~"node is not an element"); + fn is_anchor_element(&self) -> bool { + match self.type_id() { + ElementNodeTypeId(HTMLAnchorElementTypeId) => true, + _ => false } - self.transmute_mut(f) } #[inline] - pub fn is_image_element(self) -> bool { + fn is_doctype(&self) -> bool { match self.type_id() { - ElementNodeTypeId(HTMLImageElementTypeId) => true, - _ => false, - } - } - - pub fn with_mut_image_element<R>(self, f: |&mut HTMLImageElement| -> R) -> R { - if !self.is_image_element() { - fail!(~"node is not an image element"); + DoctypeNodeTypeId => true, + _ => false } - self.transmute_mut(f) - } - - pub fn is_iframe_element(self) -> bool { - self.type_id() == ElementNodeTypeId(HTMLIframeElementTypeId) } #[inline] - pub fn is_object_element(self) -> bool { - self.type_id() == ElementNodeTypeId(HTMLObjectElementTypeId) - } - - pub fn with_mut_object_element<R>(self, f: |&mut HTMLObjectElement| -> R) -> R { - if !self.is_object_element() { - fail!(~"node is not an image element"); - } - self.transmute_mut(f) - } - - pub fn with_mut_iframe_element<R>(self, f: |&mut HTMLIFrameElement| -> R) -> R { - if !self.is_iframe_element() { - fail!(~"node is not an iframe element"); - } - self.transmute_mut(f) - } - - pub fn is_style_element(self) -> bool { - self.type_id() == ElementNodeTypeId(HTMLStyleElementTypeId) - } - - pub fn is_anchor_element(self) -> bool { - self.type_id() == ElementNodeTypeId(HTMLAnchorElementTypeId) - } - - pub unsafe fn raw_object(self) -> *mut Box<Node> { - cast::transmute(self.obj) - } - - pub fn from_raw(raw: *mut Box<Node>) -> AbstractNode { - AbstractNode { - obj: raw as *mut () - } - } - - /// Dumps the subtree rooted at this node, for debugging. - pub fn dump(&self) { - self.dump_indent(0); - } - - /// Dumps the node tree, for debugging, with indentation. - pub fn dump_indent(&self, indent: uint) { - let mut s = ~""; - for _ in range(0, indent) { - s.push_str(" "); - } - - s.push_str(self.debug_str()); - debug!("{:s}", s); - - // FIXME: this should have a pure version? - for kid in self.children() { - kid.dump_indent(indent + 1u) + fn is_text(&self) -> bool { + // FIXME(pcwalton): Temporary workaround for the lack of inlining of autogenerated `Eq` + // implementations in Rust. + match self.type_id() { + TextNodeTypeId => true, + _ => false } } - /// Returns a string that describes this node. - pub fn debug_str(&self) -> ~str { - format!("{:?}", self.type_id()) - } - - // - // Convenience accessors - // - - pub fn children(&self) -> AbstractNodeChildrenIterator { - self.node().children() - } - - pub fn child_elements(&self) -> Filter<AbstractNode, AbstractNodeChildrenIterator> { - self.node().child_elements() - } - - pub fn is_in_doc(&self) -> bool { - self.node().flags.is_in_doc() - } - - pub fn get_hover_state(&self) -> bool { - self.node().flags.get_in_hover_state() - } - - pub fn set_hover_state(&self, state: bool) { - self.mut_node().flags.set_is_in_hover_state(state); - } -} - -impl AbstractNode { - // http://dom.spec.whatwg.org/#dom-node-appendchild - pub fn AppendChild(self, node: AbstractNode) -> Fallible<AbstractNode> { - self.node().AppendChild(self, node) - } - - // http://dom.spec.whatwg.org/#dom-node-replacechild - pub fn ReplaceChild(self, node: AbstractNode, child: AbstractNode) -> Fallible<AbstractNode> { - self.node().ReplaceChild(self, node, child) - } - - // http://dom.spec.whatwg.org/#dom-node-removechild - pub fn RemoveChild(self, node: AbstractNode) -> Fallible<AbstractNode> { - self.node().RemoveChild(self, node) - } - // http://dom.spec.whatwg.org/#node-is-inserted - fn node_inserted(self) { + fn node_inserted(&self) { assert!(self.parent_node().is_some()); - let document = self.node().owner_doc(); + let mut document = self.get().owner_doc(); // Register elements having "id" attribute to the owner doc. - document.mut_document().register_nodes_with_id(&self); + if self.is_element() { + document.get_mut().register_nodes_with_id(&ElementCast::to(self)); + } - document.document().content_changed(); + document.get().content_changed(); } // http://dom.spec.whatwg.org/#node-is-removed - fn node_removed(self) { + fn node_removed(&self) { assert!(self.parent_node().is_none()); - let document = self.node().owner_doc(); + let mut document = self.get().owner_doc(); // Unregister elements having "id". - document.mut_document().unregister_nodes_with_id(&self); + if self.is_element() { + document.get_mut().unregister_nodes_with_id(&ElementCast::to(self)); + } - document.document().content_changed(); + document.get().content_changed(); } // @@ -622,71 +426,66 @@ impl AbstractNode { /// 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, before: Option<AbstractNode>) { - 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()); + fn add_child(&mut self, new_child: &mut JS<Node>, before: Option<JS<Node>>) { + assert!(new_child.parent_node().is_none()); + assert!(new_child.prev_sibling().is_none()); + assert!(new_child.next_sibling().is_none()); match before { - Some(before) => { - let before_node = before.mut_node(); + Some(mut before) => { // XXX Should assert that parent is self. - assert!(before_node.parent_node.is_some()); - match before_node.prev_sibling { + assert!(before.parent_node().is_some()); + match before.prev_sibling() { None => { // XXX Should assert that before is the first child of // self. - this_node.set_first_child(Some(new_child.clone())); + self.get_mut().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())); + Some(mut prev_sibling) => { + prev_sibling.get_mut().set_next_sibling(Some(new_child.clone())); + new_child.get_mut().set_prev_sibling(Some(prev_sibling.clone())); }, } - before_node.set_prev_sibling(Some(new_child.clone())); - new_child_node.set_next_sibling(Some(before.clone())); + before.get_mut().set_prev_sibling(Some(new_child.clone())); + new_child.get_mut().set_next_sibling(Some(before.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())); + match self.last_child() { + None => self.get_mut().set_first_child(Some(new_child.clone())), + Some(mut last_child) => { + assert!(last_child.next_sibling().is_none()); + last_child.get_mut().set_next_sibling(Some(new_child.clone())); + new_child.get_mut().set_prev_sibling(Some(last_child.clone())); } } - this_node.set_last_child(Some(new_child.clone())); + self.get_mut().set_last_child(Some(new_child.clone())); }, } - new_child_node.set_parent_node(Some((*self).clone())); + new_child.get_mut().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) { - let this_node = self.mut_node(); - let child_node = child.mut_node(); + fn remove_child(&mut self, child: &mut JS<Node>) { + let this_node = self.get_mut(); + let child_node = child.get_mut(); 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); + None => this_node.set_first_child(child_node.next_sibling.clone()), + Some(ref mut prev_sibling) => { + let prev_sibling_node = prev_sibling.get_mut(); + prev_sibling_node.set_next_sibling(child_node.next_sibling.clone()); } } 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); + None => this_node.set_last_child(child_node.prev_sibling.clone()), + Some(ref mut next_sibling) => { + let next_sibling_node = next_sibling.get_mut(); + next_sibling_node.set_prev_sibling(child_node.prev_sibling.clone()); } } @@ -694,20 +493,89 @@ impl AbstractNode { child_node.set_next_sibling(None); child_node.set_parent_node(None); } + + fn get_hover_state(&self) -> bool { + self.get().flags.get_in_hover_state() + } + + fn set_hover_state(&mut self, state: bool) { + self.get_mut().flags.set_is_in_hover_state(state); + } + + /// Iterates over this node and all its descendants, in preorder. + fn traverse_preorder(&self) -> TreeIterator { + let mut nodes = ~[]; + gather_abstract_nodes(self, &mut nodes, false); + TreeIterator::new(nodes) + } + + /// Iterates over this node and all its descendants, in postorder. + fn sequential_traverse_postorder(&self) -> TreeIterator { + let mut nodes = ~[]; + gather_abstract_nodes(self, &mut nodes, true); + TreeIterator::new(nodes) + } + + fn inclusively_following_siblings(&self) -> AbstractNodeChildrenIterator { + AbstractNodeChildrenIterator { + current_node: Some(self.clone()), + } + } + + fn is_inclusive_ancestor_of(&self, parent: &JS<Node>) -> bool { + self == parent || parent.ancestors().any(|ancestor| ancestor == *self) + } + + fn following_siblings(&self) -> AbstractNodeChildrenIterator { + AbstractNodeChildrenIterator { + current_node: self.next_sibling(), + } + } + + fn is_parent_of(&self, child: &JS<Node>) -> bool { + match child.parent_node() { + Some(ref parent) if parent == self => true, + _ => false + } + } + + /// If the given untrusted node address represents a valid DOM node in the given runtime, + /// returns it. + fn from_untrusted_node_address(runtime: *JSRuntime, candidate: UntrustedNodeAddress) + -> JS<Node> { + unsafe { + let candidate: uintptr_t = cast::transmute(candidate); + let object: *JSObject = jsfriendapi::bindgen::JS_GetAddressableObject(runtime, + candidate); + if object.is_null() { + fail!("Attempted to create a `JS<Node>` from an invalid pointer!") + } + let boxed_node: *mut Box<Node> = utils::unwrap(object); + JS::from_box(boxed_node) + } + } + + fn to_trusted_node_address(&self) -> TrustedNodeAddress { + self.get() as *Node as TrustedNodeAddress + } } // // Iteration and traversal // +type ChildElementIterator<'a> = Map<'a, JS<Node>, + JS<Element>, + Filter<'a, JS<Node>, AbstractNodeChildrenIterator>>; + pub struct AbstractNodeChildrenIterator { - priv current_node: Option<AbstractNode>, + priv current_node: Option<JS<Node>>, } -impl Iterator<AbstractNode> for AbstractNodeChildrenIterator { - fn next(&mut self) -> Option<AbstractNode> { - let node = self.current_node; - self.current_node = self.current_node.and_then(|node| { +impl Iterator<JS<Node>> for AbstractNodeChildrenIterator { + fn next(&mut self) -> Option<JS<Node>> { + let node = self.current_node.clone(); + self.current_node = node.clone().and_then(|node| { node.next_sibling() }); node @@ -715,11 +583,11 @@ impl Iterator<AbstractNode> for AbstractNodeChildrenIterator { } pub struct AncestorIterator { - priv current: Option<AbstractNode>, + priv current: Option<JS<Node>>, } -impl Iterator<AbstractNode> for AncestorIterator { - fn next(&mut self) -> Option<AbstractNode> { +impl Iterator<JS<Node>> for AncestorIterator { + fn next(&mut self) -> Option<JS<Node>> { if self.current.is_none() { return None; } @@ -734,12 +602,12 @@ impl Iterator<AbstractNode> for AncestorIterator { // FIXME: Do this without precomputing a vector of refs. // Easy for preorder; harder for postorder. pub struct TreeIterator { - priv nodes: ~[AbstractNode], + priv nodes: ~[JS<Node>], priv index: uint, } impl TreeIterator { - fn new(nodes: ~[AbstractNode]) -> TreeIterator { + fn new(nodes: ~[JS<Node>]) -> TreeIterator { TreeIterator { nodes: nodes, index: 0, @@ -747,8 +615,8 @@ impl TreeIterator { } } -impl Iterator<AbstractNode> for TreeIterator { - fn next(&mut self) -> Option<AbstractNode> { +impl Iterator<JS<Node>> for TreeIterator { + fn next(&mut self) -> Option<JS<Node>> { if self.index >= self.nodes.len() { None } else { @@ -760,15 +628,15 @@ impl Iterator<AbstractNode> for TreeIterator { } pub struct NodeIterator { - start_node: AbstractNode, - current_node: Option<AbstractNode>, + start_node: JS<Node>, + current_node: Option<JS<Node>>, depth: uint, priv include_start: bool, priv include_descendants_of_void: bool } impl NodeIterator { - pub fn new(start_node: AbstractNode, include_start: bool, include_descendants_of_void: bool) -> NodeIterator { + pub fn new(start_node: JS<Node>, include_start: bool, include_descendants_of_void: bool) -> NodeIterator { NodeIterator { start_node: start_node, current_node: None, @@ -778,44 +646,42 @@ impl NodeIterator { } } - fn next_child(&self, node: AbstractNode) -> Option<AbstractNode> { - if !self.include_descendants_of_void && - node.is_element() { - node.with_imm_element(|elem| { - if elem.is_void() { - None - } else { - node.first_child() - } - }) + fn next_child(&self, node: &JS<Node>) -> Option<JS<Node>> { + if !self.include_descendants_of_void && node.is_element() { + let elem: JS<Element> = ElementCast::to(node); + if elem.get().is_void() { + None + } else { + node.first_child() + } } else { node.first_child() } } } -impl Iterator<AbstractNode> for NodeIterator { - fn next(&mut self) -> Option<AbstractNode> { +impl Iterator<JS<Node>> for NodeIterator { + fn next(&mut self) -> Option<JS<Node>> { self.current_node = match self.current_node { None => { if self.include_start { - Some(self.start_node) + Some(self.start_node.clone()) } else { - self.next_child(self.start_node) + self.next_child(&self.start_node) } }, - Some(node) => { + Some(ref node) => { match self.next_child(node) { Some(child) => { self.depth += 1; - Some(child) + Some(child.clone()) }, - None if node == self.start_node => None, + None if node == &self.start_node => None, None => { match node.next_sibling() { Some(sibling) => Some(sibling), None => { - let mut candidate = node; + let mut candidate = node.clone(); while candidate.next_sibling().is_none() { candidate = candidate.parent_node().expect("Got to root without reaching start node"); self.depth -= 1; @@ -834,11 +700,11 @@ impl Iterator<AbstractNode> for NodeIterator { } } }; - self.current_node + self.current_node.clone() } } -fn gather_abstract_nodes(cur: &AbstractNode, refs: &mut ~[AbstractNode], postorder: bool) { +fn gather_abstract_nodes(cur: &JS<Node>, refs: &mut ~[JS<Node>], postorder: bool) { if !postorder { refs.push(cur.clone()); } @@ -850,75 +716,48 @@ fn gather_abstract_nodes(cur: &AbstractNode, refs: &mut ~[AbstractNode], postord } } -impl AbstractNode { - /// Iterates over all ancestors of this node. +impl Node { pub fn ancestors(&self) -> AncestorIterator { AncestorIterator { - current: self.parent_node(), + current: self.parent_node.clone(), } } - pub fn inclusively_following_siblings(&self) -> AbstractNodeChildrenIterator { - AbstractNodeChildrenIterator { - current_node: Some(*self), - } + pub fn owner_doc(&self) -> JS<Document> { + self.owner_doc.clone().unwrap() } - pub fn following_siblings(&self) -> AbstractNodeChildrenIterator { - AbstractNodeChildrenIterator { - current_node: self.next_sibling(), - } - } - - /// Iterates over this node and all its descendants, in preorder. - pub fn traverse_preorder(&self) -> TreeIterator { - let mut nodes = ~[]; - gather_abstract_nodes(self, &mut nodes, false); - TreeIterator::new(nodes) - } - - /// Iterates over this node and all its descendants, in postorder. - pub fn sequential_traverse_postorder(&self) -> TreeIterator { - let mut nodes = ~[]; - gather_abstract_nodes(self, &mut nodes, true); - TreeIterator::new(nodes) - } -} - -impl Node { - pub fn owner_doc(&self) -> AbstractDocument { - self.owner_doc.unwrap() - } - - pub fn set_owner_doc(&mut self, document: AbstractDocument) { - self.owner_doc = Some(document); + pub fn set_owner_doc(&mut self, document: &JS<Document>) { + self.owner_doc = Some(document.clone()); } pub fn children(&self) -> AbstractNodeChildrenIterator { AbstractNodeChildrenIterator { - current_node: self.first_child, + current_node: self.first_child.clone(), } } - pub fn child_elements(&self) -> Filter<AbstractNode, AbstractNodeChildrenIterator> { - self.children().filter(|node| node.is_element()) + pub fn child_elements(&self) -> ChildElementIterator { + self.children() + .filter(|node| node.is_element()) + .map(|node| { + let elem: JS<Element> = ElementCast::to(&node); + elem + }) } - pub fn reflect_node<N: Reflectable> - (node: @mut N, - document: AbstractDocument, - wrap_fn: extern "Rust" fn(*JSContext, *JSObject, @mut N) -> *JSObject) - -> AbstractNode { + pub fn reflect_node<N: Reflectable+NodeBase> + (node: ~N, + document: &JS<Document>, + wrap_fn: extern "Rust" fn(*JSContext, *JSObject, ~N) -> *JSObject) + -> JS<N> { assert!(node.reflector().get_jsobject().is_null()); - let node = reflect_dom_object(node, document.document().window, wrap_fn); + let node = reflect_dom_object(node, document.get().window.get(), wrap_fn); assert!(node.reflector().get_jsobject().is_not_null()); - // JS owns the node now, so transmute_copy to not increase the refcount - AbstractNode { - obj: unsafe { cast::transmute_copy(&node) }, - } + node } - pub fn new_inherited(type_id: NodeTypeId, doc: AbstractDocument) -> Node { + pub fn new_inherited(type_id: NodeTypeId, doc: JS<Document>) -> Node { Node::new_(type_id, Some(doc)) } @@ -926,13 +765,11 @@ impl Node { Node::new_(type_id, None) } - fn new_(type_id: NodeTypeId, doc: Option<AbstractDocument>) -> Node { + fn new_(type_id: NodeTypeId, doc: Option<JS<Document>>) -> Node { Node { - eventtarget: EventTarget::new_inherited(NodeTypeId), + eventtarget: EventTarget::new_inherited(NodeTargetTypeId(type_id)), type_id: type_id, - abstract: None, - parent_node: None, first_child: None, last_child: None, @@ -974,24 +811,22 @@ impl Node { } // http://dom.spec.whatwg.org/#dom-node-nodename - pub fn NodeName(&self, abstract_self: AbstractNode) -> DOMString { + pub fn NodeName(&self, abstract_self: &JS<Node>) -> DOMString { match self.type_id { ElementNodeTypeId(..) => { - abstract_self.with_imm_element(|element| { - element.TagName() - }) + let elem: JS<Element> = ElementCast::to(abstract_self); + elem.get().TagName() } TextNodeTypeId => ~"#text", ProcessingInstructionNodeTypeId => { - abstract_self.with_imm_processing_instruction(|processing_instruction| { - processing_instruction.Target() - }) + let processing_instruction: JS<ProcessingInstruction> = + ProcessingInstructionCast::to(abstract_self); + processing_instruction.get().Target() } CommentNodeTypeId => ~"#comment", DoctypeNodeTypeId => { - abstract_self.with_imm_doctype(|doctype| { - doctype.name.clone() - }) + let doctype: JS<DocumentType> = DocumentTypeCast::to(abstract_self); + doctype.get().name.clone() }, DocumentFragmentNodeTypeId => ~"#document-fragment", DocumentNodeTypeId(_) => ~"#document" @@ -1004,7 +839,7 @@ impl Node { } // http://dom.spec.whatwg.org/#dom-node-ownerdocument - pub fn GetOwnerDocument(&self) -> Option<AbstractDocument> { + pub fn GetOwnerDocument(&self) -> Option<JS<Document>> { match self.type_id { ElementNodeTypeId(..) | CommentNodeTypeId | @@ -1017,13 +852,15 @@ impl Node { } // http://dom.spec.whatwg.org/#dom-node-parentnode - pub fn GetParentNode(&self) -> Option<AbstractNode> { - self.parent_node + pub fn GetParentNode(&self) -> Option<JS<Node>> { + self.parent_node.clone() } // http://dom.spec.whatwg.org/#dom-node-parentelement - pub fn GetParentElement(&self) -> Option<AbstractNode> { - self.parent_node.filtered(|parent| parent.is_element()) + pub fn GetParentElement(&self) -> Option<JS<Element>> { + self.parent_node.clone() + .filtered(|parent| parent.is_element()) + .map(|node| ElementCast::to(&node)) } // http://dom.spec.whatwg.org/#dom-node-haschildnodes @@ -1032,34 +869,33 @@ impl Node { } // http://dom.spec.whatwg.org/#dom-node-firstchild - pub fn GetFirstChild(&self) -> Option<AbstractNode> { - self.first_child + pub fn GetFirstChild(&self) -> Option<JS<Node>> { + self.first_child.clone() } // http://dom.spec.whatwg.org/#dom-node-lastchild - pub fn GetLastChild(&self) -> Option<AbstractNode> { - self.last_child + pub fn GetLastChild(&self) -> Option<JS<Node>> { + self.last_child.clone() } // http://dom.spec.whatwg.org/#dom-node-previoussibling - pub fn GetPreviousSibling(&self) -> Option<AbstractNode> { - self.prev_sibling + pub fn GetPreviousSibling(&self) -> Option<JS<Node>> { + self.prev_sibling.clone() } // http://dom.spec.whatwg.org/#dom-node-nextsibling - pub fn GetNextSibling(&self) -> Option<AbstractNode> { - self.next_sibling + pub fn GetNextSibling(&self) -> Option<JS<Node>> { + self.next_sibling.clone() } // http://dom.spec.whatwg.org/#dom-node-nodevalue - pub fn GetNodeValue(&self, abstract_self: AbstractNode) -> Option<DOMString> { + pub fn GetNodeValue(&self, abstract_self: &JS<Node>) -> Option<DOMString> { match self.type_id { CommentNodeTypeId | TextNodeTypeId | ProcessingInstructionNodeTypeId => { - abstract_self.with_imm_characterdata(|characterdata| { - Some(characterdata.Data()) - }) + let chardata: JS<CharacterData> = CharacterDataCast::to(abstract_self); + Some(chardata.get().Data()) } _ => { None @@ -1068,23 +904,22 @@ impl Node { } // http://dom.spec.whatwg.org/#dom-node-nodevalue - pub fn SetNodeValue(&mut self, _abstract_self: AbstractNode, _val: Option<DOMString>) + pub fn SetNodeValue(&mut self, _abstract_self: &JS<Node>, _val: Option<DOMString>) -> ErrorResult { // FIXME: Stub - https://github.com/mozilla/servo/issues/1655 Ok(()) } // http://dom.spec.whatwg.org/#dom-node-textcontent - pub fn GetTextContent(&self, abstract_self: AbstractNode) -> Option<DOMString> { + pub fn GetTextContent(&self, abstract_self: &JS<Node>) -> Option<DOMString> { match self.type_id { DocumentFragmentNodeTypeId | ElementNodeTypeId(..) => { let mut content = ~""; for node in abstract_self.traverse_preorder() { if node.is_text() { - node.with_imm_text(|text| { - content.push_str(text.characterdata.data.as_slice()); - }) + let text: JS<Text> = TextCast::to(&node); + content.push_str(text.get().characterdata.data.as_slice()); } } Some(content) @@ -1092,9 +927,8 @@ impl Node { CommentNodeTypeId | TextNodeTypeId | ProcessingInstructionNodeTypeId => { - abstract_self.with_imm_characterdata(|characterdata| { - Some(characterdata.Data()) - }) + let characterdata: JS<CharacterData> = CharacterDataCast::to(abstract_self); + Some(characterdata.get().Data()) } DoctypeNodeTypeId | DocumentNodeTypeId(_) => { @@ -1104,30 +938,31 @@ impl Node { } // http://dom.spec.whatwg.org/#dom-node-childnodes - pub fn ChildNodes(&mut self, abstract_self: AbstractNode) -> @mut NodeList { + pub fn ChildNodes(&mut self, abstract_self: &JS<Node>) -> JS<NodeList> { match self.child_list { None => { - let window = self.owner_doc().document().window; - let list = NodeList::new_child_list(window, abstract_self); - self.child_list = Some(list); + let doc = self.owner_doc(); + let doc = doc.get(); + let list = NodeList::new_child_list(&doc.window, abstract_self); + self.child_list = Some(list.clone()); list } - Some(list) => list + Some(ref list) => list.clone() } } // http://dom.spec.whatwg.org/#concept-node-adopt - fn adopt(node: AbstractNode, document: AbstractDocument) { + fn adopt(node: &mut JS<Node>, document: &JS<Document>) { // Step 1. match node.parent_node() { - Some(parent) => Node::remove(node, parent, Unsuppressed), + Some(ref mut parent) => Node::remove(node, parent, Unsuppressed), None => (), } // Step 2. - if node.node().owner_doc() != document { - for descendant in node.traverse_preorder() { - descendant.mut_node().set_owner_doc(document); + if node.get().owner_doc() != *document { + for mut descendant in node.traverse_preorder() { + descendant.get_mut().set_owner_doc(document); } } @@ -1136,8 +971,8 @@ impl Node { } // http://dom.spec.whatwg.org/#concept-node-pre-insert - fn pre_insert(node: AbstractNode, parent: AbstractNode, child: Option<AbstractNode>) - -> Fallible<AbstractNode> { + fn pre_insert(node: &mut JS<Node>, parent: &mut JS<Node>, child: Option<JS<Node>>) + -> Fallible<JS<Node>> { // Step 1. match parent.type_id() { DocumentNodeTypeId(..) | @@ -1153,7 +988,7 @@ impl Node { // Step 3. match child { - Some(child) if !parent.is_parent_of(child) => return Err(NotFound), + Some(ref child) if !parent.is_parent_of(child) => return Err(NotFound), _ => () } @@ -1161,13 +996,13 @@ impl Node { match node.type_id() { TextNodeTypeId => { match node.parent_node() { - Some(parent) if parent.is_document() => return Err(HierarchyRequest), + Some(ref parent) if parent.is_document() => return Err(HierarchyRequest), _ => () } } DoctypeNodeTypeId => { match node.parent_node() { - Some(parent) if !parent.is_document() => return Err(HierarchyRequest), + Some(ref parent) if !parent.is_document() => return Err(HierarchyRequest), _ => () } } @@ -1198,8 +1033,8 @@ impl Node { return Err(HierarchyRequest); } match child { - Some(child) if child.inclusively_following_siblings() - .any(|child| child.is_doctype()) => { + Some(ref child) if child.inclusively_following_siblings() + .any(|child| child.is_doctype()) => { return Err(HierarchyRequest); } _ => (), @@ -1217,8 +1052,8 @@ impl Node { return Err(HierarchyRequest); } match child { - Some(child) if child.inclusively_following_siblings() - .any(|child| child.is_doctype()) => { + Some(ref child) if child.inclusively_following_siblings() + .any(|child| child.is_doctype()) => { return Err(HierarchyRequest); } _ => (), @@ -1230,9 +1065,9 @@ impl Node { return Err(HierarchyRequest); } match child { - Some(child) => { + Some(ref child) => { if parent.children() - .take_while(|&c| c != child) + .take_while(|c| c != child) .any(|c| c.is_element()) { return Err(HierarchyRequest); } @@ -1256,41 +1091,40 @@ impl Node { } // Step 7-8. - let referenceChild = if child != Some(node) { - child - } else { - node.next_sibling() + let referenceChild = match child { + Some(ref child) if child == node => node.next_sibling(), + _ => child }; // Step 9. - Node::adopt(node, parent.node().owner_doc()); + Node::adopt(node, &parent.get().owner_doc()); // Step 10. Node::insert(node, parent, referenceChild, Unsuppressed); // Step 11. - return Ok(node) + return Ok(node.clone()) } // http://dom.spec.whatwg.org/#concept-node-insert - fn insert(node: AbstractNode, - parent: AbstractNode, - child: Option<AbstractNode>, + fn insert(node: &mut JS<Node>, + parent: &mut JS<Node>, + child: Option<JS<Node>>, suppress_observers: SuppressObserver) { // XXX assert owner_doc // Step 1-3: ranges. // Step 4. - let nodes = match node.type_id() { + let mut nodes = match node.type_id() { DocumentFragmentNodeTypeId => node.children().collect(), - _ => ~[node], + _ => ~[node.clone()], }; // Step 5: DocumentFragment, mutation records. // Step 6: DocumentFragment. match node.type_id() { DocumentFragmentNodeTypeId => { - for c in node.children() { - Node::remove(c, node, Suppressed); + for mut c in node.children() { + Node::remove(&mut c, node, Suppressed); } }, _ => (), @@ -1298,9 +1132,9 @@ impl Node { // Step 7: mutation records. // Step 8. - for node in nodes.iter() { - parent.add_child(*node, child); - node.mut_node().flags.set_is_in_doc(parent.is_in_doc()); + for node in nodes.mut_iter() { + parent.add_child(node, child.clone()); + node.get_mut().flags.set_is_in_doc(parent.is_in_doc()); } // Step 9. @@ -1315,33 +1149,33 @@ impl Node { } // http://dom.spec.whatwg.org/#concept-node-replace-all - pub fn replace_all(node: Option<AbstractNode>, parent: AbstractNode) { + pub fn replace_all(mut node: Option<JS<Node>>, parent: &mut JS<Node>) { // Step 1. match node { - Some(node) => Node::adopt(node, parent.node().owner_doc()), + Some(ref mut node) => Node::adopt(node, &parent.get().owner_doc()), None => (), } // Step 2. - let removedNodes: ~[AbstractNode] = parent.children().collect(); + let removedNodes: ~[JS<Node>] = parent.children().collect(); // Step 3. let addedNodes = match node { None => ~[], - Some(node) => match node.type_id() { + Some(ref node) => match node.type_id() { DocumentFragmentNodeTypeId => node.children().collect(), - _ => ~[node], + _ => ~[node.clone()], }, }; // Step 4. - for child in parent.children() { - Node::remove(child, parent, Suppressed); + for mut child in parent.children() { + Node::remove(&mut child, parent, Suppressed); } // Step 5. match node { - Some(node) => Node::insert(node, parent, None, Suppressed), + Some(ref mut node) => Node::insert(node, parent, None, Suppressed), None => (), } @@ -1357,28 +1191,29 @@ impl Node { } // http://dom.spec.whatwg.org/#concept-node-pre-remove - fn pre_remove(child: AbstractNode, parent: AbstractNode) -> Fallible<AbstractNode> { + fn pre_remove(child: &mut JS<Node>, parent: &mut JS<Node>) -> Fallible<JS<Node>> { // Step 1. - if child.parent_node() != Some(parent) { - return Err(NotFound); + match child.parent_node() { + Some(ref node) if node != parent => return Err(NotFound), + _ => () } // Step 2. Node::remove(child, parent, Unsuppressed); // Step 3. - Ok(child) + Ok(child.clone()) } // http://dom.spec.whatwg.org/#concept-node-remove - fn remove(node: AbstractNode, parent: AbstractNode, suppress_observers: SuppressObserver) { - assert!(node.parent_node() == Some(parent)); + fn remove(node: &mut JS<Node>, parent: &mut JS<Node>, suppress_observers: SuppressObserver) { + assert!(node.parent_node().map_default(false, |ref node_parent| node_parent == parent)); // Step 1-5: ranges. // Step 6-7: mutation observers. // Step 8. parent.remove_child(node); - node.mut_node().flags.set_is_in_doc(false); + node.get_mut().flags.set_is_in_doc(false); // Step 9. match suppress_observers { @@ -1388,7 +1223,7 @@ impl Node { } // http://dom.spec.whatwg.org/#dom-node-textcontent - pub fn SetTextContent(&mut self, abstract_self: AbstractNode, value: Option<DOMString>) + pub fn SetTextContent(&mut self, abstract_self: &mut JS<Node>, value: Option<DOMString>) -> ErrorResult { let value = null_str_as_empty(&value); match self.type_id { @@ -1399,7 +1234,7 @@ impl Node { None } else { let document = self.owner_doc(); - Some(document.document().CreateTextNode(document, value)) + Some(NodeCast::from(&document.get().CreateTextNode(&document, value))) }; // Step 3. Node::replace_all(node, abstract_self); @@ -1409,13 +1244,12 @@ impl Node { ProcessingInstructionNodeTypeId => { self.wait_until_safe_to_modify_dom(); - abstract_self.with_mut_characterdata(|characterdata| { - characterdata.data = value.clone(); + let mut characterdata: JS<CharacterData> = CharacterDataCast::to(abstract_self); + characterdata.get_mut().data = value.clone(); - // Notify the document that the content of this node is different - let document = self.owner_doc(); - document.document().content_changed(); - }) + // Notify the document that the content of this node is different + let document = self.owner_doc(); + document.get().content_changed(); } DoctypeNodeTypeId | DocumentNodeTypeId(_) => {} @@ -1424,25 +1258,25 @@ impl Node { } // http://dom.spec.whatwg.org/#dom-node-insertbefore - pub fn InsertBefore(&self, abstract_self: AbstractNode, node: AbstractNode, child: Option<AbstractNode>) - -> Fallible<AbstractNode> { + pub fn InsertBefore(&self, abstract_self: &mut JS<Node>, node: &mut JS<Node>, child: Option<JS<Node>>) + -> Fallible<JS<Node>> { Node::pre_insert(node, abstract_self, child) } pub fn wait_until_safe_to_modify_dom(&self) { let document = self.owner_doc(); - document.document().wait_until_safe_to_modify_dom(); + document.get().wait_until_safe_to_modify_dom(); } // http://dom.spec.whatwg.org/#dom-node-appendchild - pub fn AppendChild(&self, abstract_self: AbstractNode, node: AbstractNode) - -> Fallible<AbstractNode> { + pub fn AppendChild(&self, abstract_self: &mut JS<Node>, node: &mut JS<Node>) + -> Fallible<JS<Node>> { Node::pre_insert(node, abstract_self, None) } // http://dom.spec.whatwg.org/#concept-node-replace - pub fn ReplaceChild(&self, parent: AbstractNode, node: AbstractNode, child: AbstractNode) - -> Fallible<AbstractNode> { + pub fn ReplaceChild(&self, parent: &mut JS<Node>, node: &mut JS<Node>, child: &mut JS<Node>) + -> Fallible<JS<Node>> { // Step 1. match parent.type_id() { DocumentNodeTypeId(..) | @@ -1488,7 +1322,7 @@ impl Node { 0 => (), // Step 6.1.2 1 => { - if parent.child_elements().any(|c| c != child) { + if parent.child_elements().any(|c| &NodeCast::from(&c) != child) { return Err(HierarchyRequest); } if child.following_siblings() @@ -1502,7 +1336,7 @@ impl Node { }, // Step 6.2 ElementNodeTypeId(..) => { - if parent.child_elements().any(|c| c != child) { + if parent.child_elements().any(|c| &NodeCast::from(&c) != child) { return Err(HierarchyRequest); } if child.following_siblings() @@ -1512,11 +1346,11 @@ impl Node { }, // Step 6.3 DoctypeNodeTypeId => { - if parent.children().any(|c| c.is_doctype() && c != child) { + if parent.children().any(|c| c.is_doctype() && &c != child) { return Err(HierarchyRequest); } if parent.children() - .take_while(|&c| c != child) + .take_while(|c| c != child) .any(|c| c.is_element()) { return Err(HierarchyRequest); } @@ -1531,19 +1365,19 @@ impl Node { } // Ok if not caught by previous error checks. - if node == child { - return Ok(child); + if *node == *child { + return Ok(child.clone()); } // Step 7-8. - let reference_child = if child.next_sibling() != Some(node) { - child.next_sibling() - } else { - node.next_sibling() + let next_sibling = child.next_sibling(); + let reference_child = match next_sibling { + Some(ref sibling) if sibling == node => node.next_sibling(), + _ => next_sibling }; // Step 9. - Node::adopt(node, parent.node().owner_doc()); + Node::adopt(node, &parent.get().owner_doc()); { // Step 10. @@ -1565,12 +1399,12 @@ impl Node { } // Step 15. - Ok(child) + Ok(child.clone()) } // http://dom.spec.whatwg.org/#dom-node-removechild - pub fn RemoveChild(&self, abstract_self: AbstractNode, node: AbstractNode) - -> Fallible<AbstractNode> { + pub fn RemoveChild(&self, abstract_self: &mut JS<Node>, node: &mut JS<Node>) + -> Fallible<JS<Node>> { Node::pre_remove(node, abstract_self) } @@ -1580,62 +1414,52 @@ impl Node { } // http://dom.spec.whatwg.org/#dom-node-clonenode - pub fn CloneNode(&self, _deep: bool) -> Fallible<AbstractNode> { + pub fn CloneNode(&self, _deep: bool) -> Fallible<JS<Node>> { // FIXME: stub - https://github.com/mozilla/servo/issues/1240 fail!("stub") } // http://dom.spec.whatwg.org/#dom-node-isequalnode - pub fn IsEqualNode(&self, abstract_self: AbstractNode, maybe_node: Option<AbstractNode>) -> bool { - fn is_equal_doctype(node: AbstractNode, other: AbstractNode) -> bool { - node.with_imm_doctype(|doctype| { - other.with_imm_doctype(|other_doctype| { - (doctype.name == other_doctype.name) && - (doctype.public_id == other_doctype.public_id) && - (doctype.system_id == other_doctype.system_id) - }) - }) - } - fn is_equal_element(node: AbstractNode, other: AbstractNode) -> bool { - node.with_imm_element(|element| { - other.with_imm_element(|other_element| { - // FIXME: namespace prefix - (element.namespace == other_element.namespace) && - (element.tag_name == other_element.tag_name) && - (element.attrs.len() == other_element.attrs.len()) - }) - }) - } - fn is_equal_processinginstruction(node: AbstractNode, other: AbstractNode) -> bool { - node.with_imm_processing_instruction(|pi| { - other.with_imm_processing_instruction(|other_pi| { - (pi.target == other_pi.target) && - (pi.characterdata.data == other_pi.characterdata.data) - }) - }) - } - fn is_equal_characterdata(node: AbstractNode, other: AbstractNode) -> bool { - node.with_imm_characterdata(|characterdata| { - other.with_imm_characterdata(|other_characterdata| { - characterdata.data == other_characterdata.data - }) - }) - } - fn is_equal_element_attrs(node: AbstractNode, other: AbstractNode) -> bool { - node.with_imm_element(|element| { - other.with_imm_element(|other_element| { - assert!(element.attrs.len() == other_element.attrs.len()); - element.attrs.iter().all(|attr| { - other_element.attrs.iter().any(|other_attr| { - (attr.namespace == other_attr.namespace) && - (attr.local_name == other_attr.local_name) && - (attr.value == other_attr.value) - }) - }) + pub fn IsEqualNode(&self, abstract_self: &JS<Node>, maybe_node: Option<JS<Node>>) -> bool { + fn is_equal_doctype(node: &JS<Node>, other: &JS<Node>) -> bool { + let doctype: JS<DocumentType> = DocumentTypeCast::to(node); + let other_doctype: JS<DocumentType> = DocumentTypeCast::to(other); + (doctype.get().name == other_doctype.get().name) && + (doctype.get().public_id == other_doctype.get().public_id) && + (doctype.get().system_id == other_doctype.get().system_id) + } + fn is_equal_element(node: &JS<Node>, other: &JS<Node>) -> bool { + let element: JS<Element> = ElementCast::to(node); + let other_element: JS<Element> = ElementCast::to(other); + // FIXME: namespace prefix + (element.get().namespace == other_element.get().namespace) && + (element.get().tag_name == other_element.get().tag_name) && + (element.get().attrs.len() == other_element.get().attrs.len()) + } + fn is_equal_processinginstruction(node: &JS<Node>, other: &JS<Node>) -> bool { + let pi: JS<ProcessingInstruction> = ProcessingInstructionCast::to(node); + let other_pi: JS<ProcessingInstruction> = ProcessingInstructionCast::to(other); + (pi.get().target == other_pi.get().target) && + (pi.get().characterdata.data == other_pi.get().characterdata.data) + } + fn is_equal_characterdata(node: &JS<Node>, other: &JS<Node>) -> bool { + let characterdata: JS<CharacterData> = CharacterDataCast::to(node); + let other_characterdata: JS<CharacterData> = CharacterDataCast::to(other); + characterdata.get().data == other_characterdata.get().data + } + fn is_equal_element_attrs(node: &JS<Node>, other: &JS<Node>) -> bool { + let element: JS<Element> = ElementCast::to(node); + let other_element: JS<Element> = ElementCast::to(other); + assert!(element.get().attrs.len() == other_element.get().attrs.len()); + element.get().attrs.iter().all(|attr| { + other_element.get().attrs.iter().any(|other_attr| { + (attr.get().namespace == other_attr.get().namespace) && + (attr.get().local_name == other_attr.get().local_name) && + (attr.get().value == other_attr.get().value) }) }) } - fn is_equal_node(this: AbstractNode, node: AbstractNode) -> bool { + fn is_equal_node(this: &JS<Node>, node: &JS<Node>) -> bool { // Step 2. if this.type_id() != node.type_id() { return false; @@ -1659,27 +1483,27 @@ impl Node { } // Step 6. - this.children().zip(node.children()).all(|(child, other_child)| is_equal_node(child, other_child)) + this.children().zip(node.children()).all(|(ref child, ref other_child)| is_equal_node(child, other_child)) } match maybe_node { // Step 1. None => false, // Step 2-6. - Some(node) => is_equal_node(abstract_self, node) + Some(ref node) => is_equal_node(abstract_self, node) } } // http://dom.spec.whatwg.org/#dom-node-comparedocumentposition - pub fn CompareDocumentPosition(&self, _other: AbstractNode) -> u16 { + pub fn CompareDocumentPosition(&self, _other: &JS<Node>) -> u16 { // FIXME: stub - https://github.com/mozilla/servo/issues/1655 0 } // http://dom.spec.whatwg.org/#dom-node-contains - pub fn Contains(&self, abstract_self: AbstractNode, maybe_other: Option<AbstractNode>) -> bool { + pub fn Contains(&self, abstract_self: &JS<Node>, maybe_other: Option<JS<Node>>) -> bool { match maybe_other { None => false, - Some(other) => abstract_self.is_inclusive_ancestor_of(other) + Some(ref other) => abstract_self.is_inclusive_ancestor_of(other) } } @@ -1725,33 +1549,33 @@ impl Node { // Low-level pointer stitching // - pub fn set_parent_node(&mut self, new_parent_node: Option<AbstractNode>) { + pub fn set_parent_node(&mut self, new_parent_node: Option<JS<Node>>) { let doc = self.owner_doc(); - doc.document().wait_until_safe_to_modify_dom(); + doc.get().wait_until_safe_to_modify_dom(); self.parent_node = new_parent_node } - pub fn set_first_child(&mut self, new_first_child: Option<AbstractNode>) { + pub fn set_first_child(&mut self, new_first_child: Option<JS<Node>>) { let doc = self.owner_doc(); - doc.document().wait_until_safe_to_modify_dom(); + doc.get().wait_until_safe_to_modify_dom(); self.first_child = new_first_child } - pub fn set_last_child(&mut self, new_last_child: Option<AbstractNode>) { + pub fn set_last_child(&mut self, new_last_child: Option<JS<Node>>) { let doc = self.owner_doc(); - doc.document().wait_until_safe_to_modify_dom(); + doc.get().wait_until_safe_to_modify_dom(); self.last_child = new_last_child } - pub fn set_prev_sibling(&mut self, new_prev_sibling: Option<AbstractNode>) { + pub fn set_prev_sibling(&mut self, new_prev_sibling: Option<JS<Node>>) { let doc = self.owner_doc(); - doc.document().wait_until_safe_to_modify_dom(); + doc.get().wait_until_safe_to_modify_dom(); self.prev_sibling = new_prev_sibling } - pub fn set_next_sibling(&mut self, new_next_sibling: Option<AbstractNode>) { + pub fn set_next_sibling(&mut self, new_next_sibling: Option<JS<Node>>) { let doc = self.owner_doc(); - doc.document().wait_until_safe_to_modify_dom(); + doc.get().wait_until_safe_to_modify_dom(); self.next_sibling = new_next_sibling } |