diff options
Diffstat (limited to 'src/components/script/dom/node.rs')
-rw-r--r-- | src/components/script/dom/node.rs | 205 |
1 files changed, 94 insertions, 111 deletions
diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs index b002715eb1c..a98f89b4817 100644 --- a/src/components/script/dom/node.rs +++ b/src/components/script/dom/node.rs @@ -7,7 +7,6 @@ use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{DOMString, null_str_as_empty}; use dom::bindings::utils::{ErrorResult, Fallible, NotFound, HierarchyRequest}; -use dom::bindings::utils; use dom::characterdata::CharacterData; use dom::document::{AbstractDocument, DocumentTypeId}; use dom::documenttype::DocumentType; @@ -20,12 +19,15 @@ use dom::nodelist::{NodeList}; use dom::text::Text; use js::jsapi::{JSObject, JSContext}; -use servo_util::slot::{MutSlotRef, Slot, SlotRef}; -use std::cast::transmute; + +use layout_interface::{LayoutChan, ReapLayoutDataMsg}; + use std::cast; -use std::unstable::raw::Box; -use std::util; +use std::cast::transmute; +use std::cell::{RefCell, Ref, RefMut}; use std::iter::Filter; +use std::util; +use std::unstable::raw::Box; // // The basic Node structure @@ -37,7 +39,7 @@ use std::iter::Filter; /// FIXME: This should be replaced with a trait once they can inherit from structs. #[deriving(Eq)] pub struct AbstractNode { - priv obj: *mut Box<Node>, + priv obj: *mut (), } /// An HTML node. @@ -109,30 +111,43 @@ impl Drop for Node { } /// Encapsulates the abstract layout data. +pub struct LayoutData { + priv chan: Option<LayoutChan>, + priv data: *(), +} + pub struct LayoutDataRef { - priv data: Slot<Option<*()>>, + data_cell: RefCell<Option<LayoutData>>, } impl LayoutDataRef { - #[inline] - pub fn init() -> LayoutDataRef { + pub fn new() -> LayoutDataRef { LayoutDataRef { - data: Slot::init(None), + data_cell: RefCell::new(None), } } - /// Creates a new piece of layout data from a value. - #[inline] pub unsafe fn from_data<T>(data: ~T) -> LayoutDataRef { LayoutDataRef { - data: Slot::init(Some(cast::transmute(data))), + data_cell: RefCell::new(Some(cast::transmute(data))), } } - /// Returns true if this layout data is present or false otherwise. + /// Returns true if there is layout data present. #[inline] pub fn is_present(&self) -> bool { - self.data.get().is_some() + let data_ref = self.data_cell.borrow(); + data_ref.get().is_some() + } + + /// Take the chan out of the layout data if it is present. + pub fn take_chan(&self) -> Option<LayoutChan> { + let mut data_ref = self.data_cell.borrow_mut(); + let layout_data = data_ref.get(); + match *layout_data { + None => None, + Some(..) => Some(layout_data.get_mut_ref().chan.take_unwrap()), + } } /// Borrows the layout data immutably, *asserting that there are no mutators*. Bad things will @@ -141,17 +156,15 @@ impl LayoutDataRef { /// /// FIXME(pcwalton): Enforce this invariant via the type system. Will require traversal /// functions to be trusted, but c'est la vie. - #[inline] - pub unsafe fn borrow_unchecked<'a>(&'a self) -> &'a () { - cast::transmute(self.data.borrow_unchecked()) - } + // #[inline] + // pub unsafe fn borrow_unchecked<'a>(&'a self) -> &'a () { + // self.data.borrow_unchecked() + // } /// Borrows the layout data immutably. This function is *not* thread-safe. #[inline] - pub fn borrow<'a>(&'a self) -> SlotRef<'a,()> { - unsafe { - cast::transmute(self.data.borrow()) - } + pub fn borrow<'a>(&'a self) -> Ref<'a,Option<LayoutData>> { + self.data_cell.borrow() } /// Borrows the layout data mutably. This function is *not* thread-safe. @@ -160,10 +173,8 @@ impl LayoutDataRef { /// prevent CSS selector matching from mutably accessing nodes it's not supposed to and racing /// on it. This has already resulted in one bug! #[inline] - pub fn mutate<'a>(&'a self) -> MutSlotRef<'a,()> { - unsafe { - cast::transmute(self.data.mutate()) - } + pub fn borrow_mut<'a>(&'a self) -> RefMut<'a,Option<LayoutData>> { + self.data_cell.borrow_mut() } } @@ -193,13 +204,15 @@ impl Clone for AbstractNode { impl AbstractNode { pub fn node<'a>(&'a self) -> &'a Node { unsafe { - &(*self.obj).data + let box_: *mut Box<Node> = cast::transmute(self.obj); + &(*box_).data } } pub fn mut_node<'a>(&'a self) -> &'a mut Node { unsafe { - &mut (*self.obj).data + let box_: *mut Box<Node> = cast::transmute(self.obj); + &mut (*box_).data } } @@ -217,20 +230,20 @@ impl AbstractNode { pub fn is_element(&self) -> bool { match self.type_id() { - ElementNodeTypeId(*) => true, + ElementNodeTypeId(..) => true, _ => false } } pub fn is_document(&self) -> bool { match self.type_id() { - DocumentNodeTypeId(*) => true, + DocumentNodeTypeId(..) => true, _ => false } } } -impl<'self> AbstractNode { +impl<'a> AbstractNode { // Unsafe accessors pub unsafe fn as_cacheable_wrapper(&self) -> @mut Reflectable { @@ -252,7 +265,7 @@ impl<'self> AbstractNode { /// FIXME(pcwalton): Mark unsafe? pub fn from_box<T>(ptr: *mut Box<T>) -> AbstractNode { AbstractNode { - obj: ptr as *mut Box<Node> + obj: ptr as *mut () } } @@ -291,27 +304,27 @@ impl<'self> AbstractNode { // Downcasting borrows // - pub fn transmute<T, R>(self, f: &fn(&T) -> R) -> R { + 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); + let box_: *Box<T> = transmute(self.obj); + let rv = f(&(*box_).data); node.abstract = old; rv } } - pub fn transmute_mut<T, R>(self, f: &fn(&mut T) -> R) -> R { + 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)); + let box_: *Box<T> = transmute(self.obj); + let rv = f(cast::transmute(&(*box_).data)); node.abstract = old; rv } @@ -323,14 +336,14 @@ impl<'self> AbstractNode { self.is_text() || self.is_comment() } - pub fn with_imm_characterdata<R>(self, f: &fn(&CharacterData) -> R) -> R { + pub fn with_imm_characterdata<R>(self, f: |&CharacterData| -> R) -> R { if !self.is_characterdata() { fail!(~"node is not characterdata"); } self.transmute(f) } - pub fn with_mut_characterdata<R>(self, f: &fn(&mut CharacterData) -> R) -> R { + pub fn with_mut_characterdata<R>(self, f: |&mut CharacterData| -> R) -> R { if !self.is_characterdata() { fail!(~"node is not characterdata"); } @@ -341,14 +354,14 @@ impl<'self> AbstractNode { self.type_id() == DoctypeNodeTypeId } - pub fn with_imm_doctype<R>(self, f: &fn(&DocumentType) -> R) -> R { + pub fn with_imm_doctype<R>(self, f: |&DocumentType| -> R) -> R { if !self.is_doctype() { fail!(~"node is not doctype"); } self.transmute(f) } - pub fn with_mut_doctype<R>(self, f: &fn(&mut DocumentType) -> R) -> R { + pub fn with_mut_doctype<R>(self, f: |&mut DocumentType| -> R) -> R { if !self.is_doctype() { fail!(~"node is not doctype"); } @@ -375,14 +388,14 @@ impl<'self> AbstractNode { } } - pub fn with_imm_text<R>(self, f: &fn(&Text) -> R) -> R { + 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: &fn(&mut Text) -> R) -> R { + pub fn with_mut_text<R>(self, f: |&mut Text| -> R) -> R { if !self.is_text() { fail!(~"node is not text"); } @@ -390,7 +403,7 @@ impl<'self> AbstractNode { } // FIXME: This should be doing dynamic borrow checking for safety. - pub fn with_imm_element<R>(self, f: &fn(&Element) -> R) -> R { + pub fn with_imm_element<R>(self, f: |&Element| -> R) -> R { if !self.is_element() { fail!(~"node is not an element"); } @@ -398,7 +411,7 @@ impl<'self> AbstractNode { } // FIXME: This should be doing dynamic borrow checking for safety. - pub fn as_mut_element<R>(self, f: &fn(&mut Element) -> R) -> R { + pub fn as_mut_element<R>(self, f: |&mut Element| -> R) -> R { if !self.is_element() { fail!(~"node is not an element"); } @@ -413,7 +426,7 @@ impl<'self> AbstractNode { } } - pub fn with_mut_image_element<R>(self, f: &fn(&mut HTMLImageElement) -> R) -> R { + 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"); } @@ -424,7 +437,7 @@ impl<'self> AbstractNode { self.type_id() == ElementNodeTypeId(HTMLIframeElementTypeId) } - pub fn with_mut_iframe_element<R>(self, f: &fn(&mut HTMLIFrameElement) -> R) -> R { + 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"); } @@ -440,12 +453,12 @@ impl<'self> AbstractNode { } pub unsafe fn raw_object(self) -> *mut Box<Node> { - self.obj + cast::transmute(self.obj) } pub fn from_raw(raw: *mut Box<Node>) -> AbstractNode { AbstractNode { - obj: raw + obj: raw as *mut () } } @@ -479,10 +492,6 @@ impl<'self> AbstractNode { // Convenience accessors // - fn is_leaf(&self) -> bool { - self.first_child().is_none() - } - pub fn children(&self) -> AbstractNodeChildrenIterator { self.node().children() } @@ -610,35 +619,6 @@ impl AbstractNode { child_node.set_next_sibling(None); child_node.set_parent_node(None); } - - // - // Low-level pointer stitching wrappers - // - - fn set_parent_node(&self, new_parent_node: Option<AbstractNode>) { - let node = self.mut_node(); - node.set_parent_node(new_parent_node) - } - - fn set_first_child(&self, new_first_child: Option<AbstractNode>) { - let node = self.mut_node(); - node.set_first_child(new_first_child) - } - - fn set_last_child(&self, new_last_child: Option<AbstractNode>) { - let node = self.mut_node(); - node.set_last_child(new_last_child) - } - - fn set_prev_sibling(&self, new_prev_sibling: Option<AbstractNode>) { - let node = self.mut_node(); - node.set_prev_sibling(new_prev_sibling) - } - - fn set_next_sibling(&self, new_next_sibling: Option<AbstractNode>) { - let node = self.mut_node(); - node.set_next_sibling(new_next_sibling) - } } // @@ -652,9 +632,9 @@ pub struct AbstractNodeChildrenIterator { impl Iterator<AbstractNode> for AbstractNodeChildrenIterator { fn next(&mut self) -> Option<AbstractNode> { let node = self.current_node; - self.current_node = do self.current_node.and_then |node| { + self.current_node = self.current_node.and_then(|node| { node.next_sibling() - }; + }); node } } @@ -766,9 +746,9 @@ impl Node { assert!(node.reflector().get_jsobject().is_null()); let node = reflect_dom_object(node, document.document().window, wrap_fn); assert!(node.reflector().get_jsobject().is_not_null()); - // This surrenders memory management of the node! + // JS owns the node now, so transmute_copy to not increase the refcount AbstractNode { - obj: unsafe { transmute(node) }, + obj: unsafe { cast::transmute_copy(&node) }, } } @@ -798,16 +778,19 @@ impl Node { flags: NodeFlags::new(type_id), - layout_data: LayoutDataRef::init(), + layout_data: LayoutDataRef::new(), } } /// 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 = util::replace(&mut self.layout_data, LayoutDataRef::init()); - let js_window = utils::global_object_for_dom_object(self); - (*js_window).data.page.reap_dead_layout_data(layout_data) + let layout_data = util::replace(&mut self.layout_data, LayoutDataRef::new()); + let layout_chan = layout_data.take_chan(); + match layout_chan { + None => {} + Some(chan) => chan.send(ReapLayoutDataMsg(layout_data)), + } } } @@ -825,17 +808,17 @@ impl Node { pub fn NodeName(&self, abstract_self: AbstractNode) -> DOMString { match self.type_id { - ElementNodeTypeId(*) => { - do abstract_self.with_imm_element |element| { + ElementNodeTypeId(..) => { + abstract_self.with_imm_element(|element| { element.TagName() - } + }) } CommentNodeTypeId => ~"#comment", TextNodeTypeId => ~"#text", DoctypeNodeTypeId => { - do abstract_self.with_imm_doctype |doctype| { + abstract_self.with_imm_doctype(|doctype| { doctype.name.clone() - } + }) }, DocumentFragmentNodeTypeId => ~"#document-fragment", DocumentNodeTypeId(_) => ~"#document" @@ -848,7 +831,7 @@ impl Node { pub fn GetOwnerDocument(&self) -> Option<AbstractDocument> { match self.type_id { - ElementNodeTypeId(*) | + ElementNodeTypeId(..) | CommentNodeTypeId | TextNodeTypeId | DoctypeNodeTypeId | @@ -889,9 +872,9 @@ impl Node { match self.type_id { // ProcessingInstruction CommentNodeTypeId | TextNodeTypeId => { - do abstract_self.with_imm_characterdata() |characterdata| { + abstract_self.with_imm_characterdata(|characterdata| { Some(characterdata.Data()) - } + }) } _ => { None @@ -906,21 +889,21 @@ impl Node { pub fn GetTextContent(&self, abstract_self: AbstractNode) -> Option<DOMString> { match self.type_id { - DocumentFragmentNodeTypeId | ElementNodeTypeId(*) => { + DocumentFragmentNodeTypeId | ElementNodeTypeId(..) => { let mut content = ~""; for node in abstract_self.traverse_preorder() { if node.is_text() { - do node.with_imm_text() |text| { + node.with_imm_text(|text| { content = content + text.element.Data(); - } + }) } } Some(content) } CommentNodeTypeId | TextNodeTypeId => { - do abstract_self.with_imm_characterdata() |characterdata| { + abstract_self.with_imm_characterdata(|characterdata| { Some(characterdata.Data()) - } + }) } DoctypeNodeTypeId | DocumentNodeTypeId(_) => { None @@ -968,9 +951,9 @@ impl Node { // Step 1. match parent.type_id() { - DocumentNodeTypeId(*) | + DocumentNodeTypeId(..) | DocumentFragmentNodeTypeId | - ElementNodeTypeId(*) => (), + ElementNodeTypeId(..) => (), _ => { return Err(HierarchyRequest); }, @@ -999,7 +982,7 @@ impl Node { TextNodeTypeId | // ProcessingInstructionNodeTypeId | CommentNodeTypeId => (), - DocumentNodeTypeId(*) => return Err(HierarchyRequest), + DocumentNodeTypeId(..) => return Err(HierarchyRequest), } // Step 5. @@ -1241,7 +1224,7 @@ impl Node { -> ErrorResult { let value = null_str_as_empty(&value); match self.type_id { - DocumentFragmentNodeTypeId | ElementNodeTypeId(*) => { + DocumentFragmentNodeTypeId | ElementNodeTypeId(..) => { // Step 1-2. let node = if value.len() == 0 { None @@ -1255,13 +1238,13 @@ impl Node { CommentNodeTypeId | TextNodeTypeId => { self.wait_until_safe_to_modify_dom(); - do abstract_self.with_mut_characterdata() |characterdata| { + abstract_self.with_mut_characterdata(|characterdata| { characterdata.data = value.clone(); // Notify the document that the content of this node is different let document = self.owner_doc(); document.document().content_changed(); - } + }) } DoctypeNodeTypeId | DocumentNodeTypeId(_) => {} } |