auto merge of #3518 : Manishearth/servo/trace-cleanup, r=jdm

Now that we use `JSTraceable` (defined in `script`), we can create arbitrary implementations on non-`script` types (eg `Url` or `RequestHeaderCollection`) where in the past we had to rely on `Traceable` and `Untraceable` to achieve cross-crate impls of `Encodable`.

This removes the two completely. They can be reintroduced if required, though the `untraceable!` macro should suffice.

Fixes #3469
This commit is contained in:
bors-servo 2014-10-06 10:15:33 -06:00
commit b34df7c343
39 changed files with 588 additions and 627 deletions

View file

@ -77,20 +77,20 @@ pub trait LayoutDataAccess {
impl<'ln> LayoutDataAccess for LayoutNode<'ln> { impl<'ln> LayoutDataAccess for LayoutNode<'ln> {
#[inline(always)] #[inline(always)]
unsafe fn borrow_layout_data_unchecked(&self) -> *const Option<LayoutDataWrapper> { unsafe fn borrow_layout_data_unchecked(&self) -> *const Option<LayoutDataWrapper> {
mem::transmute(self.get().layout_data.deref().borrow_unchecked()) mem::transmute(self.get().layout_data.borrow_unchecked())
} }
#[inline(always)] #[inline(always)]
fn borrow_layout_data<'a>(&'a self) -> Ref<'a,Option<LayoutDataWrapper>> { fn borrow_layout_data<'a>(&'a self) -> Ref<'a,Option<LayoutDataWrapper>> {
unsafe { unsafe {
mem::transmute(self.get().layout_data.deref().borrow()) mem::transmute(self.get().layout_data.borrow())
} }
} }
#[inline(always)] #[inline(always)]
fn mutate_layout_data<'a>(&'a self) -> RefMut<'a,Option<LayoutDataWrapper>> { fn mutate_layout_data<'a>(&'a self) -> RefMut<'a,Option<LayoutDataWrapper>> {
unsafe { unsafe {
mem::transmute(self.get().layout_data.deref().borrow_mut()) mem::transmute(self.get().layout_data.borrow_mut())
} }
} }
} }

View file

