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.rs205
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(_) => {}
}