diff --git a/src/components/main/layout/wrapper.rs b/src/components/main/layout/wrapper.rs index f2d8f094f8d..3fa7b918785 100644 --- a/src/components/main/layout/wrapper.rs +++ b/src/components/main/layout/wrapper.rs @@ -136,6 +136,10 @@ pub struct LayoutNode<'a> { /// Being chained to a ContravariantLifetime prevents `LayoutNode`s from escaping. pub chain: ContravariantLifetime<'a>, + + /// Padding to ensure the transmute `JS` -> `LayoutNode`, `LayoutNode` -> `UnsafeLayoutNode`, + /// and `UnsafeLayoutNode` -> others. + pad: uint } impl<'ln> Clone for LayoutNode<'ln> { @@ -143,6 +147,7 @@ impl<'ln> Clone for LayoutNode<'ln> { LayoutNode { node: self.node.clone(), chain: self.chain, + pad: 0, } } } @@ -160,6 +165,7 @@ impl<'ln> TLayoutNode for LayoutNode<'ln> { LayoutNode { node: node.transmute_copy(), chain: self.chain, + pad: 0, } } @@ -175,7 +181,7 @@ impl<'ln> TLayoutNode for LayoutNode<'ln> { fn first_child(&self) -> Option> { unsafe { - self.get_jsmanaged().first_child_ref().map(|node| self.new_with_this_lifetime(node)) + self.get_jsmanaged().first_child_ref().map(|node| self.new_with_this_lifetime(&node)) } } @@ -196,6 +202,7 @@ impl<'ln> LayoutNode<'ln> { f(LayoutNode { node: node, chain: ContravariantLifetime, + pad: 0, }) } @@ -223,19 +230,19 @@ impl<'ln> LayoutNode<'ln> { impl<'ln> TNode> for LayoutNode<'ln> { fn parent_node(&self) -> Option> { unsafe { - self.node.parent_node_ref().map(|node| self.new_with_this_lifetime(node)) + self.node.parent_node_ref().map(|node| self.new_with_this_lifetime(&node)) } } fn prev_sibling(&self) -> Option> { unsafe { - self.node.prev_sibling_ref().map(|node| self.new_with_this_lifetime(node)) + self.node.prev_sibling_ref().map(|node| self.new_with_this_lifetime(&node)) } } fn next_sibling(&self) -> Option> { unsafe { - self.node.next_sibling_ref().map(|node| self.new_with_this_lifetime(node)) + self.node.next_sibling_ref().map(|node| self.new_with_this_lifetime(&node)) } } @@ -425,6 +432,7 @@ impl<'ln> TLayoutNode for ThreadSafeLayoutNode<'ln> { node: LayoutNode { node: node.transmute_copy(), chain: self.node.chain, + pad: 0, }, pseudo: Normal, } @@ -463,7 +471,7 @@ impl<'ln> TLayoutNode for ThreadSafeLayoutNode<'ln> { } unsafe { - self.get_jsmanaged().first_child_ref().map(|node| self.new_with_this_lifetime(node)) + self.get_jsmanaged().first_child_ref().map(|node| self.new_with_this_lifetime(&node)) } } @@ -513,10 +521,10 @@ impl<'ln> ThreadSafeLayoutNode<'ln> { /// Returns the next sibling of this node. Unsafe and private because this can lead to races. unsafe fn next_sibling(&self) -> Option> { if self.pseudo == Before || self.pseudo == BeforeBlock { - return self.get_jsmanaged().first_child_ref().map(|node| self.new_with_this_lifetime(node)) + return self.get_jsmanaged().first_child_ref().map(|node| self.new_with_this_lifetime(&node)) } - self.get_jsmanaged().next_sibling_ref().map(|node| self.new_with_this_lifetime(node)) + self.get_jsmanaged().next_sibling_ref().map(|node| self.new_with_this_lifetime(&node)) } /// Returns an iterator over this node's children. diff --git a/src/components/script/dom/attr.rs b/src/components/script/dom/attr.rs index 68300bcb29f..1b49c9f05c2 100644 --- a/src/components/script/dom/attr.rs +++ b/src/components/script/dom/attr.rs @@ -13,6 +13,7 @@ use dom::virtualmethods::vtable_for; use servo_util::namespace; use servo_util::namespace::Namespace; use servo_util::str::DOMString; +use std::cell::Cell; pub enum AttrSettingType { FirstSetAttr, @@ -29,7 +30,7 @@ pub struct Attr { pub prefix: Option, /// the element that owns this attribute. - pub owner: JS, + pub owner: Cell>, } impl Reflectable for Attr { @@ -53,7 +54,7 @@ impl Attr { name: name, //TODO: Intern attribute names namespace: namespace, prefix: prefix, - owner: owner.unrooted(), + owner: Cell::new(owner.unrooted()), } } @@ -65,7 +66,7 @@ impl Attr { } pub fn set_value(&mut self, set_type: AttrSettingType, value: DOMString) { - let mut owner = self.owner.root(); + let mut owner = self.owner.get().root(); let node: &mut JSRef = NodeCast::from_mut_ref(&mut *owner); let namespace_is_null = self.namespace == namespace::Null; diff --git a/src/components/script/dom/attrlist.rs b/src/components/script/dom/attrlist.rs index 8ed4dca07a4..107cd5a184e 100644 --- a/src/components/script/dom/attrlist.rs +++ b/src/components/script/dom/attrlist.rs @@ -39,11 +39,11 @@ pub trait AttrListMethods { impl<'a> AttrListMethods for JSRef<'a, AttrList> { fn Length(&self) -> u32 { - self.owner.root().attrs.len() as u32 + self.owner.root().attrs.borrow().len() as u32 } fn Item(&self, index: u32) -> Option> { - self.owner.root().attrs.as_slice().get(index as uint).map(|x| Temporary::new(x.clone())) + self.owner.root().attrs.borrow().as_slice().get(index as uint).map(|x| Temporary::new(x.clone())) } fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option> { diff --git a/src/components/script/dom/bindings/js.rs b/src/components/script/dom/bindings/js.rs index 67642c32573..bbceae0ad6d 100644 --- a/src/components/script/dom/bindings/js.rs +++ b/src/components/script/dom/bindings/js.rs @@ -47,7 +47,7 @@ use layout_interface::TrustedNodeAddress; use script_task::StackRoots; use std::cast; -use std::cell::RefCell; +use std::cell::{Cell, RefCell}; use std::kinds::marker::ContravariantLifetime; /// A type that represents a JS-owned value that is rooted for the lifetime of this value. @@ -111,7 +111,7 @@ impl Temporary { /// A rooted, JS-owned value. Must only be used as a field in other JS-owned types. pub struct JS { - ptr: RefCell<*mut T> + ptr: *T } impl Eq for JS { @@ -134,7 +134,7 @@ impl JS { pub unsafe fn from_trusted_node_address(inner: TrustedNodeAddress) -> JS { let TrustedNodeAddress(addr) = inner; JS { - ptr: RefCell::new(addr as *mut Node) + ptr: addr as *Node } } } @@ -143,7 +143,7 @@ impl JS { pub unsafe fn from_trusted_xhr_address(inner: TrustedXHRAddress) -> JS { let TrustedXHRAddress(addr) = inner; JS { - ptr: RefCell::new(addr as *mut XMLHttpRequest) + ptr: addr as *XMLHttpRequest } } } @@ -152,7 +152,7 @@ impl JS { /// Create a new JS-owned value wrapped from a raw Rust pointer. pub unsafe fn from_raw(raw: *mut T) -> JS { JS { - ptr: RefCell::new(raw) + ptr: raw as *T } } @@ -269,6 +269,15 @@ impl, U: Reflectable> OptionalSettable for Option> { } } +impl, U: Reflectable> OptionalSettable for Cell>> { + fn assign(&mut self, val: Option) { + let mut item = self.get(); + item.assign(val); + self.set(item); + } +} + + /// Root a rootable Option type (used for Option>) pub trait OptionalRootable { fn root<'a, 'b>(self) -> Option>; @@ -394,7 +403,7 @@ pub struct Root<'a, 'b, T> { /// Reference to rooted value that must not outlive this container jsref: JSRef<'b, T>, /// Pointer to underlying Rust data - ptr: RefCell<*mut T>, + ptr: *T, /// On-stack JS pointer to assuage conservative stack scanner js_ptr: *mut JSObject, } @@ -445,25 +454,23 @@ impl<'a, 'b, T: Reflectable> DerefMut> for Root<'a, 'b, T> { impl<'a, T: Reflectable> Deref for JSRef<'a, T> { fn deref<'b>(&'b self) -> &'b T { - let borrow = self.ptr.borrow(); unsafe { - &**borrow + &*self.ptr } } } impl<'a, T: Reflectable> DerefMut for JSRef<'a, T> { fn deref_mut<'b>(&'b mut self) -> &'b mut T { - let mut borrowed = self.ptr.borrow_mut(); unsafe { - &mut **borrowed + &mut *(self.ptr as *mut T) } } } /// Encapsulates a reference to something that is guaranteed to be alive. This is freely copyable. pub struct JSRef<'a, T> { - ptr: RefCell<*mut T>, + ptr: *T, chain: ContravariantLifetime<'a>, } @@ -495,7 +502,7 @@ impl<'a,T> JSRef<'a,T> { pub fn unrooted(&self) -> JS { JS { - ptr: self.ptr.clone() + ptr: self.ptr } } } diff --git a/src/components/script/dom/bindings/trace.rs b/src/components/script/dom/bindings/trace.rs index 26decbc450a..9c7f295795e 100644 --- a/src/components/script/dom/bindings/trace.rs +++ b/src/components/script/dom/bindings/trace.rs @@ -160,3 +160,23 @@ impl, E> Encodable for Traceable { Ok(()) } } + +/// for a field which contains DOMType +impl, S: Encoder, E> Encodable for Cell> { + fn encode(&self, s: &mut S) -> Result<(), E> { + self.get().encode(s) + } +} + +impl, S: Encoder, E> Encodable for Cell>> { + fn encode(&self, s: &mut S) -> Result<(), E> { + self.get().encode(s) + } +} + +/// for a field which contains non-POD type contains DOMType +impl, S: Encoder, E> Encodable for RefCell>> { + fn encode(&self, s: &mut S) -> Result<(), E> { + self.borrow().encode(s) + } +} diff --git a/src/components/script/dom/clientrectlist.rs b/src/components/script/dom/clientrectlist.rs index 6072b86df71..6c069807151 100644 --- a/src/components/script/dom/clientrectlist.rs +++ b/src/components/script/dom/clientrectlist.rs @@ -18,9 +18,10 @@ pub struct ClientRectList { impl ClientRectList { pub fn new_inherited(window: &JSRef, rects: Vec>) -> ClientRectList { + let rects = rects.iter().map(|rect| rect.unrooted()).collect(); ClientRectList { reflector_: Reflector::new(), - rects: rects.iter().map(|rect| rect.unrooted()).collect(), + rects: rects, window: window.unrooted(), } } @@ -44,8 +45,9 @@ impl<'a> ClientRectListMethods for JSRef<'a, ClientRectList> { } fn Item(&self, index: u32) -> Option> { - if index < self.rects.len() as u32 { - Some(Temporary::new(self.rects.get(index as uint).clone())) + let rects = &self.rects; + if index < rects.len() as u32 { + Some(Temporary::new(rects.get(index as uint).clone())) } else { None } diff --git a/src/components/script/dom/element.rs b/src/components/script/dom/element.rs index 0a6320b5bb0..d694b3724fc 100644 --- a/src/components/script/dom/element.rs +++ b/src/components/script/dom/element.rs @@ -31,6 +31,7 @@ use servo_util::str::{DOMString, null_str_as_empty_ref, split_html_space_chars}; use std::ascii::StrAsciiExt; use std::cast; +use std::cell::{Cell, RefCell}; #[deriving(Encodable)] pub struct Element { @@ -38,9 +39,9 @@ pub struct Element { pub local_name: DOMString, // TODO: This should be an atom, not a DOMString. pub namespace: Namespace, pub prefix: Option, - pub attrs: Vec>, + pub attrs: RefCell>>, pub style_attribute: Option, - pub attr_list: Option> + pub attr_list: Cell>> } impl ElementDerived for EventTarget { @@ -147,8 +148,8 @@ impl Element { local_name: local_name, namespace: namespace, prefix: prefix, - attrs: vec!(), - attr_list: None, + attrs: RefCell::new(vec!()), + attr_list: Cell::new(None), style_attribute: None, } } @@ -167,7 +168,9 @@ impl RawLayoutElementHelpers for Element { #[inline] unsafe fn get_attr_val_for_layout(&self, namespace: &Namespace, name: &str) -> Option<&'static str> { - self.attrs.iter().find(|attr: & &JS| { + // cast to point to T in RefCell directly + let attrs: *Vec> = cast::transmute(&self.attrs); + (*attrs).iter().find(|attr: & &JS| { let attr = attr.unsafe_get(); name == (*attr).local_name && (*attr).namespace == *namespace }).map(|attr| { @@ -232,7 +235,7 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> { let element: &Element = self.deref(); let is_html_element = self.html_element_in_html_document(); - element.attrs.iter().map(|attr| attr.root()).find(|attr| { + element.attrs.borrow().iter().map(|attr| attr.root()).find(|attr| { let same_name = if is_html_element { name.to_ascii_lower() == attr.local_name } else { @@ -284,7 +287,7 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> { fn do_set_attribute(&mut self, local_name: DOMString, value: DOMString, name: DOMString, namespace: Namespace, prefix: Option, cb: |&JSRef| -> bool) { - let idx = self.deref().attrs.iter() + let idx = self.deref().attrs.borrow().iter() .map(|attr| attr.root()) .position(|attr| cb(&*attr)); let (idx, set_type) = match idx { @@ -293,18 +296,18 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> { let window = window_from_node(self).root(); let attr = Attr::new(&*window, local_name.clone(), value.clone(), name, namespace.clone(), prefix, self); - self.deref_mut().attrs.push_unrooted(&attr); - (self.deref().attrs.len() - 1, FirstSetAttr) + self.deref().attrs.borrow_mut().push_unrooted(&attr); + (self.deref().attrs.borrow().len() - 1, FirstSetAttr) } }; - self.deref_mut().attrs.get(idx).root().set_value(set_type, value); + self.deref().attrs.borrow().get(idx).root().set_value(set_type, value); } fn remove_attribute(&mut self, namespace: Namespace, name: DOMString) -> ErrorResult { let (_, local_name) = get_attribute_parts(name.clone()); - let idx = self.deref().attrs.iter().map(|attr| attr.root()).position(|attr| { + let idx = self.deref().attrs.borrow().iter().map(|attr| attr.root()).position(|attr| { attr.local_name == local_name }); @@ -317,12 +320,12 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> { } if namespace == namespace::Null { - let removed_raw_value = self.deref().attrs.get(idx).root().Value(); + let removed_raw_value = self.deref().attrs.borrow().get(idx).root().Value(); vtable_for(NodeCast::from_mut_ref(self)) .before_remove_attr(local_name.clone(), removed_raw_value); } - self.deref_mut().attrs.remove(idx); + self.deref().attrs.borrow_mut().remove(idx); } }; @@ -469,7 +472,7 @@ impl<'a> ElementMethods for JSRef<'a, Element> { // http://dom.spec.whatwg.org/#dom-element-attributes fn Attributes(&mut self) -> Temporary { - match self.attr_list { + match self.attr_list.get() { None => (), Some(ref list) => return Temporary::new(list.clone()), } @@ -481,7 +484,7 @@ impl<'a> ElementMethods for JSRef<'a, Element> { let window = doc.deref().window.root(); let list = AttrList::new(&*window, self); self.attr_list.assign(Some(list)); - Temporary::new(self.attr_list.get_ref().clone()) + Temporary::new(self.attr_list.get().get_ref().clone()) } // http://dom.spec.whatwg.org/#dom-element-getattribute diff --git a/src/components/script/dom/event.rs b/src/components/script/dom/event.rs index 9f7ab79dddb..8da845845a1 100644 --- a/src/components/script/dom/event.rs +++ b/src/components/script/dom/event.rs @@ -10,6 +10,7 @@ use dom::bindings::error::Fallible; use dom::eventtarget::EventTarget; use dom::window::Window; use servo_util::str::DOMString; +use std::cell::Cell; use geom::point::Point2D; @@ -46,8 +47,8 @@ pub enum EventTypeId { pub struct Event { pub type_id: EventTypeId, pub reflector_: Reflector, - pub current_target: Option>, - pub target: Option>, + pub current_target: Cell>>, + pub target: Cell>>, pub type_: DOMString, pub phase: EventPhase, pub canceled: bool, @@ -66,8 +67,8 @@ impl Event { Event { type_id: type_id, reflector_: Reflector::new(), - current_target: None, - target: None, + current_target: Cell::new(None), + target: Cell::new(None), phase: PhaseNone, type_: "".to_owned(), canceled: false, @@ -123,11 +124,11 @@ impl<'a> EventMethods for JSRef<'a, Event> { } fn GetTarget(&self) -> Option> { - self.target.as_ref().map(|target| Temporary::new(target.clone())) + self.target.get().as_ref().map(|target| Temporary::new(target.clone())) } fn GetCurrentTarget(&self) -> Option> { - self.current_target.as_ref().map(|target| Temporary::new(target.clone())) + self.current_target.get().as_ref().map(|target| Temporary::new(target.clone())) } fn DefaultPrevented(&self) -> bool { @@ -173,7 +174,7 @@ impl<'a> EventMethods for JSRef<'a, Event> { self.stop_immediate = false; self.canceled = false; self.trusted = false; - self.target = None; + self.target.set(None); self.type_ = type_; self.bubbles = bubbles; self.cancelable = cancelable; diff --git a/src/components/script/dom/eventdispatcher.rs b/src/components/script/dom/eventdispatcher.rs index 11db1eb7b2b..819bd135bf6 100644 --- a/src/components/script/dom/eventdispatcher.rs +++ b/src/components/script/dom/eventdispatcher.rs @@ -140,7 +140,7 @@ pub fn dispatch_event<'a, 'b>(target: &JSRef<'a, EventTarget>, event.dispatching = false; event.phase = PhaseNone; - event.current_target = None; + event.current_target.set(None); !event.DefaultPrevented() } diff --git a/src/components/script/dom/formdata.rs b/src/components/script/dom/formdata.rs index 13f1a2de58b..1b778c7cc68 100644 --- a/src/components/script/dom/formdata.rs +++ b/src/components/script/dom/formdata.rs @@ -10,7 +10,6 @@ use dom::blob::Blob; use dom::htmlformelement::HTMLFormElement; use dom::window::Window; use servo_util::str::DOMString; - use collections::hashmap::HashMap; #[deriving(Encodable)] diff --git a/src/components/script/dom/htmlserializer.rs b/src/components/script/dom/htmlserializer.rs index 817f84f91a6..ea33f79fee0 100644 --- a/src/components/script/dom/htmlserializer.rs +++ b/src/components/script/dom/htmlserializer.rs @@ -106,7 +106,7 @@ fn serialize_doctype(doctype: &JSRef, html: &mut StrBuf) { fn serialize_elem(elem: &JSRef, open_elements: &mut Vec<~str>, html: &mut StrBuf) { html.push_char('<'); html.push_str(elem.deref().local_name); - for attr in elem.deref().attrs.iter() { + for attr in elem.deref().attrs.borrow().iter() { let attr = attr.root(); serialize_attr(&*attr, html); }; diff --git a/src/components/script/dom/mouseevent.rs b/src/components/script/dom/mouseevent.rs index 994a18d7be6..55326b8afcd 100644 --- a/src/components/script/dom/mouseevent.rs +++ b/src/components/script/dom/mouseevent.rs @@ -12,6 +12,7 @@ use dom::eventtarget::EventTarget; use dom::uievent::{UIEvent, UIEventMethods}; use dom::window::Window; use servo_util::str::DOMString; +use std::cell::Cell; #[deriving(Encodable)] pub struct MouseEvent { @@ -25,7 +26,7 @@ pub struct MouseEvent { pub alt_key: bool, pub meta_key: bool, pub button: u16, - pub related_target: Option> + pub related_target: Cell>> } impl MouseEventDerived for Event { @@ -47,7 +48,7 @@ impl MouseEvent { alt_key: false, meta_key: false, button: 0, - related_target: None + related_target: Cell::new(None) } } @@ -168,7 +169,7 @@ impl<'a> MouseEventMethods for JSRef<'a, MouseEvent> { } fn GetRelatedTarget(&self) -> Option> { - self.related_target.clone().map(|target| Temporary::new(target)) + self.related_target.get().clone().map(|target| Temporary::new(target)) } fn GetModifierState(&self, _keyArg: DOMString) -> bool { diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs index 1a9c70f2806..87a5229b2d5 100644 --- a/src/components/script/dom/node.rs +++ b/src/components/script/dom/node.rs @@ -41,7 +41,7 @@ use libc; use libc::uintptr_t; use std::cast::transmute; use std::cast; -use std::cell::{RefCell, Ref, RefMut}; +use std::cell::{Cell, RefCell, Ref, RefMut}; use std::iter::{Map, Filter}; use std::mem; use style::ComputedValues; @@ -63,25 +63,25 @@ pub struct Node { pub type_id: NodeTypeId, /// The parent of this node. - pub parent_node: Option>, + pub parent_node: Cell>>, /// The first child of this node. - pub first_child: Option>, + pub first_child: Cell>>, /// The last child of this node. - pub last_child: Option>, + pub last_child: Cell>>, /// The next sibling of this node. - pub next_sibling: Option>, + pub next_sibling: Cell>>, /// The previous sibling of this node. - pub prev_sibling: Option>, + pub prev_sibling: Cell>>, /// The document that this node belongs to. - owner_doc: Option>, + owner_doc: Cell>>, /// The live list of children return by .childNodes. - pub child_list: Option>, + pub child_list: Cell>>, /// A bitfield of flags for node items. flags: NodeFlags, @@ -327,26 +327,26 @@ impl<'a> PrivateNodeHelpers for JSRef<'a, Node> { /// /// Fails unless `child` is a child of this node. (FIXME: This is not yet checked.) fn remove_child(&mut self, child: &mut JSRef) { - assert!(child.parent_node.is_some()); + assert!(child.parent_node.get().is_some()); - match child.prev_sibling.root() { + match child.prev_sibling.get().root() { None => { - let next_sibling = child.next_sibling.root(); + let next_sibling = child.next_sibling.get().root(); self.set_first_child(next_sibling.root_ref()); } Some(ref mut prev_sibling) => { - let next_sibling = child.next_sibling.root(); + let next_sibling = child.next_sibling.get().root(); prev_sibling.set_next_sibling(next_sibling.root_ref()); } } - match child.next_sibling.root() { + match child.next_sibling.get().root() { None => { - let prev_sibling = child.prev_sibling.root(); + let prev_sibling = child.prev_sibling.get().root(); self.set_last_child(prev_sibling.root_ref()); } Some(ref mut next_sibling) => { - let prev_sibling = child.prev_sibling.root(); + let prev_sibling = child.prev_sibling.get().root(); next_sibling.set_prev_sibling(prev_sibling.root_ref()); } } @@ -475,25 +475,25 @@ impl<'a> NodeHelpers for JSRef<'a, Node> { } fn parent_node(&self) -> Option> { - self.deref().parent_node.clone().map(|node| Temporary::new(node)) + self.deref().parent_node.get().map(|node| Temporary::new(node)) } fn first_child(&self) -> Option> { - self.deref().first_child.clone().map(|node| Temporary::new(node)) + self.deref().first_child.get().map(|node| Temporary::new(node)) } fn last_child(&self) -> Option> { - self.deref().last_child.clone().map(|node| Temporary::new(node)) + self.deref().last_child.get().map(|node| Temporary::new(node)) } /// Returns the previous sibling of this node. Fails if this node is borrowed mutably. fn prev_sibling(&self) -> Option> { - self.deref().prev_sibling.clone().map(|node| Temporary::new(node)) + self.deref().prev_sibling.get().map(|node| Temporary::new(node)) } /// Returns the next sibling of this node. Fails if this node is borrowed mutably. fn next_sibling(&self) -> Option> { - self.deref().next_sibling.clone().map(|node| Temporary::new(node)) + self.deref().next_sibling.get().map(|node| Temporary::new(node)) } #[inline] @@ -593,12 +593,12 @@ impl<'a> NodeHelpers for JSRef<'a, Node> { fn ancestors(&self) -> AncestorIterator { AncestorIterator { - current: self.parent_node.clone().map(|node| (*node.root()).clone()), + current: self.parent_node.get().map(|node| (*node.root()).clone()), } } fn owner_doc(&self) -> Temporary { - Temporary::new(self.owner_doc.get_ref().clone()) + Temporary::new(self.owner_doc.get().get_ref().clone()) } fn set_owner_doc(&mut self, document: &JSRef) { @@ -607,7 +607,7 @@ impl<'a> NodeHelpers for JSRef<'a, Node> { fn children(&self) -> AbstractNodeChildrenIterator { AbstractNodeChildrenIterator { - current_node: self.first_child.clone().map(|node| (*node.root()).clone()), + current_node: self.first_child.get().map(|node| (*node.root()).clone()), } } @@ -654,13 +654,13 @@ pub fn from_untrusted_node_address(runtime: *mut JSRuntime, candidate: Untrusted pub trait LayoutNodeHelpers { unsafe fn type_id_for_layout(&self) -> NodeTypeId; - unsafe fn parent_node_ref<'a>(&'a self) -> Option<&'a JS>; - unsafe fn first_child_ref<'a>(&'a self) -> Option<&'a JS>; - unsafe fn last_child_ref<'a>(&'a self) -> Option<&'a JS>; - unsafe fn prev_sibling_ref<'a>(&'a self) -> Option<&'a JS>; - unsafe fn next_sibling_ref<'a>(&'a self) -> Option<&'a JS>; + unsafe fn parent_node_ref<'a>(&'a self) -> Option>; + unsafe fn first_child_ref<'a>(&'a self) -> Option>; + unsafe fn last_child_ref<'a>(&'a self) -> Option>; + unsafe fn prev_sibling_ref<'a>(&'a self) -> Option>; + unsafe fn next_sibling_ref<'a>(&'a self) -> Option>; - unsafe fn owner_doc_for_layout<'a>(&'a self) -> &'a JS; + unsafe fn owner_doc_for_layout<'a>(&'a self) -> JS; unsafe fn is_element_for_layout(&self) -> bool; } @@ -675,32 +675,32 @@ impl LayoutNodeHelpers for JS { } #[inline] - unsafe fn parent_node_ref<'a>(&'a self) -> Option<&'a JS> { - (*self.unsafe_get()).parent_node.as_ref() + unsafe fn parent_node_ref<'a>(&'a self) -> Option> { + (*self.unsafe_get()).parent_node.get() } #[inline] - unsafe fn first_child_ref<'a>(&'a self) -> Option<&'a JS> { - (*self.unsafe_get()).first_child.as_ref() + unsafe fn first_child_ref<'a>(&'a self) -> Option> { + (*self.unsafe_get()).first_child.get() } #[inline] - unsafe fn last_child_ref<'a>(&'a self) -> Option<&'a JS> { - (*self.unsafe_get()).last_child.as_ref() + unsafe fn last_child_ref<'a>(&'a self) -> Option> { + (*self.unsafe_get()).last_child.get() } #[inline] - unsafe fn prev_sibling_ref<'a>(&'a self) -> Option<&'a JS> { - (*self.unsafe_get()).prev_sibling.as_ref() + unsafe fn prev_sibling_ref<'a>(&'a self) -> Option> { + (*self.unsafe_get()).prev_sibling.get() } #[inline] - unsafe fn next_sibling_ref<'a>(&'a self) -> Option<&'a JS> { - (*self.unsafe_get()).next_sibling.as_ref() + unsafe fn next_sibling_ref<'a>(&'a self) -> Option> { + (*self.unsafe_get()).next_sibling.get() } - unsafe fn owner_doc_for_layout<'a>(&'a self) -> &'a JS { - (*self.unsafe_get()).owner_doc.get_ref() + unsafe fn owner_doc_for_layout<'a>(&'a self) -> JS { + (*self.unsafe_get()).owner_doc.get().unwrap() } } @@ -822,7 +822,7 @@ impl<'a> Iterator> for NodeIterator { self.current_node = match self.current_node.as_ref().map(|node| node.root()) { None => { if self.include_start { - Some(self.start_node.clone()) + Some(self.start_node) } else { self.next_child(&*self.start_node.root()) .map(|child| child.unrooted()) @@ -860,7 +860,7 @@ impl<'a> Iterator> for NodeIterator { } } }; - self.current_node.clone().map(|node| (*node.root()).clone()) + self.current_node.map(|node| (*node.root()).clone()) } } @@ -911,14 +911,14 @@ impl Node { eventtarget: EventTarget::new_inherited(NodeTargetTypeId(type_id)), type_id: type_id, - parent_node: None, - first_child: None, - last_child: None, - next_sibling: None, - prev_sibling: None, + parent_node: Cell::new(None), + first_child: Cell::new(None), + last_child: Cell::new(None), + next_sibling: Cell::new(None), + prev_sibling: Cell::new(None), - owner_doc: doc.unrooted(), - child_list: None, + owner_doc: Cell::new(doc.unrooted()), + child_list: Cell::new(None), flags: NodeFlags::new(type_id), @@ -1297,8 +1297,8 @@ impl Node { // FIXME: https://github.com/mozilla/servo/issues/1737 copy_elem.namespace = node_elem.namespace.clone(); let window = document.deref().window.root(); - for attr in node_elem.attrs.iter().map(|attr| attr.root()) { - copy_elem.attrs.push_unrooted( + for attr in node_elem.attrs.borrow().iter().map(|attr| attr.root()) { + copy_elem.attrs.borrow_mut().push_unrooted( &Attr::new(&*window, attr.deref().local_name.clone(), attr.deref().value.clone(), attr.deref().name.clone(), attr.deref().namespace.clone(), @@ -1427,12 +1427,12 @@ impl<'a> NodeMethods for JSRef<'a, Node> { // http://dom.spec.whatwg.org/#dom-node-parentnode fn GetParentNode(&self) -> Option> { - self.parent_node.clone().map(|node| Temporary::new(node)) + self.parent_node.get().map(|node| Temporary::new(node)) } // http://dom.spec.whatwg.org/#dom-node-parentelement fn GetParentElement(&self) -> Option> { - self.parent_node.clone() + self.parent_node.get() .and_then(|parent| { let parent = parent.root(); ElementCast::to_ref(&*parent).map(|elem| { @@ -1443,12 +1443,12 @@ impl<'a> NodeMethods for JSRef<'a, Node> { // http://dom.spec.whatwg.org/#dom-node-haschildnodes fn HasChildNodes(&self) -> bool { - self.first_child.is_some() + self.first_child.get().is_some() } // http://dom.spec.whatwg.org/#dom-node-childnodes fn ChildNodes(&mut self) -> Temporary { - match self.child_list { + match self.child_list.get() { None => (), Some(ref list) => return Temporary::new(list.clone()), } @@ -1457,27 +1457,27 @@ impl<'a> NodeMethods for JSRef<'a, Node> { 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()) + Temporary::new(self.child_list.get().get_ref().clone()) } // http://dom.spec.whatwg.org/#dom-node-firstchild fn GetFirstChild(&self) -> Option> { - self.first_child.clone().map(|node| Temporary::new(node)) + self.first_child.get().map(|node| Temporary::new(node)) } // http://dom.spec.whatwg.org/#dom-node-lastchild fn GetLastChild(&self) -> Option> { - self.last_child.clone().map(|node| Temporary::new(node)) + self.last_child.get().map(|node| Temporary::new(node)) } // http://dom.spec.whatwg.org/#dom-node-previoussibling fn GetPreviousSibling(&self) -> Option> { - self.prev_sibling.clone().map(|node| Temporary::new(node)) + self.prev_sibling.get().map(|node| Temporary::new(node)) } // http://dom.spec.whatwg.org/#dom-node-nextsibling fn GetNextSibling(&self) -> Option> { - self.next_sibling.clone().map(|node| Temporary::new(node)) + self.next_sibling.get().map(|node| Temporary::new(node)) } // http://dom.spec.whatwg.org/#dom-node-nodevalue @@ -1766,9 +1766,11 @@ impl<'a> NodeMethods for JSRef<'a, Node> { let element: &JSRef = ElementCast::to_ref(node).unwrap(); let other_element: &JSRef = ElementCast::to_ref(other).unwrap(); // FIXME: namespace prefix - (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()) + let element = element.deref(); + let other_element = other_element.deref(); + (element.namespace == other_element.namespace) && + (element.local_name == other_element.local_name) && + (element.attrs.borrow().len() == other_element.attrs.borrow().len()) } fn is_equal_processinginstruction(node: &JSRef, other: &JSRef) -> bool { let pi: &JSRef = ProcessingInstructionCast::to_ref(node).unwrap(); @@ -1784,9 +1786,11 @@ impl<'a> NodeMethods for JSRef<'a, Node> { fn is_equal_element_attrs(node: &JSRef, other: &JSRef) -> bool { let element: &JSRef = ElementCast::to_ref(node).unwrap(); let other_element: &JSRef = 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| { + let element = element.deref(); + let other_element = other_element.deref(); + assert!(element.attrs.borrow().len() == other_element.attrs.borrow().len()); + element.attrs.borrow().iter().map(|attr| attr.root()).all(|attr| { + other_element.attrs.borrow().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) diff --git a/src/components/script/dom/performance.rs b/src/components/script/dom/performance.rs index 13910eb701d..fca1b6d4ebf 100644 --- a/src/components/script/dom/performance.rs +++ b/src/components/script/dom/performance.rs @@ -7,7 +7,6 @@ use dom::bindings::js::{JS, JSRef, Temporary}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::performancetiming::{PerformanceTiming, PerformanceTimingMethods}; use dom::window::Window; - use time; pub type DOMHighResTimeStamp = f64; @@ -20,9 +19,10 @@ pub struct Performance { impl Performance { fn new_inherited(window: &JSRef) -> Performance { + let timing = PerformanceTiming::new(window).root().root_ref().unrooted(); Performance { reflector_: Reflector::new(), - timing: PerformanceTiming::new(window).root().root_ref().unrooted(), + timing: timing, } } diff --git a/src/components/script/dom/testbinding.rs b/src/components/script/dom/testbinding.rs index 4b753785e10..ce2a2841f8c 100644 --- a/src/components/script/dom/testbinding.rs +++ b/src/components/script/dom/testbinding.rs @@ -15,10 +15,12 @@ use servo_util::str::DOMString; use js::jsapi::JSContext; use js::jsval::{JSVal, NullValue}; +use std::cell::Cell; + #[deriving(Encodable)] pub struct TestBinding { pub reflector: Reflector, - pub window: JS, + pub window: Cell>, } pub trait TestBindingMethods { @@ -243,19 +245,19 @@ pub trait TestBindingMethods { impl<'a> TestBindingMethods for JSRef<'a, TestBinding> { fn InterfaceAttribute(&self) -> Temporary { - let window = self.window.root(); + let window = self.window.get().root(); Blob::new(&*window) } fn GetInterfaceAttributeNullable(&self) -> Option> { - let window = self.window.root(); + let window = self.window.get().root(); Some(Blob::new(&*window)) } fn ReceiveInterface(&self) -> Temporary { - let window = self.window.root(); + let window = self.window.get().root(); Blob::new(&*window) } fn ReceiveNullableInterface(&self) -> Option> { - let window = self.window.root(); + let window = self.window.get().root(); Some(Blob::new(&*window)) } } diff --git a/src/components/script/dom/uievent.rs b/src/components/script/dom/uievent.rs index c0e852d2971..8182a371a80 100644 --- a/src/components/script/dom/uievent.rs +++ b/src/components/script/dom/uievent.rs @@ -86,7 +86,7 @@ pub trait UIEventMethods { impl<'a> UIEventMethods for JSRef<'a, UIEvent> { fn GetView(&self) -> Option> { - self.view.clone().map(|view| Temporary::new(view)) + self.view.map(|view| Temporary::new(view)) } fn Detail(&self) -> i32 { diff --git a/src/components/script/dom/validitystate.rs b/src/components/script/dom/validitystate.rs index ffb7ca95864..f4c4aa114cf 100644 --- a/src/components/script/dom/validitystate.rs +++ b/src/components/script/dom/validitystate.rs @@ -6,11 +6,12 @@ use dom::bindings::codegen::BindingDeclarations::ValidityStateBinding; use dom::bindings::js::{JS, JSRef, Temporary}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::window::Window; +use std::cell::Cell; #[deriving(Encodable)] pub struct ValidityState { pub reflector_: Reflector, - pub window: JS, + pub window: Cell>, pub state: u8, } @@ -18,7 +19,7 @@ impl ValidityState { pub fn new_inherited(window: &JSRef) -> ValidityState { ValidityState { reflector_: Reflector::new(), - window: window.unrooted(), + window: Cell::new(window.unrooted()), state: 0, } } diff --git a/src/components/script/dom/window.rs b/src/components/script/dom/window.rs index 0c71edb69a0..da13ef4a197 100644 --- a/src/components/script/dom/window.rs +++ b/src/components/script/dom/window.rs @@ -30,6 +30,7 @@ use js::jsapi::{JS_GC, JS_GetRuntime}; use js::jsval::{NullValue, JSVal}; use collections::hashmap::HashMap; +use std::cell::Cell; use std::cmp; use std::comm::{channel, Sender}; use std::comm::Select; @@ -69,16 +70,16 @@ impl TimerHandle { pub struct Window { pub eventtarget: EventTarget, pub script_chan: ScriptChan, - pub console: Option>, - pub location: Option>, - pub navigator: Option>, + pub console: Cell>>, + pub location: Cell>>, + pub navigator: Cell>>, pub image_cache_task: ImageCacheTask, pub active_timers: Box>, pub next_timer_handle: i32, pub compositor: Untraceable>, pub browser_context: Option, pub page: Rc, - pub performance: Option>, + pub performance: Cell>>, pub navigationStart: u64, pub navigationStartPrecise: f64, } @@ -200,28 +201,28 @@ impl<'a> WindowMethods for JSRef<'a, Window> { } fn Location(&mut self) -> Temporary { - if self.location.is_none() { + if self.location.get().is_none() { let page = self.deref().page.clone(); let location = Location::new(self, page); self.location.assign(Some(location)); } - Temporary::new(self.location.get_ref().clone()) + Temporary::new(self.location.get().get_ref().clone()) } fn Console(&mut self) -> Temporary { - if self.console.is_none() { + if self.console.get().is_none() { let console = Console::new(self); self.console.assign(Some(console)); } - Temporary::new(self.console.get_ref().clone()) + Temporary::new(self.console.get().get_ref().clone()) } fn Navigator(&mut self) -> Temporary { - if self.navigator.is_none() { + if self.navigator.get().is_none() { let navigator = Navigator::new(self); self.navigator.assign(Some(navigator)); } - Temporary::new(self.navigator.get_ref().clone()) + Temporary::new(self.navigator.get().get_ref().clone()) } fn Confirm(&self, _message: DOMString) -> bool { @@ -269,11 +270,11 @@ impl<'a> WindowMethods for JSRef<'a, Window> { } fn Performance(&mut self) -> Temporary { - if self.performance.is_none() { + if self.performance.get().is_none() { let performance = Performance::new(self); self.performance.assign(Some(performance)); } - Temporary::new(self.performance.get_ref().clone()) + Temporary::new(self.performance.get().get_ref().clone()) } fn GetOnload(&self) -> Option { @@ -441,16 +442,16 @@ impl Window { let win = box Window { eventtarget: EventTarget::new_inherited(WindowTypeId), script_chan: script_chan, - console: None, + console: Cell::new(None), compositor: Untraceable::new(compositor), page: page, - location: None, - navigator: None, + location: Cell::new(None), + navigator: Cell::new(None), image_cache_task: image_cache_task, active_timers: box HashMap::new(), next_timer_handle: 0, browser_context: None, - performance: None, + performance: Cell::new(None), navigationStart: time::get_time().sec as u64, navigationStartPrecise: time::precise_time_s(), }; diff --git a/src/components/script/dom/xmlhttprequest.rs b/src/components/script/dom/xmlhttprequest.rs index f718ea106be..3630b912d70 100644 --- a/src/components/script/dom/xmlhttprequest.rs +++ b/src/components/script/dom/xmlhttprequest.rs @@ -32,6 +32,7 @@ use url::Url; use libc; use libc::c_void; +use std::cell::Cell; use std::comm::channel; use std::io::{BufReader, MemWriter}; use std::from_str::FromStr; @@ -98,14 +99,14 @@ pub struct XMLHttpRequest { ready_state: XMLHttpRequestState, timeout: u32, with_credentials: bool, - upload: Option>, + upload: Cell>>, response_url: DOMString, status: u16, status_text: ByteString, response: ByteString, response_type: XMLHttpRequestResponseType, response_text: DOMString, - response_xml: Option>, + response_xml: Cell>>, response_headers: Untraceable, // Associated concepts @@ -129,14 +130,14 @@ impl XMLHttpRequest { ready_state: Unsent, timeout: 0u32, with_credentials: false, - upload: None, + upload: Cell::new(None), response_url: "".to_owned(), status: 0, status_text: ByteString::new(vec!()), response: ByteString::new(vec!()), response_type: _empty, response_text: "".to_owned(), - response_xml: None, + response_xml: Cell::new(None), response_headers: Untraceable::new(ResponseHeaderCollection::new()), request_method: Untraceable::new(Get), @@ -385,7 +386,7 @@ impl<'a> XMLHttpRequestMethods<'a> for JSRef<'a, XMLHttpRequest> { self.with_credentials = with_credentials } fn Upload(&self) -> Temporary { - Temporary::new(self.upload.get_ref().clone()) + Temporary::new(self.upload.get().get_ref().clone()) } fn Send(&mut self, data: Option) -> ErrorResult { if self.ready_state != Opened || self.send_flag { @@ -407,7 +408,7 @@ impl<'a> XMLHttpRequestMethods<'a> for JSRef<'a, XMLHttpRequest> { }; if !self.sync { // Step 8 - let upload_target = &*self.upload.root().unwrap(); + let upload_target = &*self.upload.get().root().unwrap(); let event_target: &JSRef = EventTargetCast::from_ref(upload_target); if event_target.handlers.iter().len() > 0 { self.upload_events = true; @@ -498,7 +499,7 @@ impl<'a> XMLHttpRequestMethods<'a> for JSRef<'a, XMLHttpRequest> { self.response_text.clone() } fn GetResponseXML(&self) -> Option> { - self.response_xml.clone().map(|response| Temporary::new(response)) + self.response_xml.get().map(|response| Temporary::new(response)) } } @@ -637,7 +638,7 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> { fn dispatch_progress_event(&self, upload: bool, type_: DOMString, loaded: u64, total: Option) { let win = &*self.global.root(); - let upload_target = &*self.upload.root().unwrap(); + let upload_target = &*self.upload.get().root().unwrap(); let mut progressevent = ProgressEvent::new(win, type_, false, false, total.is_some(), loaded, total.unwrap_or(0)).root(); diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs index 3a40303321b..ce268d35ff9 100644 --- a/src/components/script/script_task.rs +++ b/src/components/script/script_task.rs @@ -162,7 +162,7 @@ pub struct Page { resize_event: Untraceable>>>, /// Pending scroll to fragment event, if any - fragment_node: Traceable>>>, + fragment_node: Cell>>, /// Associated resource task for use by DOM objects like XMLHttpRequest pub resource_task: Untraceable, @@ -221,7 +221,7 @@ impl Page { url: Untraceable::new(RefCell::new(None)), next_subpage_id: Untraceable::new(Cell::new(SubpageId(0))), resize_event: Untraceable::new(Cell::new(None)), - fragment_node: Traceable::new(RefCell::new(None)), + fragment_node: Cell::new(None), last_reflow_id: Traceable::new(Cell::new(0)), resource_task: Untraceable::new(resource_task), constellation_chan: Untraceable::new(constellation_chan), @@ -1043,8 +1043,8 @@ impl ScriptTask { let _ = wintarget.dispatch_event_with_target(Some((*doctarget).clone()), &mut *event); - let mut fragment_node = page.fragment_node.deref().borrow_mut(); - (*fragment_node).assign(fragment.map_or(None, |fragid| page.find_fragment_node(fragid))); + let mut fragment_node = page.fragment_node.get(); + fragment_node.assign(fragment.map_or(None, |fragid| page.find_fragment_node(fragid))); let ConstellationChan(ref chan) = self.constellation_chan; chan.send(LoadCompleteMsg(page.id, url)); @@ -1080,7 +1080,7 @@ impl ScriptTask { page.reflow(ReflowForDisplay, self.chan.clone(), self.compositor) } - let mut fragment_node = page.fragment_node.deref().borrow_mut(); + let mut fragment_node = page.fragment_node.get(); match fragment_node.take().map(|node| node.root()) { Some(node) => self.scroll_fragment_point(pipeline_id, &*node), None => {}