@ -113,7 +113,7 @@ pub trait TLayoutNode {
fail!("not an iframe element!") fail!("not an iframe element!")
} }
let iframe_element: JS<HTMLIFrameElement> = self.get_jsmanaged().transmute_copy(); let iframe_element: JS<HTMLIFrameElement> = self.get_jsmanaged().transmute_copy();
let size = (*iframe_element.unsafe_get()).size.deref().get().unwrap(); let size = (*iframe_element.unsafe_get()).size.get().unwrap();
(size.pipeline_id, size.subpage_id) (size.pipeline_id, size.subpage_id)
} }
} }
@ -187,7 +187,7 @@ impl<'ln> TLayoutNode for LayoutNode<'ln> {
unsafe { unsafe {
if self.get().is_text() { if self.get().is_text() {
let text: JS<Text> = self.get_jsmanaged().transmute_copy(); let text: JS<Text> = self.get_jsmanaged().transmute_copy();
(*text.unsafe_get()).characterdata.data.deref().borrow().clone() (*text.unsafe_get()).characterdata.data.borrow().clone()
} else if self.get().is_htmlinputelement() { } else if self.get().is_htmlinputelement() {
let input: JS<HTMLInputElement> = self.get_jsmanaged().transmute_copy(); let input: JS<HTMLInputElement> = self.get_jsmanaged().transmute_copy();
input.get_value_for_layout() input.get_value_for_layout()
@ -390,7 +390,7 @@ pub struct LayoutElement<'le> {
impl<'le> LayoutElement<'le> { impl<'le> LayoutElement<'le> {
pub fn style_attribute(&self) -> &'le Option<PropertyDeclarationBlock> { pub fn style_attribute(&self) -> &'le Option<PropertyDeclarationBlock> {
let style: &Option<PropertyDeclarationBlock> = unsafe { let style: &Option<PropertyDeclarationBlock> = unsafe {
let style: &RefCell<Option<PropertyDeclarationBlock>> = self.element.style_attribute.deref(); let style: &RefCell<Option<PropertyDeclarationBlock>> = &self.element.style_attribute;
// cast to the direct reference to T placed on the head of RefCell<T> // cast to the direct reference to T placed on the head of RefCell<T>
mem::transmute(style) mem::transmute(style)
}; };
@ -667,7 +667,7 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
#[inline(always)] #[inline(always)]
pub fn borrow_layout_data<'a>(&'a self) -> Ref<'a,Option<LayoutDataWrapper>> { pub fn borrow_layout_data<'a>(&'a self) -> Ref<'a,Option<LayoutDataWrapper>> {
unsafe { unsafe {
mem::transmute(self.get().layout_data.deref().borrow()) mem::transmute(self.get().layout_data.borrow())
} }
} }
@ -675,7 +675,7 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
#[inline(always)] #[inline(always)]
pub fn mutate_layout_data<'a>(&'a self) -> RefMut<'a,Option<LayoutDataWrapper>> { pub fn mutate_layout_data<'a>(&'a self) -> RefMut<'a,Option<LayoutDataWrapper>> {
unsafe { unsafe {
mem::transmute(self.get().layout_data.deref().borrow_mut()) mem::transmute(self.get().layout_data.borrow_mut())
} }
} }
@ -711,7 +711,7 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
Some(TextNodeTypeId) => { Some(TextNodeTypeId) => {
unsafe { unsafe {
let text: JS<Text> = self.get_jsmanaged().transmute_copy(); let text: JS<Text> = self.get_jsmanaged().transmute_copy();
if !is_whitespace((*text.unsafe_get()).characterdata.data.deref().borrow().as_slice()) { if !is_whitespace((*text.unsafe_get()).characterdata.data.borrow().as_slice()) {
return false return false
} }

View file

@ -7,7 +7,6 @@ use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
use dom::bindings::codegen::InheritTypes::NodeCast; use dom::bindings::codegen::InheritTypes::NodeCast;
use dom::bindings::global; use dom::bindings::global;
use dom::bindings::js::{JS, JSRef, Temporary}; use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::element::{Element, AttributeHandlers}; use dom::element::{Element, AttributeHandlers};
use dom::node::Node; use dom::node::Node;
@ -76,7 +75,7 @@ impl Str for AttrValue {
pub struct Attr { pub struct Attr {
reflector_: Reflector, reflector_: Reflector,
local_name: Atom, local_name: Atom,
value: Traceable<RefCell<AttrValue>>, value: RefCell<AttrValue>,
pub name: Atom, pub name: Atom,
pub namespace: Namespace, pub namespace: Namespace,
pub prefix: Option<DOMString>, pub prefix: Option<DOMString>,
@ -98,7 +97,7 @@ impl Attr {
Attr { Attr {
reflector_: Reflector::new(), reflector_: Reflector::new(),
local_name: local_name, local_name: local_name,
value: Traceable::new(RefCell::new(value)), value: RefCell::new(value),
name: name, name: name,
namespace: namespace, namespace: namespace,
prefix: prefix, prefix: prefix,
@ -170,7 +169,7 @@ impl<'a> AttrHelpers<'a> for JSRef<'a, Attr> {
FirstSetAttr => {} FirstSetAttr => {}
} }
*self.value.deref().borrow_mut() = value; *self.value.borrow_mut() = value;
if namespace_is_null { if namespace_is_null {
vtable_for(&node).after_set_attr( vtable_for(&node).after_set_attr(
@ -207,13 +206,13 @@ pub trait AttrHelpersForLayout {
impl AttrHelpersForLayout for Attr { impl AttrHelpersForLayout for Attr {
unsafe fn value_ref_forever(&self) -> &'static str { unsafe fn value_ref_forever(&self) -> &'static str {
// cast to point to T in RefCell<T> directly // cast to point to T in RefCell<T> directly
let value = mem::transmute::<&RefCell<AttrValue>, &AttrValue>(self.value.deref()); let value = mem::transmute::<&RefCell<AttrValue>, &AttrValue>(&self.value);
value.as_slice() value.as_slice()
} }
unsafe fn value_atom_forever(&self) -> Option<Atom> { unsafe fn value_atom_forever(&self) -> Option<Atom> {
// cast to point to T in RefCell<T> directly // cast to point to T in RefCell<T> directly
let value = mem::transmute::<&RefCell<AttrValue>, &AttrValue>(self.value.deref()); let value = mem::transmute::<&RefCell<AttrValue>, &AttrValue>(&self.value);
match *value { match *value {
AtomAttrValue(ref val) => Some(val.clone()), AtomAttrValue(ref val) => Some(val.clone()),
_ => None, _ => None,
@ -222,7 +221,7 @@ impl AttrHelpersForLayout for Attr {
unsafe fn value_tokens_forever(&self) -> Option<Items<Atom>> { unsafe fn value_tokens_forever(&self) -> Option<Items<Atom>> {
// cast to point to T in RefCell<T> directly // cast to point to T in RefCell<T> directly
let value = mem::transmute::<&RefCell<AttrValue>, &AttrValue>(self.value.deref()); let value = mem::transmute::<&RefCell<AttrValue>, &AttrValue>(&self.value);
match *value { match *value {
TokenListAttrValue(_, ref tokens) => Some(tokens.iter()), TokenListAttrValue(_, ref tokens) => Some(tokens.iter()),
_ => None, _ => None,

View file

@ -15,9 +15,9 @@ The outline is:
1. SpiderMonkey's GC calls `JSClass.trace` defined in `FooBinding` when marking phase. This JSClass is basis of each wrapper JSObject. 1. SpiderMonkey's GC calls `JSClass.trace` defined in `FooBinding` when marking phase. This JSClass is basis of each wrapper JSObject.
2. `JSClass.trace` calls `Foo::trace()` (an implementation of `JSTraceable`). 2. `JSClass.trace` calls `Foo::trace()` (an implementation of `JSTraceable`).
This is typically derived via a #[jstraceable] annotation This is typically derived via a #[jstraceable] annotation
3. For all fields (except those wrapped in `Untraceable`), `Foo::trace()` 3. For all fields, `Foo::trace()`
calls `trace()` on the field. For example, for fields of type `JS<T>`, `JS<T>::trace()` calls calls `trace()` on the field. For example, for fields of type `JS<T>`, `JS<T>::trace()` calls
`trace_reflector()`. `trace_reflector()`. Non-JS-managed types have an empty inline `trace()` method, achieved via `untraceable!` or similar.
4. `trace_reflector()` fetches the reflector that is reachable from a Rust object, and notifies it to the GC with using JSTracer. 4. `trace_reflector()` fetches the reflector that is reachable from a Rust object, and notifies it to the GC with using JSTracer.
5. This operation continues to the end of the graph. 5. This operation continues to the end of the graph.
6. Finally, GC gets whether Rust object lives or not from JSObjects which is hold by Rust object. 6. Finally, GC gets whether Rust object lives or not from JSObjects which is hold by Rust object.

View file

@ -6,7 +6,6 @@
use dom::bindings::global::global_object_for_js_object; use dom::bindings::global::global_object_for_js_object;
use dom::bindings::js::JSRef; use dom::bindings::js::JSRef;
use dom::bindings::trace::Traceable;
use dom::bindings::utils::Reflectable; use dom::bindings::utils::Reflectable;
use js::jsapi::{JSContext, JSObject, JS_WrapObject, JS_ObjectIsCallable}; use js::jsapi::{JSContext, JSObject, JS_WrapObject, JS_ObjectIsCallable};
use js::jsapi::JS_GetProperty; use js::jsapi::JS_GetProperty;
@ -37,7 +36,7 @@ impl CallbackFunction {
pub fn new(callback: *mut JSObject) -> CallbackFunction { pub fn new(callback: *mut JSObject) -> CallbackFunction {
CallbackFunction { CallbackFunction {
object: CallbackObject { object: CallbackObject {
callback: Traceable::new(callback) callback: callback
} }
} }
} }
@ -57,7 +56,7 @@ pub struct CallbackInterface {
#[jstraceable] #[jstraceable]
struct CallbackObject { struct CallbackObject {
/// The underlying `JSObject`. /// The underlying `JSObject`.
callback: Traceable<*mut JSObject>, callback: *mut JSObject,
} }
/// A trait to be implemented by concrete IDL callback function and /// A trait to be implemented by concrete IDL callback function and
@ -72,14 +71,14 @@ pub trait CallbackContainer {
impl CallbackInterface { impl CallbackInterface {
/// Returns the underlying `JSObject`. /// Returns the underlying `JSObject`.
pub fn callback(&self) -> *mut JSObject { pub fn callback(&self) -> *mut JSObject {
*self.object.callback self.object.callback
} }
} }
impl CallbackFunction { impl CallbackFunction {
/// Returns the underlying `JSObject`. /// Returns the underlying `JSObject`.
pub fn callback(&self) -> *mut JSObject { pub fn callback(&self) -> *mut JSObject {
*self.object.callback self.object.callback
} }
} }
@ -88,7 +87,7 @@ impl CallbackInterface {
pub fn new(callback: *mut JSObject) -> CallbackInterface { pub fn new(callback: *mut JSObject) -> CallbackInterface {
CallbackInterface { CallbackInterface {
object: CallbackObject { object: CallbackObject {
callback: Traceable::new(callback) callback: callback
} }
} }
} }

View file

@ -67,7 +67,7 @@ impl<'a> GlobalRef<'a> {
pub fn resource_task(&self) -> ResourceTask { pub fn resource_task(&self) -> ResourceTask {
match *self { match *self {
Window(ref window) => window.page().resource_task.deref().clone(), Window(ref window) => window.page().resource_task.clone(),
Worker(ref worker) => worker.resource_task().clone(), Worker(ref worker) => worker.resource_task().clone(),
} }
} }

View file

@ -13,7 +13,7 @@
//! through `ProxyTraps.trace` otherwise.) //! through `ProxyTraps.trace` otherwise.)
//! 2. `_trace` calls `Foo::trace()` (an implementation of `JSTraceable`). //! 2. `_trace` calls `Foo::trace()` (an implementation of `JSTraceable`).
//! This is typically derived via a #[jstraceable] annotation //! This is typically derived via a #[jstraceable] annotation
//! 3. For all fields (except those wrapped in `Untraceable`), `Foo::trace()` //! 3. For all fields, `Foo::trace()`
//! calls `trace()` on the field. //! calls `trace()` on the field.
//! For example, for fields of type `JS<T>`, `JS<T>::trace()` calls //! For example, for fields of type `JS<T>`, `JS<T>::trace()` calls
//! `trace_reflector()`. //! `trace_reflector()`.
@ -41,7 +41,18 @@ use script_traits::ScriptControlChan;
use std::collections::hashmap::HashMap; use std::collections::hashmap::HashMap;
use collections::hash::Hash; use collections::hash::Hash;
use style::PropertyDeclarationBlock; use style::PropertyDeclarationBlock;
use std::comm::{Receiver, Sender};
use hubbub::hubbub::QuirksMode;
use string_cache::{Atom, Namespace}; use string_cache::{Atom, Namespace};
use js::rust::Cx;
use http::headers::response::HeaderCollection as ResponseHeaderCollection;
use http::headers::request::HeaderCollection as RequestHeaderCollection;
use http::method::Method;
use std::io::timer::Timer;
use servo_msg::compositor_msg::ScriptListener;
use servo_msg::constellation_msg::ConstellationChan;
use layout_interface::{LayoutRPC, LayoutChan};
use dom::bindings::utils::WindowProxyHandler;
impl<T: Reflectable> JSTraceable for JS<T> { impl<T: Reflectable> JSTraceable for JS<T> {
fn trace(&self, trc: *mut JSTracer) { fn trace(&self, trc: *mut JSTracer) {
@ -90,65 +101,6 @@ pub fn trace_object(tracer: *mut JSTracer, description: &str, obj: *mut JSObject
} }
} }
/// Encapsulates a type that cannot easily have `Encodable` derived automagically,
/// but also does not need to be made known to the SpiderMonkey garbage collector.
///
/// Use only with types that are not associated with a JS reflector and do not contain
/// fields of types associated with JS reflectors.
///
/// This should really only be used for types that are from other crates,
/// so we can't implement `Encodable`. See more details: mozilla#2662.
pub struct Untraceable<T> {
inner: T,
}
impl<T> Untraceable<T> {
pub fn new(val: T) -> Untraceable<T> {
Untraceable {
inner: val
}
}
}
impl<T> Deref<T> for Untraceable<T> {
fn deref<'a>(&'a self) -> &'a T {
&self.inner
}
}
impl<T> DerefMut<T> for Untraceable<T> {
fn deref_mut<'a>(&'a mut self) -> &'a mut T {
&mut self.inner
}
}
/// Encapsulates a type that can be traced but is boxed in a type we don't
/// control (such as `RefCell`).
///
/// Wrap a field in Traceable and implement the `Encodable` trait
/// for that new concrete type to achieve magic compiler-derived trace hooks.
///
/// We always prefer this, in case the contained type ever changes to something that should be traced.
/// See more details: mozilla#2662.
#[deriving(PartialEq, Clone)]
pub struct Traceable<T> {
inner: T
}
impl<T> Traceable<T> {
pub fn new(val: T) -> Traceable<T> {
Traceable {
inner: val
}
}
}
impl<T> Deref<T> for Traceable<T> {
fn deref<'a>(&'a self) -> &'a T {
&self.inner
}
}
impl<T: JSTraceable> JSTraceable for RefCell<T> { impl<T: JSTraceable> JSTraceable for RefCell<T> {
fn trace(&self, trc: *mut JSTracer) { fn trace(&self, trc: *mut JSTracer) {
self.borrow().trace(trc) self.borrow().trace(trc)
@ -157,7 +109,7 @@ impl<T: JSTraceable> JSTraceable for RefCell<T> {
impl<T: JSTraceable> JSTraceable for Rc<T> { impl<T: JSTraceable> JSTraceable for Rc<T> {
fn trace(&self, trc: *mut JSTracer) { fn trace(&self, trc: *mut JSTracer) {
self.deref().trace(trc) (**self).trace(trc)
} }
} }
@ -167,28 +119,21 @@ impl<T: JSTraceable> JSTraceable for Box<T> {
} }
} }
impl<T: JSTraceable+Copy> JSTraceable for Traceable<Cell<T>> {
fn trace(&self, trc: *mut JSTracer) {
self.deref().get().trace(trc)
}
}
impl<T: JSTraceable+Copy> JSTraceable for Cell<T> { impl<T: JSTraceable+Copy> JSTraceable for Cell<T> {
fn trace(&self, trc: *mut JSTracer) { fn trace(&self, trc: *mut JSTracer) {
self.get().trace(trc) self.get().trace(trc)
} }
} }
impl JSTraceable for Traceable<*mut JSObject> { impl JSTraceable for *mut JSObject {
fn trace(&self, trc: *mut JSTracer) { fn trace(&self, trc: *mut JSTracer) {
trace_object(trc, "object", **self); trace_object(trc, "object", *self);
} }
} }
impl JSTraceable for Traceable<JSVal> { impl JSTraceable for JSVal {
fn trace(&self, trc: *mut JSTracer) { fn trace(&self, trc: *mut JSTracer) {
trace_jsval(trc, "val", **self); trace_jsval(trc, "val", *self);
} }
} }
@ -220,16 +165,33 @@ impl<K: Eq+Hash+JSTraceable, V: JSTraceable> JSTraceable for HashMap<K, V> {
} }
} }
impl<A: JSTraceable, B: JSTraceable> JSTraceable for (A, B) {
#[inline]
fn trace(&self, trc: *mut JSTracer) {
let (ref a, ref b) = *self;
a.trace(trc);
b.trace(trc);
}
}
untraceable!(bool, f32, f64, String, Url) untraceable!(bool, f32, f64, String, Url)
untraceable!(uint, u8, u16, u32, u64) untraceable!(uint, u8, u16, u32, u64)
untraceable!(int, i8, i16, i32, i64) untraceable!(int, i8, i16, i32, i64)
untraceable!(Untraceable<T>) untraceable!(Sender<T>)
untraceable!(Receiver<T>)
untraceable!(ImageCacheTask, ScriptControlChan) untraceable!(ImageCacheTask, ScriptControlChan)
untraceable!(Atom, Namespace) untraceable!(Atom, Namespace, Timer)
untraceable!(PropertyDeclarationBlock) untraceable!(PropertyDeclarationBlock)
// These three are interdependent, if you plan to put jsmanaged data // These three are interdependent, if you plan to put jsmanaged data
// in one of these make sure it is propagated properly to containing structs // in one of these make sure it is propagated properly to containing structs
untraceable!(SubpageId, WindowSizeData, PipelineId) untraceable!(SubpageId, WindowSizeData, PipelineId)
untraceable!(QuirksMode)
untraceable!(Cx)
untraceable!(ResponseHeaderCollection, RequestHeaderCollection, Method)
untraceable!(ConstellationChan)
untraceable!(LayoutChan)
untraceable!(WindowProxyHandler)
impl<'a> JSTraceable for &'a str { impl<'a> JSTraceable for &'a str {
#[inline] #[inline]
@ -238,3 +200,23 @@ impl<'a> JSTraceable for &'a str {
} }
} }
impl<A,B> JSTraceable for fn(A) -> B {
#[inline]
fn trace(&self, _: *mut JSTracer) {
// Do nothing
}
}
impl JSTraceable for Box<ScriptListener+'static> {
#[inline]
fn trace(&self, _: *mut JSTracer) {
// Do nothing
}
}
impl JSTraceable for Box<LayoutRPC+'static> {
#[inline]
fn trace(&self, _: *mut JSTracer) {
// Do nothing
}
}

View file

@ -10,7 +10,6 @@ use dom::bindings::conversions::IDLInterface;
use dom::bindings::error::throw_type_error; use dom::bindings::error::throw_type_error;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, Temporary, Root}; use dom::bindings::js::{JS, Temporary, Root};
use dom::bindings::trace::Untraceable;
use dom::browsercontext; use dom::browsercontext;
use dom::window; use dom::window;
use servo_util::str::DOMString; use servo_util::str::DOMString;
@ -50,15 +49,17 @@ use js::{JSPROP_ENUMERATE, JSPROP_READONLY, JSPROP_PERMANENT};
use js::JSFUN_CONSTRUCTOR; use js::JSFUN_CONSTRUCTOR;
use js; use js;
pub struct WindowProxyHandler(pub *const libc::c_void);
#[allow(raw_pointer_deriving)] #[allow(raw_pointer_deriving)]
#[jstraceable] #[jstraceable]
pub struct GlobalStaticData { pub struct GlobalStaticData {
pub windowproxy_handler: Untraceable<*const libc::c_void>, pub windowproxy_handler: WindowProxyHandler,
} }
pub fn GlobalStaticData() -> GlobalStaticData { pub fn GlobalStaticData() -> GlobalStaticData {
GlobalStaticData { GlobalStaticData {
windowproxy_handler: Untraceable::new(browsercontext::new_window_proxy_handler()), windowproxy_handler: browsercontext::new_window_proxy_handler(),
} }
} }
@ -659,7 +660,7 @@ pub extern fn outerize_global(_cx: *mut JSContext, obj: JSHandleObject) -> *mut
IDLInterface::get_prototype_depth(None::<window::Window>)) IDLInterface::get_prototype_depth(None::<window::Window>))
.unwrap() .unwrap()
.root(); .root();
win.deref().browser_context.deref().borrow().as_ref().unwrap().window_proxy() win.deref().browser_context.borrow().as_ref().unwrap().window_proxy()
} }
} }

View file

@ -3,8 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::bindings::js::{JS, JSRef, Temporary}; use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::trace::Traceable; use dom::bindings::utils::{Reflectable, WindowProxyHandler};
use dom::bindings::utils::Reflectable;
use dom::document::Document; use dom::document::Document;
use dom::window::Window; use dom::window::Window;
@ -12,7 +11,6 @@ use js::jsapi::JSObject;
use js::glue::{WrapperNew, CreateWrapperProxyHandler, ProxyTraps}; use js::glue::{WrapperNew, CreateWrapperProxyHandler, ProxyTraps};
use js::rust::with_compartment; use js::rust::with_compartment;
use libc::c_void;
use std::ptr; use std::ptr;
#[allow(raw_pointer_deriving)] #[allow(raw_pointer_deriving)]
@ -20,7 +18,7 @@ use std::ptr;
pub struct BrowserContext { pub struct BrowserContext {
history: Vec<SessionHistoryEntry>, history: Vec<SessionHistoryEntry>,
active_index: uint, active_index: uint,
window_proxy: Traceable<*mut JSObject>, window_proxy: *mut JSObject,
} }
impl BrowserContext { impl BrowserContext {
@ -28,7 +26,7 @@ impl BrowserContext {
let mut context = BrowserContext { let mut context = BrowserContext {
history: vec!(SessionHistoryEntry::new(document)), history: vec!(SessionHistoryEntry::new(document)),
active_index: 0, active_index: 0,
window_proxy: Traceable::new(ptr::null_mut()), window_proxy: ptr::null_mut(),
}; };
context.create_window_proxy(); context.create_window_proxy();
context context
@ -44,8 +42,8 @@ impl BrowserContext {
} }
pub fn window_proxy(&self) -> *mut JSObject { pub fn window_proxy(&self) -> *mut JSObject {
assert!(self.window_proxy.deref().is_not_null()); assert!(self.window_proxy.is_not_null());
*self.window_proxy self.window_proxy
} }
fn create_window_proxy(&mut self) { fn create_window_proxy(&mut self) {
@ -53,16 +51,16 @@ impl BrowserContext {
let page = win.deref().page(); let page = win.deref().page();
let js_info = page.js_info(); let js_info = page.js_info();
let handler = js_info.as_ref().unwrap().dom_static.windowproxy_handler; let WindowProxyHandler(handler) = js_info.as_ref().unwrap().dom_static.windowproxy_handler;
assert!(handler.deref().is_not_null()); assert!(handler.is_not_null());
let parent = win.deref().reflector().get_jsobject(); let parent = win.deref().reflector().get_jsobject();
let cx = js_info.as_ref().unwrap().js_context.deref().deref().ptr; let cx = js_info.as_ref().unwrap().js_context.deref().ptr;
let wrapper = with_compartment(cx, parent, || unsafe { let wrapper = with_compartment(cx, parent, || unsafe {
WrapperNew(cx, parent, *handler.deref()) WrapperNew(cx, parent, handler)
}); });
assert!(wrapper.is_not_null()); assert!(wrapper.is_not_null());
self.window_proxy = Traceable::new(wrapper); self.window_proxy = wrapper;
} }
} }
@ -114,8 +112,8 @@ static proxy_handler: ProxyTraps = ProxyTraps {
trace: None trace: None
}; };
pub fn new_window_proxy_handler() -> *const c_void { pub fn new_window_proxy_handler() -> WindowProxyHandler {
unsafe { unsafe {
CreateWrapperProxyHandler(&proxy_handler) WindowProxyHandler(CreateWrapperProxyHandler(&proxy_handler))
} }
} }

View file

@ -6,7 +6,6 @@ use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding;
use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2DMethods; use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2DMethods;
use dom::bindings::global::{GlobalRef, GlobalField}; use dom::bindings::global::{GlobalRef, GlobalField};
use dom::bindings::js::{JS, JSRef, Temporary}; use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::trace::Untraceable;
use dom::bindings::utils::{Reflector, Reflectable, reflect_dom_object}; use dom::bindings::utils::{Reflector, Reflectable, reflect_dom_object};
use dom::htmlcanvaselement::HTMLCanvasElement; use dom::htmlcanvaselement::HTMLCanvasElement;
@ -21,7 +20,7 @@ use canvas::canvas_render_task::{CanvasMsg, CanvasRenderTask, ClearRect, Close,
pub struct CanvasRenderingContext2D { pub struct CanvasRenderingContext2D {
reflector_: Reflector, reflector_: Reflector,
global: GlobalField, global: GlobalField,
renderer: Untraceable<Sender<CanvasMsg>>, renderer: Sender<CanvasMsg>,
canvas: JS<HTMLCanvasElement>, canvas: JS<HTMLCanvasElement>,
} }
@ -30,7 +29,7 @@ impl CanvasRenderingContext2D {
CanvasRenderingContext2D { CanvasRenderingContext2D {
reflector_: Reflector::new(), reflector_: Reflector::new(),
global: GlobalField::from_rooted(global), global: GlobalField::from_rooted(global),
renderer: Untraceable::new(CanvasRenderTask::start(size)), renderer: CanvasRenderTask::start(size),
canvas: JS::from_rooted(canvas), canvas: JS::from_rooted(canvas),
} }
} }
@ -41,7 +40,7 @@ impl CanvasRenderingContext2D {
} }
pub fn recreate(&self, size: Size2D<i32>) { pub fn recreate(&self, size: Size2D<i32>) {
self.renderer.deref().send(Recreate(size)); self.renderer.send(Recreate(size));
} }
} }
@ -52,17 +51,17 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
fn FillRect(self, x: f64, y: f64, width: f64, height: f64) { fn FillRect(self, x: f64, y: f64, width: f64, height: f64) {
let rect = Rect(Point2D(x as f32, y as f32), Size2D(width as f32, height as f32)); let rect = Rect(Point2D(x as f32, y as f32), Size2D(width as f32, height as f32));
self.renderer.deref().send(FillRect(rect)); self.renderer.send(FillRect(rect));
} }
fn ClearRect(self, x: f64, y: f64, width: f64, height: f64) { fn ClearRect(self, x: f64, y: f64, width: f64, height: f64) {
let rect = Rect(Point2D(x as f32, y as f32), Size2D(width as f32, height as f32)); let rect = Rect(Point2D(x as f32, y as f32), Size2D(width as f32, height as f32));
self.renderer.deref().send(ClearRect(rect)); self.renderer.send(ClearRect(rect));
} }
fn StrokeRect(self, x: f64, y: f64, width: f64, height: f64) { fn StrokeRect(self, x: f64, y: f64, width: f64, height: f64) {
let rect = Rect(Point2D(x as f32, y as f32), Size2D(width as f32, height as f32)); let rect = Rect(Point2D(x as f32, y as f32), Size2D(width as f32, height as f32));
self.renderer.deref().send(StrokeRect(rect)); self.renderer.send(StrokeRect(rect));
} }
} }

View file

@ -8,7 +8,6 @@ use dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods
use dom::bindings::codegen::InheritTypes::{CharacterDataDerived, NodeCast}; use dom::bindings::codegen::InheritTypes::{CharacterDataDerived, NodeCast};
use dom::bindings::error::{Fallible, ErrorResult, IndexSize}; use dom::bindings::error::{Fallible, ErrorResult, IndexSize};
use dom::bindings::js::JSRef; use dom::bindings::js::JSRef;
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector}; use dom::bindings::utils::{Reflectable, Reflector};
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::eventtarget::{EventTarget, NodeTargetTypeId};
@ -21,7 +20,7 @@ use std::cell::RefCell;
#[must_root] #[must_root]
pub struct CharacterData { pub struct CharacterData {
pub node: Node, pub node: Node,
pub data: Traceable<RefCell<DOMString>>, pub data: RefCell<DOMString>,
} }
impl CharacterDataDerived for EventTarget { impl CharacterDataDerived for EventTarget {
@ -39,31 +38,31 @@ impl CharacterData {
pub fn new_inherited(id: NodeTypeId, data: DOMString, document: JSRef<Document>) -> CharacterData { pub fn new_inherited(id: NodeTypeId, data: DOMString, document: JSRef<Document>) -> CharacterData {
CharacterData { CharacterData {
node: Node::new_inherited(id, document), node: Node::new_inherited(id, document),
data: Traceable::new(RefCell::new(data)), data: RefCell::new(data),
} }
} }
} }
impl<'a> CharacterDataMethods for JSRef<'a, CharacterData> { impl<'a> CharacterDataMethods for JSRef<'a, CharacterData> {
fn Data(self) -> DOMString { fn Data(self) -> DOMString {
self.data.deref().borrow().clone() self.data.borrow().clone()
} }
fn SetData(self, arg: DOMString) -> ErrorResult { fn SetData(self, arg: DOMString) -> ErrorResult {
*self.data.deref().borrow_mut() = arg; *self.data.borrow_mut() = arg;
Ok(()) Ok(())
} }
fn Length(self) -> u32 { fn Length(self) -> u32 {
self.data.deref().borrow().len() as u32 self.data.borrow().len() as u32
} }
fn SubstringData(self, offset: u32, count: u32) -> Fallible<DOMString> { fn SubstringData(self, offset: u32, count: u32) -> Fallible<DOMString> {
Ok(self.data.deref().borrow().as_slice().slice(offset as uint, count as uint).to_string()) Ok(self.data.borrow().as_slice().slice(offset as uint, count as uint).to_string())
} }
fn AppendData(self, arg: DOMString) -> ErrorResult { fn AppendData(self, arg: DOMString) -> ErrorResult {
self.data.deref().borrow_mut().push_str(arg.as_slice()); self.data.borrow_mut().push_str(arg.as_slice());
Ok(()) Ok(())
} }
@ -76,7 +75,7 @@ impl<'a> CharacterDataMethods for JSRef<'a, CharacterData> {
} }
fn ReplaceData(self, offset: u32, count: u32, arg: DOMString) -> ErrorResult { fn ReplaceData(self, offset: u32, count: u32, arg: DOMString) -> ErrorResult {
let length = self.data.deref().borrow().len() as u32; let length = self.data.borrow().len() as u32;
if offset > length { if offset > length {
return Err(IndexSize); return Err(IndexSize);
} }
@ -85,10 +84,10 @@ impl<'a> CharacterDataMethods for JSRef<'a, CharacterData> {
} else { } else {
count count
}; };
let mut data = self.data.deref().borrow().as_slice().slice(0, offset as uint).to_string(); let mut data = self.data.borrow().as_slice().slice(0, offset as uint).to_string();
data.push_str(arg.as_slice()); data.push_str(arg.as_slice());
data.push_str(self.data.deref().borrow().as_slice().slice((offset + count) as uint, length as uint)); data.push_str(self.data.borrow().as_slice().slice((offset + count) as uint, length as uint));
*self.data.deref().borrow_mut() = data; *self.data.borrow_mut() = data;
// FIXME: Once we have `Range`, we should implement step7 to step11 // FIXME: Once we have `Range`, we should implement step7 to step11
Ok(()) Ok(())
} }

View file

@ -9,7 +9,6 @@ use dom::bindings::codegen::InheritTypes::{EventCast, CustomEventDerived};
use dom::bindings::error::Fallible; use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::event::{Event, EventTypeId, CustomEventTypeId}; use dom::event::{Event, EventTypeId, CustomEventTypeId};
use js::jsapi::JSContext; use js::jsapi::JSContext;
@ -22,7 +21,7 @@ use std::cell::Cell;
#[must_root] #[must_root]
pub struct CustomEvent { pub struct CustomEvent {
event: Event, event: Event,
detail: Traceable<Cell<Traceable<JSVal>>>, detail: Cell<JSVal>,
} }
impl CustomEventDerived for Event { impl CustomEventDerived for Event {
@ -35,7 +34,7 @@ impl CustomEvent {
fn new_inherited(type_id: EventTypeId) -> CustomEvent { fn new_inherited(type_id: EventTypeId) -> CustomEvent {
CustomEvent { CustomEvent {
event: Event::new_inherited(type_id), event: Event::new_inherited(type_id),
detail: Traceable::new(Cell::new(Traceable::new(NullValue()))), detail: Cell::new(NullValue()),
} }
} }
@ -58,7 +57,7 @@ impl CustomEvent {
impl<'a> CustomEventMethods for JSRef<'a, CustomEvent> { impl<'a> CustomEventMethods for JSRef<'a, CustomEvent> {
fn Detail(self, _cx: *mut JSContext) -> JSVal { fn Detail(self, _cx: *mut JSContext) -> JSVal {
*self.detail.deref().get() self.detail.get()
} }
fn InitCustomEvent(self, fn InitCustomEvent(self,
@ -67,7 +66,7 @@ impl<'a> CustomEventMethods for JSRef<'a, CustomEvent> {
can_bubble: bool, can_bubble: bool,
cancelable: bool, cancelable: bool,
detail: JSVal) { detail: JSVal) {
self.detail.deref().set(Traceable::new(detail)); self.detail.set(detail);
let event: JSRef<Event> = EventCast::from_ref(self); let event: JSRef<Event> = EventCast::from_ref(self);
event.InitEvent(type_, can_bubble, cancelable); event.InitEvent(type_, can_bubble, cancelable);
} }

View file

@ -9,7 +9,6 @@ use dom::bindings::codegen::InheritTypes::DedicatedWorkerGlobalScopeDerived;
use dom::bindings::codegen::InheritTypes::{EventTargetCast, WorkerGlobalScopeCast}; use dom::bindings::codegen::InheritTypes::{EventTargetCast, WorkerGlobalScopeCast};
use dom::bindings::global; use dom::bindings::global;
use dom::bindings::js::{JSRef, Temporary, RootCollection}; use dom::bindings::js::{JSRef, Temporary, RootCollection};
use dom::bindings::trace::Untraceable;
use dom::bindings::utils::{Reflectable, Reflector}; use dom::bindings::utils::{Reflectable, Reflector};
use dom::eventtarget::{EventTarget, EventTargetHelpers}; use dom::eventtarget::{EventTarget, EventTargetHelpers};
use dom::eventtarget::WorkerGlobalScopeTypeId; use dom::eventtarget::WorkerGlobalScopeTypeId;
@ -40,10 +39,10 @@ use url::Url;
#[must_root] #[must_root]
pub struct DedicatedWorkerGlobalScope { pub struct DedicatedWorkerGlobalScope {
workerglobalscope: WorkerGlobalScope, workerglobalscope: WorkerGlobalScope,
receiver: Untraceable<Receiver<ScriptMsg>>, receiver: Receiver<ScriptMsg>,
/// Sender to the parent thread. /// Sender to the parent thread.
parent_sender: ScriptChan, parent_sender: ScriptChan,
worker: Untraceable<TrustedWorkerAddress>, worker: TrustedWorkerAddress,
} }
impl DedicatedWorkerGlobalScope { impl DedicatedWorkerGlobalScope {
@ -59,9 +58,9 @@ impl DedicatedWorkerGlobalScope {
workerglobalscope: WorkerGlobalScope::new_inherited( workerglobalscope: WorkerGlobalScope::new_inherited(
DedicatedGlobalScope, worker_url, cx, resource_task, DedicatedGlobalScope, worker_url, cx, resource_task,
own_sender), own_sender),
receiver: Untraceable::new(receiver), receiver: receiver,
parent_sender: parent_sender, parent_sender: parent_sender,
worker: Untraceable::new(worker), worker: worker,
} }
} }
@ -120,7 +119,7 @@ impl DedicatedWorkerGlobalScope {
let target: JSRef<EventTarget> = let target: JSRef<EventTarget> =
EventTargetCast::from_ref(*global); EventTargetCast::from_ref(*global);
loop { loop {
match global.receiver.deref().recv_opt() { match global.receiver.recv_opt() {
Ok(DOMMessage(data, nbytes)) => { Ok(DOMMessage(data, nbytes)) => {
let mut message = UndefinedValue(); let mut message = UndefinedValue();
unsafe { unsafe {
@ -160,7 +159,7 @@ impl<'a> DedicatedWorkerGlobalScopeMethods for JSRef<'a, DedicatedWorkerGlobalSc
} }
let ScriptChan(ref sender) = self.parent_sender; let ScriptChan(ref sender) = self.parent_sender;
sender.send(WorkerPostMessage(*self.worker, data, nbytes)); sender.send(WorkerPostMessage(self.worker, data, nbytes));
} }
fn GetOnmessage(self) -> Option<EventHandlerNonNull> { fn GetOnmessage(self) -> Option<EventHandlerNonNull> {
@ -181,7 +180,7 @@ trait PrivateDedicatedWorkerGlobalScopeHelpers {
impl<'a> PrivateDedicatedWorkerGlobalScopeHelpers for JSRef<'a, DedicatedWorkerGlobalScope> { impl<'a> PrivateDedicatedWorkerGlobalScopeHelpers for JSRef<'a, DedicatedWorkerGlobalScope> {
fn delayed_release_worker(self) { fn delayed_release_worker(self) {
let ScriptChan(ref sender) = self.parent_sender; let ScriptChan(ref sender) = self.parent_sender;
sender.send(WorkerRelease(*self.worker)); sender.send(WorkerRelease(self.worker));
} }
} }

View file

@ -23,7 +23,6 @@ use dom::bindings::global::GlobalRef;
use dom::bindings::global; use dom::bindings::global;
use dom::bindings::js::{MutNullableJS, JS, JSRef, Temporary, OptionalSettable, TemporaryPushable}; use dom::bindings::js::{MutNullableJS, JS, JSRef, Temporary, OptionalSettable, TemporaryPushable};
use dom::bindings::js::OptionalRootable; use dom::bindings::js::OptionalRootable;
use dom::bindings::trace::{Traceable, Untraceable};
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::bindings::utils::{xml_name_type, InvalidXMLName, Name, QName}; use dom::bindings::utils::{xml_name_type, InvalidXMLName, Name, QName};
use dom::comment::Comment; use dom::comment::Comment;
@ -81,14 +80,14 @@ pub struct Document {
pub node: Node, pub node: Node,
reflector_: Reflector, reflector_: Reflector,
pub window: JS<Window>, pub window: JS<Window>,
idmap: Traceable<RefCell<HashMap<Atom, Vec<JS<Element>>>>>, idmap: RefCell<HashMap<Atom, Vec<JS<Element>>>>,
implementation: MutNullableJS<DOMImplementation>, implementation: MutNullableJS<DOMImplementation>,
content_type: DOMString, content_type: DOMString,
last_modified: Traceable<RefCell<Option<DOMString>>>, last_modified: RefCell<Option<DOMString>>,
pub encoding_name: Traceable<RefCell<DOMString>>, pub encoding_name: RefCell<DOMString>,
pub is_html_document: bool, pub is_html_document: bool,
url: Untraceable<Url>, url: Url,
quirks_mode: Untraceable<Cell<QuirksMode>>, quirks_mode: Cell<QuirksMode>,
images: MutNullableJS<HTMLCollection>, images: MutNullableJS<HTMLCollection>,
embeds: MutNullableJS<HTMLCollection>, embeds: MutNullableJS<HTMLCollection>,
links: MutNullableJS<HTMLCollection>, links: MutNullableJS<HTMLCollection>,
@ -177,23 +176,23 @@ pub trait DocumentHelpers<'a> {
impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> { impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
fn url(self) -> &'a Url { fn url(self) -> &'a Url {
&*self.extended_deref().url &self.extended_deref().url
} }
fn quirks_mode(self) -> QuirksMode { fn quirks_mode(self) -> QuirksMode {
self.quirks_mode.deref().get() self.quirks_mode.get()
} }
fn set_quirks_mode(self, mode: QuirksMode) { fn set_quirks_mode(self, mode: QuirksMode) {
self.quirks_mode.deref().set(mode); self.quirks_mode.set(mode);
} }
fn set_last_modified(self, value: DOMString) { fn set_last_modified(self, value: DOMString) {
*self.last_modified.deref().borrow_mut() = Some(value); *self.last_modified.borrow_mut() = Some(value);
} }
fn set_encoding_name(self, name: DOMString) { fn set_encoding_name(self, name: DOMString) {
*self.encoding_name.deref().borrow_mut() = name; *self.encoding_name.borrow_mut() = name;
} }
fn content_changed(self) { fn content_changed(self) {
@ -213,7 +212,7 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
fn unregister_named_element(self, fn unregister_named_element(self,
to_unregister: JSRef<Element>, to_unregister: JSRef<Element>,
id: Atom) { id: Atom) {
let mut idmap = self.idmap.deref().borrow_mut(); let mut idmap = self.idmap.borrow_mut();
let is_empty = match idmap.find_mut(&id) { let is_empty = match idmap.find_mut(&id) {
None => false, None => false,
Some(elements) => { Some(elements) => {
@ -240,7 +239,7 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
}); });
assert!(!id.as_slice().is_empty()); assert!(!id.as_slice().is_empty());
let mut idmap = self.idmap.deref().borrow_mut(); let mut idmap = self.idmap.borrow_mut();
// FIXME https://github.com/mozilla/rust/issues/13195 // FIXME https://github.com/mozilla/rust/issues/13195
// Use mangle() when it exists again. // Use mangle() when it exists again.
@ -309,7 +308,7 @@ impl Document {
node: Node::new_without_doc(DocumentNodeTypeId), node: Node::new_without_doc(DocumentNodeTypeId),
reflector_: Reflector::new(), reflector_: Reflector::new(),
window: JS::from_rooted(window), window: JS::from_rooted(window),
idmap: Traceable::new(RefCell::new(HashMap::new())), idmap: RefCell::new(HashMap::new()),
implementation: Default::default(), implementation: Default::default(),
content_type: match content_type { content_type: match content_type {
Some(string) => string.clone(), Some(string) => string.clone(),
@ -320,12 +319,12 @@ impl Document {
NonHTMLDocument => "application/xml".to_string() NonHTMLDocument => "application/xml".to_string()
} }
}, },
last_modified: Traceable::new(RefCell::new(None)), last_modified: RefCell::new(None),
url: Untraceable::new(url), url: url,
// http://dom.spec.whatwg.org/#concept-document-quirks // http://dom.spec.whatwg.org/#concept-document-quirks
quirks_mode: Untraceable::new(Cell::new(NoQuirks)), quirks_mode: Cell::new(NoQuirks),
// http://dom.spec.whatwg.org/#concept-document-encoding // http://dom.spec.whatwg.org/#concept-document-encoding
encoding_name: Traceable::new(RefCell::new("utf-8".to_string())), encoding_name: RefCell::new("utf-8".to_string()),
is_html_document: is_html_document == HTMLDocument, is_html_document: is_html_document == HTMLDocument,
images: Default::default(), images: Default::default(),
embeds: Default::default(), embeds: Default::default(),
@ -419,7 +418,7 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
// http://dom.spec.whatwg.org/#dom-document-compatmode // http://dom.spec.whatwg.org/#dom-document-compatmode
fn CompatMode(self) -> DOMString { fn CompatMode(self) -> DOMString {
match self.quirks_mode.deref().get() { match self.quirks_mode.get() {
LimitedQuirks | NoQuirks => "CSS1Compat".to_string(), LimitedQuirks | NoQuirks => "CSS1Compat".to_string(),
FullQuirks => "BackCompat".to_string() FullQuirks => "BackCompat".to_string()
} }
@ -427,7 +426,7 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
// http://dom.spec.whatwg.org/#dom-document-characterset // http://dom.spec.whatwg.org/#dom-document-characterset
fn CharacterSet(self) -> DOMString { fn CharacterSet(self) -> DOMString {
self.encoding_name.deref().borrow().as_slice().to_ascii_lower() self.encoding_name.borrow().as_slice().to_ascii_lower()
} }
// http://dom.spec.whatwg.org/#dom-document-content_type // http://dom.spec.whatwg.org/#dom-document-content_type
@ -474,7 +473,7 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
// http://dom.spec.whatwg.org/#dom-nonelementparentnode-getelementbyid // http://dom.spec.whatwg.org/#dom-nonelementparentnode-getelementbyid
fn GetElementById(self, id: DOMString) -> Option<Temporary<Element>> { fn GetElementById(self, id: DOMString) -> Option<Temporary<Element>> {
let id = Atom::from_slice(id.as_slice()); let id = Atom::from_slice(id.as_slice());
match self.idmap.deref().borrow().find(&id) { match self.idmap.borrow().find(&id) {
None => None, None => None,
Some(ref elements) => Some(Temporary::new((*elements)[0].clone())), Some(ref elements) => Some(Temporary::new((*elements)[0].clone())),
} }
@ -648,7 +647,7 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
for child in title_elem.children() { for child in title_elem.children() {
if child.is_text() { if child.is_text() {
let text: JSRef<Text> = TextCast::to_ref(child).unwrap(); let text: JSRef<Text> = TextCast::to_ref(child).unwrap();
title.push_str(text.deref().characterdata.data.deref().borrow().as_slice()); title.push_str(text.deref().characterdata.data.borrow().as_slice());
} }
} }
}); });

View file

@ -14,7 +14,6 @@ use dom::bindings::codegen::Bindings::NamedNodeMapBinding::NamedNodeMapMethods;
use dom::bindings::codegen::InheritTypes::{ElementDerived, NodeCast}; use dom::bindings::codegen::InheritTypes::{ElementDerived, NodeCast};
use dom::bindings::js::{MutNullableJS, JS, JSRef, Temporary, TemporaryPushable}; use dom::bindings::js::{MutNullableJS, JS, JSRef, Temporary, TemporaryPushable};
use dom::bindings::js::{OptionalSettable, OptionalRootable, Root}; use dom::bindings::js::{OptionalSettable, OptionalRootable, Root};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector}; use dom::bindings::utils::{Reflectable, Reflector};
use dom::bindings::error::{ErrorResult, Fallible, NamespaceError, InvalidCharacter, Syntax}; use dom::bindings::error::{ErrorResult, Fallible, NamespaceError, InvalidCharacter, Syntax};
use dom::bindings::utils::{QName, Name, InvalidXMLName, xml_name_type}; use dom::bindings::utils::{QName, Name, InvalidXMLName, xml_name_type};
@ -51,7 +50,7 @@ pub struct Element {
pub namespace: Namespace, pub namespace: Namespace,
pub prefix: Option<DOMString>, pub prefix: Option<DOMString>,
pub attrs: RefCell<Vec<JS<Attr>>>, pub attrs: RefCell<Vec<JS<Attr>>>,
pub style_attribute: Traceable<RefCell<Option<style::PropertyDeclarationBlock>>>, pub style_attribute: RefCell<Option<style::PropertyDeclarationBlock>>,
pub attr_list: MutNullableJS<NamedNodeMap>, pub attr_list: MutNullableJS<NamedNodeMap>,
class_list: MutNullableJS<DOMTokenList>, class_list: MutNullableJS<DOMTokenList>,
} }
@ -159,7 +158,7 @@ impl Element {
attrs: RefCell::new(vec!()), attrs: RefCell::new(vec!()),
attr_list: Default::default(), attr_list: Default::default(),
class_list: Default::default(), class_list: Default::default(),
style_attribute: Traceable::new(RefCell::new(None)), style_attribute: RefCell::new(None),
} }
} }
@ -851,7 +850,7 @@ impl<'a> VirtualMethods for JSRef<'a, Element> {
let doc = document_from_node(*self).root(); let doc = document_from_node(*self).root();
let base_url = doc.deref().url().clone(); let base_url = doc.deref().url().clone();
let style = Some(style::parse_style_attribute(value.as_slice(), &base_url)); let style = Some(style::parse_style_attribute(value.as_slice(), &base_url));
*self.deref().style_attribute.deref().borrow_mut() = style; *self.deref().style_attribute.borrow_mut() = style;
} }
"id" => { "id" => {
let node: JSRef<Node> = NodeCast::from_ref(*self); let node: JSRef<Node> = NodeCast::from_ref(*self);
@ -875,7 +874,7 @@ impl<'a> VirtualMethods for JSRef<'a, Element> {
match name.as_slice() { match name.as_slice() {
"style" => { "style" => {
*self.deref().style_attribute.deref().borrow_mut() = None; *self.deref().style_attribute.borrow_mut() = None;
} }
"id" => { "id" => {
let node: JSRef<Node> = NodeCast::from_ref(*self); let node: JSRef<Node> = NodeCast::from_ref(*self);

View file

@ -7,7 +7,6 @@ use dom::bindings::codegen::Bindings::EventBinding::{EventConstants, EventMethod
use dom::bindings::error::Fallible; use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{MutNullableJS, JSRef, Temporary}; use dom::bindings::js::{MutNullableJS, JSRef, Temporary};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::eventtarget::EventTarget; use dom::eventtarget::EventTarget;
use servo_util::str::DOMString; use servo_util::str::DOMString;
@ -43,16 +42,16 @@ pub struct Event {
reflector_: Reflector, reflector_: Reflector,
pub current_target: MutNullableJS<EventTarget>, pub current_target: MutNullableJS<EventTarget>,
pub target: MutNullableJS<EventTarget>, pub target: MutNullableJS<EventTarget>,
type_: Traceable<RefCell<DOMString>>, type_: RefCell<DOMString>,
pub phase: Traceable<Cell<EventPhase>>, pub phase: Cell<EventPhase>,
pub canceled: Traceable<Cell<bool>>, pub canceled: Cell<bool>,
pub stop_propagation: Traceable<Cell<bool>>, pub stop_propagation: Cell<bool>,
pub stop_immediate: Traceable<Cell<bool>>, pub stop_immediate: Cell<bool>,
pub cancelable: Traceable<Cell<bool>>, pub cancelable: Cell<bool>,
pub bubbles: Traceable<Cell<bool>>, pub bubbles: Cell<bool>,
pub trusted: Traceable<Cell<bool>>, pub trusted: Cell<bool>,
pub dispatching: Traceable<Cell<bool>>, pub dispatching: Cell<bool>,
pub initialized: Traceable<Cell<bool>>, pub initialized: Cell<bool>,
timestamp: u64, timestamp: u64,
} }
@ -63,16 +62,16 @@ impl Event {
reflector_: Reflector::new(), reflector_: Reflector::new(),
current_target: Default::default(), current_target: Default::default(),
target: Default::default(), target: Default::default(),
phase: Traceable::new(Cell::new(PhaseNone)), phase: Cell::new(PhaseNone),
type_: Traceable::new(RefCell::new("".to_string())), type_: RefCell::new("".to_string()),
canceled: Traceable::new(Cell::new(false)), canceled: Cell::new(false),
cancelable: Traceable::new(Cell::new(true)), cancelable: Cell::new(true),
bubbles: Traceable::new(Cell::new(false)), bubbles: Cell::new(false),
trusted: Traceable::new(Cell::new(false)), trusted: Cell::new(false),
dispatching: Traceable::new(Cell::new(false)), dispatching: Cell::new(false),
stop_propagation: Traceable::new(Cell::new(false)), stop_propagation: Cell::new(false),
stop_immediate: Traceable::new(Cell::new(false)), stop_immediate: Cell::new(false),
initialized: Traceable::new(Cell::new(false)), initialized: Cell::new(false),
timestamp: time::get_time().sec as u64, timestamp: time::get_time().sec as u64,
} }
} }
@ -88,7 +87,7 @@ impl Event {
can_bubble: bool, can_bubble: bool,
cancelable: bool) -> Temporary<Event> { cancelable: bool) -> Temporary<Event> {
let event = Event::new_uninitialized(global).root(); let event = Event::new_uninitialized(global).root();
event.deref().InitEvent(type_, can_bubble, cancelable); event.InitEvent(type_, can_bubble, cancelable);
Temporary::from_rooted(*event) Temporary::from_rooted(*event)
} }
@ -101,11 +100,11 @@ impl Event {
impl<'a> EventMethods for JSRef<'a, Event> { impl<'a> EventMethods for JSRef<'a, Event> {
fn EventPhase(self) -> u16 { fn EventPhase(self) -> u16 {
self.phase.deref().get() as u16 self.phase.get() as u16
} }
fn Type(self) -> DOMString { fn Type(self) -> DOMString {
self.type_.deref().borrow().clone() self.type_.borrow().clone()
} }
fn GetTarget(self) -> Option<Temporary<EventTarget>> { fn GetTarget(self) -> Option<Temporary<EventTarget>> {
@ -117,30 +116,30 @@ impl<'a> EventMethods for JSRef<'a, Event> {
} }
fn DefaultPrevented(self) -> bool { fn DefaultPrevented(self) -> bool {
self.canceled.deref().get() self.canceled.get()
} }
fn PreventDefault(self) { fn PreventDefault(self) {
if self.cancelable.deref().get() { if self.cancelable.get() {
self.canceled.deref().set(true) self.canceled.set(true)
} }
} }
fn StopPropagation(self) { fn StopPropagation(self) {
self.stop_propagation.deref().set(true); self.stop_propagation.set(true);
} }
fn StopImmediatePropagation(self) { fn StopImmediatePropagation(self) {
self.stop_immediate.deref().set(true); self.stop_immediate.set(true);
self.stop_propagation.deref().set(true); self.stop_propagation.set(true);
} }
fn Bubbles(self) -> bool { fn Bubbles(self) -> bool {
self.bubbles.deref().get() self.bubbles.get()
} }
fn Cancelable(self) -> bool { fn Cancelable(self) -> bool {
self.cancelable.deref().get() self.cancelable.get()
} }
fn TimeStamp(self) -> u64 { fn TimeStamp(self) -> u64 {
@ -151,22 +150,22 @@ impl<'a> EventMethods for JSRef<'a, Event> {
type_: DOMString, type_: DOMString,
bubbles: bool, bubbles: bool,
cancelable: bool) { cancelable: bool) {
self.initialized.deref().set(true); self.initialized.set(true);
if self.dispatching.deref().get() { if self.dispatching.get() {
return; return;
} }
self.stop_propagation.deref().set(false); self.stop_propagation.set(false);
self.stop_immediate.deref().set(false); self.stop_immediate.set(false);
self.canceled.deref().set(false); self.canceled.set(false);
self.trusted.deref().set(false); self.trusted.set(false);
self.target.clear(); self.target.clear();
*self.type_.deref().borrow_mut() = type_; *self.type_.borrow_mut() = type_;
self.bubbles.deref().set(bubbles); self.bubbles.set(bubbles);
self.cancelable.deref().set(cancelable); self.cancelable.set(cancelable);
} }
fn IsTrusted(self) -> bool { fn IsTrusted(self) -> bool {
self.trusted.deref().get() self.trusted.get()
} }
} }

View file

@ -15,18 +15,18 @@ use dom::virtualmethods::vtable_for;
pub fn dispatch_event<'a, 'b>(target: JSRef<'a, EventTarget>, pub fn dispatch_event<'a, 'b>(target: JSRef<'a, EventTarget>,
pseudo_target: Option<JSRef<'b, EventTarget>>, pseudo_target: Option<JSRef<'b, EventTarget>>,
event: JSRef<Event>) -> bool { event: JSRef<Event>) -> bool {
assert!(!event.deref().dispatching.deref().get()); assert!(!event.dispatching.get());
event.target.assign(Some(match pseudo_target { event.target.assign(Some(match pseudo_target {
Some(pseudo_target) => pseudo_target, Some(pseudo_target) => pseudo_target,
None => target.clone(), None => target.clone(),
})); }));
event.dispatching.deref().set(true); event.dispatching.set(true);
let type_ = event.Type(); let type_ = event.Type();
//TODO: no chain if not participating in a tree //TODO: no chain if not participating in a tree
let mut chain: Vec<Root<EventTarget>> = if target.deref().is_node() { let mut chain: Vec<Root<EventTarget>> = if target.is_node() {
let target_node: JSRef<Node> = NodeCast::to_ref(target).unwrap(); let target_node: JSRef<Node> = NodeCast::to_ref(target).unwrap();
target_node.ancestors().map(|ancestor| { target_node.ancestors().map(|ancestor| {
let ancestor_target: JSRef<EventTarget> = EventTargetCast::from_ref(ancestor); let ancestor_target: JSRef<EventTarget> = EventTargetCast::from_ref(ancestor);
@ -36,7 +36,7 @@ pub fn dispatch_event<'a, 'b>(target: JSRef<'a, EventTarget>,
vec!() vec!()
}; };
event.deref().phase.deref().set(PhaseCapturing); event.phase.set(PhaseCapturing);
//FIXME: The "callback this value" should be currentTarget //FIXME: The "callback this value" should be currentTarget
@ -49,12 +49,12 @@ pub fn dispatch_event<'a, 'b>(target: JSRef<'a, EventTarget>,
// Explicitly drop any exception on the floor. // Explicitly drop any exception on the floor.
let _ = listener.HandleEvent_(**cur_target, event, ReportExceptions); let _ = listener.HandleEvent_(**cur_target, event, ReportExceptions);
if event.deref().stop_immediate.deref().get() { if event.stop_immediate.get() {
break; break;
} }
} }
event.deref().stop_propagation.deref().get() event.stop_propagation.get()
} }
None => false None => false
}; };
@ -65,17 +65,17 @@ pub fn dispatch_event<'a, 'b>(target: JSRef<'a, EventTarget>,
} }
/* at target */ /* at target */
if !event.deref().stop_propagation.deref().get() { if !event.stop_propagation.get() {
event.phase.deref().set(PhaseAtTarget); event.phase.set(PhaseAtTarget);
event.current_target.assign(Some(target.clone())); event.current_target.assign(Some(target.clone()));
let opt_listeners = target.deref().get_listeners(type_.as_slice()); let opt_listeners = target.get_listeners(type_.as_slice());
for listeners in opt_listeners.iter() { for listeners in opt_listeners.iter() {
for listener in listeners.iter() { for listener in listeners.iter() {
// Explicitly drop any exception on the floor. // Explicitly drop any exception on the floor.
let _ = listener.HandleEvent_(target, event, ReportExceptions); let _ = listener.HandleEvent_(target, event, ReportExceptions);
if event.deref().stop_immediate.deref().get() { if event.stop_immediate.get() {
break; break;
} }
} }
@ -83,23 +83,23 @@ pub fn dispatch_event<'a, 'b>(target: JSRef<'a, EventTarget>,
} }
/* bubbling */ /* bubbling */
if event.deref().bubbles.deref().get() && !event.deref().stop_propagation.deref().get() { if event.bubbles.get() && !event.stop_propagation.get() {
event.deref().phase.deref().set(PhaseBubbling); event.phase.set(PhaseBubbling);
for cur_target in chain.iter() { for cur_target in chain.iter() {
let stopped = match cur_target.deref().get_listeners_for(type_.as_slice(), Bubbling) { let stopped = match cur_target.get_listeners_for(type_.as_slice(), Bubbling) {
Some(listeners) => { Some(listeners) => {
event.deref().current_target.assign(Some(cur_target.deref().clone())); event.current_target.assign(Some(cur_target.deref().clone()));
for listener in listeners.iter() { for listener in listeners.iter() {
// Explicitly drop any exception on the floor. // Explicitly drop any exception on the floor.
let _ = listener.HandleEvent_(**cur_target, event, ReportExceptions); let _ = listener.HandleEvent_(**cur_target, event, ReportExceptions);
if event.deref().stop_immediate.deref().get() { if event.stop_immediate.get() {
break; break;
} }
} }
event.deref().stop_propagation.deref().get() event.stop_propagation.get()
} }
None => false None => false
}; };
@ -131,8 +131,8 @@ pub fn dispatch_event<'a, 'b>(target: JSRef<'a, EventTarget>,
let _ = chain.pop(); let _ = chain.pop();
} }
event.dispatching.deref().set(false); event.dispatching.set(false);
event.phase.deref().set(PhaseNone); event.phase.set(PhaseNone);
event.current_target.clear(); event.current_target.clear();
!event.DefaultPrevented() !event.DefaultPrevented()

View file

@ -8,7 +8,6 @@ use dom::bindings::codegen::Bindings::EventListenerBinding::EventListener;
use dom::bindings::codegen::Bindings::EventTargetBinding::EventTargetMethods; use dom::bindings::codegen::Bindings::EventTargetBinding::EventTargetMethods;
use dom::bindings::error::{Fallible, InvalidState, report_pending_exception}; use dom::bindings::error::{Fallible, InvalidState, report_pending_exception};
use dom::bindings::js::JSRef; use dom::bindings::js::JSRef;
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector}; use dom::bindings::utils::{Reflectable, Reflector};
use dom::event::Event; use dom::event::Event;
use dom::eventdispatcher::dispatch_event; use dom::eventdispatcher::dispatch_event;
@ -70,7 +69,7 @@ pub struct EventListenerEntry {
pub struct EventTarget { pub struct EventTarget {
pub type_id: EventTargetTypeId, pub type_id: EventTargetTypeId,
reflector_: Reflector, reflector_: Reflector,
handlers: Traceable<RefCell<HashMap<DOMString, Vec<EventListenerEntry>>>>, handlers: RefCell<HashMap<DOMString, Vec<EventListenerEntry>>>,
} }
impl EventTarget { impl EventTarget {
@ -78,19 +77,19 @@ impl EventTarget {
EventTarget { EventTarget {
type_id: type_id, type_id: type_id,
reflector_: Reflector::new(), reflector_: Reflector::new(),
handlers: Traceable::new(RefCell::new(HashMap::new())), handlers: RefCell::new(HashMap::new()),
} }
} }
pub fn get_listeners(&self, type_: &str) -> Option<Vec<EventListener>> { pub fn get_listeners(&self, type_: &str) -> Option<Vec<EventListener>> {
self.handlers.deref().borrow().find_equiv(&type_).map(|listeners| { self.handlers.borrow().find_equiv(&type_).map(|listeners| {
listeners.iter().map(|entry| entry.listener.get_listener()).collect() listeners.iter().map(|entry| entry.listener.get_listener()).collect()
}) })
} }
pub fn get_listeners_for(&self, type_: &str, desired_phase: ListenerPhase) pub fn get_listeners_for(&self, type_: &str, desired_phase: ListenerPhase)
-> Option<Vec<EventListener>> { -> Option<Vec<EventListener>> {
self.handlers.deref().borrow().find_equiv(&type_).map(|listeners| { self.handlers.borrow().find_equiv(&type_).map(|listeners| {
let filtered = listeners.iter().filter(|entry| entry.phase == desired_phase); let filtered = listeners.iter().filter(|entry| entry.phase == desired_phase);
filtered.map(|entry| entry.listener.get_listener()).collect() filtered.map(|entry| entry.listener.get_listener()).collect()
}) })
@ -122,7 +121,7 @@ impl<'a> EventTargetHelpers for JSRef<'a, EventTarget> {
fn dispatch_event_with_target(self, fn dispatch_event_with_target(self,
target: Option<JSRef<EventTarget>>, target: Option<JSRef<EventTarget>>,
event: JSRef<Event>) -> Fallible<bool> { event: JSRef<Event>) -> Fallible<bool> {
if event.deref().dispatching.deref().get() || !event.deref().initialized.deref().get() { if event.deref().dispatching.get() || !event.deref().initialized.get() {
return Err(InvalidState); return Err(InvalidState);
} }
Ok(dispatch_event(self, target, event)) Ok(dispatch_event(self, target, event))
@ -131,7 +130,7 @@ impl<'a> EventTargetHelpers for JSRef<'a, EventTarget> {
fn set_inline_event_listener(self, fn set_inline_event_listener(self,
ty: DOMString, ty: DOMString,
listener: Option<EventListener>) { listener: Option<EventListener>) {
let mut handlers = self.handlers.deref().borrow_mut(); let mut handlers = self.handlers.borrow_mut();
let entries = handlers.find_or_insert_with(ty, |_| vec!()); let entries = handlers.find_or_insert_with(ty, |_| vec!());
let idx = entries.iter().position(|&entry| { let idx = entries.iter().position(|&entry| {
match entry.listener { match entry.listener {
@ -161,7 +160,7 @@ impl<'a> EventTargetHelpers for JSRef<'a, EventTarget> {
} }
fn get_inline_event_listener(self, ty: DOMString) -> Option<EventListener> { fn get_inline_event_listener(self, ty: DOMString) -> Option<EventListener> {
let handlers = self.handlers.deref().borrow(); let handlers = self.handlers.borrow();
let entries = handlers.find(&ty); let entries = handlers.find(&ty);
entries.and_then(|entries| entries.iter().find(|entry| { entries.and_then(|entries| entries.iter().find(|entry| {
match entry.listener { match entry.listener {
@ -224,7 +223,7 @@ impl<'a> EventTargetHelpers for JSRef<'a, EventTarget> {
} }
fn has_handlers(self) -> bool { fn has_handlers(self) -> bool {
!self.handlers.deref().borrow().is_empty() !self.handlers.borrow().is_empty()
} }
} }
@ -235,7 +234,7 @@ impl<'a> EventTargetMethods for JSRef<'a, EventTarget> {
capture: bool) { capture: bool) {
match listener { match listener {
Some(listener) => { Some(listener) => {
let mut handlers = self.handlers.deref().borrow_mut(); let mut handlers = self.handlers.borrow_mut();
let entry = handlers.find_or_insert_with(ty, |_| vec!()); let entry = handlers.find_or_insert_with(ty, |_| vec!());
let phase = if capture { Capturing } else { Bubbling }; let phase = if capture { Capturing } else { Bubbling };
let new_entry = EventListenerEntry { let new_entry = EventListenerEntry {
@ -256,7 +255,7 @@ impl<'a> EventTargetMethods for JSRef<'a, EventTarget> {
capture: bool) { capture: bool) {
match listener { match listener {
Some(listener) => { Some(listener) => {
let mut handlers = self.handlers.deref().borrow_mut(); let mut handlers = self.handlers.borrow_mut();
let mut entry = handlers.find_mut(&ty); let mut entry = handlers.find_mut(&ty);
for entry in entry.iter_mut() { for entry in entry.iter_mut() {
let phase = if capture { Capturing } else { Bubbling }; let phase = if capture { Capturing } else { Bubbling };

View file

@ -9,7 +9,6 @@ use dom::bindings::codegen::UnionTypes::FileOrString::{FileOrString, eFile, eStr
use dom::bindings::error::{Fallible}; use dom::bindings::error::{Fallible};
use dom::bindings::global::{GlobalRef, GlobalField}; use dom::bindings::global::{GlobalRef, GlobalField};
use dom::bindings::js::{JS, JSRef, Temporary}; use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::blob::Blob; use dom::blob::Blob;
use dom::file::File; use dom::file::File;
@ -29,7 +28,7 @@ pub enum FormDatum {
#[jstraceable] #[jstraceable]
#[must_root] #[must_root]
pub struct FormData { pub struct FormData {
data: Traceable<RefCell<HashMap<DOMString, Vec<FormDatum>>>>, data: RefCell<HashMap<DOMString, Vec<FormDatum>>>,
reflector_: Reflector, reflector_: Reflector,
global: GlobalField, global: GlobalField,
form: Option<JS<HTMLFormElement>> form: Option<JS<HTMLFormElement>>
@ -38,7 +37,7 @@ pub struct FormData {
impl FormData { impl FormData {
fn new_inherited(form: Option<JSRef<HTMLFormElement>>, global: &GlobalRef) -> FormData { fn new_inherited(form: Option<JSRef<HTMLFormElement>>, global: &GlobalRef) -> FormData {
FormData { FormData {
data: Traceable::new(RefCell::new(HashMap::new())), data: RefCell::new(HashMap::new()),
reflector_: Reflector::new(), reflector_: Reflector::new(),
global: GlobalField::from_rooted(global), global: GlobalField::from_rooted(global),
form: form.map(|f| JS::from_rooted(f)), form: form.map(|f| JS::from_rooted(f)),
@ -59,22 +58,22 @@ impl<'a> FormDataMethods for JSRef<'a, FormData> {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
fn Append(self, name: DOMString, value: JSRef<Blob>, filename: Option<DOMString>) { fn Append(self, name: DOMString, value: JSRef<Blob>, filename: Option<DOMString>) {
let file = FileData(JS::from_rooted(self.get_file_from_blob(value, filename))); let file = FileData(JS::from_rooted(self.get_file_from_blob(value, filename)));
self.data.deref().borrow_mut().insert_or_update_with(name.clone(), vec!(file.clone()), self.data.borrow_mut().insert_or_update_with(name.clone(), vec!(file.clone()),
|_k, v| {v.push(file.clone());}); |_k, v| {v.push(file.clone());});
} }
fn Append_(self, name: DOMString, value: DOMString) { fn Append_(self, name: DOMString, value: DOMString) {
self.data.deref().borrow_mut().insert_or_update_with(name, vec!(StringData(value.clone())), self.data.borrow_mut().insert_or_update_with(name, vec!(StringData(value.clone())),
|_k, v| {v.push(StringData(value.clone()));}); |_k, v| {v.push(StringData(value.clone()));});
} }
fn Delete(self, name: DOMString) { fn Delete(self, name: DOMString) {
self.data.deref().borrow_mut().remove(&name); self.data.borrow_mut().remove(&name);
} }
fn Get(self, name: DOMString) -> Option<FileOrString> { fn Get(self, name: DOMString) -> Option<FileOrString> {
if self.data.deref().borrow().contains_key_equiv(&name) { if self.data.borrow().contains_key_equiv(&name) {
match (*self.data.deref().borrow())[name][0].clone() { match (*self.data.borrow())[name][0].clone() {
StringData(ref s) => Some(eString(s.clone())), StringData(ref s) => Some(eString(s.clone())),
FileData(ref f) => { FileData(ref f) => {
Some(eFile(f.clone())) Some(eFile(f.clone()))
@ -86,16 +85,16 @@ impl<'a> FormDataMethods for JSRef<'a, FormData> {
} }
fn Has(self, name: DOMString) -> bool { fn Has(self, name: DOMString) -> bool {
self.data.deref().borrow().contains_key_equiv(&name) self.data.borrow().contains_key_equiv(&name)
} }
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
fn Set(self, name: DOMString, value: JSRef<Blob>, filename: Option<DOMString>) { fn Set(self, name: DOMString, value: JSRef<Blob>, filename: Option<DOMString>) {
let file = FileData(JS::from_rooted(self.get_file_from_blob(value, filename))); let file = FileData(JS::from_rooted(self.get_file_from_blob(value, filename)));
self.data.deref().borrow_mut().insert(name, vec!(file)); self.data.borrow_mut().insert(name, vec!(file));
} }
fn Set_(self, name: DOMString, value: DOMString) { fn Set_(self, name: DOMString, value: DOMString) {
self.data.deref().borrow_mut().insert(name, vec!(StringData(value))); self.data.borrow_mut().insert(name, vec!(StringData(value)));
} }
} }

View file

@ -8,7 +8,6 @@ use dom::bindings::codegen::InheritTypes::HTMLCanvasElementDerived;
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast}; use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast};
use dom::bindings::global::Window; use dom::bindings::global::Window;
use dom::bindings::js::{MutNullableJS, JSRef, Temporary, OptionalSettable}; use dom::bindings::js::{MutNullableJS, JSRef, Temporary, OptionalSettable};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector}; use dom::bindings::utils::{Reflectable, Reflector};
use dom::canvasrenderingcontext2d::CanvasRenderingContext2D; use dom::canvasrenderingcontext2d::CanvasRenderingContext2D;
use dom::document::Document; use dom::document::Document;
@ -33,9 +32,9 @@ static DefaultHeight: u32 = 150;
#[must_root] #[must_root]
pub struct HTMLCanvasElement { pub struct HTMLCanvasElement {
pub htmlelement: HTMLElement, pub htmlelement: HTMLElement,
context: Traceable<MutNullableJS<CanvasRenderingContext2D>>, context: MutNullableJS<CanvasRenderingContext2D>,
width: Traceable<Cell<u32>>, width: Cell<u32>,
height: Traceable<Cell<u32>>, height: Cell<u32>,
} }
impl HTMLCanvasElementDerived for EventTarget { impl HTMLCanvasElementDerived for EventTarget {
@ -48,9 +47,9 @@ impl HTMLCanvasElement {
fn new_inherited(localName: DOMString, document: JSRef<Document>) -> HTMLCanvasElement { fn new_inherited(localName: DOMString, document: JSRef<Document>) -> HTMLCanvasElement {
HTMLCanvasElement { HTMLCanvasElement {
htmlelement: HTMLElement::new_inherited(HTMLCanvasElementTypeId, localName, document), htmlelement: HTMLElement::new_inherited(HTMLCanvasElementTypeId, localName, document),
context: Traceable::new(Default::default()), context: Default::default(),
width: Traceable::new(Cell::new(DefaultWidth)), width: Cell::new(DefaultWidth),
height: Traceable::new(Cell::new(DefaultHeight)), height: Cell::new(DefaultHeight),
} }
} }

View file

@ -8,7 +8,6 @@ use dom::bindings::codegen::Bindings::HTMLIFrameElementBinding::HTMLIFrameElemen
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast}; use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast};
use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLIFrameElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLIFrameElementDerived};
use dom::bindings::js::{JSRef, Temporary, OptionalRootable}; use dom::bindings::js::{JSRef, Temporary, OptionalRootable};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector}; use dom::bindings::utils::{Reflectable, Reflector};
use dom::document::Document; use dom::document::Document;
use dom::element::{HTMLIFrameElementTypeId, Element}; use dom::element::{HTMLIFrameElementTypeId, Element};
@ -44,8 +43,8 @@ enum SandboxAllowance {
#[must_root] #[must_root]
pub struct HTMLIFrameElement { pub struct HTMLIFrameElement {
pub htmlelement: HTMLElement, pub htmlelement: HTMLElement,
pub size: Traceable<Cell<Option<IFrameSize>>>, pub size: Cell<Option<IFrameSize>>,
pub sandbox: Traceable<Cell<Option<u8>>>, pub sandbox: Cell<Option<u8>>,
} }
impl HTMLIFrameElementDerived for EventTarget { impl HTMLIFrameElementDerived for EventTarget {
@ -69,7 +68,7 @@ pub trait HTMLIFrameElementHelpers {
impl<'a> HTMLIFrameElementHelpers for JSRef<'a, HTMLIFrameElement> { impl<'a> HTMLIFrameElementHelpers for JSRef<'a, HTMLIFrameElement> {
fn is_sandboxed(self) -> bool { fn is_sandboxed(self) -> bool {
self.sandbox.deref().get().is_some() self.sandbox.get().is_some()
} }
fn get_url(self) -> Option<Url> { fn get_url(self) -> Option<Url> {
@ -103,12 +102,12 @@ impl<'a> HTMLIFrameElementHelpers for JSRef<'a, HTMLIFrameElement> {
let page = window.deref().page(); let page = window.deref().page();
let subpage_id = page.get_next_subpage_id(); let subpage_id = page.get_next_subpage_id();
self.deref().size.deref().set(Some(IFrameSize { self.deref().size.set(Some(IFrameSize {
pipeline_id: page.id, pipeline_id: page.id,
subpage_id: subpage_id, subpage_id: subpage_id,
})); }));
let ConstellationChan(ref chan) = *page.constellation_chan.deref(); let ConstellationChan(ref chan) = page.constellation_chan;
chan.send(LoadIframeUrlMsg(url, page.id, subpage_id, sandboxed)); chan.send(LoadIframeUrlMsg(url, page.id, subpage_id, sandboxed));
} }
} }
@ -117,8 +116,8 @@ impl HTMLIFrameElement {
fn new_inherited(localName: DOMString, document: JSRef<Document>) -> HTMLIFrameElement { fn new_inherited(localName: DOMString, document: JSRef<Document>) -> HTMLIFrameElement {
HTMLIFrameElement { HTMLIFrameElement {
htmlelement: HTMLElement::new_inherited(HTMLIFrameElementTypeId, localName, document), htmlelement: HTMLElement::new_inherited(HTMLIFrameElementTypeId, localName, document),
size: Traceable::new(Cell::new(None)), size: Cell::new(None),
sandbox: Traceable::new(Cell::new(None)), sandbox: Cell::new(None),
} }
} }
@ -151,14 +150,14 @@ impl<'a> HTMLIFrameElementMethods for JSRef<'a, HTMLIFrameElement> {
} }
fn GetContentWindow(self) -> Option<Temporary<Window>> { fn GetContentWindow(self) -> Option<Temporary<Window>> {
self.size.deref().get().and_then(|size| { self.size.get().and_then(|size| {
let window = window_from_node(self).root(); let window = window_from_node(self).root();
let children = window.deref().page.children.deref().borrow(); let children = window.deref().page.children.borrow();
let child = children.iter().find(|child| { let child = children.iter().find(|child| {
child.subpage_id.unwrap() == size.subpage_id child.subpage_id.unwrap() == size.subpage_id
}); });
child.and_then(|page| { child.and_then(|page| {
page.frame.deref().borrow().as_ref().map(|frame| { page.frame.borrow().as_ref().map(|frame| {
Temporary::new(frame.window.clone()) Temporary::new(frame.window.clone())
}) })
}) })
@ -191,7 +190,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLIFrameElement> {
_ => AllowNothing _ => AllowNothing
} as u8; } as u8;
} }
self.deref().sandbox.deref().set(Some(modes)); self.deref().sandbox.set(Some(modes));
} }
if "src" == name.as_slice() { if "src" == name.as_slice() {
@ -209,7 +208,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLIFrameElement> {
} }
if "sandbox" == name.as_slice() { if "sandbox" == name.as_slice() {
self.deref().sandbox.deref().set(None); self.deref().sandbox.set(None);
} }
} }

View file

@ -7,7 +7,6 @@ use dom::bindings::codegen::Bindings::HTMLImageElementBinding;
use dom::bindings::codegen::Bindings::HTMLImageElementBinding::HTMLImageElementMethods; use dom::bindings::codegen::Bindings::HTMLImageElementBinding::HTMLImageElementMethods;
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast, HTMLElementCast, HTMLImageElementDerived}; use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast, HTMLElementCast, HTMLImageElementDerived};
use dom::bindings::js::{JS, JSRef, Temporary}; use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::trace::Untraceable;
use dom::bindings::utils::{Reflectable, Reflector}; use dom::bindings::utils::{Reflectable, Reflector};
use dom::document::Document; use dom::document::Document;
use dom::element::{Element, HTMLImageElementTypeId}; use dom::element::{Element, HTMLImageElementTypeId};
@ -29,7 +28,7 @@ use std::cell::RefCell;
#[must_root] #[must_root]
pub struct HTMLImageElement { pub struct HTMLImageElement {
pub htmlelement: HTMLElement, pub htmlelement: HTMLElement,
image: Untraceable<RefCell<Option<Url>>>, image: RefCell<Option<Url>>,
} }
impl HTMLImageElementDerived for EventTarget { impl HTMLImageElementDerived for EventTarget {
@ -52,13 +51,13 @@ impl<'a> PrivateHTMLImageElementHelpers for JSRef<'a, HTMLImageElement> {
let image_cache = &window.image_cache_task; let image_cache = &window.image_cache_task;
match value { match value {
None => { None => {
*self.image.deref().borrow_mut() = None; *self.image.borrow_mut() = None;
} }
Some((src, base_url)) => { Some((src, base_url)) => {
let img_url = UrlParser::new().base_url(base_url).parse(src.as_slice()); let img_url = UrlParser::new().base_url(base_url).parse(src.as_slice());
// FIXME: handle URL parse errors more gracefully. // FIXME: handle URL parse errors more gracefully.
let img_url = img_url.unwrap(); let img_url = img_url.unwrap();
*self.image.deref().borrow_mut() = Some(img_url.clone()); *self.image.borrow_mut() = Some(img_url.clone());
// inform the image cache to load this, but don't store a // inform the image cache to load this, but don't store a
// handle. // handle.
@ -75,7 +74,7 @@ impl HTMLImageElement {
fn new_inherited(localName: DOMString, document: JSRef<Document>) -> HTMLImageElement { fn new_inherited(localName: DOMString, document: JSRef<Document>) -> HTMLImageElement {
HTMLImageElement { HTMLImageElement {
htmlelement: HTMLElement::new_inherited(HTMLImageElementTypeId, localName, document), htmlelement: HTMLElement::new_inherited(HTMLImageElementTypeId, localName, document),
image: Untraceable::new(RefCell::new(None)), image: RefCell::new(None),
} }
} }

View file

@ -118,7 +118,7 @@ impl<'a> PrivateHTMLLinkElementHelpers for JSRef<'a, HTMLLinkElement> {
let window = window_from_node(self).root(); let window = window_from_node(self).root();
match UrlParser::new().base_url(&window.deref().page().get_url()).parse(href) { match UrlParser::new().base_url(&window.deref().page().get_url()).parse(href) {
Ok(url) => { Ok(url) => {
let LayoutChan(ref layout_chan) = *window.deref().page().layout_chan; let LayoutChan(ref layout_chan) = window.deref().page().layout_chan;
layout_chan.send(LoadStylesheetMsg(url)); layout_chan.send(LoadStylesheetMsg(url));
} }
Err(e) => debug!("Parsing url {:s} failed: {:?}", href, e) Err(e) => debug!("Parsing url {:s} failed: {:?}", href, e)

View file

@ -69,7 +69,7 @@ pub fn serialize(iterator: &mut NodeIterator) -> String {
fn serialize_comment(comment: JSRef<Comment>, html: &mut String) { fn serialize_comment(comment: JSRef<Comment>, html: &mut String) {
html.push_str("<!--"); html.push_str("<!--");
html.push_str(comment.deref().characterdata.data.deref().borrow().as_slice()); html.push_str(comment.deref().characterdata.data.borrow().as_slice());
html.push_str("-->"); html.push_str("-->");
} }
@ -82,11 +82,11 @@ fn serialize_text(text: JSRef<Text>, html: &mut String) {
"style" | "script" | "xmp" | "iframe" | "style" | "script" | "xmp" | "iframe" |
"noembed" | "noframes" | "plaintext" | "noembed" | "noframes" | "plaintext" |
"noscript" if elem.deref().namespace == ns!(HTML) "noscript" if elem.deref().namespace == ns!(HTML)
=> html.push_str(text.deref().characterdata.data.deref().borrow().as_slice()), => html.push_str(text.deref().characterdata.data.borrow().as_slice()),
_ => escape(text.deref().characterdata.data.deref().borrow().as_slice(), false, html) _ => escape(text.deref().characterdata.data.borrow().as_slice(), false, html)
} }
} }
_ => escape(text.deref().characterdata.data.deref().borrow().as_slice(), false, html) _ => escape(text.deref().characterdata.data.borrow().as_slice(), false, html)
} }
} }
@ -95,7 +95,7 @@ fn serialize_processing_instruction(processing_instruction: JSRef<ProcessingInst
html.push_str("<?"); html.push_str("<?");
html.push_str(processing_instruction.deref().target.as_slice()); html.push_str(processing_instruction.deref().target.as_slice());
html.push_char(' '); html.push_char(' ');
html.push_str(processing_instruction.deref().characterdata.data.deref().borrow().as_slice()); html.push_str(processing_instruction.deref().characterdata.data.borrow().as_slice());
html.push_str("?>"); html.push_str("?>");
} }
@ -120,7 +120,7 @@ fn serialize_elem(elem: JSRef<Element>, open_elements: &mut Vec<String>, html: &
match node.first_child().map(|child| child.root()) { match node.first_child().map(|child| child.root()) {
Some(ref child) if child.is_text() => { Some(ref child) if child.is_text() => {
let text: JSRef<CharacterData> = CharacterDataCast::to_ref(**child).unwrap(); let text: JSRef<CharacterData> = CharacterDataCast::to_ref(**child).unwrap();
if text.deref().data.deref().borrow().len() > 0 && text.deref().data.deref().borrow().as_slice().char_at(0) == '\n' { if text.deref().data.borrow().len() > 0 && text.deref().data.borrow().as_slice().char_at(0) == '\n' {
html.push_char('\x0A'); html.push_char('\x0A');
} }
}, },

View file

@ -57,7 +57,7 @@ impl<'a> StyleElementHelpers for JSRef<'a, HTMLStyleElement> {
let data = node.GetTextContent().expect("Element.textContent must be a string"); let data = node.GetTextContent().expect("Element.textContent must be a string");
let sheet = Stylesheet::from_str(data.as_slice(), url); let sheet = Stylesheet::from_str(data.as_slice(), url);
let LayoutChan(ref layout_chan) = *win.deref().page().layout_chan; let LayoutChan(ref layout_chan) = win.deref().page().layout_chan;
layout_chan.send(AddStylesheetMsg(sheet)); layout_chan.send(AddStylesheetMsg(sheet));
} }
} }

View file

@ -9,7 +9,6 @@ use dom::bindings::codegen::InheritTypes::{EventCast, MessageEventDerived};
use dom::bindings::error::Fallible; use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::event::{Event, MessageEventTypeId}; use dom::event::{Event, MessageEventTypeId};
use dom::eventtarget::{EventTarget, EventTargetHelpers}; use dom::eventtarget::{EventTarget, EventTargetHelpers};
@ -23,7 +22,7 @@ use js::jsval::JSVal;
#[must_root] #[must_root]
pub struct MessageEvent { pub struct MessageEvent {
event: Event, event: Event,
data: Traceable<JSVal>, data: JSVal,
origin: DOMString, origin: DOMString,
lastEventId: DOMString, lastEventId: DOMString,
} }
@ -39,7 +38,7 @@ impl MessageEvent {
-> MessageEvent { -> MessageEvent {
MessageEvent { MessageEvent {
event: Event::new_inherited(MessageEventTypeId), event: Event::new_inherited(MessageEventTypeId),
data: Traceable::new(data), data: data,
origin: origin, origin: origin,
lastEventId: lastEventId, lastEventId: lastEventId,
} }
@ -81,7 +80,7 @@ impl MessageEvent {
impl<'a> MessageEventMethods for JSRef<'a, MessageEvent> { impl<'a> MessageEventMethods for JSRef<'a, MessageEvent> {
fn Data(self, _cx: *mut JSContext) -> JSVal { fn Data(self, _cx: *mut JSContext) -> JSVal {
*self.data self.data
} }
fn Origin(self) -> DOMString { fn Origin(self) -> DOMString {

View file

@ -10,7 +10,6 @@ use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::global; use dom::bindings::global;
use dom::bindings::js::{MutNullableJS, JSRef, RootedReference, Temporary, OptionalSettable}; use dom::bindings::js::{MutNullableJS, JSRef, RootedReference, Temporary, OptionalSettable};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::event::{Event, MouseEventTypeId}; use dom::event::{Event, MouseEventTypeId};
use dom::eventtarget::EventTarget; use dom::eventtarget::EventTarget;
@ -24,15 +23,15 @@ use std::default::Default;
#[must_root] #[must_root]
pub struct MouseEvent { pub struct MouseEvent {
pub mouseevent: UIEvent, pub mouseevent: UIEvent,
pub screen_x: Traceable<Cell<i32>>, pub screen_x: Cell<i32>,
pub screen_y: Traceable<Cell<i32>>, pub screen_y: Cell<i32>,
pub client_x: Traceable<Cell<i32>>, pub client_x: Cell<i32>,
pub client_y: Traceable<Cell<i32>>, pub client_y: Cell<i32>,
pub ctrl_key: Traceable<Cell<bool>>, pub ctrl_key: Cell<bool>,
pub shift_key: Traceable<Cell<bool>>, pub shift_key: Cell<bool>,
pub alt_key: Traceable<Cell<bool>>, pub alt_key: Cell<bool>,
pub meta_key: Traceable<Cell<bool>>, pub meta_key: Cell<bool>,
pub button: Traceable<Cell<i16>>, pub button: Cell<i16>,
pub related_target: MutNullableJS<EventTarget> pub related_target: MutNullableJS<EventTarget>
} }
@ -46,15 +45,15 @@ impl MouseEvent {
fn new_inherited() -> MouseEvent { fn new_inherited() -> MouseEvent {
MouseEvent { MouseEvent {
mouseevent: UIEvent::new_inherited(MouseEventTypeId), mouseevent: UIEvent::new_inherited(MouseEventTypeId),
screen_x: Traceable::new(Cell::new(0)), screen_x: Cell::new(0),
screen_y: Traceable::new(Cell::new(0)), screen_y: Cell::new(0),
client_x: Traceable::new(Cell::new(0)), client_x: Cell::new(0),
client_y: Traceable::new(Cell::new(0)), client_y: Cell::new(0),
ctrl_key: Traceable::new(Cell::new(false)), ctrl_key: Cell::new(false),
shift_key: Traceable::new(Cell::new(false)), shift_key: Cell::new(false),
alt_key: Traceable::new(Cell::new(false)), alt_key: Cell::new(false),
meta_key: Traceable::new(Cell::new(false)), meta_key: Cell::new(false),
button: Traceable::new(Cell::new(0)), button: Cell::new(0),
related_target: Default::default(), related_target: Default::default(),
} }
} }
@ -82,7 +81,7 @@ impl MouseEvent {
button: i16, button: i16,
relatedTarget: Option<JSRef<EventTarget>>) -> Temporary<MouseEvent> { relatedTarget: Option<JSRef<EventTarget>>) -> Temporary<MouseEvent> {
let ev = MouseEvent::new_uninitialized(window).root(); let ev = MouseEvent::new_uninitialized(window).root();
ev.deref().InitMouseEvent(type_, canBubble, cancelable, view, detail, ev.InitMouseEvent(type_, canBubble, cancelable, view, detail,
screenX, screenY, clientX, clientY, screenX, screenY, clientX, clientY,
ctrlKey, altKey, shiftKey, metaKey, ctrlKey, altKey, shiftKey, metaKey,
button, relatedTarget); button, relatedTarget);
@ -107,39 +106,39 @@ impl MouseEvent {
impl<'a> MouseEventMethods for JSRef<'a, MouseEvent> { impl<'a> MouseEventMethods for JSRef<'a, MouseEvent> {
fn ScreenX(self) -> i32 { fn ScreenX(self) -> i32 {
self.screen_x.deref().get() self.screen_x.get()
} }
fn ScreenY(self) -> i32 { fn ScreenY(self) -> i32 {
self.screen_y.deref().get() self.screen_y.get()
} }
fn ClientX(self) -> i32 { fn ClientX(self) -> i32 {
self.client_x.deref().get() self.client_x.get()
} }
fn ClientY(self) -> i32 { fn ClientY(self) -> i32 {
self.client_y.deref().get() self.client_y.get()
} }
fn CtrlKey(self) -> bool { fn CtrlKey(self) -> bool {
self.ctrl_key.deref().get() self.ctrl_key.get()
} }
fn ShiftKey(self) -> bool { fn ShiftKey(self) -> bool {
self.shift_key.deref().get() self.shift_key.get()
} }
fn AltKey(self) -> bool { fn AltKey(self) -> bool {
self.alt_key.deref().get() self.alt_key.get()
} }
fn MetaKey(self) -> bool { fn MetaKey(self) -> bool {
self.meta_key.deref().get() self.meta_key.get()
} }
fn Button(self) -> i16 { fn Button(self) -> i16 {
self.button.deref().get() self.button.get()
} }
fn GetRelatedTarget(self) -> Option<Temporary<EventTarget>> { fn GetRelatedTarget(self) -> Option<Temporary<EventTarget>> {
@ -164,15 +163,15 @@ impl<'a> MouseEventMethods for JSRef<'a, MouseEvent> {
relatedTargetArg: Option<JSRef<EventTarget>>) { relatedTargetArg: Option<JSRef<EventTarget>>) {
let uievent: JSRef<UIEvent> = UIEventCast::from_ref(self); let uievent: JSRef<UIEvent> = UIEventCast::from_ref(self);
uievent.InitUIEvent(typeArg, canBubbleArg, cancelableArg, viewArg, detailArg); uievent.InitUIEvent(typeArg, canBubbleArg, cancelableArg, viewArg, detailArg);
self.screen_x.deref().set(screenXArg); self.screen_x.set(screenXArg);
self.screen_y.deref().set(screenYArg); self.screen_y.set(screenYArg);
self.client_x.deref().set(clientXArg); self.client_x.set(clientXArg);
self.client_y.deref().set(clientYArg); self.client_y.set(clientYArg);
self.ctrl_key.deref().set(ctrlKeyArg); self.ctrl_key.set(ctrlKeyArg);
self.alt_key.deref().set(altKeyArg); self.alt_key.set(altKeyArg);
self.shift_key.deref().set(shiftKeyArg); self.shift_key.set(shiftKeyArg);
self.meta_key.deref().set(metaKeyArg); self.meta_key.set(metaKeyArg);
self.button.deref().set(buttonArg); self.button.set(buttonArg);
self.related_target.assign(relatedTargetArg); self.related_target.assign(relatedTargetArg);
} }
} }

View file

@ -25,7 +25,7 @@ use dom::bindings::global;
use dom::bindings::js::{JS, JSRef, RootedReference, Temporary, Root}; use dom::bindings::js::{JS, JSRef, RootedReference, Temporary, Root};
use dom::bindings::js::{OptionalSettable, TemporaryPushable, OptionalRootedRootable}; use dom::bindings::js::{OptionalSettable, TemporaryPushable, OptionalRootedRootable};
use dom::bindings::js::{ResultRootable, OptionalRootable, MutNullableJS}; use dom::bindings::js::{ResultRootable, OptionalRootable, MutNullableJS};
use dom::bindings::trace::{Traceable, Untraceable}; use dom::bindings::trace::JSTraceable;
use dom::bindings::utils; use dom::bindings::utils;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::characterdata::CharacterData; use dom::characterdata::CharacterData;
@ -53,7 +53,7 @@ use servo_util::geometry::Au;
use servo_util::str::{DOMString, null_str_as_empty}; use servo_util::str::{DOMString, null_str_as_empty};
use style::{parse_selector_list_from_str, matches}; use style::{parse_selector_list_from_str, matches};
use js::jsapi::{JSContext, JSObject, JSRuntime}; use js::jsapi::{JSContext, JSObject, JSTracer, JSRuntime};
use js::jsfriendapi; use js::jsfriendapi;
use libc; use libc;
use libc::uintptr_t; use libc::uintptr_t;
@ -102,13 +102,13 @@ pub struct Node {
child_list: MutNullableJS<NodeList>, child_list: MutNullableJS<NodeList>,
/// A bitfield of flags for node items. /// A bitfield of flags for node items.
flags: Traceable<RefCell<NodeFlags>>, flags: RefCell<NodeFlags>,
/// Layout information. Only the layout task may touch this data. /// Layout information. Only the layout task may touch this data.
/// ///
/// Must be sent back to the layout task to be destroyed when this /// Must be sent back to the layout task to be destroyed when this
/// node is finalized. /// node is finalized.
pub layout_data: Untraceable<LayoutDataRef>, pub layout_data: LayoutDataRef,
unique_id: RefCell<String>, unique_id: RefCell<String>,
} }
@ -189,6 +189,8 @@ pub struct LayoutDataRef {
pub data_cell: RefCell<Option<LayoutData>>, pub data_cell: RefCell<Option<LayoutData>>,
} }
untraceable!(LayoutDataRef)
impl LayoutDataRef { impl LayoutDataRef {
pub fn new() -> LayoutDataRef { pub fn new() -> LayoutDataRef {
LayoutDataRef { LayoutDataRef {
@ -453,7 +455,7 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
} }
fn is_in_doc(self) -> bool { fn is_in_doc(self) -> bool {
self.deref().flags.deref().borrow().contains(IsInDoc) self.deref().flags.borrow().contains(IsInDoc)
} }
/// Returns the type ID of this node. Fails if this node is borrowed mutably. /// Returns the type ID of this node. Fails if this node is borrowed mutably.
@ -512,38 +514,38 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
} }
fn get_hover_state(self) -> bool { fn get_hover_state(self) -> bool {
self.flags.deref().borrow().contains(InHoverState) self.flags.borrow().contains(InHoverState)
} }
fn set_hover_state(self, state: bool) { fn set_hover_state(self, state: bool) {
if state { if state {
self.flags.deref().borrow_mut().insert(InHoverState); self.flags.borrow_mut().insert(InHoverState);
} else { } else {
self.flags.deref().borrow_mut().remove(InHoverState); self.flags.borrow_mut().remove(InHoverState);
} }
} }
fn get_disabled_state(self) -> bool { fn get_disabled_state(self) -> bool {
self.flags.deref().borrow().contains(InDisabledState) self.flags.borrow().contains(InDisabledState)
} }
fn set_disabled_state(self, state: bool) { fn set_disabled_state(self, state: bool) {
if state { if state {
self.flags.deref().borrow_mut().insert(InDisabledState); self.flags.borrow_mut().insert(InDisabledState);
} else { } else {
self.flags.deref().borrow_mut().remove(InDisabledState); self.flags.borrow_mut().remove(InDisabledState);
} }
} }
fn get_enabled_state(self) -> bool { fn get_enabled_state(self) -> bool {
self.flags.deref().borrow().contains(InEnabledState) self.flags.borrow().contains(InEnabledState)
} }
fn set_enabled_state(self, state: bool) { fn set_enabled_state(self, state: bool) {
if state { if state {
self.flags.deref().borrow_mut().insert(InEnabledState); self.flags.borrow_mut().insert(InEnabledState);
} else { } else {
self.flags.deref().borrow_mut().remove(InEnabledState); self.flags.borrow_mut().remove(InEnabledState);
} }
} }
@ -1034,9 +1036,9 @@ impl Node {
owner_doc: MutNullableJS::new(doc), owner_doc: MutNullableJS::new(doc),
child_list: Default::default(), child_list: Default::default(),
flags: Traceable::new(RefCell::new(NodeFlags::new(type_id))), flags: RefCell::new(NodeFlags::new(type_id)),
layout_data: Untraceable::new(LayoutDataRef::new()), layout_data: LayoutDataRef::new(),
unique_id: RefCell::new("".to_string()), unique_id: RefCell::new("".to_string()),
} }
@ -1236,9 +1238,9 @@ impl Node {
let is_in_doc = parent.is_in_doc(); let is_in_doc = parent.is_in_doc();
for kid in node.traverse_preorder() { for kid in node.traverse_preorder() {
if is_in_doc { if is_in_doc {
kid.flags.deref().borrow_mut().insert(IsInDoc); kid.flags.borrow_mut().insert(IsInDoc);
} else { } else {
kid.flags.deref().borrow_mut().remove(IsInDoc); kid.flags.borrow_mut().remove(IsInDoc);
} }
} }
} }
@ -1325,7 +1327,7 @@ impl Node {
// Step 8. // Step 8.
parent.remove_child(node); parent.remove_child(node);
node.deref().flags.deref().borrow_mut().remove(IsInDoc); node.deref().flags.borrow_mut().remove(IsInDoc);
// Step 9. // Step 9.
match suppress_observers { match suppress_observers {
@ -1362,7 +1364,7 @@ impl Node {
CommentNodeTypeId => { CommentNodeTypeId => {
let comment: JSRef<Comment> = CommentCast::to_ref(node).unwrap(); let comment: JSRef<Comment> = CommentCast::to_ref(node).unwrap();
let comment = comment.deref(); let comment = comment.deref();
let comment = Comment::new(comment.characterdata.data.deref().borrow().clone(), *document); let comment = Comment::new(comment.characterdata.data.borrow().clone(), *document);
NodeCast::from_temporary(comment) NodeCast::from_temporary(comment)
}, },
DocumentNodeTypeId => { DocumentNodeTypeId => {
@ -1386,14 +1388,14 @@ impl Node {
TextNodeTypeId => { TextNodeTypeId => {
let text: JSRef<Text> = TextCast::to_ref(node).unwrap(); let text: JSRef<Text> = TextCast::to_ref(node).unwrap();
let text = text.deref(); let text = text.deref();
let text = Text::new(text.characterdata.data.deref().borrow().clone(), *document); let text = Text::new(text.characterdata.data.borrow().clone(), *document);
NodeCast::from_temporary(text) NodeCast::from_temporary(text)
}, },
ProcessingInstructionNodeTypeId => { ProcessingInstructionNodeTypeId => {
let pi: JSRef<ProcessingInstruction> = ProcessingInstructionCast::to_ref(node).unwrap(); let pi: JSRef<ProcessingInstruction> = ProcessingInstructionCast::to_ref(node).unwrap();
let pi = pi.deref(); let pi = pi.deref();
let pi = ProcessingInstruction::new(pi.target.clone(), let pi = ProcessingInstruction::new(pi.target.clone(),
pi.characterdata.data.deref().borrow().clone(), *document); pi.characterdata.data.borrow().clone(), *document);
NodeCast::from_temporary(pi) NodeCast::from_temporary(pi)
}, },
}.root(); }.root();
@ -1412,7 +1414,7 @@ impl Node {
DocumentNodeTypeId => { DocumentNodeTypeId => {
let node_doc: JSRef<Document> = DocumentCast::to_ref(node).unwrap(); let node_doc: JSRef<Document> = DocumentCast::to_ref(node).unwrap();
let copy_doc: JSRef<Document> = DocumentCast::to_ref(*copy).unwrap(); let copy_doc: JSRef<Document> = DocumentCast::to_ref(*copy).unwrap();
copy_doc.set_encoding_name(node_doc.encoding_name.deref().borrow().clone()); copy_doc.set_encoding_name(node_doc.encoding_name.borrow().clone());
copy_doc.set_quirks_mode(node_doc.quirks_mode()); copy_doc.set_quirks_mode(node_doc.quirks_mode());
}, },
ElementNodeTypeId(..) => { ElementNodeTypeId(..) => {
@ -1449,7 +1451,7 @@ impl Node {
/// Sends layout data, if any, back to the layout task to be destroyed. /// Sends layout data, if any, back to the layout task to be destroyed.
unsafe fn reap_layout_data(&mut self) { unsafe fn reap_layout_data(&mut self) {
if self.layout_data.is_present() { if self.layout_data.is_present() {
let layout_data = mem::replace(self.layout_data.deref_mut(), LayoutDataRef::new()); let layout_data = mem::replace(&mut self.layout_data, LayoutDataRef::new());
let layout_chan = layout_data.take_chan(); let layout_chan = layout_data.take_chan();
match layout_chan { match layout_chan {
None => {} None => {}
@ -1660,7 +1662,7 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
self.wait_until_safe_to_modify_dom(); self.wait_until_safe_to_modify_dom();
let characterdata: JSRef<CharacterData> = CharacterDataCast::to_ref(self).unwrap(); let characterdata: JSRef<CharacterData> = CharacterDataCast::to_ref(self).unwrap();
*characterdata.data.deref().borrow_mut() = value; *characterdata.data.borrow_mut() = value;
// Notify the document that the content of this node is different // Notify the document that the content of this node is different
let document = self.owner_doc().root(); let document = self.owner_doc().root();
@ -1873,12 +1875,12 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
let pi: JSRef<ProcessingInstruction> = ProcessingInstructionCast::to_ref(node).unwrap(); let pi: JSRef<ProcessingInstruction> = ProcessingInstructionCast::to_ref(node).unwrap();
let other_pi: JSRef<ProcessingInstruction> = ProcessingInstructionCast::to_ref(other).unwrap(); let other_pi: JSRef<ProcessingInstruction> = ProcessingInstructionCast::to_ref(other).unwrap();
(pi.deref().target == other_pi.deref().target) && (pi.deref().target == other_pi.deref().target) &&
(*pi.deref().characterdata.data.deref().borrow() == *other_pi.deref().characterdata.data.deref().borrow()) (*pi.deref().characterdata.data.borrow() == *other_pi.deref().characterdata.data.borrow())
} }
fn is_equal_characterdata(node: JSRef<Node>, other: JSRef<Node>) -> bool { fn is_equal_characterdata(node: JSRef<Node>, other: JSRef<Node>) -> bool {
let characterdata: JSRef<CharacterData> = CharacterDataCast::to_ref(node).unwrap(); let characterdata: JSRef<CharacterData> = CharacterDataCast::to_ref(node).unwrap();
let other_characterdata: JSRef<CharacterData> = CharacterDataCast::to_ref(other).unwrap(); let other_characterdata: JSRef<CharacterData> = CharacterDataCast::to_ref(other).unwrap();
*characterdata.deref().data.deref().borrow() == *other_characterdata.deref().data.deref().borrow() *characterdata.deref().data.borrow() == *other_characterdata.deref().data.borrow()
} }
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();

View file

@ -14,7 +14,6 @@ use dom::bindings::codegen::Bindings::NodeFilterBinding::NodeFilter;
use dom::bindings::error::{ErrorResult, Fallible}; use dom::bindings::error::{ErrorResult, Fallible};
use dom::bindings::global::Window; use dom::bindings::global::Window;
use dom::bindings::js::{JS, JSRef, OptionalRootable, Temporary}; use dom::bindings::js::{JS, JSRef, OptionalRootable, Temporary};
use dom::bindings::trace::Untraceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::document::Document; use dom::document::Document;
use dom::node::{Node, NodeHelpers}; use dom::node::{Node, NodeHelpers};
@ -334,7 +333,7 @@ impl<'a> PrivateTreeWalkerHelpers<'a> for JSRef<'a, TreeWalker> {
// "6. Return result." // "6. Return result."
match self.filter { match self.filter {
FilterNone => Ok(NodeFilterConstants::FILTER_ACCEPT), FilterNone => Ok(NodeFilterConstants::FILTER_ACCEPT),
FilterNative(f) => Ok((*f)(node)), FilterNative(f) => Ok((f)(node)),
FilterJS(callback) => callback.AcceptNode_(self, node, RethrowExceptions) FilterJS(callback) => callback.AcceptNode_(self, node, RethrowExceptions)
} }
} }
@ -554,7 +553,7 @@ impl<'a> Iterator<JSRef<'a, Node>> for JSRef<'a, TreeWalker> {
#[jstraceable] #[jstraceable]
pub enum Filter { pub enum Filter {
FilterNone, FilterNone,
FilterNative(Untraceable<fn (node: JSRef<Node>) -> u16>), FilterNative(fn (node: JSRef<Node>) -> u16),
FilterJS(NodeFilter) FilterJS(NodeFilter)
} }

View file

@ -10,7 +10,7 @@ use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::global; use dom::bindings::global;
use dom::bindings::js::{MutNullableJS, JSRef, RootedReference, Temporary, OptionalSettable}; use dom::bindings::js::{MutNullableJS, JSRef, RootedReference, Temporary, OptionalSettable};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::event::{Event, EventTypeId, UIEventTypeId}; use dom::event::{Event, EventTypeId, UIEventTypeId};
use dom::window::Window; use dom::window::Window;
@ -24,7 +24,7 @@ use std::default::Default;
pub struct UIEvent { pub struct UIEvent {
pub event: Event, pub event: Event,
view: MutNullableJS<Window>, view: MutNullableJS<Window>,
detail: Traceable<Cell<i32>> detail: Cell<i32>
} }
impl UIEventDerived for Event { impl UIEventDerived for Event {
@ -38,7 +38,7 @@ impl UIEvent {
UIEvent { UIEvent {
event: Event::new_inherited(type_id), event: Event::new_inherited(type_id),
view: Default::default(), view: Default::default(),
detail: Traceable::new(Cell::new(0)), detail: Cell::new(0),
} }
} }
@ -75,7 +75,7 @@ impl<'a> UIEventMethods for JSRef<'a, UIEvent> {
} }
fn Detail(self) -> i32 { fn Detail(self) -> i32 {
self.detail.deref().get() self.detail.get()
} }
fn InitUIEvent(self, fn InitUIEvent(self,
@ -87,7 +87,7 @@ impl<'a> UIEventMethods for JSRef<'a, UIEvent> {
let event: JSRef<Event> = EventCast::from_ref(self); let event: JSRef<Event> = EventCast::from_ref(self);
event.InitEvent(type_, can_bubble, cancelable); event.InitEvent(type_, can_bubble, cancelable);
self.view.assign(view); self.view.assign(view);
self.detail.deref().set(detail); self.detail.set(detail);
} }
} }

View file

@ -8,7 +8,6 @@ use dom::bindings::codegen::UnionTypes::StringOrURLSearchParams::{StringOrURLSea
use dom::bindings::error::{Fallible}; use dom::bindings::error::{Fallible};
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use servo_util::str::DOMString; use servo_util::str::DOMString;
@ -24,14 +23,14 @@ use std::ascii::OwnedStrAsciiExt;
#[jstraceable] #[jstraceable]
#[must_root] #[must_root]
pub struct URLSearchParams { pub struct URLSearchParams {
data: Traceable<RefCell<HashMap<DOMString, Vec<DOMString>>>>, data: RefCell<HashMap<DOMString, Vec<DOMString>>>,
reflector_: Reflector, reflector_: Reflector,
} }
impl URLSearchParams { impl URLSearchParams {
fn new_inherited() -> URLSearchParams { fn new_inherited() -> URLSearchParams {
URLSearchParams { URLSearchParams {
data: Traceable::new(RefCell::new(HashMap::new())), data: RefCell::new(HashMap::new()),
reflector_: Reflector::new(), reflector_: Reflector::new(),
} }
} }
@ -51,8 +50,8 @@ impl URLSearchParams {
}, },
Some(eURLSearchParams(u)) => { Some(eURLSearchParams(u)) => {
let u = u.root(); let u = u.root();
let mut map = usp.deref().data.deref().borrow_mut(); let mut map = usp.deref().data.borrow_mut();
*map = u.data.deref().borrow().clone(); *map = u.data.borrow().clone();
}, },
None => {} None => {}
} }
@ -62,26 +61,26 @@ impl URLSearchParams {
impl<'a> URLSearchParamsMethods for JSRef<'a, URLSearchParams> { impl<'a> URLSearchParamsMethods for JSRef<'a, URLSearchParams> {
fn Append(self, name: DOMString, value: DOMString) { fn Append(self, name: DOMString, value: DOMString) {
self.data.deref().borrow_mut().insert_or_update_with(name, vec!(value.clone()), self.data.borrow_mut().insert_or_update_with(name, vec!(value.clone()),
|_k, v| v.push(value.clone())); |_k, v| v.push(value.clone()));
self.update_steps(); self.update_steps();
} }
fn Delete(self, name: DOMString) { fn Delete(self, name: DOMString) {
self.data.deref().borrow_mut().remove(&name); self.data.borrow_mut().remove(&name);
self.update_steps(); self.update_steps();
} }
fn Get(self, name: DOMString) -> Option<DOMString> { fn Get(self, name: DOMString) -> Option<DOMString> {
self.data.deref().borrow().find_equiv(&name).map(|v| v[0].clone()) self.data.borrow().find_equiv(&name).map(|v| v[0].clone())
} }
fn Has(self, name: DOMString) -> bool { fn Has(self, name: DOMString) -> bool {
self.data.deref().borrow().contains_key_equiv(&name) self.data.borrow().contains_key_equiv(&name)
} }
fn Set(self, name: DOMString, value: DOMString) { fn Set(self, name: DOMString, value: DOMString) {
self.data.deref().borrow_mut().insert(name, vec!(value)); self.data.borrow_mut().insert(name, vec!(value));
self.update_steps(); self.update_steps();
} }
} }
@ -129,7 +128,7 @@ impl URLSearchParamsHelpers for URLSearchParams {
let encoding = encoding.unwrap_or(UTF_8 as EncodingRef); let encoding = encoding.unwrap_or(UTF_8 as EncodingRef);
let mut buf = vec!(); let mut buf = vec!();
let mut first_pair = true; let mut first_pair = true;
for (k, v) in self.data.deref().borrow().iter() { for (k, v) in self.data.borrow().iter() {
let name = serialize_string(k, encoding); let name = serialize_string(k, encoding);
for val in v.iter() { for val in v.iter() {
let value = serialize_string(val, encoding); let value = serialize_string(val, encoding);

View file

@ -9,7 +9,6 @@ use dom::bindings::codegen::InheritTypes::EventTargetCast;
use dom::bindings::error::{Fallible, InvalidCharacter}; use dom::bindings::error::{Fallible, InvalidCharacter};
use dom::bindings::global; use dom::bindings::global;
use dom::bindings::js::{MutNullableJS, JSRef, Temporary, OptionalSettable}; use dom::bindings::js::{MutNullableJS, JSRef, Temporary, OptionalSettable};
use dom::bindings::trace::{Traceable, Untraceable};
use dom::bindings::utils::{Reflectable, Reflector}; use dom::bindings::utils::{Reflectable, Reflector};
use dom::browsercontext::BrowserContext; use dom::browsercontext::BrowserContext;
use dom::console::Console; use dom::console::Console;
@ -60,7 +59,7 @@ pub struct TimerId(i32);
pub struct TimerHandle { pub struct TimerHandle {
handle: TimerId, handle: TimerId,
pub data: TimerData, pub data: TimerData,
cancel_chan: Untraceable<Option<Sender<()>>>, cancel_chan: Option<Sender<()>>,
} }
impl Hash for TimerId { impl Hash for TimerId {
@ -86,10 +85,10 @@ pub struct Window {
location: MutNullableJS<Location>, location: MutNullableJS<Location>,
navigator: MutNullableJS<Navigator>, navigator: MutNullableJS<Navigator>,
pub image_cache_task: ImageCacheTask, pub image_cache_task: ImageCacheTask,
pub active_timers: Traceable<RefCell<HashMap<TimerId, TimerHandle>>>, pub active_timers: RefCell<HashMap<TimerId, TimerHandle>>,
next_timer_handle: Traceable<Cell<i32>>, next_timer_handle: Cell<i32>,
pub compositor: Untraceable<Box<ScriptListener+'static>>, pub compositor: Box<ScriptListener+'static>,
pub browser_context: Traceable<RefCell<Option<BrowserContext>>>, pub browser_context: RefCell<Option<BrowserContext>>,
pub page: Rc<Page>, pub page: Rc<Page>,
performance: MutNullableJS<Performance>, performance: MutNullableJS<Performance>,
pub navigationStart: u64, pub navigationStart: u64,
@ -100,7 +99,7 @@ pub struct Window {
impl Window { impl Window {
pub fn get_cx(&self) -> *mut JSContext { pub fn get_cx(&self) -> *mut JSContext {
let js_info = self.page().js_info(); let js_info = self.page().js_info();
(**js_info.as_ref().unwrap().js_context).ptr (*js_info.as_ref().unwrap().js_context).ptr
} }
pub fn page<'a>(&'a self) -> &'a Page { pub fn page<'a>(&'a self) -> &'a Page {
@ -126,7 +125,7 @@ impl Drop for Window {
#[jstraceable] #[jstraceable]
pub struct TimerData { pub struct TimerData {
pub is_interval: bool, pub is_interval: bool,
pub funval: Traceable<JSVal>, pub funval: JSVal,
} }
// http://www.whatwg.org/html/#atob // http://www.whatwg.org/html/#atob
@ -250,7 +249,7 @@ impl<'a> WindowMethods for JSRef<'a, Window> {
} }
fn ClearTimeout(self, handle: i32) { fn ClearTimeout(self, handle: i32) {
let mut timers = self.active_timers.deref().borrow_mut(); let mut timers = self.active_timers.borrow_mut();
let mut timer_handle = timers.pop(&TimerId(handle)); let mut timer_handle = timers.pop(&TimerId(handle));
match timer_handle { match timer_handle {
Some(ref mut handle) => handle.cancel(), Some(ref mut handle) => handle.cancel(),
@ -416,7 +415,7 @@ impl<'a> WindowHelpers for JSRef<'a, Window> {
} }
fn init_browser_context(self, doc: JSRef<Document>) { fn init_browser_context(self, doc: JSRef<Document>) {
*self.browser_context.deref().borrow_mut() = Some(BrowserContext::new(doc)); *self.browser_context.borrow_mut() = Some(BrowserContext::new(doc));
} }
/// Commence a new URL load which will either replace this window or scroll to a fragment. /// Commence a new URL load which will either replace this window or scroll to a fragment.
@ -437,7 +436,7 @@ impl<'a> WindowHelpers for JSRef<'a, Window> {
fn handle_fire_timer(self, timer_id: TimerId, cx: *mut JSContext) { fn handle_fire_timer(self, timer_id: TimerId, cx: *mut JSContext) {
let this_value = self.reflector().get_jsobject(); let this_value = self.reflector().get_jsobject();
let data = match self.active_timers.deref().borrow().find(&timer_id) { let data = match self.active_timers.borrow().find(&timer_id) {
None => return, None => return,
Some(timer_handle) => timer_handle.data, Some(timer_handle) => timer_handle.data,
}; };
@ -446,13 +445,13 @@ impl<'a> WindowHelpers for JSRef<'a, Window> {
with_compartment(cx, this_value, || { with_compartment(cx, this_value, || {
let mut rval = NullValue(); let mut rval = NullValue();
unsafe { unsafe {
JS_CallFunctionValue(cx, this_value, *data.funval, JS_CallFunctionValue(cx, this_value, data.funval,
0, ptr::null_mut(), &mut rval); 0, ptr::null_mut(), &mut rval);
} }
}); });
if !data.is_interval { if !data.is_interval {
self.active_timers.deref().borrow_mut().remove(&timer_id); self.active_timers.borrow_mut().remove(&timer_id);
} }
} }
} }
@ -460,8 +459,8 @@ impl<'a> WindowHelpers for JSRef<'a, Window> {
impl<'a> PrivateWindowHelpers for JSRef<'a, Window> { impl<'a> PrivateWindowHelpers for JSRef<'a, Window> {
fn set_timeout_or_interval(self, callback: JSVal, timeout: i32, is_interval: bool) -> i32 { fn set_timeout_or_interval(self, callback: JSVal, timeout: i32, is_interval: bool) -> i32 {
let timeout = cmp::max(0, timeout) as u64; let timeout = cmp::max(0, timeout) as u64;
let handle = self.next_timer_handle.deref().get(); let handle = self.next_timer_handle.get();
self.next_timer_handle.deref().set(handle + 1); self.next_timer_handle.set(handle + 1);
// Post a delayed message to the per-window timer task; it will dispatch it // Post a delayed message to the per-window timer task; it will dispatch it
// to the relevant script handler that will deal with it. // to the relevant script handler that will deal with it.
@ -507,13 +506,13 @@ impl<'a> PrivateWindowHelpers for JSRef<'a, Window> {
let timer_id = TimerId(handle); let timer_id = TimerId(handle);
let timer = TimerHandle { let timer = TimerHandle {
handle: timer_id, handle: timer_id,
cancel_chan: Untraceable::new(Some(cancel_chan)), cancel_chan: Some(cancel_chan),
data: TimerData { data: TimerData {
is_interval: is_interval, is_interval: is_interval,
funval: Traceable::new(callback), funval: callback,
} }
}; };
self.active_timers.deref().borrow_mut().insert(timer_id, timer); self.active_timers.borrow_mut().insert(timer_id, timer);
handle handle
} }
} }
@ -531,14 +530,14 @@ impl Window {
script_chan: script_chan, script_chan: script_chan,
control_chan: control_chan, control_chan: control_chan,
console: Default::default(), console: Default::default(),
compositor: Untraceable::new(compositor), compositor: compositor,
page: page, page: page,
location: Default::default(), location: Default::default(),
navigator: Default::default(), navigator: Default::default(),
image_cache_task: image_cache_task, image_cache_task: image_cache_task,
active_timers: Traceable::new(RefCell::new(HashMap::new())), active_timers: RefCell::new(HashMap::new()),
next_timer_handle: Traceable::new(Cell::new(0)), next_timer_handle: Cell::new(0),
browser_context: Traceable::new(RefCell::new(None)), browser_context: RefCell::new(None),
performance: Default::default(), performance: Default::default(),
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

@ -9,6 +9,7 @@ use dom::bindings::codegen::InheritTypes::EventTargetCast;
use dom::bindings::error::{Fallible, Syntax}; use dom::bindings::error::{Fallible, Syntax};
use dom::bindings::global::{GlobalRef, GlobalField}; use dom::bindings::global::{GlobalRef, GlobalField};
use dom::bindings::js::{JS, JSRef, Temporary}; use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::trace::JSTraceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope; use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope;
use dom::eventtarget::{EventTarget, EventTargetHelpers, WorkerTypeId}; use dom::eventtarget::{EventTarget, EventTargetHelpers, WorkerTypeId};
@ -18,7 +19,7 @@ use script_task::{ScriptChan, DOMMessage};
use servo_util::str::DOMString; use servo_util::str::DOMString;
use js::glue::JS_STRUCTURED_CLONE_VERSION; use js::glue::JS_STRUCTURED_CLONE_VERSION;
use js::jsapi::{JSContext, JS_AddObjectRoot, JS_RemoveObjectRoot}; use js::jsapi::{JSContext, JS_AddObjectRoot, JS_RemoveObjectRoot, JSTracer};
use js::jsapi::{JS_ReadStructuredClone, JS_WriteStructuredClone}; use js::jsapi::{JS_ReadStructuredClone, JS_WriteStructuredClone};
use js::jsval::{JSVal, UndefinedValue}; use js::jsval::{JSVal, UndefinedValue};
use url::UrlParser; use url::UrlParser;
@ -28,6 +29,7 @@ use std::cell::Cell;
use std::ptr; use std::ptr;
pub struct TrustedWorkerAddress(pub *const c_void); pub struct TrustedWorkerAddress(pub *const c_void);
untraceable!(TrustedWorkerAddress)
#[jstraceable] #[jstraceable]
#[must_root] #[must_root]

View file

@ -4,7 +4,6 @@
use dom::bindings::codegen::Bindings::WorkerGlobalScopeBinding::WorkerGlobalScopeMethods; use dom::bindings::codegen::Bindings::WorkerGlobalScopeBinding::WorkerGlobalScopeMethods;
use dom::bindings::error::{ErrorResult, Fallible, Syntax, Network, FailureUnknown}; use dom::bindings::error::{ErrorResult, Fallible, Syntax, Network, FailureUnknown};
use dom::bindings::trace::Untraceable;
use dom::bindings::global; use dom::bindings::global;
use dom::bindings::js::{MutNullableJS, JSRef, Temporary, OptionalSettable}; use dom::bindings::js::{MutNullableJS, JSRef, Temporary, OptionalSettable};
use dom::bindings::utils::{Reflectable, Reflector}; use dom::bindings::utils::{Reflectable, Reflector};
@ -35,9 +34,9 @@ pub enum WorkerGlobalScopeId {
#[must_root] #[must_root]
pub struct WorkerGlobalScope { pub struct WorkerGlobalScope {
pub eventtarget: EventTarget, pub eventtarget: EventTarget,
worker_url: Untraceable<Url>, worker_url: Url,
js_context: Untraceable<Rc<Cx>>, js_context: Rc<Cx>,
resource_task: Untraceable<ResourceTask>, resource_task: ResourceTask,
script_chan: ScriptChan, script_chan: ScriptChan,
location: MutNullableJS<WorkerLocation>, location: MutNullableJS<WorkerLocation>,
navigator: MutNullableJS<WorkerNavigator>, navigator: MutNullableJS<WorkerNavigator>,
@ -52,9 +51,9 @@ impl WorkerGlobalScope {
script_chan: ScriptChan) -> WorkerGlobalScope { script_chan: ScriptChan) -> WorkerGlobalScope {
WorkerGlobalScope { WorkerGlobalScope {
eventtarget: EventTarget::new_inherited(WorkerGlobalScopeTypeId(type_id)), eventtarget: EventTarget::new_inherited(WorkerGlobalScopeTypeId(type_id)),
worker_url: Untraceable::new(worker_url), worker_url: worker_url,
js_context: Untraceable::new(cx), js_context: cx,
resource_task: Untraceable::new(resource_task), resource_task: resource_task,
script_chan: script_chan, script_chan: script_chan,
location: Default::default(), location: Default::default(),
navigator: Default::default(), navigator: Default::default(),
@ -67,11 +66,11 @@ impl WorkerGlobalScope {
} }
pub fn resource_task<'a>(&'a self) -> &'a ResourceTask { pub fn resource_task<'a>(&'a self) -> &'a ResourceTask {
&*self.resource_task & self.resource_task
} }
pub fn get_url<'a>(&'a self) -> &'a Url { pub fn get_url<'a>(&'a self) -> &'a Url {
&*self.worker_url &self.worker_url
} }
pub fn script_chan<'a>(&'a self) -> &'a ScriptChan { pub fn script_chan<'a>(&'a self) -> &'a ScriptChan {
@ -86,7 +85,7 @@ impl<'a> WorkerGlobalScopeMethods for JSRef<'a, WorkerGlobalScope> {
fn Location(self) -> Temporary<WorkerLocation> { fn Location(self) -> Temporary<WorkerLocation> {
if self.location.get().is_none() { if self.location.get().is_none() {
let location = WorkerLocation::new(self, self.worker_url.deref().clone()); let location = WorkerLocation::new(self, self.worker_url.clone());
self.location.assign(Some(location)); self.location.assign(Some(location));
} }
self.location.get().unwrap() self.location.get().unwrap()
@ -95,7 +94,7 @@ impl<'a> WorkerGlobalScopeMethods for JSRef<'a, WorkerGlobalScope> {
fn ImportScripts(self, url_strings: Vec<DOMString>) -> ErrorResult { fn ImportScripts(self, url_strings: Vec<DOMString>) -> ErrorResult {
let mut urls = Vec::with_capacity(url_strings.len()); let mut urls = Vec::with_capacity(url_strings.len());
for url in url_strings.into_iter() { for url in url_strings.into_iter() {
let url = UrlParser::new().base_url(&*self.worker_url) let url = UrlParser::new().base_url(&self.worker_url)
.parse(url.as_slice()); .parse(url.as_slice());
match url { match url {
Ok(url) => urls.push(url), Ok(url) => urls.push(url),
@ -104,14 +103,14 @@ impl<'a> WorkerGlobalScopeMethods for JSRef<'a, WorkerGlobalScope> {
} }
for url in urls.into_iter() { for url in urls.into_iter() {
let (url, source) = match load_whole_resource(&*self.resource_task, url) { let (url, source) = match load_whole_resource(&self.resource_task, url) {
Err(_) => return Err(Network), Err(_) => return Err(Network),
Ok((metadata, bytes)) => { Ok((metadata, bytes)) => {
(metadata.final_url, String::from_utf8(bytes).unwrap()) (metadata.final_url, String::from_utf8(bytes).unwrap())
} }
}; };
match self.js_context.deref().evaluate_script( match self.js_context.evaluate_script(
self.reflector().get_jsobject(), source, url.serialize(), 1) { self.reflector().get_jsobject(), source, url.serialize(), 1) {
Ok(_) => (), Ok(_) => (),
Err(_) => { Err(_) => {

View file

@ -6,7 +6,6 @@ use dom::bindings::codegen::Bindings::WorkerLocationBinding;
use dom::bindings::codegen::Bindings::WorkerLocationBinding::WorkerLocationMethods; use dom::bindings::codegen::Bindings::WorkerLocationBinding::WorkerLocationMethods;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::global::Worker; use dom::bindings::global::Worker;
use dom::bindings::trace::Untraceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::urlhelper::UrlHelper; use dom::urlhelper::UrlHelper;
use dom::workerglobalscope::WorkerGlobalScope; use dom::workerglobalscope::WorkerGlobalScope;
@ -19,14 +18,14 @@ use url::Url;
#[must_root] #[must_root]
pub struct WorkerLocation { pub struct WorkerLocation {
reflector_: Reflector, reflector_: Reflector,
url: Untraceable<Url>, url: Url,
} }
impl WorkerLocation { impl WorkerLocation {
fn new_inherited(url: Url) -> WorkerLocation { fn new_inherited(url: Url) -> WorkerLocation {
WorkerLocation { WorkerLocation {
reflector_: Reflector::new(), reflector_: Reflector::new(),
url: Untraceable::new(url), url: url,
} }
} }
@ -39,15 +38,15 @@ impl WorkerLocation {
impl<'a> WorkerLocationMethods for JSRef<'a, WorkerLocation> { impl<'a> WorkerLocationMethods for JSRef<'a, WorkerLocation> {
fn Href(self) -> DOMString { fn Href(self) -> DOMString {
UrlHelper::Href(self.url.deref()) UrlHelper::Href(&self.url)
} }
fn Search(self) -> DOMString { fn Search(self) -> DOMString {
UrlHelper::Search(self.url.deref()) UrlHelper::Search(&self.url)
} }
fn Hash(self) -> DOMString { fn Hash(self) -> DOMString {
UrlHelper::Hash(self.url.deref()) UrlHelper::Hash(&self.url)
} }
} }

View file

@ -15,7 +15,6 @@ use dom::bindings::error::{Network, Syntax, Security, Abort, Timeout};
use dom::bindings::global::{GlobalField, GlobalRef, WorkerField}; use dom::bindings::global::{GlobalField, GlobalRef, WorkerField};
use dom::bindings::js::{MutNullableJS, JS, JSRef, Temporary, OptionalRootedRootable}; use dom::bindings::js::{MutNullableJS, JS, JSRef, Temporary, OptionalRootedRootable};
use dom::bindings::str::ByteString; use dom::bindings::str::ByteString;
use dom::bindings::trace::{Traceable, Untraceable};
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::document::Document; use dom::document::Document;
use dom::event::Event; use dom::event::Event;
@ -107,68 +106,68 @@ enum SyncOrAsync<'a> {
#[must_root] #[must_root]
pub struct XMLHttpRequest { pub struct XMLHttpRequest {
eventtarget: XMLHttpRequestEventTarget, eventtarget: XMLHttpRequestEventTarget,
ready_state: Traceable<Cell<XMLHttpRequestState>>, ready_state: Cell<XMLHttpRequestState>,
timeout: Traceable<Cell<u32>>, timeout: Cell<u32>,
with_credentials: Traceable<Cell<bool>>, with_credentials: Cell<bool>,
upload: JS<XMLHttpRequestUpload>, upload: JS<XMLHttpRequestUpload>,
response_url: DOMString, response_url: DOMString,
status: Traceable<Cell<u16>>, status: Cell<u16>,
status_text: Traceable<RefCell<ByteString>>, status_text: RefCell<ByteString>,
response: Traceable<RefCell<ByteString>>, response: RefCell<ByteString>,
response_type: Traceable<Cell<XMLHttpRequestResponseType>>, response_type: Cell<XMLHttpRequestResponseType>,
response_xml: MutNullableJS<Document>, response_xml: MutNullableJS<Document>,
response_headers: Untraceable<RefCell<ResponseHeaderCollection>>, response_headers: RefCell<ResponseHeaderCollection>,
// Associated concepts // Associated concepts
request_method: Untraceable<RefCell<Method>>, request_method: RefCell<Method>,
request_url: Untraceable<RefCell<Option<Url>>>, request_url: RefCell<Option<Url>>,
request_headers: Untraceable<RefCell<RequestHeaderCollection>>, request_headers: RefCell<RequestHeaderCollection>,
request_body_len: Traceable<Cell<uint>>, request_body_len: Cell<uint>,
sync: Traceable<Cell<bool>>, sync: Cell<bool>,
upload_complete: Traceable<Cell<bool>>, upload_complete: Cell<bool>,
upload_events: Traceable<Cell<bool>>, upload_events: Cell<bool>,
send_flag: Traceable<Cell<bool>>, send_flag: Cell<bool>,
global: GlobalField, global: GlobalField,
pinned_count: Traceable<Cell<uint>>, pinned_count: Cell<uint>,
timer: Untraceable<RefCell<Timer>>, timer: RefCell<Timer>,
fetch_time: Traceable<Cell<i64>>, fetch_time: Cell<i64>,
timeout_pinned: Traceable<Cell<bool>>, timeout_pinned: Cell<bool>,
terminate_sender: Untraceable<RefCell<Option<Sender<Error>>>>, terminate_sender: RefCell<Option<Sender<Error>>>,
} }
impl XMLHttpRequest { impl XMLHttpRequest {
fn new_inherited(global: &GlobalRef) -> XMLHttpRequest { fn new_inherited(global: &GlobalRef) -> XMLHttpRequest {
XMLHttpRequest { XMLHttpRequest {
eventtarget: XMLHttpRequestEventTarget::new_inherited(XMLHttpRequestTypeId), eventtarget: XMLHttpRequestEventTarget::new_inherited(XMLHttpRequestTypeId),
ready_state: Traceable::new(Cell::new(Unsent)), ready_state: Cell::new(Unsent),
timeout: Traceable::new(Cell::new(0u32)), timeout: Cell::new(0u32),
with_credentials: Traceable::new(Cell::new(false)), with_credentials: Cell::new(false),
upload: JS::from_rooted(XMLHttpRequestUpload::new(global)), upload: JS::from_rooted(XMLHttpRequestUpload::new(global)),
response_url: "".to_string(), response_url: "".to_string(),
status: Traceable::new(Cell::new(0)), status: Cell::new(0),
status_text: Traceable::new(RefCell::new(ByteString::new(vec!()))), status_text: RefCell::new(ByteString::new(vec!())),
response: Traceable::new(RefCell::new(ByteString::new(vec!()))), response: RefCell::new(ByteString::new(vec!())),
response_type: Traceable::new(Cell::new(_empty)), response_type: Cell::new(_empty),
response_xml: Default::default(), response_xml: Default::default(),
response_headers: Untraceable::new(RefCell::new(ResponseHeaderCollection::new())), response_headers: RefCell::new(ResponseHeaderCollection::new()),
request_method: Untraceable::new(RefCell::new(Get)), request_method: RefCell::new(Get),
request_url: Untraceable::new(RefCell::new(None)), request_url: RefCell::new(None),
request_headers: Untraceable::new(RefCell::new(RequestHeaderCollection::new())), request_headers: RefCell::new(RequestHeaderCollection::new()),
request_body_len: Traceable::new(Cell::new(0)), request_body_len: Cell::new(0),
sync: Traceable::new(Cell::new(false)), sync: Cell::new(false),
send_flag: Traceable::new(Cell::new(false)), send_flag: Cell::new(false),
upload_complete: Traceable::new(Cell::new(false)), upload_complete: Cell::new(false),
upload_events: Traceable::new(Cell::new(false)), upload_events: Cell::new(false),
global: GlobalField::from_rooted(global), global: GlobalField::from_rooted(global),
pinned_count: Traceable::new(Cell::new(0)), pinned_count: Cell::new(0),
timer: Untraceable::new(RefCell::new(Timer::new().unwrap())), timer: RefCell::new(Timer::new().unwrap()),
fetch_time: Traceable::new(Cell::new(0)), fetch_time: Cell::new(0),
timeout_pinned: Traceable::new(Cell::new(false)), timeout_pinned: Cell::new(false),
terminate_sender: Untraceable::new(RefCell::new(None)), terminate_sender: RefCell::new(None),
} }
} }
pub fn new(global: &GlobalRef) -> Temporary<XMLHttpRequest> { pub fn new(global: &GlobalRef) -> Temporary<XMLHttpRequest> {
@ -276,7 +275,7 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
} }
fn ReadyState(self) -> u16 { fn ReadyState(self) -> u16 {
self.ready_state.deref().get() as u16 self.ready_state.get() as u16
} }
fn Open(self, method: ByteString, url: DOMString) -> ErrorResult { fn Open(self, method: ByteString, url: DOMString) -> ErrorResult {
@ -306,7 +305,7 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
Some(ExtensionMethod(ref t)) if t.as_slice() == "TRACK" => Err(Security), Some(ExtensionMethod(ref t)) if t.as_slice() == "TRACK" => Err(Security),
Some(_) if method.is_token() => { Some(_) if method.is_token() => {
*self.request_method.deref().borrow_mut() = maybe_method.unwrap(); *self.request_method.borrow_mut() = maybe_method.unwrap();
// Step 6 // Step 6
let base = self.global.root().root_ref().get_url(); let base = self.global.root().root_ref().get_url();
@ -315,22 +314,22 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
Err(_) => return Err(Syntax) // Step 7 Err(_) => return Err(Syntax) // Step 7
}; };
// XXXManishearth Do some handling of username/passwords // XXXManishearth Do some handling of username/passwords
if self.sync.deref().get() { if self.sync.get() {
// FIXME: This should only happen if the global environment is a document environment // FIXME: This should only happen if the global environment is a document environment
if self.timeout.deref().get() != 0 || self.with_credentials.deref().get() || self.response_type.deref().get() != _empty { if self.timeout.get() != 0 || self.with_credentials.get() || self.response_type.get() != _empty {
return Err(InvalidAccess) return Err(InvalidAccess)
} }
} }
// XXXManishearth abort existing requests // XXXManishearth abort existing requests
// Step 12 // Step 12
*self.request_url.deref().borrow_mut() = Some(parsed_url); *self.request_url.borrow_mut() = Some(parsed_url);
*self.request_headers.deref().borrow_mut() = RequestHeaderCollection::new(); *self.request_headers.borrow_mut() = RequestHeaderCollection::new();
self.send_flag.deref().set(false); self.send_flag.set(false);
*self.status_text.deref().borrow_mut() = ByteString::new(vec!()); *self.status_text.borrow_mut() = ByteString::new(vec!());
self.status.deref().set(0); self.status.set(0);
// Step 13 // Step 13
if self.ready_state.deref().get() != Opened { if self.ready_state.get() != Opened {
self.change_ready_state(Opened); self.change_ready_state(Opened);
} }
Ok(()) Ok(())
@ -342,11 +341,11 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
} }
fn Open_(self, method: ByteString, url: DOMString, async: bool, fn Open_(self, method: ByteString, url: DOMString, async: bool,
_username: Option<DOMString>, _password: Option<DOMString>) -> ErrorResult { _username: Option<DOMString>, _password: Option<DOMString>) -> ErrorResult {
self.sync.deref().set(!async); self.sync.set(!async);
self.Open(method, url) self.Open(method, url)
} }
fn SetRequestHeader(self, name: ByteString, mut value: ByteString) -> ErrorResult { fn SetRequestHeader(self, name: ByteString, mut value: ByteString) -> ErrorResult {
if self.ready_state.deref().get() != Opened || self.send_flag.deref().get() { if self.ready_state.get() != Opened || self.send_flag.get() {
return Err(InvalidState); // Step 1, 2 return Err(InvalidState); // Step 1, 2
} }
if !name.is_token() || !value.is_field_value() { if !name.is_token() || !value.is_field_value() {
@ -371,7 +370,7 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
}, },
None => return Err(Syntax) None => return Err(Syntax)
}; };
let mut collection = self.request_headers.deref().borrow_mut(); let mut collection = self.request_headers.borrow_mut();
// Steps 6,7 // Steps 6,7
@ -410,20 +409,20 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
} }
} }
fn Timeout(self) -> u32 { fn Timeout(self) -> u32 {
self.timeout.deref().get() self.timeout.get()
} }
fn SetTimeout(self, timeout: u32) -> ErrorResult { fn SetTimeout(self, timeout: u32) -> ErrorResult {
if self.sync.deref().get() { if self.sync.get() {
// FIXME: Not valid for a worker environment // FIXME: Not valid for a worker environment
Err(InvalidState) Err(InvalidState)
} else { } else {
self.timeout.deref().set(timeout); self.timeout.set(timeout);
if self.send_flag.deref().get() { if self.send_flag.get() {
if timeout == 0 { if timeout == 0 {
self.cancel_timeout(); self.cancel_timeout();
return Ok(()); return Ok(());
} }
let progress = time::now().to_timespec().sec - self.fetch_time.deref().get(); let progress = time::now().to_timespec().sec - self.fetch_time.get();
if timeout > (progress * 1000) as u32 { if timeout > (progress * 1000) as u32 {
self.set_timeout(timeout - (progress * 1000) as u32); self.set_timeout(timeout - (progress * 1000) as u32);
} else { } else {
@ -435,20 +434,20 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
} }
} }
fn WithCredentials(self) -> bool { fn WithCredentials(self) -> bool {
self.with_credentials.deref().get() self.with_credentials.get()
} }
fn SetWithCredentials(self, with_credentials: bool) { fn SetWithCredentials(self, with_credentials: bool) {
self.with_credentials.deref().set(with_credentials); self.with_credentials.set(with_credentials);
} }
fn Upload(self) -> Temporary<XMLHttpRequestUpload> { fn Upload(self) -> Temporary<XMLHttpRequestUpload> {
Temporary::new(self.upload) Temporary::new(self.upload)
} }
fn Send(self, data: Option<SendParam>) -> ErrorResult { fn Send(self, data: Option<SendParam>) -> ErrorResult {
if self.ready_state.deref().get() != Opened || self.send_flag.deref().get() { if self.ready_state.get() != Opened || self.send_flag.get() {
return Err(InvalidState); // Step 1, 2 return Err(InvalidState); // Step 1, 2
} }
let data = match *self.request_method.deref().borrow() { let data = match *self.request_method.borrow() {
Get | Head => None, // Step 3 Get | Head => None, // Step 3
_ => data _ => data
}; };
@ -456,15 +455,15 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
self.request_body_len.set(extracted.as_ref().map(|e| e.len()).unwrap_or(0)); self.request_body_len.set(extracted.as_ref().map(|e| e.len()).unwrap_or(0));
// Step 6 // Step 6
self.upload_events.deref().set(false); self.upload_events.set(false);
// Step 7 // Step 7
self.upload_complete.deref().set(match extracted { self.upload_complete.set(match extracted {
None => true, None => true,
Some (ref v) if v.len() == 0 => true, Some (ref v) if v.len() == 0 => true,
_ => false _ => false
}); });
let mut addr = None; let mut addr = None;
if !self.sync.deref().get() { if !self.sync.get() {
// If one of the event handlers below aborts the fetch, // If one of the event handlers below aborts the fetch,
// the assertion in release_once() will fail since we haven't pinned it yet. // the assertion in release_once() will fail since we haven't pinned it yet.
// Pin early to avoid dealing with this // Pin early to avoid dealing with this
@ -476,29 +475,29 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
let upload_target = *self.upload.root(); let upload_target = *self.upload.root();
let event_target: JSRef<EventTarget> = EventTargetCast::from_ref(upload_target); let event_target: JSRef<EventTarget> = EventTargetCast::from_ref(upload_target);
if event_target.has_handlers() { if event_target.has_handlers() {
self.upload_events.deref().set(true); self.upload_events.set(true);
} }
// Step 9 // Step 9
self.send_flag.deref().set(true); self.send_flag.set(true);
self.dispatch_response_progress_event("loadstart".to_string()); self.dispatch_response_progress_event("loadstart".to_string());
if !self.upload_complete.deref().get() { if !self.upload_complete.get() {
self.dispatch_upload_progress_event("loadstart".to_string(), Some(0)); self.dispatch_upload_progress_event("loadstart".to_string(), Some(0));
} }
} }
if self.ready_state.deref().get() == Unsent { if self.ready_state.get() == Unsent {
// The progress events above might have run abort(), in which case we terminate the fetch. // The progress events above might have run abort(), in which case we terminate the fetch.
return Ok(()); return Ok(());
} }
let global = self.global.root(); let global = self.global.root();
let resource_task = global.root_ref().resource_task(); let resource_task = global.root_ref().resource_task();
let mut load_data = LoadData::new(self.request_url.deref().borrow().clone().unwrap()); let mut load_data = LoadData::new(self.request_url.borrow().clone().unwrap());
load_data.data = extracted; load_data.data = extracted;
// Default headers // Default headers
let request_headers = self.request_headers.deref(); let ref request_headers = self.request_headers;
if request_headers.borrow().content_type.is_none() { if request_headers.borrow().content_type.is_none() {
let parameters = vec!((String::from_str("charset"), String::from_str("UTF-8"))); let parameters = vec!((String::from_str("charset"), String::from_str("UTF-8")));
request_headers.borrow_mut().content_type = match data { request_headers.borrow_mut().content_type = match data {
@ -522,14 +521,14 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
request_headers.borrow_mut().accept = Some(String::from_str("*/*")) request_headers.borrow_mut().accept = Some(String::from_str("*/*"))
} }
load_data.headers = (*self.request_headers.deref().borrow()).clone(); load_data.headers = (*self.request_headers.borrow()).clone();
load_data.method = (*self.request_method.deref().borrow()).clone(); load_data.method = (*self.request_method.borrow()).clone();
let (terminate_sender, terminate_receiver) = channel(); let (terminate_sender, terminate_receiver) = channel();
*self.terminate_sender.deref().borrow_mut() = Some(terminate_sender); *self.terminate_sender.borrow_mut() = Some(terminate_sender);
// CORS stuff // CORS stuff
let referer_url = self.global.root().root_ref().get_url(); let referer_url = self.global.root().root_ref().get_url();
let mode = if self.upload_events.deref().get() { let mode = if self.upload_events.get() {
ForcedPreflightMode ForcedPreflightMode
} else { } else {
CORSMode CORSMode
@ -547,25 +546,25 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
buf.push_str(format!("{:u}", p).as_slice()); buf.push_str(format!("{:u}", p).as_slice());
}); });
referer_url.serialize_path().map(|ref h| buf.push_str(h.as_slice())); referer_url.serialize_path().map(|ref h| buf.push_str(h.as_slice()));
self.request_headers.deref().borrow_mut().referer = Some(buf); self.request_headers.borrow_mut().referer = Some(buf);
}, },
Ok(Some(ref req)) => self.insert_trusted_header("origin".to_string(), Ok(Some(ref req)) => self.insert_trusted_header("origin".to_string(),
format!("{}", req.origin)), format!("{}", req.origin)),
_ => {} _ => {}
} }
if self.sync.deref().get() { if self.sync.get() {
return XMLHttpRequest::fetch(&mut Sync(self), resource_task, load_data, return XMLHttpRequest::fetch(&mut Sync(self), resource_task, load_data,
terminate_receiver, cors_request); terminate_receiver, cors_request);
} else { } else {
let builder = TaskBuilder::new().named("XHRTask"); let builder = TaskBuilder::new().named("XHRTask");
self.fetch_time.deref().set(time::now().to_timespec().sec); self.fetch_time.set(time::now().to_timespec().sec);
let script_chan = global.root_ref().script_chan().clone(); let script_chan = global.root_ref().script_chan().clone();
builder.spawn(proc() { builder.spawn(proc() {
let _ = XMLHttpRequest::fetch(&mut Async(addr.unwrap(), script_chan), let _ = XMLHttpRequest::fetch(&mut Async(addr.unwrap(), script_chan),
resource_task, load_data, terminate_receiver, cors_request); resource_task, load_data, terminate_receiver, cors_request);
}); });
let timeout = self.timeout.deref().get(); let timeout = self.timeout.get();
if timeout > 0 { if timeout > 0 {
self.set_timeout(timeout); self.set_timeout(timeout);
} }
@ -573,22 +572,22 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
Ok(()) Ok(())
} }
fn Abort(self) { fn Abort(self) {
self.terminate_sender.deref().borrow().as_ref().map(|s| s.send_opt(Abort)); self.terminate_sender.borrow().as_ref().map(|s| s.send_opt(Abort));
match self.ready_state.deref().get() { match self.ready_state.get() {
Opened if self.send_flag.deref().get() => self.process_partial_response(ErroredMsg(Some(Abort))), Opened if self.send_flag.get() => self.process_partial_response(ErroredMsg(Some(Abort))),
HeadersReceived | Loading => self.process_partial_response(ErroredMsg(Some(Abort))), HeadersReceived | Loading => self.process_partial_response(ErroredMsg(Some(Abort))),
_ => {} _ => {}
}; };
self.ready_state.deref().set(Unsent); self.ready_state.set(Unsent);
} }
fn ResponseURL(self) -> DOMString { fn ResponseURL(self) -> DOMString {
self.response_url.clone() self.response_url.clone()
} }
fn Status(self) -> u16 { fn Status(self) -> u16 {
self.status.deref().get() self.status.get()
} }
fn StatusText(self) -> ByteString { fn StatusText(self) -> ByteString {
self.status_text.deref().borrow().clone() self.status_text.borrow().clone()
} }
fn GetResponseHeader(self, name: ByteString) -> Option<ByteString> { fn GetResponseHeader(self, name: ByteString) -> Option<ByteString> {
self.filter_response_headers().iter().find(|h| { self.filter_response_headers().iter().find(|h| {
@ -610,7 +609,7 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
ByteString::new(vec) ByteString::new(vec)
} }
fn ResponseType(self) -> XMLHttpRequestResponseType { fn ResponseType(self) -> XMLHttpRequestResponseType {
self.response_type.deref().get() self.response_type.get()
} }
fn SetResponseType(self, response_type: XMLHttpRequestResponseType) -> ErrorResult { fn SetResponseType(self, response_type: XMLHttpRequestResponseType) -> ErrorResult {
match self.global { match self.global {
@ -618,28 +617,28 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
=> return Ok(()), => return Ok(()),
_ => {} _ => {}
} }
match self.ready_state.deref().get() { match self.ready_state.get() {
Loading | XHRDone => Err(InvalidState), Loading | XHRDone => Err(InvalidState),
_ if self.sync.deref().get() => Err(InvalidAccess), _ if self.sync.get() => Err(InvalidAccess),
_ => { _ => {
self.response_type.deref().set(response_type); self.response_type.set(response_type);
Ok(()) Ok(())
} }
} }
} }
fn Response(self, cx: *mut JSContext) -> JSVal { fn Response(self, cx: *mut JSContext) -> JSVal {
match self.response_type.deref().get() { match self.response_type.get() {
_empty | Text => { _empty | Text => {
let ready_state = self.ready_state.deref().get(); let ready_state = self.ready_state.get();
if ready_state == XHRDone || ready_state == Loading { if ready_state == XHRDone || ready_state == Loading {
self.text_response().to_jsval(cx) self.text_response().to_jsval(cx)
} else { } else {
"".to_string().to_jsval(cx) "".to_string().to_jsval(cx)
} }
}, },
_ if self.ready_state.deref().get() != XHRDone => NullValue(), _ if self.ready_state.get() != XHRDone => NullValue(),
Json => { Json => {
let decoded = UTF_8.decode(self.response.deref().borrow().as_slice(), DecodeReplace).unwrap().to_string(); let decoded = UTF_8.decode(self.response.borrow().as_slice(), DecodeReplace).unwrap().to_string();
let decoded: Vec<u16> = decoded.as_slice().utf16_units().collect(); let decoded: Vec<u16> = decoded.as_slice().utf16_units().collect();
let mut vp = UndefinedValue(); let mut vp = UndefinedValue();
unsafe { unsafe {
@ -652,14 +651,14 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
} }
_ => { _ => {
// XXXManishearth handle other response types // XXXManishearth handle other response types
self.response.deref().borrow().to_jsval(cx) self.response.borrow().to_jsval(cx)
} }
} }
} }
fn GetResponseText(self) -> Fallible<DOMString> { fn GetResponseText(self) -> Fallible<DOMString> {
match self.response_type.deref().get() { match self.response_type.get() {
_empty | Text => { _empty | Text => {
match self.ready_state.deref().get() { match self.ready_state.get() {
Loading | XHRDone => Ok(self.text_response()), Loading | XHRDone => Ok(self.text_response()),
_ => Ok("".to_string()) _ => Ok("".to_string())
} }
@ -716,25 +715,25 @@ trait PrivateXMLHttpRequestHelpers {
impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> { impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> {
// Creates a trusted address to the object, and roots it. Always pair this with a release() // Creates a trusted address to the object, and roots it. Always pair this with a release()
unsafe fn to_trusted(self) -> TrustedXHRAddress { unsafe fn to_trusted(self) -> TrustedXHRAddress {
if self.pinned_count.deref().get() == 0 { if self.pinned_count.get() == 0 {
JS_AddObjectRoot(self.global.root().root_ref().get_cx(), self.reflector().rootable()); JS_AddObjectRoot(self.global.root().root_ref().get_cx(), self.reflector().rootable());
} }
let pinned_count = self.pinned_count.deref().get(); let pinned_count = self.pinned_count.get();
self.pinned_count.deref().set(pinned_count + 1); self.pinned_count.set(pinned_count + 1);
TrustedXHRAddress(self.deref() as *const XMLHttpRequest as *const libc::c_void) TrustedXHRAddress(self.deref() as *const XMLHttpRequest as *const libc::c_void)
} }
fn release_once(self) { fn release_once(self) {
if self.sync.deref().get() { if self.sync.get() {
// Lets us call this at various termination cases without having to // Lets us call this at various termination cases without having to
// check self.sync every time, since the pinning mechanism only is // check self.sync every time, since the pinning mechanism only is
// meaningful during an async fetch // meaningful during an async fetch
return; return;
} }
assert!(self.pinned_count.deref().get() > 0) assert!(self.pinned_count.get() > 0)
let pinned_count = self.pinned_count.deref().get(); let pinned_count = self.pinned_count.get();
self.pinned_count.deref().set(pinned_count - 1); self.pinned_count.set(pinned_count - 1);
if self.pinned_count.deref().get() == 0 { if self.pinned_count.get() == 0 {
unsafe { unsafe {
JS_RemoveObjectRoot(self.global.root().root_ref().get_cx(), self.reflector().rootable()); JS_RemoveObjectRoot(self.global.root().root_ref().get_cx(), self.reflector().rootable());
} }
@ -742,8 +741,8 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> {
} }
fn change_ready_state(self, rs: XMLHttpRequestState) { fn change_ready_state(self, rs: XMLHttpRequestState) {
assert!(self.ready_state.deref().get() != rs) assert!(self.ready_state.get() != rs)
self.ready_state.deref().set(rs); self.ready_state.set(rs);
let global = self.global.root(); let global = self.global.root();
let event = Event::new(&global.root_ref(), let event = Event::new(&global.root_ref(),
"readystatechange".to_string(), "readystatechange".to_string(),
@ -760,9 +759,9 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> {
// Part of step 13, send() (processing request end of file) // Part of step 13, send() (processing request end of file)
// Substep 1 // Substep 1
self.upload_complete.deref().set(true); self.upload_complete.set(true);
// Substeps 2-4 // Substeps 2-4
if !self.sync.deref().get() { if !self.sync.get() {
self.dispatch_upload_progress_event("progress".to_string(), None); self.dispatch_upload_progress_event("progress".to_string(), None);
self.dispatch_upload_progress_event("load".to_string(), None); self.dispatch_upload_progress_event("load".to_string(), None);
self.dispatch_upload_progress_event("loadend".to_string(), None); self.dispatch_upload_progress_event("loadend".to_string(), None);
@ -770,16 +769,16 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> {
// Part of step 13, send() (processing response) // Part of step 13, send() (processing response)
// XXXManishearth handle errors, if any (substep 1) // XXXManishearth handle errors, if any (substep 1)
// Substep 2 // Substep 2
*self.status_text.deref().borrow_mut() = ByteString::new(status.reason().container_into_owned_bytes()); *self.status_text.borrow_mut() = ByteString::new(status.reason().container_into_owned_bytes());
self.status.deref().set(status.code()); self.status.set(status.code());
match headers { match headers {
Some(ref h) => { Some(ref h) => {
*self.response_headers.deref().borrow_mut() = h.clone(); *self.response_headers.borrow_mut() = h.clone();
} }
None => {} None => {}
}; };
// Substep 3 // Substep 3
if self.ready_state.deref().get() == Opened && !self.sync.deref().get() { if self.ready_state.get() == Opened && !self.sync.get() {
self.change_ready_state(HeadersReceived); self.change_ready_state(HeadersReceived);
} }
}, },
@ -789,13 +788,13 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> {
// XXXManishearth handle errors, if any (substep 1) // XXXManishearth handle errors, if any (substep 1)
// Substep 2 // Substep 2
if self.ready_state.deref().get() == HeadersReceived && !self.sync.deref().get() { if self.ready_state.get() == HeadersReceived && !self.sync.get() {
self.change_ready_state(Loading); self.change_ready_state(Loading);
} }
// Substep 3 // Substep 3
*self.response.deref().borrow_mut() = partial_response; *self.response.borrow_mut() = partial_response;
// Substep 4 // Substep 4
if !self.sync.deref().get() { if !self.sync.get() {
self.dispatch_response_progress_event("progress".to_string()); self.dispatch_response_progress_event("progress".to_string());
} }
}, },
@ -804,9 +803,9 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> {
// XXXManishearth handle errors, if any (substep 1) // XXXManishearth handle errors, if any (substep 1)
// Substep 3 // Substep 3
if self.ready_state.deref().get() == Loading || self.sync.deref().get() { if self.ready_state.get() == Loading || self.sync.get() {
// Subsubsteps 2-4 // Subsubsteps 2-4
self.send_flag.deref().set(false); self.send_flag.set(false);
self.change_ready_state(XHRDone); self.change_ready_state(XHRDone);
// Subsubsteps 5-7 // Subsubsteps 5-7
@ -818,7 +817,7 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> {
self.release_once(); self.release_once();
}, },
ErroredMsg(e) => { ErroredMsg(e) => {
self.send_flag.deref().set(false); self.send_flag.set(false);
// XXXManishearth set response to NetworkError // XXXManishearth set response to NetworkError
self.change_ready_state(XHRDone); self.change_ready_state(XHRDone);
let errormsg = match e { let errormsg = match e {
@ -828,7 +827,7 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> {
_ => unreachable!() _ => unreachable!()
}; };
let upload_complete: &Cell<bool> = self.upload_complete.deref(); let upload_complete: &Cell<bool> = &self.upload_complete;
if !upload_complete.get() { if !upload_complete.get() {
upload_complete.set(true); upload_complete.set(true);
self.dispatch_upload_progress_event("progress".to_string(), None); self.dispatch_upload_progress_event("progress".to_string(), None);
@ -843,8 +842,8 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> {
self.release_once(); self.release_once();
}, },
TimeoutMsg => { TimeoutMsg => {
match self.ready_state.deref().get() { match self.ready_state.get() {
Opened if self.send_flag.deref().get() => self.process_partial_response(ErroredMsg(Some(Timeout))), Opened if self.send_flag.get() => self.process_partial_response(ErroredMsg(Some(Timeout))),
Loading | HeadersReceived => self.process_partial_response(ErroredMsg(Some(Timeout))), Loading | HeadersReceived => self.process_partial_response(ErroredMsg(Some(Timeout))),
_ => self.release_once() _ => self.release_once()
}; };
@ -855,7 +854,7 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> {
fn insert_trusted_header(self, name: String, value: String) { fn insert_trusted_header(self, name: String, value: String) {
// Insert a header without checking spec-compliance // Insert a header without checking spec-compliance
// Use for hardcoded headers // Use for hardcoded headers
let mut collection = self.request_headers.deref().borrow_mut(); let mut collection = self.request_headers.borrow_mut();
let value_bytes = value.into_bytes(); let value_bytes = value.into_bytes();
let mut reader = BufReader::new(value_bytes.as_slice()); let mut reader = BufReader::new(value_bytes.as_slice());
let maybe_header: Option<Header> = HeaderEnum::value_from_stream( let maybe_header: Option<Header> = HeaderEnum::value_from_stream(
@ -888,26 +887,26 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> {
} }
fn dispatch_response_progress_event(self, type_: DOMString) { fn dispatch_response_progress_event(self, type_: DOMString) {
let len = self.response.deref().borrow().len() as u64; let len = self.response.borrow().len() as u64;
let total = self.response_headers.deref().borrow().content_length.map(|x| {x as u64}); let total = self.response_headers.borrow().content_length.map(|x| {x as u64});
self.dispatch_progress_event(false, type_, len, total); self.dispatch_progress_event(false, type_, len, total);
} }
fn set_timeout(self, timeout: u32) { fn set_timeout(self, timeout: u32) {
// Sets up the object to timeout in a given number of milliseconds // Sets up the object to timeout in a given number of milliseconds
// This will cancel all previous timeouts // This will cancel all previous timeouts
let oneshot = self.timer.deref().borrow_mut() let oneshot = self.timer.borrow_mut()
.oneshot(Duration::milliseconds(timeout as i64)); .oneshot(Duration::milliseconds(timeout as i64));
let addr = unsafe { let addr = unsafe {
self.to_trusted() // This will increment the pin counter by one self.to_trusted() // This will increment the pin counter by one
}; };
if self.timeout_pinned.deref().get() { if self.timeout_pinned.get() {
// Already pinned due to a timeout, no need to pin it again since the old timeout was cancelled above // Already pinned due to a timeout, no need to pin it again since the old timeout was cancelled above
self.release_once(); self.release_once();
} }
self.timeout_pinned.deref().set(true); self.timeout_pinned.set(true);
let global = self.global.root(); let global = self.global.root();
let script_chan = global.root_ref().script_chan().clone(); let script_chan = global.root_ref().script_chan().clone();
let terminate_sender = (*self.terminate_sender.deref().borrow()).clone(); let terminate_sender = (*self.terminate_sender.borrow()).clone();
spawn_named("XHR:Timer", proc () { spawn_named("XHR:Timer", proc () {
match oneshot.recv_opt() { match oneshot.recv_opt() {
Ok(_) => { Ok(_) => {
@ -926,16 +925,16 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> {
} }
fn cancel_timeout(self) { fn cancel_timeout(self) {
// Cancels timeouts on the object, if any // Cancels timeouts on the object, if any
if self.timeout_pinned.deref().get() { if self.timeout_pinned.get() {
self.timeout_pinned.deref().set(false); self.timeout_pinned.set(false);
self.release_once(); self.release_once();
} }
// oneshot() closes the previous channel, canceling the timeout // oneshot() closes the previous channel, canceling the timeout
self.timer.deref().borrow_mut().oneshot(Zero::zero()); self.timer.borrow_mut().oneshot(Zero::zero());
} }
fn text_response(self) -> DOMString { fn text_response(self) -> DOMString {
let mut encoding = UTF_8 as EncodingRef; let mut encoding = UTF_8 as EncodingRef;
match self.response_headers.deref().borrow().content_type { match self.response_headers.borrow().content_type {
Some(ref x) => { Some(ref x) => {
for &(ref name, ref value) in x.parameters.iter() { for &(ref name, ref value) in x.parameters.iter() {
if name.as_slice().eq_ignore_ascii_case("charset") { if name.as_slice().eq_ignore_ascii_case("charset") {
@ -947,12 +946,12 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> {
} }
// According to Simon, decode() should never return an error, so unwrap()ing // According to Simon, decode() should never return an error, so unwrap()ing
// the result should be fine. XXXManishearth have a closer look at this later // the result should be fine. XXXManishearth have a closer look at this later
encoding.decode(self.response.deref().borrow().as_slice(), DecodeReplace).unwrap().to_string() encoding.decode(self.response.borrow().as_slice(), DecodeReplace).unwrap().to_string()
} }
fn filter_response_headers(self) -> ResponseHeaderCollection { fn filter_response_headers(self) -> ResponseHeaderCollection {
// http://fetch.spec.whatwg.org/#concept-response-header-list // http://fetch.spec.whatwg.org/#concept-response-header-list
let mut headers = ResponseHeaderCollection::new(); let mut headers = ResponseHeaderCollection::new();
for header in self.response_headers.deref().borrow().iter() { for header in self.response_headers.borrow().iter() {
match header.header_name().as_slice().to_ascii_lower().as_slice() { match header.header_name().as_slice().to_ascii_lower().as_slice() {
"set-cookie" | "set-cookie2" => {}, "set-cookie" | "set-cookie2" => {},
// XXXManishearth additional CORS filtering goes here // XXXManishearth additional CORS filtering goes here

View file

@ -492,7 +492,7 @@ pub fn parse_html(page: &Page,
for child in scriptnode.children() { for child in scriptnode.children() {
debug!("child = {:?}", child); debug!("child = {:?}", child);
let text: JSRef<Text> = TextCast::to_ref(child).unwrap(); let text: JSRef<Text> = TextCast::to_ref(child).unwrap();
data.push_str(text.deref().characterdata.data.deref().borrow().as_slice()); data.push_str(text.deref().characterdata.data.borrow().as_slice());
} }
debug!("script data = {:?}", data); debug!("script data = {:?}", data);

View file

@ -5,7 +5,6 @@
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods; use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::InheritTypes::NodeCast; use dom::bindings::codegen::InheritTypes::NodeCast;
use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable}; use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable};
use dom::bindings::trace::{Traceable, Untraceable};
use dom::bindings::utils::GlobalStaticData; use dom::bindings::utils::GlobalStaticData;
use dom::document::{Document, DocumentHelpers}; use dom::document::{Document, DocumentHelpers};
use dom::element::Element; use dom::element::Element;
@ -42,50 +41,50 @@ pub struct Page {
pub subpage_id: Option<SubpageId>, pub subpage_id: Option<SubpageId>,
/// Unique id for last reflow request; used for confirming completion reply. /// Unique id for last reflow request; used for confirming completion reply.
pub last_reflow_id: Traceable<Cell<uint>>, pub last_reflow_id: Cell<uint>,
/// The outermost frame containing the document, window, and page URL. /// The outermost frame containing the document, window, and page URL.
pub frame: Traceable<RefCell<Option<Frame>>>, pub frame: RefCell<Option<Frame>>,
/// A handle for communicating messages to the layout task. /// A handle for communicating messages to the layout task.
pub layout_chan: Untraceable<LayoutChan>, pub layout_chan: LayoutChan,
/// A handle to perform RPC calls into the layout, quickly. /// A handle to perform RPC calls into the layout, quickly.
layout_rpc: Untraceable<Box<LayoutRPC+'static>>, layout_rpc: Box<LayoutRPC+'static>,
/// The port that we will use to join layout. If this is `None`, then layout is not running. /// The port that we will use to join layout. If this is `None`, then layout is not running.
pub layout_join_port: Untraceable<RefCell<Option<Receiver<()>>>>, pub layout_join_port: RefCell<Option<Receiver<()>>>,
/// What parts of the document are dirty, if any. /// What parts of the document are dirty, if any.
damage: Traceable<RefCell<Option<DocumentDamage>>>, damage: RefCell<Option<DocumentDamage>>,
/// The current size of the window, in pixels. /// The current size of the window, in pixels.
pub window_size: Traceable<Cell<WindowSizeData>>, pub window_size: Cell<WindowSizeData>,
js_info: Traceable<RefCell<Option<JSPageInfo>>>, js_info: RefCell<Option<JSPageInfo>>,
/// Cached copy of the most recent url loaded by the script /// Cached copy of the most recent url loaded by the script
/// TODO(tkuehn): this currently does not follow any particular caching policy /// TODO(tkuehn): this currently does not follow any particular caching policy
/// and simply caches pages forever (!). The bool indicates if reflow is required /// and simply caches pages forever (!). The bool indicates if reflow is required
/// when reloading. /// when reloading.
url: Untraceable<RefCell<Option<(Url, bool)>>>, url: RefCell<Option<(Url, bool)>>,
next_subpage_id: Traceable<Cell<SubpageId>>, next_subpage_id: Cell<SubpageId>,
/// Pending resize event, if any. /// Pending resize event, if any.
pub resize_event: Untraceable<Cell<Option<WindowSizeData>>>, pub resize_event: Cell<Option<WindowSizeData>>,
/// Pending scroll to fragment event, if any /// Pending scroll to fragment event, if any
pub fragment_name: RefCell<Option<String>>, pub fragment_name: RefCell<Option<String>>,
/// 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: ResourceTask,
/// A handle for communicating messages to the constellation task. /// A handle for communicating messages to the constellation task.
pub constellation_chan: Untraceable<ConstellationChan>, pub constellation_chan: ConstellationChan,
// Child Pages. // Child Pages.
pub children: Traceable<RefCell<Vec<Rc<Page>>>>, pub children: RefCell<Vec<Rc<Page>>>,
/// Number of pending reflows that were sent while layout was active. /// Number of pending reflows that were sent while layout was active.
pub pending_reflows: Cell<int>, pub pending_reflows: Cell<int>,
@ -111,7 +110,7 @@ impl IterablePage for Rc<Page> {
} }
fn find(&self, id: PipelineId) -> Option<Rc<Page>> { fn find(&self, id: PipelineId) -> Option<Rc<Page>> {
if self.id == id { return Some(self.clone()); } if self.id == id { return Some(self.clone()); }
for page in self.children.deref().borrow().iter() { for page in self.children.borrow().iter() {
let found = page.find(id); let found = page.find(id);
if found.is_some() { return found; } if found.is_some() { return found; }
} }
@ -129,7 +128,7 @@ impl Page {
js_context: Rc<Cx>) -> Page { js_context: Rc<Cx>) -> Page {
let js_info = JSPageInfo { let js_info = JSPageInfo {
dom_static: GlobalStaticData(), dom_static: GlobalStaticData(),
js_context: Untraceable::new(js_context), js_context: js_context,
}; };
let layout_rpc: Box<LayoutRPC> = { let layout_rpc: Box<LayoutRPC> = {
let (rpc_send, rpc_recv) = channel(); let (rpc_send, rpc_recv) = channel();
@ -140,21 +139,21 @@ impl Page {
Page { Page {
id: id, id: id,
subpage_id: subpage_id, subpage_id: subpage_id,
frame: Traceable::new(RefCell::new(None)), frame: RefCell::new(None),
layout_chan: Untraceable::new(layout_chan), layout_chan: layout_chan,
layout_rpc: Untraceable::new(layout_rpc), layout_rpc: layout_rpc,
layout_join_port: Untraceable::new(RefCell::new(None)), layout_join_port: RefCell::new(None),
damage: Traceable::new(RefCell::new(None)), damage: RefCell::new(None),
window_size: Traceable::new(Cell::new(window_size)), window_size: Cell::new(window_size),
js_info: Traceable::new(RefCell::new(Some(js_info))), js_info: RefCell::new(Some(js_info)),
url: Untraceable::new(RefCell::new(None)), url: RefCell::new(None),
next_subpage_id: Traceable::new(Cell::new(SubpageId(0))), next_subpage_id: Cell::new(SubpageId(0)),
resize_event: Untraceable::new(Cell::new(None)), resize_event: Cell::new(None),
fragment_name: RefCell::new(None), fragment_name: RefCell::new(None),
last_reflow_id: Traceable::new(Cell::new(0)), last_reflow_id: Cell::new(0),
resource_task: Untraceable::new(resource_task), resource_task: resource_task,
constellation_chan: Untraceable::new(constellation_chan), constellation_chan: constellation_chan,
children: Traceable::new(RefCell::new(vec!())), children: RefCell::new(vec!()),
pending_reflows: Cell::new(0), pending_reflows: Cell::new(0),
avoided_reflows: Cell::new(0), avoided_reflows: Cell::new(0),
} }
@ -165,7 +164,7 @@ impl Page {
if damaged { if damaged {
let frame = self.frame(); let frame = self.frame();
let window = frame.as_ref().unwrap().window.root(); let window = frame.as_ref().unwrap().window.root();
self.reflow(goal, window.control_chan.clone(), &**window.compositor); self.reflow(goal, window.control_chan.clone(), &*window.compositor);
} else { } else {
self.avoided_reflows.set(self.avoided_reflows.get() + 1); self.avoided_reflows.set(self.avoided_reflows.get() + 1);
} }
@ -177,7 +176,7 @@ impl Page {
// doing a query reflow. // doing a query reflow.
self.flush_layout(ReflowForDisplay); self.flush_layout(ReflowForDisplay);
self.join_layout(); //FIXME: is this necessary, or is layout_rpc's mutex good enough? self.join_layout(); //FIXME: is this necessary, or is layout_rpc's mutex good enough?
let layout_rpc: &LayoutRPC = &**self.layout_rpc; let layout_rpc: &LayoutRPC = &*self.layout_rpc;
layout_rpc layout_rpc
} }
@ -185,7 +184,6 @@ impl Page {
pub fn remove(&self, id: PipelineId) -> Option<Rc<Page>> { pub fn remove(&self, id: PipelineId) -> Option<Rc<Page>> {
let remove_idx = { let remove_idx = {
self.children self.children
.deref()
.borrow_mut() .borrow_mut()
.iter_mut() .iter_mut()
.enumerate() .enumerate()
@ -197,9 +195,9 @@ impl Page {
.map(|(idx, _)| idx) .map(|(idx, _)| idx)
}; };
match remove_idx { match remove_idx {
Some(idx) => return Some(self.children.deref().borrow_mut().remove(idx).unwrap()), Some(idx) => return Some(self.children.borrow_mut().remove(idx).unwrap()),
None => { None => {
for page_tree in self.children.deref().borrow_mut().iter_mut() { for page_tree in self.children.borrow_mut().iter_mut() {
match page_tree.remove(id) { match page_tree.remove(id) {
found @ Some(_) => return found, found @ Some(_) => return found,
None => (), // keep going... None => (), // keep going...
@ -215,7 +213,7 @@ impl Iterator<Rc<Page>> for PageIterator {
fn next(&mut self) -> Option<Rc<Page>> { fn next(&mut self) -> Option<Rc<Page>> {
if !self.stack.is_empty() { if !self.stack.is_empty() {
let next = self.stack.pop().unwrap(); let next = self.stack.pop().unwrap();
for child in next.children.deref().borrow().iter() { for child in next.children.borrow().iter() {
self.stack.push(child.clone()); self.stack.push(child.clone());
} }
Some(next.clone()) Some(next.clone())
@ -227,33 +225,33 @@ impl Iterator<Rc<Page>> for PageIterator {
impl Page { impl Page {
pub fn mut_js_info<'a>(&'a self) -> RefMut<'a, Option<JSPageInfo>> { pub fn mut_js_info<'a>(&'a self) -> RefMut<'a, Option<JSPageInfo>> {
self.js_info.deref().borrow_mut() self.js_info.borrow_mut()
} }
pub fn js_info<'a>(&'a self) -> Ref<'a, Option<JSPageInfo>> { pub fn js_info<'a>(&'a self) -> Ref<'a, Option<JSPageInfo>> {
self.js_info.deref().borrow() self.js_info.borrow()
} }
pub fn url<'a>(&'a self) -> Ref<'a, Option<(Url, bool)>> { pub fn url<'a>(&'a self) -> Ref<'a, Option<(Url, bool)>> {
self.url.deref().borrow() self.url.borrow()
} }
pub fn mut_url<'a>(&'a self) -> RefMut<'a, Option<(Url, bool)>> { pub fn mut_url<'a>(&'a self) -> RefMut<'a, Option<(Url, bool)>> {
self.url.deref().borrow_mut() self.url.borrow_mut()
} }
pub fn frame<'a>(&'a self) -> Ref<'a, Option<Frame>> { pub fn frame<'a>(&'a self) -> Ref<'a, Option<Frame>> {
self.frame.deref().borrow() self.frame.borrow()
} }
pub fn mut_frame<'a>(&'a self) -> RefMut<'a, Option<Frame>> { pub fn mut_frame<'a>(&'a self) -> RefMut<'a, Option<Frame>> {
self.frame.deref().borrow_mut() self.frame.borrow_mut()
} }
pub fn get_next_subpage_id(&self) -> SubpageId { pub fn get_next_subpage_id(&self) -> SubpageId {
let subpage_id = self.next_subpage_id.deref().get(); let subpage_id = self.next_subpage_id.get();
let SubpageId(id_num) = subpage_id; let SubpageId(id_num) = subpage_id;
self.next_subpage_id.deref().set(SubpageId(id_num + 1)); self.next_subpage_id.set(SubpageId(id_num + 1));
subpage_id subpage_id
} }
@ -267,7 +265,7 @@ impl Page {
None => {}, None => {},
Some(root) => { Some(root) => {
let root: JSRef<Node> = NodeCast::from_ref(*root); let root: JSRef<Node> = NodeCast::from_ref(*root);
let mut damage = *self.damage.deref().borrow_mut(); let mut damage = *self.damage.borrow_mut();
match damage { match damage {
None => {} None => {}
Some(ref mut damage) => { Some(ref mut damage) => {
@ -278,7 +276,7 @@ impl Page {
} }
} }
*self.damage.deref().borrow_mut() = Some(DocumentDamage { *self.damage.borrow_mut() = Some(DocumentDamage {
root: root.to_trusted_node_address(), root: root.to_trusted_node_address(),
level: level, level: level,
}) })
@ -297,7 +295,7 @@ impl Page {
/// Sends a ping to layout and waits for the response. The response will arrive when the /// Sends a ping to layout and waits for the response. The response will arrive when the
/// layout task has finished any pending request messages. /// layout task has finished any pending request messages.
pub fn join_layout(&self) { pub fn join_layout(&self) {
let mut layout_join_port = self.layout_join_port.deref().borrow_mut(); let mut layout_join_port = self.layout_join_port.borrow_mut();
if layout_join_port.is_some() { if layout_join_port.is_some() {
let join_port = replace(&mut *layout_join_port, None); let join_port = replace(&mut *layout_join_port, None);
match join_port { match join_port {
@ -355,15 +353,15 @@ impl Page {
// Layout will let us know when it's done. // Layout will let us know when it's done.
let (join_chan, join_port) = channel(); let (join_chan, join_port) = channel();
let mut layout_join_port = self.layout_join_port.deref().borrow_mut(); let mut layout_join_port = self.layout_join_port.borrow_mut();
*layout_join_port = Some(join_port); *layout_join_port = Some(join_port);
let last_reflow_id = self.last_reflow_id.deref(); let last_reflow_id = &self.last_reflow_id;
last_reflow_id.set(last_reflow_id.get() + 1); last_reflow_id.set(last_reflow_id.get() + 1);
let root: JSRef<Node> = NodeCast::from_ref(*root); let root: JSRef<Node> = NodeCast::from_ref(*root);
let mut damage = self.damage.deref().borrow_mut(); let mut damage = self.damage.borrow_mut();
let window_size = self.window_size.deref().get(); let window_size = self.window_size.get();
// Send new document and relevant styles to layout. // Send new document and relevant styles to layout.
let reflow = box Reflow { let reflow = box Reflow {
@ -378,7 +376,7 @@ impl Page {
id: last_reflow_id.get(), id: last_reflow_id.get(),
}; };
let LayoutChan(ref chan) = *self.layout_chan; let LayoutChan(ref chan) = self.layout_chan;
chan.send(ReflowMsg(reflow)); chan.send(ReflowMsg(reflow));
debug!("script: layout forked") debug!("script: layout forked")
@ -450,5 +448,5 @@ pub struct JSPageInfo {
/// Global static data related to the DOM. /// Global static data related to the DOM.
pub dom_static: GlobalStaticData, pub dom_static: GlobalStaticData,
/// The JavaScript context. /// The JavaScript context.
pub js_context: Untraceable<Rc<Cx>>, pub js_context: Rc<Cx>,
} }

View file

@ -395,14 +395,14 @@ impl ScriptTask {
let mut page = self.page.borrow_mut(); let mut page = self.page.borrow_mut();
for page in page.iter() { for page in page.iter() {
// Only process a resize if layout is idle. // Only process a resize if layout is idle.
let layout_join_port = page.layout_join_port.deref().borrow(); let layout_join_port = page.layout_join_port.borrow();
if layout_join_port.is_none() { if layout_join_port.is_none() {
let mut resize_event = page.resize_event.deref().get(); let mut resize_event = page.resize_event.get();
match resize_event.take() { match resize_event.take() {
Some(size) => resizes.push((page.id, size)), Some(size) => resizes.push((page.id, size)),
None => () None => ()
} }
page.resize_event.deref().set(None); page.resize_event.set(None);
} }
} }
} }
@ -457,7 +457,7 @@ impl ScriptTask {
FromConstellation(ResizeMsg(id, size)) => { FromConstellation(ResizeMsg(id, size)) => {
let mut page = self.page.borrow_mut(); let mut page = self.page.borrow_mut();
let page = page.find(id).expect("resize sent to nonexistent pipeline"); let page = page.find(id).expect("resize sent to nonexistent pipeline");
page.resize_event.deref().set(Some(size)); page.resize_event.set(Some(size));
} }
_ => { _ => {
sequential.push(event); sequential.push(event);
@ -594,15 +594,15 @@ impl ScriptTask {
whose parent has a PipelineId which does not correspond to a pipeline in the script whose parent has a PipelineId which does not correspond to a pipeline in the script
task's page tree. This is a bug."); task's page tree. This is a bug.");
let new_page = { let new_page = {
let window_size = parent_page.window_size.deref().get(); let window_size = parent_page.window_size.get();
Page::new(new_pipeline_id, Some(subpage_id), Page::new(new_pipeline_id, Some(subpage_id),
LayoutChan(layout_chan.downcast_ref::<Sender<layout_interface::Msg>>().unwrap().clone()), LayoutChan(layout_chan.downcast_ref::<Sender<layout_interface::Msg>>().unwrap().clone()),
window_size, window_size,
parent_page.resource_task.deref().clone(), parent_page.resource_task.clone(),
self.constellation_chan.clone(), self.constellation_chan.clone(),
self.js_context.borrow().as_ref().unwrap().clone()) self.js_context.borrow().as_ref().unwrap().clone())
}; };
parent_page.children.deref().borrow_mut().push(Rc::new(new_page)); parent_page.children.borrow_mut().push(Rc::new(new_page));
} }
/// Handles a timer that fired. /// Handles a timer that fired.
@ -622,9 +622,9 @@ impl ScriptTask {
let page = page.find(pipeline_id).expect( let page = page.find(pipeline_id).expect(
"ScriptTask: received a load message for a layout channel that is not associated \ "ScriptTask: received a load message for a layout channel that is not associated \
with this script task. This is a bug."); with this script task. This is a bug.");
let last_reflow_id = page.last_reflow_id.deref().get(); let last_reflow_id = page.last_reflow_id.get();
if last_reflow_id == reflow_id { if last_reflow_id == reflow_id {
let mut layout_join_port = page.layout_join_port.deref().borrow_mut(); let mut layout_join_port = page.layout_join_port.borrow_mut();
*layout_join_port = None; *layout_join_port = None;
} }
@ -649,7 +649,7 @@ impl ScriptTask {
let mut page = self.page.borrow_mut(); let mut page = self.page.borrow_mut();
let page = page.find(id).expect("Received resize message for PipelineId not associated let page = page.find(id).expect("Received resize message for PipelineId not associated
with a page in the page tree. This is a bug."); with a page in the page tree. This is a bug.");
page.window_size.deref().set(new_size); page.window_size.set(new_size);
match &mut *page.mut_url() { match &mut *page.mut_url() {
&Some((_, ref mut needs_reflow)) => *needs_reflow = true, &Some((_, ref mut needs_reflow)) => *needs_reflow = true,
&None => (), &None => (),
@ -866,7 +866,7 @@ impl ScriptTask {
let window = { let window = {
let page = get_page(&*self.page.borrow(), pipeline_id); let page = get_page(&*self.page.borrow(), pipeline_id);
page.window_size.deref().set(new_size); page.window_size.set(new_size);
let frame = page.frame(); let frame = page.frame();
if frame.is_some() { if frame.is_some() {
@ -911,7 +911,7 @@ impl ScriptTask {
let page = get_page(&*self.page.borrow(), pipeline_id); let page = get_page(&*self.page.borrow(), pipeline_id);
let frame = page.frame(); let frame = page.frame();
if frame.is_some() { if frame.is_some() {
let in_layout = page.layout_join_port.deref().borrow().is_some(); let in_layout = page.layout_join_port.borrow().is_some();
if in_layout { if in_layout {
page.pending_reflows.set(page.pending_reflows.get() + 1); page.pending_reflows.set(page.pending_reflows.get() + 1);
} else { } else {
@ -1062,7 +1062,7 @@ fn shut_down_layout(page_tree: &Rc<Page>, rt: *mut JSRuntime) {
// Tell the layout task to begin shutting down, and wait until it // Tell the layout task to begin shutting down, and wait until it
// processed this message. // processed this message.
let (response_chan, response_port) = channel(); let (response_chan, response_port) = channel();
let LayoutChan(ref chan) = *page.layout_chan; let LayoutChan(ref chan) = page.layout_chan;
chan.send(layout_interface::PrepareToExitMsg(response_chan)); chan.send(layout_interface::PrepareToExitMsg(response_chan));
response_port.recv(); response_port.recv();
} }
@ -1085,7 +1085,7 @@ fn shut_down_layout(page_tree: &Rc<Page>, rt: *mut JSRuntime) {
// Destroy the layout task. If there were node leaks, layout will now crash safely. // Destroy the layout task. If there were node leaks, layout will now crash safely.
for page in page_tree.iter() { for page in page_tree.iter() {
let LayoutChan(ref chan) = *page.layout_chan; let LayoutChan(ref chan) = page.layout_chan;
chan.send(layout_interface::ExitNowMsg); chan.send(layout_interface::ExitNowMsg);
} }
} }