auto merge of #2490 : saneyuki/servo/js, r=jdm

This only change to make `JS<T> ` to a POD type about #1854, except using `Cell`/`RefCell` for interior mutability.

Fix #1854

@jdm r?
This commit is contained in:
bors-servo 2014-05-29 16:21:57 -04:00
commit e511c04935
20 changed files with 212 additions and 161 deletions

View file

@ -136,6 +136,10 @@ pub struct LayoutNode<'a> {
/// Being chained to a ContravariantLifetime prevents `LayoutNode`s from escaping. /// Being chained to a ContravariantLifetime prevents `LayoutNode`s from escaping.
pub chain: ContravariantLifetime<'a>, pub chain: ContravariantLifetime<'a>,
/// Padding to ensure the transmute `JS<T>` -> `LayoutNode`, `LayoutNode` -> `UnsafeLayoutNode`,
/// and `UnsafeLayoutNode` -> others.
pad: uint
} }
impl<'ln> Clone for LayoutNode<'ln> { impl<'ln> Clone for LayoutNode<'ln> {
@ -143,6 +147,7 @@ impl<'ln> Clone for LayoutNode<'ln> {
LayoutNode { LayoutNode {
node: self.node.clone(), node: self.node.clone(),
chain: self.chain, chain: self.chain,
pad: 0,
} }
} }
} }
@ -160,6 +165,7 @@ impl<'ln> TLayoutNode for LayoutNode<'ln> {
LayoutNode { LayoutNode {
node: node.transmute_copy(), node: node.transmute_copy(),
chain: self.chain, chain: self.chain,
pad: 0,
} }
} }
@ -175,7 +181,7 @@ impl<'ln> TLayoutNode for LayoutNode<'ln> {
fn first_child(&self) -> Option<LayoutNode<'ln>> { fn first_child(&self) -> Option<LayoutNode<'ln>> {
unsafe { 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 { f(LayoutNode {
node: node, node: node,
chain: ContravariantLifetime, chain: ContravariantLifetime,
pad: 0,
}) })
} }
@ -223,19 +230,19 @@ impl<'ln> LayoutNode<'ln> {
impl<'ln> TNode<LayoutElement<'ln>> for LayoutNode<'ln> { impl<'ln> TNode<LayoutElement<'ln>> for LayoutNode<'ln> {
fn parent_node(&self) -> Option<LayoutNode<'ln>> { fn parent_node(&self) -> Option<LayoutNode<'ln>> {
unsafe { 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<LayoutNode<'ln>> { fn prev_sibling(&self) -> Option<LayoutNode<'ln>> {
unsafe { 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<LayoutNode<'ln>> { fn next_sibling(&self) -> Option<LayoutNode<'ln>> {
unsafe { 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: LayoutNode {
node: node.transmute_copy(), node: node.transmute_copy(),
chain: self.node.chain, chain: self.node.chain,
pad: 0,
}, },
pseudo: Normal, pseudo: Normal,
} }
@ -463,7 +471,7 @@ impl<'ln> TLayoutNode for ThreadSafeLayoutNode<'ln> {
} }
unsafe { 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. /// Returns the next sibling of this node. Unsafe and private because this can lead to races.
unsafe fn next_sibling(&self) -> Option<ThreadSafeLayoutNode<'ln>> { unsafe fn next_sibling(&self) -> Option<ThreadSafeLayoutNode<'ln>> {
if self.pseudo == Before || self.pseudo == BeforeBlock { 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. /// Returns an iterator over this node's children.

View file

@ -13,6 +13,7 @@ use dom::virtualmethods::vtable_for;
use servo_util::namespace; use servo_util::namespace;
use servo_util::namespace::Namespace; use servo_util::namespace::Namespace;
use servo_util::str::DOMString; use servo_util::str::DOMString;
use std::cell::Cell;
pub enum AttrSettingType { pub enum AttrSettingType {
FirstSetAttr, FirstSetAttr,
@ -29,7 +30,7 @@ pub struct Attr {
pub prefix: Option<DOMString>, pub prefix: Option<DOMString>,
/// the element that owns this attribute. /// the element that owns this attribute.
pub owner: JS<Element>, pub owner: Cell<JS<Element>>,
} }
impl Reflectable for Attr { impl Reflectable for Attr {
@ -53,7 +54,7 @@ impl Attr {
name: name, //TODO: Intern attribute names name: name, //TODO: Intern attribute names
namespace: namespace, namespace: namespace,
prefix: prefix, 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) { 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<Node> = NodeCast::from_mut_ref(&mut *owner); let node: &mut JSRef<Node> = NodeCast::from_mut_ref(&mut *owner);
let namespace_is_null = self.namespace == namespace::Null; let namespace_is_null = self.namespace == namespace::Null;

View file

@ -39,11 +39,11 @@ pub trait AttrListMethods {
impl<'a> AttrListMethods for JSRef<'a, AttrList> { impl<'a> AttrListMethods for JSRef<'a, AttrList> {
fn Length(&self) -> u32 { 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<Temporary<Attr>> { fn Item(&self, index: u32) -> Option<Temporary<Attr>> {
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<Temporary<Attr>> { fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Temporary<Attr>> {

View file

@ -47,7 +47,7 @@ use layout_interface::TrustedNodeAddress;
use script_task::StackRoots; use script_task::StackRoots;
use std::cast; use std::cast;
use std::cell::RefCell; use std::cell::{Cell, RefCell};
use std::kinds::marker::ContravariantLifetime; use std::kinds::marker::ContravariantLifetime;
/// A type that represents a JS-owned value that is rooted for the lifetime of this value. /// A type that represents a JS-owned value that is rooted for the lifetime of this value.
@ -111,7 +111,7 @@ impl<T: Reflectable> Temporary<T> {
/// A rooted, JS-owned value. Must only be used as a field in other JS-owned types. /// A rooted, JS-owned value. Must only be used as a field in other JS-owned types.
pub struct JS<T> { pub struct JS<T> {
ptr: RefCell<*mut T> ptr: *T
} }
impl<T> Eq for JS<T> { impl<T> Eq for JS<T> {
@ -134,7 +134,7 @@ impl JS<Node> {
pub unsafe fn from_trusted_node_address(inner: TrustedNodeAddress) -> JS<Node> { pub unsafe fn from_trusted_node_address(inner: TrustedNodeAddress) -> JS<Node> {
let TrustedNodeAddress(addr) = inner; let TrustedNodeAddress(addr) = inner;
JS { JS {
ptr: RefCell::new(addr as *mut Node) ptr: addr as *Node
} }
} }
} }
@ -143,7 +143,7 @@ impl JS<XMLHttpRequest> {
pub unsafe fn from_trusted_xhr_address(inner: TrustedXHRAddress) -> JS<XMLHttpRequest> { pub unsafe fn from_trusted_xhr_address(inner: TrustedXHRAddress) -> JS<XMLHttpRequest> {
let TrustedXHRAddress(addr) = inner; let TrustedXHRAddress(addr) = inner;
JS { JS {
ptr: RefCell::new(addr as *mut XMLHttpRequest) ptr: addr as *XMLHttpRequest
} }
} }
} }
@ -152,7 +152,7 @@ impl<T: Reflectable> JS<T> {
/// Create a new JS-owned value wrapped from a raw Rust pointer. /// Create a new JS-owned value wrapped from a raw Rust pointer.
pub unsafe fn from_raw(raw: *mut T) -> JS<T> { pub unsafe fn from_raw(raw: *mut T) -> JS<T> {
JS { JS {
ptr: RefCell::new(raw) ptr: raw as *T
} }
} }
@ -269,6 +269,15 @@ impl<T: Assignable<U>, U: Reflectable> OptionalSettable<T> for Option<JS<U>> {
} }
} }
impl<T: Assignable<U>, U: Reflectable> OptionalSettable<T> for Cell<Option<JS<U>>> {
fn assign(&mut self, val: Option<T>) {
let mut item = self.get();
item.assign(val);
self.set(item);
}
}
/// Root a rootable Option type (used for Option<Temporary<T>>) /// Root a rootable Option type (used for Option<Temporary<T>>)
pub trait OptionalRootable<T> { pub trait OptionalRootable<T> {
fn root<'a, 'b>(self) -> Option<Root<'a, 'b, T>>; fn root<'a, 'b>(self) -> Option<Root<'a, 'b, T>>;
@ -394,7 +403,7 @@ pub struct Root<'a, 'b, T> {
/// Reference to rooted value that must not outlive this container /// Reference to rooted value that must not outlive this container
jsref: JSRef<'b, T>, jsref: JSRef<'b, T>,
/// Pointer to underlying Rust data /// Pointer to underlying Rust data
ptr: RefCell<*mut T>, ptr: *T,
/// On-stack JS pointer to assuage conservative stack scanner /// On-stack JS pointer to assuage conservative stack scanner
js_ptr: *mut JSObject, js_ptr: *mut JSObject,
} }
@ -445,25 +454,23 @@ impl<'a, 'b, T: Reflectable> DerefMut<JSRef<'b, T>> for Root<'a, 'b, T> {
impl<'a, T: Reflectable> Deref<T> for JSRef<'a, T> { impl<'a, T: Reflectable> Deref<T> for JSRef<'a, T> {
fn deref<'b>(&'b self) -> &'b T { fn deref<'b>(&'b self) -> &'b T {
let borrow = self.ptr.borrow();
unsafe { unsafe {
&**borrow &*self.ptr
} }
} }
} }
impl<'a, T: Reflectable> DerefMut<T> for JSRef<'a, T> { impl<'a, T: Reflectable> DerefMut<T> for JSRef<'a, T> {
fn deref_mut<'b>(&'b mut self) -> &'b mut T { fn deref_mut<'b>(&'b mut self) -> &'b mut T {
let mut borrowed = self.ptr.borrow_mut();
unsafe { unsafe {
&mut **borrowed &mut *(self.ptr as *mut T)
} }
} }
} }
/// Encapsulates a reference to something that is guaranteed to be alive. This is freely copyable. /// Encapsulates a reference to something that is guaranteed to be alive. This is freely copyable.
pub struct JSRef<'a, T> { pub struct JSRef<'a, T> {
ptr: RefCell<*mut T>, ptr: *T,
chain: ContravariantLifetime<'a>, chain: ContravariantLifetime<'a>,
} }
@ -495,7 +502,7 @@ impl<'a,T> JSRef<'a,T> {
pub fn unrooted(&self) -> JS<T> { pub fn unrooted(&self) -> JS<T> {
JS { JS {
ptr: self.ptr.clone() ptr: self.ptr
} }
} }
} }

View file

@ -160,3 +160,23 @@ impl<S: Encoder<E>, E> Encodable<S, E> for Traceable<JSVal> {
Ok(()) Ok(())
} }
} }
/// for a field which contains DOMType
impl<T: Reflectable+Encodable<S, E>, S: Encoder<E>, E> Encodable<S, E> for Cell<JS<T>> {
fn encode(&self, s: &mut S) -> Result<(), E> {
self.get().encode(s)
}
}
impl<T: Reflectable+Encodable<S, E>, S: Encoder<E>, E> Encodable<S, E> for Cell<Option<JS<T>>> {
fn encode(&self, s: &mut S) -> Result<(), E> {
self.get().encode(s)
}
}
/// for a field which contains non-POD type contains DOMType
impl<T: Reflectable+Encodable<S, E>, S: Encoder<E>, E> Encodable<S, E> for RefCell<Vec<JS<T>>> {
fn encode(&self, s: &mut S) -> Result<(), E> {
self.borrow().encode(s)
}
}

View file

@ -18,9 +18,10 @@ pub struct ClientRectList {
impl ClientRectList { impl ClientRectList {
pub fn new_inherited(window: &JSRef<Window>, pub fn new_inherited(window: &JSRef<Window>,
rects: Vec<JSRef<ClientRect>>) -> ClientRectList { rects: Vec<JSRef<ClientRect>>) -> ClientRectList {
let rects = rects.iter().map(|rect| rect.unrooted()).collect();
ClientRectList { ClientRectList {
reflector_: Reflector::new(), reflector_: Reflector::new(),
rects: rects.iter().map(|rect| rect.unrooted()).collect(), rects: rects,
window: window.unrooted(), window: window.unrooted(),
} }
} }
@ -44,8 +45,9 @@ impl<'a> ClientRectListMethods for JSRef<'a, ClientRectList> {
} }
fn Item(&self, index: u32) -> Option<Temporary<ClientRect>> { fn Item(&self, index: u32) -> Option<Temporary<ClientRect>> {
if index < self.rects.len() as u32 { let rects = &self.rects;
Some(Temporary::new(self.rects.get(index as uint).clone())) if index < rects.len() as u32 {
Some(Temporary::new(rects.get(index as uint).clone()))
} else { } else {
None None
} }

View file

@ -31,6 +31,7 @@ use servo_util::str::{DOMString, null_str_as_empty_ref, split_html_space_chars};
use std::ascii::StrAsciiExt; use std::ascii::StrAsciiExt;
use std::cast; use std::cast;
use std::cell::{Cell, RefCell};
#[deriving(Encodable)] #[deriving(Encodable)]
pub struct Element { pub struct Element {
@ -38,9 +39,9 @@ pub struct Element {
pub local_name: DOMString, // TODO: This should be an atom, not a DOMString. pub local_name: DOMString, // TODO: This should be an atom, not a DOMString.
pub namespace: Namespace, pub namespace: Namespace,
pub prefix: Option<DOMString>, pub prefix: Option<DOMString>,
pub attrs: Vec<JS<Attr>>, pub attrs: RefCell<Vec<JS<Attr>>>,
pub style_attribute: Option<style::PropertyDeclarationBlock>, pub style_attribute: Option<style::PropertyDeclarationBlock>,
pub attr_list: Option<JS<AttrList>> pub attr_list: Cell<Option<JS<AttrList>>>
} }
impl ElementDerived for EventTarget { impl ElementDerived for EventTarget {
@ -147,8 +148,8 @@ impl Element {
local_name: local_name, local_name: local_name,
namespace: namespace, namespace: namespace,
prefix: prefix, prefix: prefix,
attrs: vec!(), attrs: RefCell::new(vec!()),
attr_list: None, attr_list: Cell::new(None),
style_attribute: None, style_attribute: None,
} }
} }
@ -167,7 +168,9 @@ impl RawLayoutElementHelpers for Element {
#[inline] #[inline]
unsafe fn get_attr_val_for_layout(&self, namespace: &Namespace, name: &str) unsafe fn get_attr_val_for_layout(&self, namespace: &Namespace, name: &str)
-> Option<&'static str> { -> Option<&'static str> {
self.attrs.iter().find(|attr: & &JS<Attr>| { // cast to point to T in RefCell<T> directly
let attrs: *Vec<JS<Attr>> = cast::transmute(&self.attrs);
(*attrs).iter().find(|attr: & &JS<Attr>| {
let attr = attr.unsafe_get(); let attr = attr.unsafe_get();
name == (*attr).local_name && (*attr).namespace == *namespace name == (*attr).local_name && (*attr).namespace == *namespace
}).map(|attr| { }).map(|attr| {
@ -232,7 +235,7 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
let element: &Element = self.deref(); let element: &Element = self.deref();
let is_html_element = self.html_element_in_html_document(); 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 { let same_name = if is_html_element {
name.to_ascii_lower() == attr.local_name name.to_ascii_lower() == attr.local_name
} else { } else {
@ -284,7 +287,7 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
fn do_set_attribute(&mut self, local_name: DOMString, value: DOMString, fn do_set_attribute(&mut self, local_name: DOMString, value: DOMString,
name: DOMString, namespace: Namespace, name: DOMString, namespace: Namespace,
prefix: Option<DOMString>, cb: |&JSRef<Attr>| -> bool) { prefix: Option<DOMString>, cb: |&JSRef<Attr>| -> bool) {
let idx = self.deref().attrs.iter() let idx = self.deref().attrs.borrow().iter()
.map(|attr| attr.root()) .map(|attr| attr.root())
.position(|attr| cb(&*attr)); .position(|attr| cb(&*attr));
let (idx, set_type) = match idx { 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 window = window_from_node(self).root();
let attr = Attr::new(&*window, local_name.clone(), value.clone(), let attr = Attr::new(&*window, local_name.clone(), value.clone(),
name, namespace.clone(), prefix, self); name, namespace.clone(), prefix, self);
self.deref_mut().attrs.push_unrooted(&attr); self.deref().attrs.borrow_mut().push_unrooted(&attr);
(self.deref().attrs.len() - 1, FirstSetAttr) (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 { fn remove_attribute(&mut self, namespace: Namespace, name: DOMString) -> ErrorResult {
let (_, local_name) = get_attribute_parts(name.clone()); 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 attr.local_name == local_name
}); });
@ -317,12 +320,12 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
} }
if namespace == namespace::Null { 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)) vtable_for(NodeCast::from_mut_ref(self))
.before_remove_attr(local_name.clone(), removed_raw_value); .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 // http://dom.spec.whatwg.org/#dom-element-attributes
fn Attributes(&mut self) -> Temporary<AttrList> { fn Attributes(&mut self) -> Temporary<AttrList> {
match self.attr_list { match self.attr_list.get() {
None => (), None => (),
Some(ref list) => return Temporary::new(list.clone()), 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 window = doc.deref().window.root();
let list = AttrList::new(&*window, self); let list = AttrList::new(&*window, self);
self.attr_list.assign(Some(list)); 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 // http://dom.spec.whatwg.org/#dom-element-getattribute

View file

@ -10,6 +10,7 @@ use dom::bindings::error::Fallible;
use dom::eventtarget::EventTarget; use dom::eventtarget::EventTarget;
use dom::window::Window; use dom::window::Window;
use servo_util::str::DOMString; use servo_util::str::DOMString;
use std::cell::Cell;
use geom::point::Point2D; use geom::point::Point2D;
@ -46,8 +47,8 @@ pub enum EventTypeId {
pub struct Event { pub struct Event {
pub type_id: EventTypeId, pub type_id: EventTypeId,
pub reflector_: Reflector, pub reflector_: Reflector,
pub current_target: Option<JS<EventTarget>>, pub current_target: Cell<Option<JS<EventTarget>>>,
pub target: Option<JS<EventTarget>>, pub target: Cell<Option<JS<EventTarget>>>,
pub type_: DOMString, pub type_: DOMString,
pub phase: EventPhase, pub phase: EventPhase,
pub canceled: bool, pub canceled: bool,
@ -66,8 +67,8 @@ impl Event {
Event { Event {
type_id: type_id, type_id: type_id,
reflector_: Reflector::new(), reflector_: Reflector::new(),
current_target: None, current_target: Cell::new(None),
target: None, target: Cell::new(None),
phase: PhaseNone, phase: PhaseNone,
type_: "".to_owned(), type_: "".to_owned(),
canceled: false, canceled: false,
@ -123,11 +124,11 @@ impl<'a> EventMethods for JSRef<'a, Event> {
} }
fn GetTarget(&self) -> Option<Temporary<EventTarget>> { fn GetTarget(&self) -> Option<Temporary<EventTarget>> {
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<Temporary<EventTarget>> { fn GetCurrentTarget(&self) -> Option<Temporary<EventTarget>> {
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 { fn DefaultPrevented(&self) -> bool {
@ -173,7 +174,7 @@ impl<'a> EventMethods for JSRef<'a, Event> {
self.stop_immediate = false; self.stop_immediate = false;
self.canceled = false; self.canceled = false;
self.trusted = false; self.trusted = false;
self.target = None; self.target.set(None);
self.type_ = type_; self.type_ = type_;
self.bubbles = bubbles; self.bubbles = bubbles;
self.cancelable = cancelable; self.cancelable = cancelable;

View file

@ -140,7 +140,7 @@ pub fn dispatch_event<'a, 'b>(target: &JSRef<'a, EventTarget>,
event.dispatching = false; event.dispatching = false;
event.phase = PhaseNone; event.phase = PhaseNone;
event.current_target = None; event.current_target.set(None);
!event.DefaultPrevented() !event.DefaultPrevented()
} }

View file

@ -10,7 +10,6 @@ use dom::blob::Blob;
use dom::htmlformelement::HTMLFormElement; use dom::htmlformelement::HTMLFormElement;
use dom::window::Window; use dom::window::Window;
use servo_util::str::DOMString; use servo_util::str::DOMString;
use collections::hashmap::HashMap; use collections::hashmap::HashMap;
#[deriving(Encodable)] #[deriving(Encodable)]

View file

@ -106,7 +106,7 @@ fn serialize_doctype(doctype: &JSRef<DocumentType>, html: &mut StrBuf) {
fn serialize_elem(elem: &JSRef<Element>, open_elements: &mut Vec<~str>, html: &mut StrBuf) { fn serialize_elem(elem: &JSRef<Element>, open_elements: &mut Vec<~str>, html: &mut StrBuf) {
html.push_char('<'); html.push_char('<');
html.push_str(elem.deref().local_name); 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(); let attr = attr.root();
serialize_attr(&*attr, html); serialize_attr(&*attr, html);
}; };

View file

@ -12,6 +12,7 @@ use dom::eventtarget::EventTarget;
use dom::uievent::{UIEvent, UIEventMethods}; use dom::uievent::{UIEvent, UIEventMethods};
use dom::window::Window; use dom::window::Window;
use servo_util::str::DOMString; use servo_util::str::DOMString;
use std::cell::Cell;
#[deriving(Encodable)] #[deriving(Encodable)]
pub struct MouseEvent { pub struct MouseEvent {
@ -25,7 +26,7 @@ pub struct MouseEvent {
pub alt_key: bool, pub alt_key: bool,
pub meta_key: bool, pub meta_key: bool,
pub button: u16, pub button: u16,
pub related_target: Option<JS<EventTarget>> pub related_target: Cell<Option<JS<EventTarget>>>
} }
impl MouseEventDerived for Event { impl MouseEventDerived for Event {
@ -47,7 +48,7 @@ impl MouseEvent {
alt_key: false, alt_key: false,
meta_key: false, meta_key: false,
button: 0, 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<Temporary<EventTarget>> { fn GetRelatedTarget(&self) -> Option<Temporary<EventTarget>> {
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 { fn GetModifierState(&self, _keyArg: DOMString) -> bool {

View file

@ -41,7 +41,7 @@ use libc;
use libc::uintptr_t; use libc::uintptr_t;
use std::cast::transmute; use std::cast::transmute;
use std::cast; use std::cast;
use std::cell::{RefCell, Ref, RefMut}; use std::cell::{Cell, RefCell, Ref, RefMut};
use std::iter::{Map, Filter}; use std::iter::{Map, Filter};
use std::mem; use std::mem;
use style::ComputedValues; use style::ComputedValues;
@ -63,25 +63,25 @@ pub struct Node {
pub type_id: NodeTypeId, pub type_id: NodeTypeId,
/// The parent of this node. /// The parent of this node.
pub parent_node: Option<JS<Node>>, pub parent_node: Cell<Option<JS<Node>>>,
/// The first child of this node. /// The first child of this node.
pub first_child: Option<JS<Node>>, pub first_child: Cell<Option<JS<Node>>>,
/// The last child of this node. /// The last child of this node.
pub last_child: Option<JS<Node>>, pub last_child: Cell<Option<JS<Node>>>,
/// The next sibling of this node. /// The next sibling of this node.
pub next_sibling: Option<JS<Node>>, pub next_sibling: Cell<Option<JS<Node>>>,
/// The previous sibling of this node. /// The previous sibling of this node.
pub prev_sibling: Option<JS<Node>>, pub prev_sibling: Cell<Option<JS<Node>>>,
/// The document that this node belongs to. /// The document that this node belongs to.
owner_doc: Option<JS<Document>>, owner_doc: Cell<Option<JS<Document>>>,
/// The live list of children return by .childNodes. /// The live list of children return by .childNodes.
pub child_list: Option<JS<NodeList>>, pub child_list: Cell<Option<JS<NodeList>>>,
/// A bitfield of flags for node items. /// A bitfield of flags for node items.
flags: NodeFlags, 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.) /// Fails unless `child` is a child of this node. (FIXME: This is not yet checked.)
fn remove_child(&mut self, child: &mut JSRef<Node>) { fn remove_child(&mut self, child: &mut JSRef<Node>) {
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 => { None => {
let next_sibling = child.next_sibling.root(); let next_sibling = child.next_sibling.get().root();
self.set_first_child(next_sibling.root_ref()); self.set_first_child(next_sibling.root_ref());
} }
Some(ref mut prev_sibling) => { 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()); prev_sibling.set_next_sibling(next_sibling.root_ref());
} }
} }
match child.next_sibling.root() { match child.next_sibling.get().root() {
None => { None => {
let prev_sibling = child.prev_sibling.root(); let prev_sibling = child.prev_sibling.get().root();
self.set_last_child(prev_sibling.root_ref()); self.set_last_child(prev_sibling.root_ref());
} }
Some(ref mut next_sibling) => { 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()); 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<Temporary<Node>> { fn parent_node(&self) -> Option<Temporary<Node>> {
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<Temporary<Node>> { fn first_child(&self) -> Option<Temporary<Node>> {
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<Temporary<Node>> { fn last_child(&self) -> Option<Temporary<Node>> {
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. /// Returns the previous sibling of this node. Fails if this node is borrowed mutably.
fn prev_sibling(&self) -> Option<Temporary<Node>> { fn prev_sibling(&self) -> Option<Temporary<Node>> {
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. /// Returns the next sibling of this node. Fails if this node is borrowed mutably.
fn next_sibling(&self) -> Option<Temporary<Node>> { fn next_sibling(&self) -> Option<Temporary<Node>> {
self.deref().next_sibling.clone().map(|node| Temporary::new(node)) self.deref().next_sibling.get().map(|node| Temporary::new(node))
} }
#[inline] #[inline]
@ -593,12 +593,12 @@ impl<'a> NodeHelpers for JSRef<'a, Node> {
fn ancestors(&self) -> AncestorIterator { fn ancestors(&self) -> AncestorIterator {
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<Document> { fn owner_doc(&self) -> Temporary<Document> {
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<Document>) { fn set_owner_doc(&mut self, document: &JSRef<Document>) {
@ -607,7 +607,7 @@ impl<'a> NodeHelpers for JSRef<'a, Node> {
fn children(&self) -> AbstractNodeChildrenIterator { fn children(&self) -> AbstractNodeChildrenIterator {
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 { pub trait LayoutNodeHelpers {
unsafe fn type_id_for_layout(&self) -> NodeTypeId; unsafe fn type_id_for_layout(&self) -> NodeTypeId;
unsafe fn parent_node_ref<'a>(&'a self) -> Option<&'a JS<Node>>; unsafe fn parent_node_ref<'a>(&'a self) -> Option<JS<Node>>;
unsafe fn first_child_ref<'a>(&'a self) -> Option<&'a JS<Node>>; unsafe fn first_child_ref<'a>(&'a self) -> Option<JS<Node>>;
unsafe fn last_child_ref<'a>(&'a self) -> Option<&'a JS<Node>>; unsafe fn last_child_ref<'a>(&'a self) -> Option<JS<Node>>;
unsafe fn prev_sibling_ref<'a>(&'a self) -> Option<&'a JS<Node>>; unsafe fn prev_sibling_ref<'a>(&'a self) -> Option<JS<Node>>;
unsafe fn next_sibling_ref<'a>(&'a self) -> Option<&'a JS<Node>>; unsafe fn next_sibling_ref<'a>(&'a self) -> Option<JS<Node>>;
unsafe fn owner_doc_for_layout<'a>(&'a self) -> &'a JS<Document>; unsafe fn owner_doc_for_layout<'a>(&'a self) -> JS<Document>;
unsafe fn is_element_for_layout(&self) -> bool; unsafe fn is_element_for_layout(&self) -> bool;
} }
@ -675,32 +675,32 @@ impl LayoutNodeHelpers for JS<Node> {
} }
#[inline] #[inline]
unsafe fn parent_node_ref<'a>(&'a self) -> Option<&'a JS<Node>> { unsafe fn parent_node_ref<'a>(&'a self) -> Option<JS<Node>> {
(*self.unsafe_get()).parent_node.as_ref() (*self.unsafe_get()).parent_node.get()
} }
#[inline] #[inline]
unsafe fn first_child_ref<'a>(&'a self) -> Option<&'a JS<Node>> { unsafe fn first_child_ref<'a>(&'a self) -> Option<JS<Node>> {
(*self.unsafe_get()).first_child.as_ref() (*self.unsafe_get()).first_child.get()
} }
#[inline] #[inline]
unsafe fn last_child_ref<'a>(&'a self) -> Option<&'a JS<Node>> { unsafe fn last_child_ref<'a>(&'a self) -> Option<JS<Node>> {
(*self.unsafe_get()).last_child.as_ref() (*self.unsafe_get()).last_child.get()
} }
#[inline] #[inline]
unsafe fn prev_sibling_ref<'a>(&'a self) -> Option<&'a JS<Node>> { unsafe fn prev_sibling_ref<'a>(&'a self) -> Option<JS<Node>> {
(*self.unsafe_get()).prev_sibling.as_ref() (*self.unsafe_get()).prev_sibling.get()
} }
#[inline] #[inline]
unsafe fn next_sibling_ref<'a>(&'a self) -> Option<&'a JS<Node>> { unsafe fn next_sibling_ref<'a>(&'a self) -> Option<JS<Node>> {
(*self.unsafe_get()).next_sibling.as_ref() (*self.unsafe_get()).next_sibling.get()
} }
unsafe fn owner_doc_for_layout<'a>(&'a self) -> &'a JS<Document> { unsafe fn owner_doc_for_layout<'a>(&'a self) -> JS<Document> {
(*self.unsafe_get()).owner_doc.get_ref() (*self.unsafe_get()).owner_doc.get().unwrap()
} }
} }
@ -822,7 +822,7 @@ impl<'a> Iterator<JSRef<'a, Node>> for NodeIterator {
self.current_node = match self.current_node.as_ref().map(|node| node.root()) { self.current_node = match self.current_node.as_ref().map(|node| node.root()) {
None => { None => {
if self.include_start { if self.include_start {
Some(self.start_node.clone()) Some(self.start_node)
} else { } else {
self.next_child(&*self.start_node.root()) self.next_child(&*self.start_node.root())
.map(|child| child.unrooted()) .map(|child| child.unrooted())
@ -860,7 +860,7 @@ impl<'a> Iterator<JSRef<'a, Node>> 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)), eventtarget: EventTarget::new_inherited(NodeTargetTypeId(type_id)),
type_id: type_id, type_id: type_id,
parent_node: None, parent_node: Cell::new(None),
first_child: None, first_child: Cell::new(None),
last_child: None, last_child: Cell::new(None),
next_sibling: None, next_sibling: Cell::new(None),
prev_sibling: None, prev_sibling: Cell::new(None),
owner_doc: doc.unrooted(), owner_doc: Cell::new(doc.unrooted()),
child_list: None, child_list: Cell::new(None),
flags: NodeFlags::new(type_id), flags: NodeFlags::new(type_id),
@ -1297,8 +1297,8 @@ impl Node {
// FIXME: https://github.com/mozilla/servo/issues/1737 // FIXME: https://github.com/mozilla/servo/issues/1737
copy_elem.namespace = node_elem.namespace.clone(); copy_elem.namespace = node_elem.namespace.clone();
let window = document.deref().window.root(); let window = document.deref().window.root();
for attr in node_elem.attrs.iter().map(|attr| attr.root()) { for attr in node_elem.attrs.borrow().iter().map(|attr| attr.root()) {
copy_elem.attrs.push_unrooted( copy_elem.attrs.borrow_mut().push_unrooted(
&Attr::new(&*window, &Attr::new(&*window,
attr.deref().local_name.clone(), attr.deref().value.clone(), attr.deref().local_name.clone(), attr.deref().value.clone(),
attr.deref().name.clone(), attr.deref().namespace.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 // http://dom.spec.whatwg.org/#dom-node-parentnode
fn GetParentNode(&self) -> Option<Temporary<Node>> { fn GetParentNode(&self) -> Option<Temporary<Node>> {
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 // http://dom.spec.whatwg.org/#dom-node-parentelement
fn GetParentElement(&self) -> Option<Temporary<Element>> { fn GetParentElement(&self) -> Option<Temporary<Element>> {
self.parent_node.clone() self.parent_node.get()
.and_then(|parent| { .and_then(|parent| {
let parent = parent.root(); let parent = parent.root();
ElementCast::to_ref(&*parent).map(|elem| { 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 // http://dom.spec.whatwg.org/#dom-node-haschildnodes
fn HasChildNodes(&self) -> bool { fn HasChildNodes(&self) -> bool {
self.first_child.is_some() self.first_child.get().is_some()
} }
// http://dom.spec.whatwg.org/#dom-node-childnodes // http://dom.spec.whatwg.org/#dom-node-childnodes
fn ChildNodes(&mut self) -> Temporary<NodeList> { fn ChildNodes(&mut self) -> Temporary<NodeList> {
match self.child_list { match self.child_list.get() {
None => (), None => (),
Some(ref list) => return Temporary::new(list.clone()), 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 window = doc.deref().window.root();
let child_list = NodeList::new_child_list(&*window, self); let child_list = NodeList::new_child_list(&*window, self);
self.child_list.assign(Some(child_list)); 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 // http://dom.spec.whatwg.org/#dom-node-firstchild
fn GetFirstChild(&self) -> Option<Temporary<Node>> { fn GetFirstChild(&self) -> Option<Temporary<Node>> {
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 // http://dom.spec.whatwg.org/#dom-node-lastchild
fn GetLastChild(&self) -> Option<Temporary<Node>> { fn GetLastChild(&self) -> Option<Temporary<Node>> {
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 // http://dom.spec.whatwg.org/#dom-node-previoussibling
fn GetPreviousSibling(&self) -> Option<Temporary<Node>> { fn GetPreviousSibling(&self) -> Option<Temporary<Node>> {
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 // http://dom.spec.whatwg.org/#dom-node-nextsibling
fn GetNextSibling(&self) -> Option<Temporary<Node>> { fn GetNextSibling(&self) -> Option<Temporary<Node>> {
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 // http://dom.spec.whatwg.org/#dom-node-nodevalue
@ -1766,9 +1766,11 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
let element: &JSRef<Element> = ElementCast::to_ref(node).unwrap(); let element: &JSRef<Element> = ElementCast::to_ref(node).unwrap();
let other_element: &JSRef<Element> = ElementCast::to_ref(other).unwrap(); let other_element: &JSRef<Element> = ElementCast::to_ref(other).unwrap();
// FIXME: namespace prefix // FIXME: namespace prefix
(element.deref().namespace == other_element.deref().namespace) && let element = element.deref();
(element.deref().local_name == other_element.deref().local_name) && let other_element = other_element.deref();
(element.deref().attrs.len() == other_element.deref().attrs.len()) (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<Node>, other: &JSRef<Node>) -> bool { fn is_equal_processinginstruction(node: &JSRef<Node>, other: &JSRef<Node>) -> bool {
let pi: &JSRef<ProcessingInstruction> = ProcessingInstructionCast::to_ref(node).unwrap(); let pi: &JSRef<ProcessingInstruction> = ProcessingInstructionCast::to_ref(node).unwrap();
@ -1784,9 +1786,11 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
fn is_equal_element_attrs(node: &JSRef<Node>, other: &JSRef<Node>) -> bool { fn is_equal_element_attrs(node: &JSRef<Node>, other: &JSRef<Node>) -> bool {
let element: &JSRef<Element> = ElementCast::to_ref(node).unwrap(); let element: &JSRef<Element> = ElementCast::to_ref(node).unwrap();
let other_element: &JSRef<Element> = ElementCast::to_ref(other).unwrap(); let other_element: &JSRef<Element> = ElementCast::to_ref(other).unwrap();
assert!(element.deref().attrs.len() == other_element.deref().attrs.len()); let element = element.deref();
element.deref().attrs.iter().map(|attr| attr.root()).all(|attr| { let other_element = other_element.deref();
other_element.deref().attrs.iter().map(|attr| attr.root()).any(|other_attr| { 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.namespace == other_attr.namespace) &&
(attr.local_name == other_attr.local_name) && (attr.local_name == other_attr.local_name) &&
(attr.value == other_attr.value) (attr.value == other_attr.value)

View file

@ -7,7 +7,6 @@ use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::performancetiming::{PerformanceTiming, PerformanceTimingMethods}; use dom::performancetiming::{PerformanceTiming, PerformanceTimingMethods};
use dom::window::Window; use dom::window::Window;
use time; use time;
pub type DOMHighResTimeStamp = f64; pub type DOMHighResTimeStamp = f64;
@ -20,9 +19,10 @@ pub struct Performance {
impl Performance { impl Performance {
fn new_inherited(window: &JSRef<Window>) -> Performance { fn new_inherited(window: &JSRef<Window>) -> Performance {
let timing = PerformanceTiming::new(window).root().root_ref().unrooted();
Performance { Performance {
reflector_: Reflector::new(), reflector_: Reflector::new(),
timing: PerformanceTiming::new(window).root().root_ref().unrooted(), timing: timing,
} }
} }

View file

@ -15,10 +15,12 @@ use servo_util::str::DOMString;
use js::jsapi::JSContext; use js::jsapi::JSContext;
use js::jsval::{JSVal, NullValue}; use js::jsval::{JSVal, NullValue};
use std::cell::Cell;
#[deriving(Encodable)] #[deriving(Encodable)]
pub struct TestBinding { pub struct TestBinding {
pub reflector: Reflector, pub reflector: Reflector,
pub window: JS<Window>, pub window: Cell<JS<Window>>,
} }
pub trait TestBindingMethods { pub trait TestBindingMethods {
@ -243,19 +245,19 @@ pub trait TestBindingMethods {
impl<'a> TestBindingMethods for JSRef<'a, TestBinding> { impl<'a> TestBindingMethods for JSRef<'a, TestBinding> {
fn InterfaceAttribute(&self) -> Temporary<Blob> { fn InterfaceAttribute(&self) -> Temporary<Blob> {
let window = self.window.root(); let window = self.window.get().root();
Blob::new(&*window) Blob::new(&*window)
} }
fn GetInterfaceAttributeNullable(&self) -> Option<Temporary<Blob>> { fn GetInterfaceAttributeNullable(&self) -> Option<Temporary<Blob>> {
let window = self.window.root(); let window = self.window.get().root();
Some(Blob::new(&*window)) Some(Blob::new(&*window))
} }
fn ReceiveInterface(&self) -> Temporary<Blob> { fn ReceiveInterface(&self) -> Temporary<Blob> {
let window = self.window.root(); let window = self.window.get().root();
Blob::new(&*window) Blob::new(&*window)
} }
fn ReceiveNullableInterface(&self) -> Option<Temporary<Blob>> { fn ReceiveNullableInterface(&self) -> Option<Temporary<Blob>> {
let window = self.window.root(); let window = self.window.get().root();
Some(Blob::new(&*window)) Some(Blob::new(&*window))
} }
} }

View file

@ -86,7 +86,7 @@ pub trait UIEventMethods {
impl<'a> UIEventMethods for JSRef<'a, UIEvent> { impl<'a> UIEventMethods for JSRef<'a, UIEvent> {
fn GetView(&self) -> Option<Temporary<Window>> { fn GetView(&self) -> Option<Temporary<Window>> {
self.view.clone().map(|view| Temporary::new(view)) self.view.map(|view| Temporary::new(view))
} }
fn Detail(&self) -> i32 { fn Detail(&self) -> i32 {

View file

@ -6,11 +6,12 @@ use dom::bindings::codegen::BindingDeclarations::ValidityStateBinding;
use dom::bindings::js::{JS, JSRef, Temporary}; use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::window::Window; use dom::window::Window;
use std::cell::Cell;
#[deriving(Encodable)] #[deriving(Encodable)]
pub struct ValidityState { pub struct ValidityState {
pub reflector_: Reflector, pub reflector_: Reflector,
pub window: JS<Window>, pub window: Cell<JS<Window>>,
pub state: u8, pub state: u8,
} }
@ -18,7 +19,7 @@ impl ValidityState {
pub fn new_inherited(window: &JSRef<Window>) -> ValidityState { pub fn new_inherited(window: &JSRef<Window>) -> ValidityState {
ValidityState { ValidityState {
reflector_: Reflector::new(), reflector_: Reflector::new(),
window: window.unrooted(), window: Cell::new(window.unrooted()),
state: 0, state: 0,
} }
} }

View file

@ -30,6 +30,7 @@ use js::jsapi::{JS_GC, JS_GetRuntime};
use js::jsval::{NullValue, JSVal}; use js::jsval::{NullValue, JSVal};
use collections::hashmap::HashMap; use collections::hashmap::HashMap;
use std::cell::Cell;
use std::cmp; use std::cmp;
use std::comm::{channel, Sender}; use std::comm::{channel, Sender};
use std::comm::Select; use std::comm::Select;
@ -69,16 +70,16 @@ impl TimerHandle {
pub struct Window { pub struct Window {
pub eventtarget: EventTarget, pub eventtarget: EventTarget,
pub script_chan: ScriptChan, pub script_chan: ScriptChan,
pub console: Option<JS<Console>>, pub console: Cell<Option<JS<Console>>>,
pub location: Option<JS<Location>>, pub location: Cell<Option<JS<Location>>>,
pub navigator: Option<JS<Navigator>>, pub navigator: Cell<Option<JS<Navigator>>>,
pub image_cache_task: ImageCacheTask, pub image_cache_task: ImageCacheTask,
pub active_timers: Box<HashMap<TimerId, TimerHandle>>, pub active_timers: Box<HashMap<TimerId, TimerHandle>>,
pub next_timer_handle: i32, pub next_timer_handle: i32,
pub compositor: Untraceable<Box<ScriptListener>>, pub compositor: Untraceable<Box<ScriptListener>>,
pub browser_context: Option<BrowserContext>, pub browser_context: Option<BrowserContext>,
pub page: Rc<Page>, pub page: Rc<Page>,
pub performance: Option<JS<Performance>>, pub performance: Cell<Option<JS<Performance>>>,
pub navigationStart: u64, pub navigationStart: u64,
pub navigationStartPrecise: f64, pub navigationStartPrecise: f64,
} }
@ -200,28 +201,28 @@ impl<'a> WindowMethods for JSRef<'a, Window> {
} }
fn Location(&mut self) -> Temporary<Location> { fn Location(&mut self) -> Temporary<Location> {
if self.location.is_none() { if self.location.get().is_none() {
let page = self.deref().page.clone(); let page = self.deref().page.clone();
let location = Location::new(self, page); let location = Location::new(self, page);
self.location.assign(Some(location)); 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<Console> { fn Console(&mut self) -> Temporary<Console> {
if self.console.is_none() { if self.console.get().is_none() {
let console = Console::new(self); let console = Console::new(self);
self.console.assign(Some(console)); 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<Navigator> { fn Navigator(&mut self) -> Temporary<Navigator> {
if self.navigator.is_none() { if self.navigator.get().is_none() {
let navigator = Navigator::new(self); let navigator = Navigator::new(self);
self.navigator.assign(Some(navigator)); 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 { fn Confirm(&self, _message: DOMString) -> bool {
@ -269,11 +270,11 @@ impl<'a> WindowMethods for JSRef<'a, Window> {
} }
fn Performance(&mut self) -> Temporary<Performance> { fn Performance(&mut self) -> Temporary<Performance> {
if self.performance.is_none() { if self.performance.get().is_none() {
let performance = Performance::new(self); let performance = Performance::new(self);
self.performance.assign(Some(performance)); self.performance.assign(Some(performance));
} }
Temporary::new(self.performance.get_ref().clone()) Temporary::new(self.performance.get().get_ref().clone())
} }
fn GetOnload(&self) -> Option<EventHandlerNonNull> { fn GetOnload(&self) -> Option<EventHandlerNonNull> {
@ -441,16 +442,16 @@ impl Window {
let win = box Window { let win = box Window {
eventtarget: EventTarget::new_inherited(WindowTypeId), eventtarget: EventTarget::new_inherited(WindowTypeId),
script_chan: script_chan, script_chan: script_chan,
console: None, console: Cell::new(None),
compositor: Untraceable::new(compositor), compositor: Untraceable::new(compositor),
page: page, page: page,
location: None, location: Cell::new(None),
navigator: None, navigator: Cell::new(None),
image_cache_task: image_cache_task, image_cache_task: image_cache_task,
active_timers: box HashMap::new(), active_timers: box HashMap::new(),
next_timer_handle: 0, next_timer_handle: 0,
browser_context: None, browser_context: None,
performance: None, performance: Cell::new(None),
navigationStart: time::get_time().sec as u64, navigationStart: time::get_time().sec as u64,
navigationStartPrecise: time::precise_time_s(), navigationStartPrecise: time::precise_time_s(),
}; };

View file

@ -32,6 +32,7 @@ use url::Url;
use libc; use libc;
use libc::c_void; use libc::c_void;
use std::cell::Cell;
use std::comm::channel; use std::comm::channel;
use std::io::{BufReader, MemWriter}; use std::io::{BufReader, MemWriter};
use std::from_str::FromStr; use std::from_str::FromStr;
@ -98,14 +99,14 @@ pub struct XMLHttpRequest {
ready_state: XMLHttpRequestState, ready_state: XMLHttpRequestState,
timeout: u32, timeout: u32,
with_credentials: bool, with_credentials: bool,
upload: Option<JS<XMLHttpRequestUpload>>, upload: Cell<Option<JS<XMLHttpRequestUpload>>>,
response_url: DOMString, response_url: DOMString,
status: u16, status: u16,
status_text: ByteString, status_text: ByteString,
response: ByteString, response: ByteString,
response_type: XMLHttpRequestResponseType, response_type: XMLHttpRequestResponseType,
response_text: DOMString, response_text: DOMString,
response_xml: Option<JS<Document>>, response_xml: Cell<Option<JS<Document>>>,
response_headers: Untraceable<ResponseHeaderCollection>, response_headers: Untraceable<ResponseHeaderCollection>,
// Associated concepts // Associated concepts
@ -129,14 +130,14 @@ impl XMLHttpRequest {
ready_state: Unsent, ready_state: Unsent,
timeout: 0u32, timeout: 0u32,
with_credentials: false, with_credentials: false,
upload: None, upload: Cell::new(None),
response_url: "".to_owned(), response_url: "".to_owned(),
status: 0, status: 0,
status_text: ByteString::new(vec!()), status_text: ByteString::new(vec!()),
response: ByteString::new(vec!()), response: ByteString::new(vec!()),
response_type: _empty, response_type: _empty,
response_text: "".to_owned(), response_text: "".to_owned(),
response_xml: None, response_xml: Cell::new(None),
response_headers: Untraceable::new(ResponseHeaderCollection::new()), response_headers: Untraceable::new(ResponseHeaderCollection::new()),
request_method: Untraceable::new(Get), request_method: Untraceable::new(Get),
@ -385,7 +386,7 @@ impl<'a> XMLHttpRequestMethods<'a> for JSRef<'a, XMLHttpRequest> {
self.with_credentials = with_credentials self.with_credentials = with_credentials
} }
fn Upload(&self) -> Temporary<XMLHttpRequestUpload> { fn Upload(&self) -> Temporary<XMLHttpRequestUpload> {
Temporary::new(self.upload.get_ref().clone()) Temporary::new(self.upload.get().get_ref().clone())
} }
fn Send(&mut self, data: Option<DOMString>) -> ErrorResult { fn Send(&mut self, data: Option<DOMString>) -> ErrorResult {
if self.ready_state != Opened || self.send_flag { if self.ready_state != Opened || self.send_flag {
@ -407,7 +408,7 @@ impl<'a> XMLHttpRequestMethods<'a> for JSRef<'a, XMLHttpRequest> {
}; };
if !self.sync { if !self.sync {
// Step 8 // Step 8
let upload_target = &*self.upload.root().unwrap(); let upload_target = &*self.upload.get().root().unwrap();
let event_target: &JSRef<EventTarget> = EventTargetCast::from_ref(upload_target); let event_target: &JSRef<EventTarget> = EventTargetCast::from_ref(upload_target);
if event_target.handlers.iter().len() > 0 { if event_target.handlers.iter().len() > 0 {
self.upload_events = true; self.upload_events = true;
@ -498,7 +499,7 @@ impl<'a> XMLHttpRequestMethods<'a> for JSRef<'a, XMLHttpRequest> {
self.response_text.clone() self.response_text.clone()
} }
fn GetResponseXML(&self) -> Option<Temporary<Document>> { fn GetResponseXML(&self) -> Option<Temporary<Document>> {
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<u64>) { fn dispatch_progress_event(&self, upload: bool, type_: DOMString, loaded: u64, total: Option<u64>) {
let win = &*self.global.root(); 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, let mut progressevent = ProgressEvent::new(win, type_, false, false,
total.is_some(), loaded, total.is_some(), loaded,
total.unwrap_or(0)).root(); total.unwrap_or(0)).root();

View file

@ -162,7 +162,7 @@ pub struct Page {
resize_event: Untraceable<Cell<Option<Size2D<uint>>>>, resize_event: Untraceable<Cell<Option<Size2D<uint>>>>,
/// Pending scroll to fragment event, if any /// Pending scroll to fragment event, if any
fragment_node: Traceable<RefCell<Option<JS<Element>>>>, fragment_node: Cell<Option<JS<Element>>>,
/// Associated resource task for use by DOM objects like XMLHttpRequest /// Associated resource task for use by DOM objects like XMLHttpRequest
pub resource_task: Untraceable<ResourceTask>, pub resource_task: Untraceable<ResourceTask>,
@ -221,7 +221,7 @@ impl Page {
url: Untraceable::new(RefCell::new(None)), url: Untraceable::new(RefCell::new(None)),
next_subpage_id: Untraceable::new(Cell::new(SubpageId(0))), next_subpage_id: Untraceable::new(Cell::new(SubpageId(0))),
resize_event: Untraceable::new(Cell::new(None)), 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)), last_reflow_id: Traceable::new(Cell::new(0)),
resource_task: Untraceable::new(resource_task), resource_task: Untraceable::new(resource_task),
constellation_chan: Untraceable::new(constellation_chan), constellation_chan: Untraceable::new(constellation_chan),
@ -1043,8 +1043,8 @@ impl ScriptTask {
let _ = wintarget.dispatch_event_with_target(Some((*doctarget).clone()), let _ = wintarget.dispatch_event_with_target(Some((*doctarget).clone()),
&mut *event); &mut *event);
let mut fragment_node = page.fragment_node.deref().borrow_mut(); let mut fragment_node = page.fragment_node.get();
(*fragment_node).assign(fragment.map_or(None, |fragid| page.find_fragment_node(fragid))); fragment_node.assign(fragment.map_or(None, |fragid| page.find_fragment_node(fragid)));
let ConstellationChan(ref chan) = self.constellation_chan; let ConstellationChan(ref chan) = self.constellation_chan;
chan.send(LoadCompleteMsg(page.id, url)); chan.send(LoadCompleteMsg(page.id, url));
@ -1080,7 +1080,7 @@ impl ScriptTask {
page.reflow(ReflowForDisplay, self.chan.clone(), self.compositor) 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()) { match fragment_node.take().map(|node| node.root()) {
Some(node) => self.scroll_fragment_point(pipeline_id, &*node), Some(node) => self.scroll_fragment_point(pipeline_id, &*node),
None => {} None => {}