aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/script/dom/node.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/script/dom/node.rs')
-rw-r--r--src/components/script/dom/node.rs1577
1 files changed, 827 insertions, 750 deletions
diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs
index d5b43a6257f..e9a2d0ca37b 100644
--- a/src/components/script/dom/node.rs
+++ b/src/components/script/dom/node.rs
@@ -6,23 +6,25 @@
use dom::attr::Attr;
use dom::bindings::codegen::InheritTypes::{CommentCast, DocumentCast, DocumentTypeCast};
-use dom::bindings::codegen::InheritTypes::{ElementCast, TextCast, NodeCast};
+use dom::bindings::codegen::InheritTypes::{ElementCast, TextCast, NodeCast, ElementDerived};
use dom::bindings::codegen::InheritTypes::{CharacterDataCast, NodeBase, NodeDerived};
use dom::bindings::codegen::InheritTypes::{ProcessingInstructionCast, EventTargetCast};
use dom::bindings::codegen::BindingDeclarations::NodeBinding::NodeConstants;
-use dom::bindings::js::JS;
+use dom::bindings::js::{JS, JSRef, RootedReference, Temporary, Root, OptionalUnrootable};
+use dom::bindings::js::{OptionalSettable, TemporaryPushable, OptionalRootedRootable};
+use dom::bindings::js::{ResultRootable, OptionalRootable};
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::bindings::error::{ErrorResult, Fallible, NotFound, HierarchyRequest};
use dom::bindings::utils;
-use dom::characterdata::CharacterData;
+use dom::characterdata::{CharacterData, CharacterDataMethods};
use dom::comment::Comment;
-use dom::document::{Document, HTMLDocument, NonHTMLDocument};
+use dom::document::{Document, DocumentMethods, DocumentHelpers, HTMLDocument, NonHTMLDocument};
use dom::documentfragment::DocumentFragment;
use dom::documenttype::DocumentType;
-use dom::element::{Element, ElementTypeId, HTMLAnchorElementTypeId};
+use dom::element::{Element, ElementMethods, ElementTypeId, HTMLAnchorElementTypeId};
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::nodelist::{NodeList};
-use dom::processinginstruction::ProcessingInstruction;
+use dom::processinginstruction::{ProcessingInstruction, ProcessingInstructionMethods};
use dom::text::Text;
use dom::virtualmethods::{VirtualMethods, vtable_for};
use dom::window::Window;
@@ -222,26 +224,161 @@ pub enum NodeTypeId {
ProcessingInstructionNodeTypeId,
}
-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>>;
+trait PrivateNodeHelpers {
+ fn set_parent_node(&mut self, new_parent_node: Option<JSRef<Node>>);
+ fn set_first_child(&mut self, new_first_child: Option<JSRef<Node>>);
+ fn set_last_child(&mut self, new_last_child: Option<JSRef<Node>>);
+ fn set_prev_sibling(&mut self, new_prev_sibling: Option<JSRef<Node>>);
+ fn set_next_sibling(&mut self, new_next_sibling: Option<JSRef<Node>>);
+
+ fn node_inserted(&self);
+ fn node_removed(&self);
+ fn add_child(&mut self, new_child: &mut JSRef<Node>, before: Option<JSRef<Node>>);
+ fn remove_child(&mut self, child: &mut JSRef<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)
+impl<'a> PrivateNodeHelpers for JSRef<'a, Node> {
+ // http://dom.spec.whatwg.org/#node-is-inserted
+ fn node_inserted(&self) {
+ assert!(self.parent_node().is_some());
+ let document = document_from_node(self).root();
+
+ if self.is_in_doc() {
+ for mut node in self.traverse_preorder() {
+ vtable_for(&mut node).bind_to_tree();
+ }
+ }
+
+ let mut parent = self.parent_node().root();
+ parent.as_mut().map(|parent| vtable_for(&mut **parent).child_inserted(self));
+
+ document.deref().content_changed();
+ }
+
+ // http://dom.spec.whatwg.org/#node-is-removed
+ fn node_removed(&self) {
+ assert!(self.parent_node().is_none());
+ let document = document_from_node(self).root();
+
+ for mut node in self.traverse_preorder() {
+ // XXX how about if the node wasn't in the tree in the first place?
+ vtable_for(&mut node).unbind_from_tree();
+ }
+
+ document.deref().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(&mut self, new_child: &mut JSRef<Node>, mut before: Option<JSRef<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(ref mut before) => {
+ // XXX Should assert that parent is self.
+ assert!(before.parent_node().is_some());
+ match before.prev_sibling().root() {
+ None => {
+ // XXX Should assert that before is the first child of
+ // self.
+ self.set_first_child(Some(new_child.clone()));
+ },
+ Some(mut prev_sibling) => {
+ prev_sibling.set_next_sibling(Some(new_child.clone()));
+ new_child.set_prev_sibling(Some((*prev_sibling).clone()));
+ },
+ }
+ before.set_prev_sibling(Some(new_child.clone()));
+ new_child.set_next_sibling(Some(before.clone()));
+ },
+ None => {
+ match self.last_child().root() {
+ None => self.set_first_child(Some(new_child.clone())),
+ Some(mut last_child) => {
+ assert!(last_child.next_sibling().is_none());
+ last_child.set_next_sibling(Some(new_child.clone()));
+ new_child.set_prev_sibling(Some((*last_child).clone()));
+ }
+ }
+
+ self.set_last_child(Some(new_child.clone()));
+ },
+ }
+
+ new_child.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(&mut self, child: &mut JSRef<Node>) {
+ assert!(child.parent_node.is_some());
+
+ match child.prev_sibling.root() {
+ None => {
+ let next_sibling = child.next_sibling.root();
+ self.set_first_child(next_sibling.root_ref());
+ }
+ Some(ref mut prev_sibling) => {
+ let next_sibling = child.next_sibling.root();
+ prev_sibling.set_next_sibling(next_sibling.root_ref());
+ }
+ }
+
+ match child.next_sibling.root() {
+ None => {
+ let prev_sibling = child.prev_sibling.root();
+ self.set_last_child(prev_sibling.root_ref());
+ }
+ Some(ref mut next_sibling) => {
+ let prev_sibling = child.prev_sibling.root();
+ next_sibling.set_prev_sibling(prev_sibling.root_ref());
+ }
+ }
+
+ child.set_prev_sibling(None);
+ child.set_next_sibling(None);
+ child.set_parent_node(None);
+ }
+
+ //
+ // Low-level pointer stitching
+ //
+
+ fn set_parent_node(&mut self, new_parent_node: Option<JSRef<Node>>) {
+ let doc = self.owner_doc().root();
+ doc.deref().wait_until_safe_to_modify_dom();
+ self.parent_node.assign(new_parent_node);
+ }
+
+ fn set_first_child(&mut self, new_first_child: Option<JSRef<Node>>) {
+ let doc = self.owner_doc().root();
+ doc.deref().wait_until_safe_to_modify_dom();
+ self.first_child.assign(new_first_child);
}
- 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)
+ fn set_last_child(&mut self, new_last_child: Option<JSRef<Node>>) {
+ let doc = self.owner_doc().root();
+ doc.deref().wait_until_safe_to_modify_dom();
+ self.last_child.assign(new_last_child);
}
- 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)
+ fn set_prev_sibling(&mut self, new_prev_sibling: Option<JSRef<Node>>) {
+ let doc = self.owner_doc().root();
+ doc.deref().wait_until_safe_to_modify_dom();
+ self.prev_sibling.assign(new_prev_sibling);
+ }
+
+ fn set_next_sibling(&mut self, new_next_sibling: Option<JSRef<Node>>) {
+ let doc = self.owner_doc().root();
+ doc.deref().wait_until_safe_to_modify_dom();
+ self.next_sibling.assign(new_next_sibling);
}
}
@@ -251,16 +388,21 @@ pub trait NodeHelpers {
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 is_inclusive_ancestor_of(&self, parent: &JSRef<Node>) -> bool;
+ fn is_parent_of(&self, child: &JSRef<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 parent_node(&self) -> Option<Temporary<Node>>;
+ fn first_child(&self) -> Option<Temporary<Node>>;
+ fn last_child(&self) -> Option<Temporary<Node>>;
+ fn prev_sibling(&self) -> Option<Temporary<Node>>;
+ fn next_sibling(&self) -> Option<Temporary<Node>>;
+
+ fn owner_doc(&self) -> Temporary<Document>;
+ fn set_owner_doc(&mut self, document: &JSRef<Document>);
+
+ fn wait_until_safe_to_modify_dom(&self);
fn is_element(&self) -> bool;
fn is_document(&self) -> bool;
@@ -268,11 +410,6 @@ pub trait NodeHelpers {
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);
@@ -280,18 +417,17 @@ pub trait NodeHelpers {
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 traverse_preorder<'a>(&'a self) -> TreeIterator<'a>;
+ fn sequential_traverse_postorder<'a>(&'a self) -> TreeIterator<'a>;
+ fn inclusively_following_siblings<'a>(&'a self) -> AbstractNodeChildrenIterator<'a>;
- fn from_untrusted_node_address(runtime: *JSRuntime, candidate: UntrustedNodeAddress) -> Self;
fn to_trusted_node_address(&self) -> TrustedNodeAddress;
fn get_bounding_content_box(&self) -> Rect<Au>;
fn get_content_boxes(&self) -> Vec<Rect<Au>>;
}
-impl NodeHelpers for JS<Node> {
+impl<'a> NodeHelpers for JSRef<'a, Node> {
/// Dumps the subtree rooted at this node, for debugging.
fn dump(&self) {
self.dump_indent(0);
@@ -318,53 +454,40 @@ impl NodeHelpers for JS<Node> {
format!("{:?}", self.type_id())
}
- /// Iterates over all ancestors of this node.
- fn ancestors(&self) -> AncestorIterator {
- self.get().ancestors()
- }
-
- fn children(&self) -> AbstractNodeChildrenIterator {
- self.get().children()
- }
-
- fn child_elements(&self) -> ChildElementIterator {
- self.get().child_elements()
- }
-
fn is_in_doc(&self) -> bool {
- self.get().flags.is_in_doc()
+ self.deref().flags.is_in_doc()
}
/// Returns the type ID of this node. Fails if this node is borrowed mutably.
fn type_id(&self) -> NodeTypeId {
- self.get().type_id
+ self.deref().type_id
}
- fn parent_node(&self) -> Option<JS<Node>> {
- self.get().parent_node.clone()
+ fn parent_node(&self) -> Option<Temporary<Node>> {
+ self.deref().parent_node.clone().map(|node| Temporary::new(node))
}
- fn first_child(&self) -> Option<JS<Node>> {
- self.get().first_child.clone()
+ fn first_child(&self) -> Option<Temporary<Node>> {
+ self.deref().first_child.clone().map(|node| Temporary::new(node))
}
- fn last_child(&self) -> Option<JS<Node>> {
- self.get().last_child.clone()
+ fn last_child(&self) -> Option<Temporary<Node>> {
+ self.deref().last_child.clone().map(|node| Temporary::new(node))
}
/// 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()
+ fn prev_sibling(&self) -> Option<Temporary<Node>> {
+ self.deref().prev_sibling.clone().map(|node| Temporary::new(node))
}
/// 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()
+ fn next_sibling(&self) -> Option<Temporary<Node>> {
+ self.deref().next_sibling.clone().map(|node| Temporary::new(node))
}
#[inline]
fn is_element(&self) -> bool {
- match self.type_id() {
+ match self.type_id {
ElementNodeTypeId(..) => true,
_ => false
}
@@ -388,7 +511,7 @@ impl NodeHelpers for JS<Node> {
#[inline]
fn is_doctype(&self) -> bool {
- match self.type_id() {
+ match self.type_id {
DoctypeNodeTypeId => true,
_ => false
}
@@ -404,177 +527,58 @@ impl NodeHelpers for JS<Node> {
}
}
- // http://dom.spec.whatwg.org/#node-is-inserted
- fn node_inserted(&self) {
- assert!(self.parent_node().is_some());
- let document = document_from_node(self);
-
- if self.is_in_doc() {
- for node in self.traverse_preorder() {
- vtable_for(&node).bind_to_tree();
- }
- }
-
- self.parent_node().map(|parent| vtable_for(&parent).child_inserted(self));
- document.get().content_changed();
- }
-
- // http://dom.spec.whatwg.org/#node-is-removed
- fn node_removed(&self) {
- assert!(self.parent_node().is_none());
- let document = document_from_node(self);
-
- for node in self.traverse_preorder() {
- // XXX how about if the node wasn't in the tree in the first place?
- vtable_for(&node).unbind_from_tree();
- }
-
- document.get().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(&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(mut before) => {
- // XXX Should assert that parent is self.
- assert!(before.parent_node().is_some());
- match before.prev_sibling() {
- None => {
- // XXX Should assert that before is the first child of
- // self.
- self.get_mut().set_first_child(Some(new_child.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.get_mut().set_prev_sibling(Some(new_child.clone()));
- new_child.get_mut().set_next_sibling(Some(before.clone()));
- },
- None => {
- 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()));
- }
- }
-
- self.get_mut().set_last_child(Some(new_child.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(&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.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.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());
- }
- }
-
- child_node.set_prev_sibling(None);
- 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()
+ self.flags.get_in_hover_state()
}
fn set_hover_state(&mut self, state: bool) {
- self.get_mut().flags.set_is_in_hover_state(state);
+ self.flags.set_is_in_hover_state(state);
}
/// Iterates over this node and all its descendants, in preorder.
- fn traverse_preorder(&self) -> TreeIterator {
+ fn traverse_preorder<'a>(&'a self) -> TreeIterator<'a> {
let mut nodes = vec!();
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 {
+ fn sequential_traverse_postorder<'a>(&'a self) -> TreeIterator<'a> {
let mut nodes = vec!();
gather_abstract_nodes(self, &mut nodes, true);
TreeIterator::new(nodes)
}
- fn inclusively_following_siblings(&self) -> AbstractNodeChildrenIterator {
+ fn inclusively_following_siblings<'a>(&'a self) -> AbstractNodeChildrenIterator<'a> {
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 is_inclusive_ancestor_of(&self, parent: &JSRef<Node>) -> bool {
+ self == parent || parent.ancestors().any(|ancestor| &ancestor == self)
}
fn following_siblings(&self) -> AbstractNodeChildrenIterator {
AbstractNodeChildrenIterator {
- current_node: self.next_sibling(),
+ current_node: self.next_sibling().root().map(|next| next.deref().clone()),
}
}
- fn is_parent_of(&self, child: &JS<Node>) -> bool {
+ fn is_parent_of(&self, child: &JSRef<Node>) -> bool {
match child.parent_node() {
- Some(ref parent) if parent == self => true,
+ Some(ref parent) if *parent == Temporary::from_rooted(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 Node = utils::unwrap(object);
- JS::from_raw(boxed_node)
- }
- }
-
fn to_trusted_node_address(&self) -> TrustedNodeAddress {
- TrustedNodeAddress(self.get() as *Node as *libc::c_void)
+ TrustedNodeAddress(self.deref() as *Node as *libc::c_void)
}
fn get_bounding_content_box(&self) -> Rect<Au> {
- let window = window_from_node(self);
- let page = window.get().page();
+ let window = window_from_node(self).root();
+ let page = window.deref().page();
let (chan, port) = channel();
let addr = self.to_trusted_node_address();
let ContentBoxResponse(rect) = page.query_layout(ContentBoxQuery(addr, chan), port);
@@ -582,63 +586,180 @@ impl NodeHelpers for JS<Node> {
}
fn get_content_boxes(&self) -> Vec<Rect<Au>> {
- let window = window_from_node(self);
- let page = window.get().page();
+ let window = window_from_node(self).root();
+ let page = window.deref().page();
let (chan, port) = channel();
let addr = self.to_trusted_node_address();
let ContentBoxesResponse(rects) = page.query_layout(ContentBoxesQuery(addr, chan), port);
rects
}
+
+ fn ancestors(&self) -> AncestorIterator {
+ AncestorIterator {
+ current: self.parent_node.clone().map(|node| (*node.root()).clone()),
+ }
+ }
+
+ fn owner_doc(&self) -> Temporary<Document> {
+ Temporary::new(self.owner_doc.get_ref().clone())
+ }
+
+ fn set_owner_doc(&mut self, document: &JSRef<Document>) {
+ self.owner_doc.assign(Some(document.clone()));
+ }
+
+ fn children(&self) -> AbstractNodeChildrenIterator {
+ AbstractNodeChildrenIterator {
+ current_node: self.first_child.clone().map(|node| (*node.root()).clone()),
+ }
+ }
+
+ fn child_elements(&self) -> ChildElementIterator {
+ self.children()
+ .filter(|node| {
+ node.is_element()
+ })
+ .map(|node| {
+ let elem: &JSRef<Element> = ElementCast::to_ref(&node).unwrap();
+ elem.clone()
+ })
+ }
+
+ fn wait_until_safe_to_modify_dom(&self) {
+ let document = self.owner_doc().root();
+ document.deref().wait_until_safe_to_modify_dom();
+ }
+
+}
+
+/// 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)
+ -> Temporary<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 Node = utils::unwrap(object);
+ Temporary::new(JS::from_raw(boxed_node))
+ }
+}
+
+pub trait LayoutNodeHelpers {
+ unsafe fn type_id_for_layout(&self) -> NodeTypeId;
+
+ unsafe fn parent_node_ref<'a>(&'a self) -> Option<&'a JS<Node>>;
+ unsafe fn first_child_ref<'a>(&'a self) -> Option<&'a JS<Node>>;
+ unsafe fn last_child_ref<'a>(&'a self) -> Option<&'a JS<Node>>;
+ unsafe fn prev_sibling_ref<'a>(&'a self) -> Option<&'a JS<Node>>;
+ unsafe fn next_sibling_ref<'a>(&'a self) -> Option<&'a JS<Node>>;
+
+ unsafe fn owner_doc_for_layout<'a>(&'a self) -> &'a JS<Document>;
+
+ unsafe fn is_element_for_layout(&self) -> bool;
}
+impl LayoutNodeHelpers for JS<Node> {
+ unsafe fn type_id_for_layout(&self) -> NodeTypeId {
+ (*self.unsafe_get()).type_id
+ }
+
+ unsafe fn is_element_for_layout(&self) -> bool {
+ (*self.unsafe_get()).is_element()
+ }
+
+ #[inline]
+ unsafe fn parent_node_ref<'a>(&'a self) -> Option<&'a JS<Node>> {
+ (*self.unsafe_get()).parent_node.as_ref()
+ }
+
+ #[inline]
+ unsafe fn first_child_ref<'a>(&'a self) -> Option<&'a JS<Node>> {
+ (*self.unsafe_get()).first_child.as_ref()
+ }
+
+ #[inline]
+ unsafe fn last_child_ref<'a>(&'a self) -> Option<&'a JS<Node>> {
+ (*self.unsafe_get()).last_child.as_ref()
+ }
+
+ #[inline]
+ unsafe fn prev_sibling_ref<'a>(&'a self) -> Option<&'a JS<Node>> {
+ (*self.unsafe_get()).prev_sibling.as_ref()
+ }
+
+ #[inline]
+ unsafe fn next_sibling_ref<'a>(&'a self) -> Option<&'a JS<Node>> {
+ (*self.unsafe_get()).next_sibling.as_ref()
+ }
+
+ unsafe fn owner_doc_for_layout<'a>(&'a self) -> &'a JS<Document> {
+ (*self.unsafe_get()).owner_doc.get_ref()
+ }
+}
+
+pub trait RawLayoutNodeHelpers {
+ unsafe fn get_hover_state_for_layout(&self) -> bool;
+}
+
+impl RawLayoutNodeHelpers for Node {
+ unsafe fn get_hover_state_for_layout(&self) -> bool {
+ self.flags.get_in_hover_state()
+ }
+}
+
+
//
// Iteration and traversal
//
-pub type ChildElementIterator<'a> = Map<'a, JS<Node>,
- JS<Element>,
- Filter<'a, JS<Node>, AbstractNodeChildrenIterator>>;
+pub type ChildElementIterator<'a, 'b> = Map<'a, JSRef<'b, Node>,
+ JSRef<'b, Element>,
+ Filter<'a, JSRef<'b, Node>, AbstractNodeChildrenIterator<'b>>>;
-pub struct AbstractNodeChildrenIterator {
- current_node: Option<JS<Node>>,
+pub struct AbstractNodeChildrenIterator<'a> {
+ current_node: Option<JSRef<'a, Node>>,
}
-impl Iterator<JS<Node>> for AbstractNodeChildrenIterator {
- fn next(&mut self) -> Option<JS<Node>> {
+impl<'a> Iterator<JSRef<'a, Node>> for AbstractNodeChildrenIterator<'a> {
+ fn next(&mut self) -> Option<JSRef<'a, Node>> {
let node = self.current_node.clone();
self.current_node = node.clone().and_then(|node| {
- node.next_sibling()
+ node.next_sibling().map(|node| (*node.root()).clone())
});
node
}
}
-pub struct AncestorIterator {
- current: Option<JS<Node>>,
+pub struct AncestorIterator<'a> {
+ current: Option<JSRef<'a, Node>>,
}
-impl Iterator<JS<Node>> for AncestorIterator {
- fn next(&mut self) -> Option<JS<Node>> {
+impl<'a> Iterator<JSRef<'a, Node>> for AncestorIterator<'a> {
+ fn next(&mut self) -> Option<JSRef<'a, Node>> {
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())
+ self.current = x.parent_node().map(|node| (*node.root()).clone());
+ Some(x)
}
}
// FIXME: Do this without precomputing a vector of refs.
// Easy for preorder; harder for postorder.
-pub struct TreeIterator {
- nodes: Vec<JS<Node>>,
+pub struct TreeIterator<'a> {
+ nodes: Vec<JSRef<'a, Node>>,
index: uint,
}
-impl TreeIterator {
- fn new(nodes: Vec<JS<Node>>) -> TreeIterator {
+impl<'a> TreeIterator<'a> {
+ fn new(nodes: Vec<JSRef<'a, Node>>) -> TreeIterator<'a> {
TreeIterator {
nodes: nodes,
index: 0,
@@ -646,8 +767,8 @@ impl TreeIterator {
}
}
-impl Iterator<JS<Node>> for TreeIterator {
- fn next(&mut self) -> Option<JS<Node>> {
+impl<'a> Iterator<JSRef<'a, Node>> for TreeIterator<'a> {
+ fn next(&mut self) -> Option<JSRef<'a, Node>> {
if self.index >= self.nodes.len() {
None
} else {
@@ -667,9 +788,11 @@ pub struct NodeIterator {
}
impl NodeIterator {
- pub fn new(start_node: JS<Node>, include_start: bool, include_descendants_of_void: bool) -> NodeIterator {
+ pub fn new<'a>(start_node: &JSRef<'a, Node>,
+ include_start: bool,
+ include_descendants_of_void: bool) -> NodeIterator {
NodeIterator {
- start_node: start_node,
+ start_node: start_node.unrooted(),
current_node: None,
depth: 0,
include_start: include_start,
@@ -677,51 +800,54 @@ impl NodeIterator {
}
}
- fn next_child(&self, node: &JS<Node>) -> Option<JS<Node>> {
+ fn next_child<'b>(&self, node: &JSRef<'b, Node>) -> Option<JSRef<Node>> {
if !self.include_descendants_of_void && node.is_element() {
- let elem: JS<Element> = ElementCast::to(node).unwrap();
- if elem.get().is_void() {
+ let elem: &JSRef<Element> = ElementCast::to_ref(node).unwrap();
+ if elem.deref().is_void() {
None
} else {
- node.first_child()
+ node.first_child().map(|child| (*child.root()).clone())
}
} else {
- node.first_child()
+ node.first_child().map(|child| (*child.root()).clone())
}
}
}
-impl Iterator<JS<Node>> for NodeIterator {
- fn next(&mut self) -> Option<JS<Node>> {
- self.current_node = match self.current_node {
+impl<'a> Iterator<JSRef<'a, Node>> for NodeIterator {
+ fn next(&mut self) -> Option<JSRef<Node>> {
+ self.current_node = match self.current_node.as_ref().map(|node| node.root()) {
None => {
if self.include_start {
Some(self.start_node.clone())
} else {
- self.next_child(&self.start_node)
+ self.next_child(&*self.start_node.root())
+ .map(|child| child.unrooted())
}
},
- Some(ref node) => {
- match self.next_child(node) {
+ Some(node) => {
+ match self.next_child(&*node) {
Some(child) => {
self.depth += 1;
- Some(child.clone())
+ Some(child.unrooted())
},
- None if node == &self.start_node => None,
+ None if node.deref().unrooted() == self.start_node => None,
None => {
- match node.next_sibling() {
- Some(sibling) => Some(sibling),
+ match node.deref().next_sibling().root() {
+ Some(sibling) => Some(sibling.deref().unrooted()),
None => {
- let mut candidate = node.clone();
+ let mut candidate = node.deref().clone();
while candidate.next_sibling().is_none() {
- candidate = candidate.parent_node().expect("Got to root without reaching start node");
+ candidate = (*candidate.parent_node()
+ .expect("Got to root without reaching start node")
+ .root()).clone();
self.depth -= 1;
- if candidate == self.start_node {
+ if candidate.unrooted() == self.start_node {
break;
}
}
- if candidate != self.start_node {
- candidate.next_sibling()
+ if candidate.unrooted() != self.start_node {
+ candidate.next_sibling().map(|node| node.root().unrooted())
} else {
None
}
@@ -731,11 +857,11 @@ impl Iterator<JS<Node>> for NodeIterator {
}
}
};
- self.current_node.clone()
+ self.current_node.clone().map(|node| (*node.root()).clone())
}
}
-fn gather_abstract_nodes(cur: &JS<Node>, refs: &mut Vec<JS<Node>>, postorder: bool) {
+fn gather_abstract_nodes<'a>(cur: &JSRef<'a, Node>, refs: &mut Vec<JSRef<'a, Node>>, postorder: bool) {
if !postorder {
refs.push(cur.clone());
}
@@ -757,55 +883,27 @@ pub enum CloneChildrenFlag {
fn as_uintptr<T>(t: &T) -> uintptr_t { t as *T as uintptr_t }
impl Node {
- pub fn ancestors(&self) -> AncestorIterator {
- AncestorIterator {
- current: self.parent_node.clone(),
- }
- }
-
- pub fn owner_doc<'a>(&'a self) -> &'a JS<Document> {
- self.owner_doc.get_ref()
- }
-
- 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.clone(),
- }
- }
-
- pub fn child_elements(&self) -> ChildElementIterator {
- self.children()
- .filter(|node| node.is_element())
- .map(|node| {
- let elem: JS<Element> = ElementCast::to(&node).unwrap();
- elem
- })
- }
-
pub fn reflect_node<N: Reflectable+NodeBase>
(node: ~N,
- document: &JS<Document>,
- wrap_fn: extern "Rust" fn(*JSContext, &JS<Window>, ~N) -> JS<N>)
- -> JS<N> {
+ document: &JSRef<Document>,
+ wrap_fn: extern "Rust" fn(*JSContext, &JSRef<Window>, ~N) -> JS<N>)
+ -> Temporary<N> {
assert!(node.reflector().get_jsobject().is_null());
- let node = reflect_dom_object(node, &document.get().window, wrap_fn);
- assert!(node.reflector().get_jsobject().is_not_null());
- node
+ let window = document.deref().window.root();
+ let node = reflect_dom_object(node, &window.root_ref(), wrap_fn).root();
+ assert!(node.deref().reflector().get_jsobject().is_not_null());
+ Temporary::from_rooted(&*node)
}
- pub fn new_inherited(type_id: NodeTypeId, doc: JS<Document>) -> Node {
- Node::new_(type_id, Some(doc))
+ pub fn new_inherited(type_id: NodeTypeId, doc: &JSRef<Document>) -> Node {
+ Node::new_(type_id, Some(doc.clone()))
}
pub fn new_without_doc(type_id: NodeTypeId) -> Node {
Node::new_(type_id, None)
}
- fn new_(type_id: NodeTypeId, doc: Option<JS<Document>>) -> Node {
+ fn new_(type_id: NodeTypeId, doc: Option<JSRef<Document>>) -> Node {
Node {
eventtarget: EventTarget::new_inherited(NodeTargetTypeId(type_id)),
type_id: type_id,
@@ -816,7 +914,7 @@ impl Node {
next_sibling: None,
prev_sibling: None,
- owner_doc: doc,
+ owner_doc: doc.unrooted(),
child_list: None,
flags: NodeFlags::new(type_id),
@@ -825,227 +923,21 @@ impl Node {
}
}
- /// Sends layout data, if any, back to the script task to be destroyed.
- pub unsafe fn reap_layout_data(&mut self) {
- if self.layout_data.is_present() {
- let layout_data = mem::replace(&mut self.layout_data, LayoutDataRef::new());
- let layout_chan = layout_data.take_chan();
- match layout_chan {
- None => {}
- Some(chan) => {
- let LayoutChan(chan) = chan;
- chan.send(ReapLayoutDataMsg(layout_data))
- },
- }
- }
- }
-
- // http://dom.spec.whatwg.org/#dom-node-nodetype
- pub fn NodeType(&self) -> u16 {
- match self.type_id {
- ElementNodeTypeId(_) => NodeConstants::ELEMENT_NODE,
- TextNodeTypeId => NodeConstants::TEXT_NODE,
- ProcessingInstructionNodeTypeId => NodeConstants::PROCESSING_INSTRUCTION_NODE,
- CommentNodeTypeId => NodeConstants::COMMENT_NODE,
- DocumentNodeTypeId => NodeConstants::DOCUMENT_NODE,
- DoctypeNodeTypeId => NodeConstants::DOCUMENT_TYPE_NODE,
- DocumentFragmentNodeTypeId => NodeConstants::DOCUMENT_FRAGMENT_NODE,
- }
- }
-
- // http://dom.spec.whatwg.org/#dom-node-nodename
- pub fn NodeName(&self, abstract_self: &JS<Node>) -> DOMString {
- match self.type_id {
- ElementNodeTypeId(..) => {
- let elem: JS<Element> = ElementCast::to(abstract_self).unwrap();
- elem.get().TagName()
- }
- TextNodeTypeId => ~"#text",
- ProcessingInstructionNodeTypeId => {
- let processing_instruction: JS<ProcessingInstruction> =
- ProcessingInstructionCast::to(abstract_self).unwrap();
- processing_instruction.get().Target()
- }
- CommentNodeTypeId => ~"#comment",
- DoctypeNodeTypeId => {
- let doctype: JS<DocumentType> = DocumentTypeCast::to(abstract_self).unwrap();
- doctype.get().name.clone()
- },
- DocumentFragmentNodeTypeId => ~"#document-fragment",
- DocumentNodeTypeId => ~"#document"
- }
- }
-
- // http://dom.spec.whatwg.org/#dom-node-baseuri
- pub fn GetBaseURI(&self) -> Option<DOMString> {
- // FIXME (#1824) implement.
- None
- }
-
- // http://dom.spec.whatwg.org/#dom-node-ownerdocument
- pub fn GetOwnerDocument(&self) -> Option<JS<Document>> {
- match self.type_id {
- ElementNodeTypeId(..) |
- CommentNodeTypeId |
- TextNodeTypeId |
- ProcessingInstructionNodeTypeId |
- DoctypeNodeTypeId |
- DocumentFragmentNodeTypeId => Some(self.owner_doc().clone()),
- DocumentNodeTypeId => None
- }
- }
-
- // http://dom.spec.whatwg.org/#dom-node-parentnode
- pub fn GetParentNode(&self) -> Option<JS<Node>> {
- self.parent_node.clone()
- }
-
- // http://dom.spec.whatwg.org/#dom-node-parentelement
- pub fn GetParentElement(&self) -> Option<JS<Element>> {
- self.parent_node.clone().and_then(|parent| ElementCast::to(&parent))
- }
-
- // http://dom.spec.whatwg.org/#dom-node-haschildnodes
- pub fn HasChildNodes(&self) -> bool {
- self.first_child.is_some()
- }
-
- // http://dom.spec.whatwg.org/#dom-node-childnodes
- pub fn ChildNodes(&mut self, abstract_self: &JS<Node>) -> JS<NodeList> {
- match self.child_list {
- None => {
- let doc = self.owner_doc().clone();
- let doc = doc.get();
- let list = NodeList::new_child_list(&doc.window, abstract_self);
- self.child_list = Some(list.clone());
- list
- }
- Some(ref list) => list.clone()
- }
- }
-
- // http://dom.spec.whatwg.org/#dom-node-firstchild
- pub fn GetFirstChild(&self) -> Option<JS<Node>> {
- self.first_child.clone()
- }
-
- // http://dom.spec.whatwg.org/#dom-node-lastchild
- pub fn GetLastChild(&self) -> Option<JS<Node>> {
- self.last_child.clone()
- }
-
- // http://dom.spec.whatwg.org/#dom-node-previoussibling
- pub fn GetPreviousSibling(&self) -> Option<JS<Node>> {
- self.prev_sibling.clone()
- }
-
- // http://dom.spec.whatwg.org/#dom-node-nextsibling
- 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: &JS<Node>) -> Option<DOMString> {
- match self.type_id {
- CommentNodeTypeId |
- TextNodeTypeId |
- ProcessingInstructionNodeTypeId => {
- let chardata: JS<CharacterData> = CharacterDataCast::to(abstract_self).unwrap();
- Some(chardata.get().Data())
- }
- _ => {
- None
- }
- }
- }
-
- // http://dom.spec.whatwg.org/#dom-node-nodevalue
- pub fn SetNodeValue(&mut self, abstract_self: &mut JS<Node>, val: Option<DOMString>)
- -> ErrorResult {
- match self.type_id {
- CommentNodeTypeId |
- TextNodeTypeId |
- ProcessingInstructionNodeTypeId => {
- self.SetTextContent(abstract_self, val)
- }
- _ => Ok(())
- }
- }
-
- // http://dom.spec.whatwg.org/#dom-node-textcontent
- 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() {
- let text: JS<Text> = TextCast::to(&node).unwrap();
- content.push_str(text.get().characterdata.data.as_slice());
- }
- }
- Some(content)
- }
- CommentNodeTypeId |
- TextNodeTypeId |
- ProcessingInstructionNodeTypeId => {
- let characterdata: JS<CharacterData> = CharacterDataCast::to(abstract_self).unwrap();
- Some(characterdata.get().Data())
- }
- DoctypeNodeTypeId |
- DocumentNodeTypeId => {
- None
- }
- }
- }
-
- // http://dom.spec.whatwg.org/#dom-node-textcontent
- 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 {
- DocumentFragmentNodeTypeId |
- ElementNodeTypeId(..) => {
- // Step 1-2.
- let node = if value.len() == 0 {
- None
- } else {
- let document = self.owner_doc();
- Some(NodeCast::from(&document.get().CreateTextNode(document, value)))
- };
- // Step 3.
- Node::replace_all(node, abstract_self);
- }
- CommentNodeTypeId |
- TextNodeTypeId |
- ProcessingInstructionNodeTypeId => {
- self.wait_until_safe_to_modify_dom();
-
- let mut characterdata: JS<CharacterData> = CharacterDataCast::to(abstract_self).unwrap();
- characterdata.get_mut().data = value.clone();
-
- // Notify the document that the content of this node is different
- let document = self.owner_doc();
- document.get().content_changed();
- }
- DoctypeNodeTypeId |
- DocumentNodeTypeId => {}
- }
- Ok(())
- }
-
// http://dom.spec.whatwg.org/#concept-node-adopt
- pub fn adopt(node: &mut JS<Node>, document: &JS<Document>) {
+ pub fn adopt(node: &mut JSRef<Node>, document: &JSRef<Document>) {
// Step 1.
- match node.parent_node() {
- Some(ref mut parent) => Node::remove(node, parent, Unsuppressed),
+ match node.parent_node().root() {
+ Some(mut parent) => {
+ Node::remove(node, &mut *parent, Unsuppressed);
+ }
None => (),
}
// Step 2.
- if document_from_node(node) != *document {
+ let node_doc = document_from_node(node).root();
+ if &*node_doc != document {
for mut descendant in node.traverse_preorder() {
- descendant.get_mut().set_owner_doc(document);
+ descendant.set_owner_doc(document);
}
}
@@ -1054,8 +946,8 @@ impl Node {
}
// http://dom.spec.whatwg.org/#concept-node-pre-insert
- fn pre_insert(node: &mut JS<Node>, parent: &mut JS<Node>, child: Option<JS<Node>>)
- -> Fallible<JS<Node>> {
+ fn pre_insert(node: &mut JSRef<Node>, parent: &mut JSRef<Node>, child: Option<JSRef<Node>>)
+ -> Fallible<Temporary<Node>> {
// Step 1.
match parent.type_id() {
DocumentNodeTypeId |
@@ -1078,13 +970,13 @@ impl Node {
// Step 4-5.
match node.type_id() {
TextNodeTypeId => {
- match node.parent_node() {
+ match node.parent_node().root() {
Some(ref parent) if parent.is_document() => return Err(HierarchyRequest),
_ => ()
}
}
DoctypeNodeTypeId => {
- match node.parent_node() {
+ match node.parent_node().root() {
Some(ref parent) if !parent.is_document() => return Err(HierarchyRequest),
_ => ()
}
@@ -1175,24 +1067,25 @@ impl Node {
// Step 7-8.
let referenceChild = match child {
- Some(ref child) if child == node => node.next_sibling(),
+ Some(ref child) if child == node => node.next_sibling().map(|node| (*node.root()).clone()),
_ => child
};
// Step 9.
- Node::adopt(node, &document_from_node(parent));
+ let document = document_from_node(parent).root();
+ Node::adopt(node, &*document);
// Step 10.
Node::insert(node, parent, referenceChild, Unsuppressed);
// Step 11.
- return Ok(node.clone())
+ return Ok(Temporary::from_rooted(node))
}
// http://dom.spec.whatwg.org/#concept-node-insert
- fn insert(node: &mut JS<Node>,
- parent: &mut JS<Node>,
- child: Option<JS<Node>>,
+ fn insert(node: &mut JSRef<Node>,
+ parent: &mut JSRef<Node>,
+ child: Option<JSRef<Node>>,
suppress_observers: SuppressObserver) {
// XXX assert owner_doc
// Step 1-3: ranges.
@@ -1217,7 +1110,7 @@ impl Node {
// Step 8.
for node in nodes.mut_iter() {
parent.add_child(node, child.clone());
- node.get_mut().flags.set_is_in_doc(parent.is_in_doc());
+ node.deref_mut().flags.set_is_in_doc(parent.is_in_doc());
}
// Step 9.
@@ -1232,15 +1125,19 @@ impl Node {
}
// http://dom.spec.whatwg.org/#concept-node-replace-all
- pub fn replace_all(mut node: Option<JS<Node>>, parent: &mut JS<Node>) {
+ fn replace_all(mut node: Option<JSRef<Node>>, parent: &mut JSRef<Node>) {
+
// Step 1.
match node {
- Some(ref mut node) => Node::adopt(node, &document_from_node(parent)),
+ Some(ref mut node) => {
+ let document = document_from_node(parent).root();
+ Node::adopt(node, &*document);
+ }
None => (),
}
// Step 2.
- let removedNodes: Vec<JS<Node>> = parent.children().collect();
+ let removedNodes: Vec<JSRef<Node>> = parent.children().collect();
// Step 3.
let addedNodes = match node {
@@ -1274,10 +1171,10 @@ impl Node {
}
// http://dom.spec.whatwg.org/#concept-node-pre-remove
- fn pre_remove(child: &mut JS<Node>, parent: &mut JS<Node>) -> Fallible<JS<Node>> {
+ fn pre_remove(child: &mut JSRef<Node>, parent: &mut JSRef<Node>) -> Fallible<Temporary<Node>> {
// Step 1.
match child.parent_node() {
- Some(ref node) if node != parent => return Err(NotFound),
+ Some(ref node) if *node != Temporary::from_rooted(parent) => return Err(NotFound),
_ => ()
}
@@ -1285,18 +1182,18 @@ impl Node {
Node::remove(child, parent, Unsuppressed);
// Step 3.
- Ok(child.clone())
+ Ok(Temporary::from_rooted(child))
}
// http://dom.spec.whatwg.org/#concept-node-remove
- fn remove(node: &mut JS<Node>, parent: &mut JS<Node>, suppress_observers: SuppressObserver) {
- assert!(node.parent_node().map_or(false, |ref node_parent| node_parent == parent));
+ fn remove(node: &mut JSRef<Node>, parent: &mut JSRef<Node>, suppress_observers: SuppressObserver) {
+ assert!(node.parent_node().map_or(false, |node_parent| node_parent == Temporary::from_rooted(parent)));
// Step 1-5: ranges.
// Step 6-7: mutation observers.
// Step 8.
parent.remove_child(node);
- node.get_mut().flags.set_is_in_doc(false);
+ node.deref_mut().flags.set_is_in_doc(false);
// Step 9.
match suppress_observers {
@@ -1306,100 +1203,103 @@ impl Node {
}
// http://dom.spec.whatwg.org/#concept-node-clone
- pub fn clone(node: &JS<Node>, maybe_doc: Option<&JS<Document>>,
- clone_children: CloneChildrenFlag) -> JS<Node> {
+ pub fn clone(node: &JSRef<Node>, maybe_doc: Option<&JSRef<Document>>,
+ clone_children: CloneChildrenFlag) -> Temporary<Node> {
+
// Step 1.
let mut document = match maybe_doc {
- Some(doc) => doc.clone(),
- None => node.get().owner_doc().clone()
+ Some(doc) => doc.unrooted().root(),
+ None => node.owner_doc().root()
};
// Step 2.
// XXXabinader: clone() for each node as trait?
- let mut copy: JS<Node> = match node.type_id() {
+ let mut copy: Root<Node> = match node.type_id() {
DoctypeNodeTypeId => {
- let doctype: JS<DocumentType> = DocumentTypeCast::to(node).unwrap();
- let doctype = doctype.get();
+ let doctype: &JSRef<DocumentType> = DocumentTypeCast::to_ref(node).unwrap();
+ let doctype = doctype.deref();
let doctype = DocumentType::new(doctype.name.clone(),
Some(doctype.public_id.clone()),
- Some(doctype.system_id.clone()), &document);
- NodeCast::from(&doctype)
+ Some(doctype.system_id.clone()), &*document);
+ NodeCast::from_unrooted(doctype)
},
DocumentFragmentNodeTypeId => {
- let doc_fragment = DocumentFragment::new(&document);
- NodeCast::from(&doc_fragment)
+ let doc_fragment = DocumentFragment::new(&*document);
+ NodeCast::from_unrooted(doc_fragment)
},
CommentNodeTypeId => {
- let comment: JS<Comment> = CommentCast::to(node).unwrap();
- let comment = comment.get();
- let comment = Comment::new(comment.characterdata.data.clone(), &document);
- NodeCast::from(&comment)
+ let comment: &JSRef<Comment> = CommentCast::to_ref(node).unwrap();
+ let comment = comment.deref();
+ let comment = Comment::new(comment.characterdata.data.clone(), &*document);
+ NodeCast::from_unrooted(comment)
},
DocumentNodeTypeId => {
- let document: JS<Document> = DocumentCast::to(node).unwrap();
- let document = document.get();
+ let document: &JSRef<Document> = DocumentCast::to_ref(node).unwrap();
let is_html_doc = match document.is_html_document {
true => HTMLDocument,
false => NonHTMLDocument
};
- let document = Document::new(&document.window, Some(document.url().clone()),
+ let window = document.window.root();
+ let document = Document::new(&*window, Some(document.url().clone()),
is_html_doc, None);
- NodeCast::from(&document)
+ NodeCast::from_unrooted(document)
},
ElementNodeTypeId(..) => {
- let element: JS<Element> = ElementCast::to(node).unwrap();
- let element = element.get();
- let element = build_element_from_tag(element.local_name.clone(), &document);
- NodeCast::from(&element)
+ let element: &JSRef<Element> = ElementCast::to_ref(node).unwrap();
+ let element = element.deref();
+ let element = build_element_from_tag(element.local_name.clone(), &*document);
+ NodeCast::from_unrooted(element)
},
TextNodeTypeId => {
- let text: JS<Text> = TextCast::to(node).unwrap();
- let text = text.get();
- let text = Text::new(text.characterdata.data.clone(), &document);
- NodeCast::from(&text)
+ let text: &JSRef<Text> = TextCast::to_ref(node).unwrap();
+ let text = text.deref();
+ let text = Text::new(text.characterdata.data.clone(), &*document);
+ NodeCast::from_unrooted(text)
},
ProcessingInstructionNodeTypeId => {
- let pi: JS<ProcessingInstruction> = ProcessingInstructionCast::to(node).unwrap();
- let pi = pi.get();
+ let pi: &JSRef<ProcessingInstruction> = ProcessingInstructionCast::to_ref(node).unwrap();
+ let pi = pi.deref();
let pi = ProcessingInstruction::new(pi.target.clone(),
- pi.characterdata.data.clone(), &document);
- NodeCast::from(&pi)
+ pi.characterdata.data.clone(), &*document);
+ NodeCast::from_unrooted(pi)
},
- };
+ }.root();
// Step 3.
- if copy.is_document() {
- document = DocumentCast::to(&copy).unwrap();
- }
- assert!(copy.get().owner_doc() == &document);
+ let document = if copy.is_document() {
+ let doc: &JSRef<Document> = DocumentCast::to_ref(&*copy).unwrap();
+ doc.unrooted().root()
+ } else {
+ document.unrooted().root()
+ };
+ assert!(&*copy.owner_doc().root() == &*document);
// Step 4 (some data already copied in step 2).
match node.type_id() {
DocumentNodeTypeId => {
- let node_doc: JS<Document> = DocumentCast::to(node).unwrap();
- let node_doc = node_doc.get();
- let mut copy_doc: JS<Document> = DocumentCast::to(&copy).unwrap();
- let copy_doc = copy_doc.get_mut();
+ let node_doc: &JSRef<Document> = DocumentCast::to_ref(node).unwrap();
+ let copy_doc: &mut JSRef<Document> = DocumentCast::to_mut_ref(&mut *copy).unwrap();
copy_doc.set_encoding_name(node_doc.encoding_name.clone());
copy_doc.set_quirks_mode(node_doc.quirks_mode());
},
ElementNodeTypeId(..) => {
- let node_elem: JS<Element> = ElementCast::to(node).unwrap();
- let node_elem = node_elem.get();
- let mut copy_elem: JS<Element> = ElementCast::to(&copy).unwrap();
+ let node_elem: &JSRef<Element> = ElementCast::to_ref(node).unwrap();
+ let node_elem = node_elem.deref();
+ let copy_elem: &mut JSRef<Element> = ElementCast::to_mut_ref(&mut *copy).unwrap();
// XXX: to avoid double borrowing compile error. we might be able to fix this after #1854
- let copy_elem_alias: JS<Element> = copy_elem.clone();
+ let copy_elem_alias = copy_elem.clone();
- let copy_elem = copy_elem.get_mut();
+ let copy_elem = copy_elem.deref_mut();
// FIXME: https://github.com/mozilla/servo/issues/1737
copy_elem.namespace = node_elem.namespace.clone();
- for attr in node_elem.attrs.iter() {
- let attr = attr.get();
- copy_elem.attrs.push(Attr::new(&document.get().window,
- attr.local_name.clone(), attr.value.clone(),
- attr.name.clone(), attr.namespace.clone(),
- attr.prefix.clone(), copy_elem_alias.clone()));
+ let window = document.deref().window.root();
+ for attr in node_elem.attrs.iter().map(|attr| attr.root()) {
+ copy_elem.attrs.push_unrooted(
+ &Attr::new(&*window,
+ attr.deref().local_name.clone(), attr.deref().value.clone(),
+ attr.deref().name.clone(), attr.deref().namespace.clone(),
+ attr.deref().prefix.clone(), &copy_elem_alias));
}
},
_ => ()
@@ -1409,38 +1309,282 @@ impl Node {
// Step 6.
if clone_children == CloneChildren {
- for ref child in node.get().children() {
- let mut child_copy = Node::clone(child, Some(&document), clone_children);
- let _inserted_node = Node::pre_insert(&mut child_copy, &mut copy, None);
+ for ref child in node.children() {
+ let mut child_copy = Node::clone(&*child, Some(&*document), clone_children).root();
+ let _inserted_node = Node::pre_insert(&mut *child_copy, &mut *copy, None);
}
}
// Step 7.
- copy
+ Temporary::from_rooted(&*copy)
}
- // http://dom.spec.whatwg.org/#dom-node-insertbefore
- 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)
+ /// Sends layout data, if any, back to the script task to be destroyed.
+ unsafe fn reap_layout_data(&mut self) {
+ if self.layout_data.is_present() {
+ let layout_data = mem::replace(&mut self.layout_data, LayoutDataRef::new());
+ let layout_chan = layout_data.take_chan();
+ match layout_chan {
+ None => {}
+ Some(chan) => {
+ let LayoutChan(chan) = chan;
+ chan.send(ReapLayoutDataMsg(layout_data))
+ },
+ }
+ }
+ }
+}
+
+pub trait NodeMethods {
+ fn NodeType(&self) -> u16;
+ fn NodeName(&self) -> DOMString;
+ fn GetBaseURI(&self) -> Option<DOMString>;
+ fn GetOwnerDocument(&self) -> Option<Temporary<Document>>;
+ fn GetParentNode(&self) -> Option<Temporary<Node>>;
+ fn GetParentElement(&self) -> Option<Temporary<Element>>;
+ fn HasChildNodes(&self) -> bool;
+ fn ChildNodes(&mut self) -> Temporary<NodeList>;
+ fn GetFirstChild(&self) -> Option<Temporary<Node>>;
+ fn GetLastChild(&self) -> Option<Temporary<Node>>;
+ fn GetPreviousSibling(&self) -> Option<Temporary<Node>>;
+ fn GetNextSibling(&self) -> Option<Temporary<Node>>;
+ fn GetNodeValue(&self) -> Option<DOMString>;
+ fn SetNodeValue(&mut self, val: Option<DOMString>) -> ErrorResult;
+ fn GetTextContent(&self) -> Option<DOMString>;
+ fn SetTextContent(&mut self, value: Option<DOMString>) -> ErrorResult;
+ fn InsertBefore(&mut self, node: &mut JSRef<Node>, child: Option<JSRef<Node>>) -> Fallible<Temporary<Node>>;
+ fn AppendChild(&mut self, node: &mut JSRef<Node>) -> Fallible<Temporary<Node>>;
+ fn ReplaceChild(&mut self, node: &mut JSRef<Node>, child: &mut JSRef<Node>) -> Fallible<Temporary<Node>>;
+ fn RemoveChild(&mut self, node: &mut JSRef<Node>) -> Fallible<Temporary<Node>>;
+ fn Normalize(&mut self);
+ fn CloneNode(&self, deep: bool) -> Temporary<Node>;
+ fn IsEqualNode(&self, maybe_node: Option<JSRef<Node>>) -> bool;
+ fn CompareDocumentPosition(&self, other: &JSRef<Node>) -> u16;
+ fn Contains(&self, maybe_other: Option<JSRef<Node>>) -> bool;
+ fn LookupPrefix(&self, _prefix: Option<DOMString>) -> Option<DOMString>;
+ fn LookupNamespaceURI(&self, _namespace: Option<DOMString>) -> Option<DOMString>;
+ fn IsDefaultNamespace(&self, _namespace: Option<DOMString>) -> bool;
+}
+
+impl<'a> NodeMethods for JSRef<'a, Node> {
+ // http://dom.spec.whatwg.org/#dom-node-nodetype
+ fn NodeType(&self) -> u16 {
+ match self.type_id {
+ ElementNodeTypeId(_) => NodeConstants::ELEMENT_NODE,
+ TextNodeTypeId => NodeConstants::TEXT_NODE,
+ ProcessingInstructionNodeTypeId => NodeConstants::PROCESSING_INSTRUCTION_NODE,
+ CommentNodeTypeId => NodeConstants::COMMENT_NODE,
+ DocumentNodeTypeId => NodeConstants::DOCUMENT_NODE,
+ DoctypeNodeTypeId => NodeConstants::DOCUMENT_TYPE_NODE,
+ DocumentFragmentNodeTypeId => NodeConstants::DOCUMENT_FRAGMENT_NODE,
+ }
+ }
+
+ // http://dom.spec.whatwg.org/#dom-node-nodename
+ fn NodeName(&self) -> DOMString {
+ match self.type_id {
+ ElementNodeTypeId(..) => {
+ let elem: &JSRef<Element> = ElementCast::to_ref(self).unwrap();
+ elem.TagName()
+ }
+ TextNodeTypeId => ~"#text",
+ ProcessingInstructionNodeTypeId => {
+ let processing_instruction: &JSRef<ProcessingInstruction> =
+ ProcessingInstructionCast::to_ref(self).unwrap();
+ processing_instruction.Target()
+ }
+ CommentNodeTypeId => ~"#comment",
+ DoctypeNodeTypeId => {
+ let doctype: &JSRef<DocumentType> = DocumentTypeCast::to_ref(self).unwrap();
+ doctype.deref().name.clone()
+ },
+ DocumentFragmentNodeTypeId => ~"#document-fragment",
+ DocumentNodeTypeId => ~"#document"
+ }
+ }
+
+ // http://dom.spec.whatwg.org/#dom-node-baseuri
+ fn GetBaseURI(&self) -> Option<DOMString> {
+ // FIXME (#1824) implement.
+ None
+ }
+
+ // http://dom.spec.whatwg.org/#dom-node-ownerdocument
+ fn GetOwnerDocument(&self) -> Option<Temporary<Document>> {
+ match self.type_id {
+ ElementNodeTypeId(..) |
+ CommentNodeTypeId |
+ TextNodeTypeId |
+ ProcessingInstructionNodeTypeId |
+ DoctypeNodeTypeId |
+ DocumentFragmentNodeTypeId => Some(self.owner_doc()),
+ DocumentNodeTypeId => None
+ }
+ }
+
+ // http://dom.spec.whatwg.org/#dom-node-parentnode
+ fn GetParentNode(&self) -> Option<Temporary<Node>> {
+ self.parent_node.clone().map(|node| Temporary::new(node))
+ }
+
+ // http://dom.spec.whatwg.org/#dom-node-parentelement
+ fn GetParentElement(&self) -> Option<Temporary<Element>> {
+ self.parent_node.clone()
+ .and_then(|parent| {
+ let parent = parent.root();
+ ElementCast::to_ref(&*parent).map(|elem| {
+ Temporary::from_rooted(elem)
+ })
+ })
+ }
+
+ // http://dom.spec.whatwg.org/#dom-node-haschildnodes
+ fn HasChildNodes(&self) -> bool {
+ self.first_child.is_some()
+ }
+
+ // http://dom.spec.whatwg.org/#dom-node-childnodes
+ fn ChildNodes(&mut self) -> Temporary<NodeList> {
+ match self.child_list {
+ None => (),
+ Some(ref list) => return Temporary::new(list.clone()),
+ }
+
+ let doc = self.owner_doc().root();
+ let window = doc.deref().window.root();
+ let child_list = NodeList::new_child_list(&*window, self);
+ self.child_list.assign(Some(child_list));
+ Temporary::new(self.child_list.get_ref().clone())
+ }
+
+ // http://dom.spec.whatwg.org/#dom-node-firstchild
+ fn GetFirstChild(&self) -> Option<Temporary<Node>> {
+ self.first_child.clone().map(|node| Temporary::new(node))
+ }
+
+ // http://dom.spec.whatwg.org/#dom-node-lastchild
+ fn GetLastChild(&self) -> Option<Temporary<Node>> {
+ self.last_child.clone().map(|node| Temporary::new(node))
+ }
+
+ // http://dom.spec.whatwg.org/#dom-node-previoussibling
+ fn GetPreviousSibling(&self) -> Option<Temporary<Node>> {
+ self.prev_sibling.clone().map(|node| Temporary::new(node))
+ }
+
+ // http://dom.spec.whatwg.org/#dom-node-nextsibling
+ fn GetNextSibling(&self) -> Option<Temporary<Node>> {
+ self.next_sibling.clone().map(|node| Temporary::new(node))
+ }
+
+ // http://dom.spec.whatwg.org/#dom-node-nodevalue
+ fn GetNodeValue(&self) -> Option<DOMString> {
+ match self.type_id {
+ CommentNodeTypeId |
+ TextNodeTypeId |
+ ProcessingInstructionNodeTypeId => {
+ let chardata: &JSRef<CharacterData> = CharacterDataCast::to_ref(self).unwrap();
+ Some(chardata.Data())
+ }
+ _ => {
+ None
+ }
+ }
+ }
+
+ // http://dom.spec.whatwg.org/#dom-node-nodevalue
+ fn SetNodeValue(&mut self, val: Option<DOMString>)
+ -> ErrorResult {
+ match self.type_id {
+ CommentNodeTypeId |
+ TextNodeTypeId |
+ ProcessingInstructionNodeTypeId => {
+ self.SetTextContent(val)
+ }
+ _ => Ok(())
+ }
+ }
+
+ // http://dom.spec.whatwg.org/#dom-node-textcontent
+ fn GetTextContent(&self) -> Option<DOMString> {
+ match self.type_id {
+ DocumentFragmentNodeTypeId |
+ ElementNodeTypeId(..) => {
+ let mut content = ~"";
+ for node in self.traverse_preorder() {
+ if node.is_text() {
+ let text: &JSRef<Text> = TextCast::to_ref(&node).unwrap();
+ content.push_str(text.deref().characterdata.data.as_slice());
+ }
+ }
+ Some(content)
+ }
+ CommentNodeTypeId |
+ TextNodeTypeId |
+ ProcessingInstructionNodeTypeId => {
+ let characterdata: &JSRef<CharacterData> = CharacterDataCast::to_ref(self).unwrap();
+ Some(characterdata.Data())
+ }
+ DoctypeNodeTypeId |
+ DocumentNodeTypeId => {
+ None
+ }
+ }
}
- pub fn wait_until_safe_to_modify_dom(&self) {
- let document = self.owner_doc();
- document.get().wait_until_safe_to_modify_dom();
+ // http://dom.spec.whatwg.org/#dom-node-textcontent
+ fn SetTextContent(&mut self, value: Option<DOMString>)
+ -> ErrorResult {
+ let value = null_str_as_empty(&value);
+ match self.type_id {
+ DocumentFragmentNodeTypeId |
+ ElementNodeTypeId(..) => {
+ // Step 1-2.
+ let node = if value.len() == 0 {
+ None
+ } else {
+ let document = self.owner_doc().root();
+ Some(NodeCast::from_unrooted(document.deref().CreateTextNode(value)))
+ }.root();
+
+ // Step 3.
+ Node::replace_all(node.root_ref(), self);
+ }
+ CommentNodeTypeId |
+ TextNodeTypeId |
+ ProcessingInstructionNodeTypeId => {
+ self.wait_until_safe_to_modify_dom();
+
+ {
+ let characterdata: &mut JSRef<CharacterData> = CharacterDataCast::to_mut_ref(self).unwrap();
+ characterdata.deref_mut().data = value.clone();
+ }
+
+ // Notify the document that the content of this node is different
+ let document = self.owner_doc().root();
+ document.deref().content_changed();
+ }
+ DoctypeNodeTypeId |
+ DocumentNodeTypeId => {}
+ }
+ Ok(())
+ }
+
+ // http://dom.spec.whatwg.org/#dom-node-insertbefore
+ fn InsertBefore(&mut self, node: &mut JSRef<Node>, child: Option<JSRef<Node>>) -> Fallible<Temporary<Node>> {
+ Node::pre_insert(node, self, child)
}
// http://dom.spec.whatwg.org/#dom-node-appendchild
- pub fn AppendChild(&self, abstract_self: &mut JS<Node>, node: &mut JS<Node>)
- -> Fallible<JS<Node>> {
- Node::pre_insert(node, abstract_self, None)
+ fn AppendChild(&mut self, node: &mut JSRef<Node>) -> Fallible<Temporary<Node>> {
+ Node::pre_insert(node, self, None)
}
// http://dom.spec.whatwg.org/#concept-node-replace
- pub fn ReplaceChild(&self, parent: &mut JS<Node>, node: &mut JS<Node>, child: &mut JS<Node>)
- -> Fallible<JS<Node>> {
+ fn ReplaceChild(&mut self, node: &mut JSRef<Node>, child: &mut JSRef<Node>) -> Fallible<Temporary<Node>> {
+
// Step 1.
- match parent.type_id() {
+ match self.type_id() {
DocumentNodeTypeId |
DocumentFragmentNodeTypeId |
ElementNodeTypeId(..) => (),
@@ -1448,19 +1592,19 @@ impl Node {
}
// Step 2.
- if node.is_inclusive_ancestor_of(parent) {
+ if node.is_inclusive_ancestor_of(self) {
return Err(HierarchyRequest);
}
// Step 3.
- if !parent.is_parent_of(child) {
+ if !self.is_parent_of(child) {
return Err(NotFound);
}
// Step 4-5.
match node.type_id() {
- TextNodeTypeId if parent.is_document() => return Err(HierarchyRequest),
- DoctypeNodeTypeId if !parent.is_document() => return Err(HierarchyRequest),
+ TextNodeTypeId if self.is_document() => return Err(HierarchyRequest),
+ DoctypeNodeTypeId if !self.is_document() => return Err(HierarchyRequest),
DocumentFragmentNodeTypeId |
DoctypeNodeTypeId |
ElementNodeTypeId(..) |
@@ -1471,7 +1615,7 @@ impl Node {
}
// Step 6.
- match parent.type_id() {
+ match self.type_id() {
DocumentNodeTypeId => {
match node.type_id() {
// Step 6.1
@@ -1484,7 +1628,7 @@ impl Node {
0 => (),
// Step 6.1.2
1 => {
- if parent.child_elements().any(|c| &NodeCast::from(&c) != child) {
+ if self.child_elements().any(|c| NodeCast::from_ref(&c) != child) {
return Err(HierarchyRequest);
}
if child.following_siblings()
@@ -1498,7 +1642,7 @@ impl Node {
},
// Step 6.2
ElementNodeTypeId(..) => {
- if parent.child_elements().any(|c| &NodeCast::from(&c) != child) {
+ if self.child_elements().any(|c| NodeCast::from_ref(&c) != child) {
return Err(HierarchyRequest);
}
if child.following_siblings()
@@ -1508,10 +1652,10 @@ impl Node {
},
// Step 6.3
DoctypeNodeTypeId => {
- if parent.children().any(|c| c.is_doctype() && &c != child) {
+ if self.children().any(|c| c.is_doctype() && &c != child) {
return Err(HierarchyRequest);
}
- if parent.children()
+ if self.children()
.take_while(|c| c != child)
.any(|c| c.is_element()) {
return Err(HierarchyRequest);
@@ -1528,25 +1672,26 @@ impl Node {
// Ok if not caught by previous error checks.
if *node == *child {
- return Ok(child.clone());
+ return Ok(Temporary::from_rooted(child));
}
// Step 7-8.
- let next_sibling = child.next_sibling();
+ let next_sibling = child.next_sibling().map(|node| (*node.root()).clone());
let reference_child = match next_sibling {
- Some(ref sibling) if sibling == node => node.next_sibling(),
+ Some(ref sibling) if sibling == node => node.next_sibling().map(|node| (*node.root()).clone()),
_ => next_sibling
};
// Step 9.
- Node::adopt(node, &document_from_node(parent));
+ let document = document_from_node(self).root();
+ Node::adopt(node, &*document);
{
// Step 10.
- Node::remove(child, parent, Suppressed);
+ Node::remove(child, self, Suppressed);
// Step 11.
- Node::insert(node, parent, reference_child, Suppressed);
+ Node::insert(node, self, reference_child, Suppressed);
}
// Step 12-14.
@@ -1561,36 +1706,36 @@ impl Node {
}
// Step 15.
- Ok(child.clone())
+ Ok(Temporary::from_rooted(child))
}
// http://dom.spec.whatwg.org/#dom-node-removechild
- pub fn RemoveChild(&self, abstract_self: &mut JS<Node>, node: &mut JS<Node>)
- -> Fallible<JS<Node>> {
- Node::pre_remove(node, abstract_self)
+ fn RemoveChild(&mut self, node: &mut JSRef<Node>)
+ -> Fallible<Temporary<Node>> {
+ Node::pre_remove(node, self)
}
// http://dom.spec.whatwg.org/#dom-node-normalize
- pub fn Normalize(&mut self, abstract_self: &mut JS<Node>) {
+ fn Normalize(&mut self) {
let mut prev_text = None;
for mut child in self.children() {
if child.is_text() {
- let characterdata: JS<CharacterData> = CharacterDataCast::to(&child).unwrap();
- if characterdata.get().Length() == 0 {
- abstract_self.remove_child(&mut child);
+ let mut child_alias = child.clone();
+ let characterdata: &JSRef<CharacterData> = CharacterDataCast::to_ref(&child).unwrap();
+ if characterdata.Length() == 0 {
+ self.remove_child(&mut child_alias);
} else {
match prev_text {
- Some(ref text_node) => {
- let mut prev_characterdata: JS<CharacterData> = CharacterDataCast::to(text_node).unwrap();
- let _ = prev_characterdata.get_mut().AppendData(characterdata.get().Data());
- abstract_self.remove_child(&mut child);
+ Some(ref mut text_node) => {
+ let prev_characterdata: &mut JSRef<CharacterData> = CharacterDataCast::to_mut_ref(text_node).unwrap();
+ let _ = prev_characterdata.AppendData(characterdata.Data());
+ self.remove_child(&mut child_alias);
},
- None => prev_text = Some(child)
+ None => prev_text = Some(child_alias)
}
}
} else {
- let c = &mut child.clone();
- child.get_mut().Normalize(c);
+ child.Normalize();
prev_text = None;
}
@@ -1598,54 +1743,54 @@ impl Node {
}
// http://dom.spec.whatwg.org/#dom-node-clonenode
- pub fn CloneNode(&self, abstract_self: &mut JS<Node>, deep: bool) -> JS<Node> {
+ fn CloneNode(&self, deep: bool) -> Temporary<Node> {
match deep {
- true => Node::clone(abstract_self, None, CloneChildren),
- false => Node::clone(abstract_self, None, DoNotCloneChildren)
+ true => Node::clone(self, None, CloneChildren),
+ false => Node::clone(self, None, DoNotCloneChildren)
}
}
// http://dom.spec.whatwg.org/#dom-node-isequalnode
- 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).unwrap();
- let other_doctype: JS<DocumentType> = DocumentTypeCast::to(other).unwrap();
- (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).unwrap();
- let other_element: JS<Element> = ElementCast::to(other).unwrap();
+ fn IsEqualNode(&self, maybe_node: Option<JSRef<Node>>) -> bool {
+ fn is_equal_doctype(node: &JSRef<Node>, other: &JSRef<Node>) -> bool {
+ let doctype: &JSRef<DocumentType> = DocumentTypeCast::to_ref(node).unwrap();
+ let other_doctype: &JSRef<DocumentType> = DocumentTypeCast::to_ref(other).unwrap();
+ (doctype.deref().name == other_doctype.deref().name) &&
+ (doctype.deref().public_id == other_doctype.deref().public_id) &&
+ (doctype.deref().system_id == other_doctype.deref().system_id)
+ }
+ fn is_equal_element(node: &JSRef<Node>, other: &JSRef<Node>) -> bool {
+ let element: &JSRef<Element> = ElementCast::to_ref(node).unwrap();
+ let other_element: &JSRef<Element> = ElementCast::to_ref(other).unwrap();
// FIXME: namespace prefix
- (element.get().namespace == other_element.get().namespace) &&
- (element.get().local_name == other_element.get().local_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).unwrap();
- let other_pi: JS<ProcessingInstruction> = ProcessingInstructionCast::to(other).unwrap();
- (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).unwrap();
- let other_characterdata: JS<CharacterData> = CharacterDataCast::to(other).unwrap();
- 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).unwrap();
- let other_element: JS<Element> = ElementCast::to(other).unwrap();
- 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)
+ (element.deref().namespace == other_element.deref().namespace) &&
+ (element.deref().local_name == other_element.deref().local_name) &&
+ (element.deref().attrs.len() == other_element.deref().attrs.len())
+ }
+ fn is_equal_processinginstruction(node: &JSRef<Node>, other: &JSRef<Node>) -> bool {
+ let pi: &JSRef<ProcessingInstruction> = ProcessingInstructionCast::to_ref(node).unwrap();
+ let other_pi: &JSRef<ProcessingInstruction> = ProcessingInstructionCast::to_ref(other).unwrap();
+ (pi.deref().target == other_pi.deref().target) &&
+ (pi.deref().characterdata.data == other_pi.deref().characterdata.data)
+ }
+ fn is_equal_characterdata(node: &JSRef<Node>, other: &JSRef<Node>) -> bool {
+ let characterdata: &JSRef<CharacterData> = CharacterDataCast::to_ref(node).unwrap();
+ let other_characterdata: &JSRef<CharacterData> = CharacterDataCast::to_ref(other).unwrap();
+ characterdata.deref().data == other_characterdata.deref().data
+ }
+ fn is_equal_element_attrs(node: &JSRef<Node>, other: &JSRef<Node>) -> bool {
+ let element: &JSRef<Element> = ElementCast::to_ref(node).unwrap();
+ let other_element: &JSRef<Element> = ElementCast::to_ref(other).unwrap();
+ assert!(element.deref().attrs.len() == other_element.deref().attrs.len());
+ element.deref().attrs.iter().map(|attr| attr.root()).all(|attr| {
+ other_element.deref().attrs.iter().map(|attr| attr.root()).any(|other_attr| {
+ (attr.namespace == other_attr.namespace) &&
+ (attr.local_name == other_attr.local_name) &&
+ (attr.value == other_attr.value)
})
})
}
- fn is_equal_node(this: &JS<Node>, node: &JS<Node>) -> bool {
+ fn is_equal_node(this: &JSRef<Node>, node: &JSRef<Node>) -> bool {
// Step 2.
if this.type_id() != node.type_id() {
return false;
@@ -1669,44 +1814,46 @@ impl Node {
}
// Step 6.
- this.children().zip(node.children()).all(|(ref child, ref 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(ref node) => is_equal_node(abstract_self, node)
+ Some(ref node) => is_equal_node(self, node)
}
}
// http://dom.spec.whatwg.org/#dom-node-comparedocumentposition
- pub fn CompareDocumentPosition(&self, abstract_self: &JS<Node>, other: &JS<Node>) -> u16 {
- if abstract_self == other {
+ fn CompareDocumentPosition(&self, other: &JSRef<Node>) -> u16 {
+ if self == other {
// step 2.
0
} else {
- let mut lastself = abstract_self.clone();
+ let mut lastself = self.clone();
let mut lastother = other.clone();
- for ancestor in abstract_self.ancestors() {
+ for ancestor in self.ancestors() {
if &ancestor == other {
// step 4.
return NodeConstants::DOCUMENT_POSITION_CONTAINS +
NodeConstants::DOCUMENT_POSITION_PRECEDING;
}
- lastself = ancestor;
+ lastself = ancestor.clone();
}
for ancestor in other.ancestors() {
- if &ancestor == abstract_self {
+ if &ancestor == self {
// step 5.
return NodeConstants::DOCUMENT_POSITION_CONTAINED_BY +
NodeConstants::DOCUMENT_POSITION_FOLLOWING;
}
- lastother = ancestor;
+ lastother = ancestor.clone();
}
if lastself != lastother {
- let abstract_uint: uintptr_t = as_uintptr(&abstract_self.get());
- let other_uint: uintptr_t = as_uintptr(&other.get());
+ let abstract_uint: uintptr_t = as_uintptr(&*self);
+ let other_uint: uintptr_t = as_uintptr(&*other);
let random = if abstract_uint < other_uint {
NodeConstants::DOCUMENT_POSITION_FOLLOWING
@@ -1724,7 +1871,7 @@ impl Node {
// step 6.
return NodeConstants::DOCUMENT_POSITION_PRECEDING;
}
- if &child == abstract_self {
+ if &child == self {
// step 7.
return NodeConstants::DOCUMENT_POSITION_FOLLOWING;
}
@@ -1734,103 +1881,33 @@ impl Node {
}
// http://dom.spec.whatwg.org/#dom-node-contains
- pub fn Contains(&self, abstract_self: &JS<Node>, maybe_other: Option<JS<Node>>) -> bool {
+ fn Contains(&self, maybe_other: Option<JSRef<Node>>) -> bool {
match maybe_other {
None => false,
- Some(ref other) => abstract_self.is_inclusive_ancestor_of(other)
+ Some(ref other) => self.is_inclusive_ancestor_of(other)
}
}
// http://dom.spec.whatwg.org/#dom-node-lookupprefix
- pub fn LookupPrefix(&self, _prefix: Option<DOMString>) -> Option<DOMString> {
+ fn LookupPrefix(&self, _prefix: Option<DOMString>) -> Option<DOMString> {
// FIXME (#1826) implement.
None
}
// http://dom.spec.whatwg.org/#dom-node-lookupnamespaceuri
- pub fn LookupNamespaceURI(&self, _namespace: Option<DOMString>) -> Option<DOMString> {
+ fn LookupNamespaceURI(&self, _namespace: Option<DOMString>) -> Option<DOMString> {
// FIXME (#1826) implement.
None
}
// http://dom.spec.whatwg.org/#dom-node-isdefaultnamespace
- pub fn IsDefaultNamespace(&self, _namespace: Option<DOMString>) -> bool {
+ fn IsDefaultNamespace(&self, _namespace: Option<DOMString>) -> bool {
// FIXME (#1826) implement.
false
}
-
- //
- // Low-level pointer stitching
- //
-
- pub fn set_parent_node(&mut self, new_parent_node: Option<JS<Node>>) {
- let doc = self.owner_doc().clone();
- 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<JS<Node>>) {
- let doc = self.owner_doc().clone();
- 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<JS<Node>>) {
- let doc = self.owner_doc().clone();
- 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<JS<Node>>) {
- let doc = self.owner_doc().clone();
- 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<JS<Node>>) {
- let doc = self.owner_doc().clone();
- doc.get().wait_until_safe_to_modify_dom();
- self.next_sibling = new_next_sibling
- }
-
- pub fn get_hover_state(&self) -> bool {
- self.flags.get_in_hover_state()
- }
-
- pub fn set_hover_state(&mut self, state: bool) {
- self.flags.set_is_in_hover_state(state);
- }
-
- #[inline]
- pub fn parent_node_ref<'a>(&'a self) -> Option<&'a JS<Node>> {
- self.parent_node.as_ref()
- }
-
- #[inline]
- pub fn first_child_ref<'a>(&'a self) -> Option<&'a JS<Node>> {
- self.first_child.as_ref()
- }
-
- #[inline]
- pub fn last_child_ref<'a>(&'a self) -> Option<&'a JS<Node>> {
- self.last_child.as_ref()
- }
-
- #[inline]
- pub fn prev_sibling_ref<'a>(&'a self) -> Option<&'a JS<Node>> {
- self.prev_sibling.as_ref()
- }
-
- #[inline]
- pub fn next_sibling_ref<'a>(&'a self) -> Option<&'a JS<Node>> {
- self.next_sibling.as_ref()
- }
-
- pub unsafe fn get_hover_state_for_layout(&self) -> bool {
- self.flags.get_in_hover_state()
- }
}
+
impl Reflectable for Node {
fn reflector<'a>(&'a self) -> &'a Reflector {
self.eventtarget.reflector()
@@ -1841,19 +1918,19 @@ impl Reflectable for Node {
}
}
-pub fn document_from_node<T: NodeBase>(derived: &JS<T>) -> JS<Document> {
- let node: JS<Node> = NodeCast::from(derived);
- node.get().owner_doc().clone()
+pub fn document_from_node<T: NodeBase>(derived: &JSRef<T>) -> Temporary<Document> {
+ let node: &JSRef<Node> = NodeCast::from_ref(derived);
+ node.owner_doc()
}
-pub fn window_from_node<T: NodeBase>(derived: &JS<T>) -> JS<Window> {
- let document: JS<Document> = document_from_node(derived);
- document.get().window.clone()
+pub fn window_from_node<T: NodeBase>(derived: &JSRef<T>) -> Temporary<Window> {
+ let document = document_from_node(derived).root();
+ Temporary::new(document.deref().window.clone())
}
-impl VirtualMethods for JS<Node> {
- fn super_type(&self) -> Option<~VirtualMethods:> {
- let eventtarget: JS<EventTarget> = EventTargetCast::from(self);
- Some(~eventtarget as ~VirtualMethods:)
+impl<'a> VirtualMethods for JSRef<'a, Node> {
+ fn super_type<'a>(&'a mut self) -> Option<&'a mut VirtualMethods:> {
+ let eventtarget: &mut JSRef<EventTarget> = EventTargetCast::from_mut_ref(self);
+ Some(eventtarget as &mut VirtualMethods:)
}
}