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> {
#[inline(always)]
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)]
fn borrow_layout_data<'a>(&'a self) -> Ref<'a,Option<LayoutDataWrapper>> {
unsafe {
mem::transmute(self.get().layout_data.deref().borrow())
mem::transmute(self.get().layout_data.borrow())
}
}
#[inline(always)]
fn mutate_layout_data<'a>(&'a self) -> RefMut<'a,Option<LayoutDataWrapper>> {
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!")
}
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)
}
}
@ -187,7 +187,7 @@ impl<'ln> TLayoutNode for LayoutNode<'ln> {
unsafe {
if self.get().is_text() {
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() {
let input: JS<HTMLInputElement> = self.get_jsmanaged().transmute_copy();
input.get_value_for_layout()
@ -390,7 +390,7 @@ pub struct LayoutElement<'le> {
impl<'le> LayoutElement<'le> {
pub fn style_attribute(&self) -> &'le Option<PropertyDeclarationBlock> {
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>
mem::transmute(style)
};
@ -667,7 +667,7 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
#[inline(always)]
pub fn borrow_layout_data<'a>(&'a self) -> Ref<'a,Option<LayoutDataWrapper>> {
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)]
pub fn mutate_layout_data<'a>(&'a self) -> RefMut<'a,Option<LayoutDataWrapper>> {
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) => {
unsafe {
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
}

View file

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

View file

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

View file

@ -67,7 +67,7 @@ impl<'a> GlobalRef<'a> {
pub fn resource_task(&self) -> ResourceTask {
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(),
}
}

View file

@ -13,7 +13,7 @@
//! through `ProxyTraps.trace` otherwise.)
//! 2. `_trace` calls `Foo::trace()` (an implementation of `JSTraceable`).
//! 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
//! `trace_reflector()`.
@ -41,7 +41,18 @@ use script_traits::ScriptControlChan;
use std::collections::hashmap::HashMap;
use collections::hash::Hash;
use style::PropertyDeclarationBlock;
use std::comm::{Receiver, Sender};
use hubbub::hubbub::QuirksMode;
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> {
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> {
fn trace(&self, trc: *mut JSTracer) {
self.borrow().trace(trc)
@ -157,7 +109,7 @@ impl<T: JSTraceable> JSTraceable for RefCell<T> {
impl<T: JSTraceable> JSTraceable for Rc<T> {
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> {
fn trace(&self, trc: *mut JSTracer) {
self.get().trace(trc)
}
}
impl JSTraceable for Traceable<*mut JSObject> {
impl JSTraceable for *mut JSObject {
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) {
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!(uint, u8, u16, u32, u64)
untraceable!(int, i8, i16, i32, i64)
untraceable!(Untraceable<T>)
untraceable!(Sender<T>)
untraceable!(Receiver<T>)
untraceable!(ImageCacheTask, ScriptControlChan)
untraceable!(Atom, Namespace)
untraceable!(Atom, Namespace, Timer)
untraceable!(PropertyDeclarationBlock)
// These three are interdependent, if you plan to put jsmanaged data
// in one of these make sure it is propagated properly to containing structs
untraceable!(SubpageId, WindowSizeData, PipelineId)
untraceable!(QuirksMode)
untraceable!(Cx)
untraceable!(ResponseHeaderCollection, RequestHeaderCollection, Method)
untraceable!(ConstellationChan)
untraceable!(LayoutChan)
untraceable!(WindowProxyHandler)
impl<'a> JSTraceable for &'a str {
#[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::global::GlobalRef;
use dom::bindings::js::{JS, Temporary, Root};
use dom::bindings::trace::Untraceable;
use dom::browsercontext;
use dom::window;
use servo_util::str::DOMString;
@ -50,15 +49,17 @@ use js::{JSPROP_ENUMERATE, JSPROP_READONLY, JSPROP_PERMANENT};
use js::JSFUN_CONSTRUCTOR;
use js;
pub struct WindowProxyHandler(pub *const libc::c_void);
#[allow(raw_pointer_deriving)]
#[jstraceable]
pub struct GlobalStaticData {
pub windowproxy_handler: Untraceable<*const libc::c_void>,
pub windowproxy_handler: WindowProxyHandler,
}
pub fn 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>))
.unwrap()
.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/. */
use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::Reflectable;
use dom::bindings::utils::{Reflectable, WindowProxyHandler};
use dom::document::Document;
use dom::window::Window;
@ -12,7 +11,6 @@ use js::jsapi::JSObject;
use js::glue::{WrapperNew, CreateWrapperProxyHandler, ProxyTraps};
use js::rust::with_compartment;
use libc::c_void;
use std::ptr;
#[allow(raw_pointer_deriving)]
@ -20,7 +18,7 @@ use std::ptr;
pub struct BrowserContext {
history: Vec<SessionHistoryEntry>,
active_index: uint,
window_proxy: Traceable<*mut JSObject>,
window_proxy: *mut JSObject,
}
impl BrowserContext {
@ -28,7 +26,7 @@ impl BrowserContext {
let mut context = BrowserContext {
history: vec!(SessionHistoryEntry::new(document)),
active_index: 0,
window_proxy: Traceable::new(ptr::null_mut()),
window_proxy: ptr::null_mut(),
};
context.create_window_proxy();
context
@ -44,8 +42,8 @@ impl BrowserContext {
}
pub fn window_proxy(&self) -> *mut JSObject {
assert!(self.window_proxy.deref().is_not_null());
*self.window_proxy
assert!(self.window_proxy.is_not_null());
self.window_proxy
}
fn create_window_proxy(&mut self) {
@ -53,16 +51,16 @@ impl BrowserContext {
let page = win.deref().page();
let js_info = page.js_info();
let handler = js_info.as_ref().unwrap().dom_static.windowproxy_handler;
assert!(handler.deref().is_not_null());
let WindowProxyHandler(handler) = js_info.as_ref().unwrap().dom_static.windowproxy_handler;
assert!(handler.is_not_null());
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 {
WrapperNew(cx, parent, *handler.deref())
WrapperNew(cx, parent, handler)
});
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
};
pub fn new_window_proxy_handler() -> *const c_void {
pub fn new_window_proxy_handler() -> WindowProxyHandler {
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::global::{GlobalRef, GlobalField};
use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::trace::Untraceable;
use dom::bindings::utils::{Reflector, Reflectable, reflect_dom_object};
use dom::htmlcanvaselement::HTMLCanvasElement;
@ -21,7 +20,7 @@ use canvas::canvas_render_task::{CanvasMsg, CanvasRenderTask, ClearRect, Close,
pub struct CanvasRenderingContext2D {
reflector_: Reflector,
global: GlobalField,
renderer: Untraceable<Sender<CanvasMsg>>,
renderer: Sender<CanvasMsg>,
canvas: JS<HTMLCanvasElement>,
}
@ -30,7 +29,7 @@ impl CanvasRenderingContext2D {
CanvasRenderingContext2D {
reflector_: Reflector::new(),
global: GlobalField::from_rooted(global),
renderer: Untraceable::new(CanvasRenderTask::start(size)),
renderer: CanvasRenderTask::start(size),
canvas: JS::from_rooted(canvas),
}
}
@ -41,7 +40,7 @@ impl CanvasRenderingContext2D {
}
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) {
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) {
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) {
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::error::{Fallible, ErrorResult, IndexSize};
use dom::bindings::js::JSRef;
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector};
use dom::document::Document;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
@ -21,7 +20,7 @@ use std::cell::RefCell;
#[must_root]
pub struct CharacterData {
pub node: Node,
pub data: Traceable<RefCell<DOMString>>,
pub data: RefCell<DOMString>,
}
impl CharacterDataDerived for EventTarget {
@ -39,31 +38,31 @@ impl CharacterData {
pub fn new_inherited(id: NodeTypeId, data: DOMString, document: JSRef<Document>) -> CharacterData {
CharacterData {
node: Node::new_inherited(id, document),
data: Traceable::new(RefCell::new(data)),
data: RefCell::new(data),
}
}
}
impl<'a> CharacterDataMethods for JSRef<'a, CharacterData> {
fn Data(self) -> DOMString {
self.data.deref().borrow().clone()
self.data.borrow().clone()
}
fn SetData(self, arg: DOMString) -> ErrorResult {
*self.data.deref().borrow_mut() = arg;
*self.data.borrow_mut() = arg;
Ok(())
}
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> {
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 {
self.data.deref().borrow_mut().push_str(arg.as_slice());
self.data.borrow_mut().push_str(arg.as_slice());
Ok(())
}
@ -76,7 +75,7 @@ impl<'a> CharacterDataMethods for JSRef<'a, CharacterData> {
}
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 {
return Err(IndexSize);
}
@ -85,10 +84,10 @@ impl<'a> CharacterDataMethods for JSRef<'a, CharacterData> {
} else {
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(self.data.deref().borrow().as_slice().slice((offset + count) as uint, length as uint));
*self.data.deref().borrow_mut() = data;
data.push_str(self.data.borrow().as_slice().slice((offset + count) as uint, length as uint));
*self.data.borrow_mut() = data;
// FIXME: Once we have `Range`, we should implement step7 to step11
Ok(())
}

View file

@ -9,7 +9,6 @@ use dom::bindings::codegen::InheritTypes::{EventCast, CustomEventDerived};
use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::event::{Event, EventTypeId, CustomEventTypeId};
use js::jsapi::JSContext;
@ -22,7 +21,7 @@ use std::cell::Cell;
#[must_root]
pub struct CustomEvent {
event: Event,
detail: Traceable<Cell<Traceable<JSVal>>>,
detail: Cell<JSVal>,
}
impl CustomEventDerived for Event {
@ -35,7 +34,7 @@ impl CustomEvent {
fn new_inherited(type_id: EventTypeId) -> CustomEvent {
CustomEvent {
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> {
fn Detail(self, _cx: *mut JSContext) -> JSVal {
*self.detail.deref().get()
self.detail.get()
}
fn InitCustomEvent(self,
@ -67,7 +66,7 @@ impl<'a> CustomEventMethods for JSRef<'a, CustomEvent> {
can_bubble: bool,
cancelable: bool,
detail: JSVal) {
self.detail.deref().set(Traceable::new(detail));
self.detail.set(detail);
let event: JSRef<Event> = EventCast::from_ref(self);
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::global;
use dom::bindings::js::{JSRef, Temporary, RootCollection};
use dom::bindings::trace::Untraceable;
use dom::bindings::utils::{Reflectable, Reflector};
use dom::eventtarget::{EventTarget, EventTargetHelpers};
use dom::eventtarget::WorkerGlobalScopeTypeId;
@ -40,10 +39,10 @@ use url::Url;
#[must_root]
pub struct DedicatedWorkerGlobalScope {
workerglobalscope: WorkerGlobalScope,
receiver: Untraceable<Receiver<ScriptMsg>>,
receiver: Receiver<ScriptMsg>,
/// Sender to the parent thread.
parent_sender: ScriptChan,
worker: Untraceable<TrustedWorkerAddress>,
worker: TrustedWorkerAddress,
}
impl DedicatedWorkerGlobalScope {
@ -59,9 +58,9 @@ impl DedicatedWorkerGlobalScope {
workerglobalscope: WorkerGlobalScope::new_inherited(
DedicatedGlobalScope, worker_url, cx, resource_task,
own_sender),
receiver: Untraceable::new(receiver),
receiver: receiver,
parent_sender: parent_sender,
worker: Untraceable::new(worker),
worker: worker,
}
}
@ -120,7 +119,7 @@ impl DedicatedWorkerGlobalScope {
let target: JSRef<EventTarget> =
EventTargetCast::from_ref(*global);
loop {
match global.receiver.deref().recv_opt() {
match global.receiver.recv_opt() {
Ok(DOMMessage(data, nbytes)) => {
let mut message = UndefinedValue();
unsafe {
@ -160,7 +159,7 @@ impl<'a> DedicatedWorkerGlobalScopeMethods for JSRef<'a, DedicatedWorkerGlobalSc
}
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> {
@ -181,7 +180,7 @@ trait PrivateDedicatedWorkerGlobalScopeHelpers {
impl<'a> PrivateDedicatedWorkerGlobalScopeHelpers for JSRef<'a, DedicatedWorkerGlobalScope> {
fn delayed_release_worker(self) {
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::js::{MutNullableJS, JS, JSRef, Temporary, OptionalSettable, TemporaryPushable};
use dom::bindings::js::OptionalRootable;
use dom::bindings::trace::{Traceable, Untraceable};
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::bindings::utils::{xml_name_type, InvalidXMLName, Name, QName};
use dom::comment::Comment;
@ -81,14 +80,14 @@ pub struct Document {
pub node: Node,
reflector_: Reflector,
pub window: JS<Window>,
idmap: Traceable<RefCell<HashMap<Atom, Vec<JS<Element>>>>>,
idmap: RefCell<HashMap<Atom, Vec<JS<Element>>>>,
implementation: MutNullableJS<DOMImplementation>,
content_type: DOMString,
last_modified: Traceable<RefCell<Option<DOMString>>>,
pub encoding_name: Traceable<RefCell<DOMString>>,
last_modified: RefCell<Option<DOMString>>,
pub encoding_name: RefCell<DOMString>,
pub is_html_document: bool,
url: Untraceable<Url>,
quirks_mode: Untraceable<Cell<QuirksMode>>,
url: Url,
quirks_mode: Cell<QuirksMode>,
images: MutNullableJS<HTMLCollection>,
embeds: MutNullableJS<HTMLCollection>,
links: MutNullableJS<HTMLCollection>,
@ -177,23 +176,23 @@ pub trait DocumentHelpers<'a> {
impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
fn url(self) -> &'a Url {
&*self.extended_deref().url
&self.extended_deref().url
}
fn quirks_mode(self) -> QuirksMode {
self.quirks_mode.deref().get()
self.quirks_mode.get()
}
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) {
*self.last_modified.deref().borrow_mut() = Some(value);
*self.last_modified.borrow_mut() = Some(value);
}
fn set_encoding_name(self, name: DOMString) {
*self.encoding_name.deref().borrow_mut() = name;
*self.encoding_name.borrow_mut() = name;
}
fn content_changed(self) {
@ -213,7 +212,7 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
fn unregister_named_element(self,
to_unregister: JSRef<Element>,
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) {
None => false,
Some(elements) => {
@ -240,7 +239,7 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
});
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
// Use mangle() when it exists again.
@ -309,7 +308,7 @@ impl Document {
node: Node::new_without_doc(DocumentNodeTypeId),
reflector_: Reflector::new(),
window: JS::from_rooted(window),
idmap: Traceable::new(RefCell::new(HashMap::new())),
idmap: RefCell::new(HashMap::new()),
implementation: Default::default(),
content_type: match content_type {
Some(string) => string.clone(),
@ -320,12 +319,12 @@ impl Document {
NonHTMLDocument => "application/xml".to_string()
}
},
last_modified: Traceable::new(RefCell::new(None)),
url: Untraceable::new(url),
last_modified: RefCell::new(None),
url: url,
// 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
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,
images: Default::default(),
embeds: Default::default(),
@ -419,7 +418,7 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
// http://dom.spec.whatwg.org/#dom-document-compatmode
fn CompatMode(self) -> DOMString {
match self.quirks_mode.deref().get() {
match self.quirks_mode.get() {
LimitedQuirks | NoQuirks => "CSS1Compat".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
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
@ -474,7 +473,7 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
// http://dom.spec.whatwg.org/#dom-nonelementparentnode-getelementbyid
fn GetElementById(self, id: DOMString) -> Option<Temporary<Element>> {
let id = Atom::from_slice(id.as_slice());
match self.idmap.deref().borrow().find(&id) {
match self.idmap.borrow().find(&id) {
None => None,
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() {
if child.is_text() {
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::js::{MutNullableJS, JS, JSRef, Temporary, TemporaryPushable};
use dom::bindings::js::{OptionalSettable, OptionalRootable, Root};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector};
use dom::bindings::error::{ErrorResult, Fallible, NamespaceError, InvalidCharacter, Syntax};
use dom::bindings::utils::{QName, Name, InvalidXMLName, xml_name_type};
@ -51,7 +50,7 @@ pub struct Element {
pub namespace: Namespace,
pub prefix: Option<DOMString>,
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>,
class_list: MutNullableJS<DOMTokenList>,
}
@ -159,7 +158,7 @@ impl Element {
attrs: RefCell::new(vec!()),
attr_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 base_url = doc.deref().url().clone();
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" => {
let node: JSRef<Node> = NodeCast::from_ref(*self);
@ -875,7 +874,7 @@ impl<'a> VirtualMethods for JSRef<'a, Element> {
match name.as_slice() {
"style" => {
*self.deref().style_attribute.deref().borrow_mut() = None;
*self.deref().style_attribute.borrow_mut() = None;
}
"id" => {
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::global::GlobalRef;
use dom::bindings::js::{MutNullableJS, JSRef, Temporary};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::eventtarget::EventTarget;
use servo_util::str::DOMString;
@ -43,16 +42,16 @@ pub struct Event {
reflector_: Reflector,
pub current_target: MutNullableJS<EventTarget>,
pub target: MutNullableJS<EventTarget>,
type_: Traceable<RefCell<DOMString>>,
pub phase: Traceable<Cell<EventPhase>>,
pub canceled: Traceable<Cell<bool>>,
pub stop_propagation: Traceable<Cell<bool>>,
pub stop_immediate: Traceable<Cell<bool>>,
pub cancelable: Traceable<Cell<bool>>,
pub bubbles: Traceable<Cell<bool>>,
pub trusted: Traceable<Cell<bool>>,
pub dispatching: Traceable<Cell<bool>>,
pub initialized: Traceable<Cell<bool>>,
type_: RefCell<DOMString>,
pub phase: Cell<EventPhase>,
pub canceled: Cell<bool>,
pub stop_propagation: Cell<bool>,
pub stop_immediate: Cell<bool>,
pub cancelable: Cell<bool>,
pub bubbles: Cell<bool>,
pub trusted: Cell<bool>,
pub dispatching: Cell<bool>,
pub initialized: Cell<bool>,
timestamp: u64,
}
@ -63,16 +62,16 @@ impl Event {
reflector_: Reflector::new(),
current_target: Default::default(),
target: Default::default(),
phase: Traceable::new(Cell::new(PhaseNone)),
type_: Traceable::new(RefCell::new("".to_string())),
canceled: Traceable::new(Cell::new(false)),
cancelable: Traceable::new(Cell::new(true)),
bubbles: Traceable::new(Cell::new(false)),
trusted: Traceable::new(Cell::new(false)),
dispatching: Traceable::new(Cell::new(false)),
stop_propagation: Traceable::new(Cell::new(false)),
stop_immediate: Traceable::new(Cell::new(false)),
initialized: Traceable::new(Cell::new(false)),
phase: Cell::new(PhaseNone),
type_: RefCell::new("".to_string()),
canceled: Cell::new(false),
cancelable: Cell::new(true),
bubbles: Cell::new(false),
trusted: Cell::new(false),
dispatching: Cell::new(false),
stop_propagation: Cell::new(false),
stop_immediate: Cell::new(false),
initialized: Cell::new(false),
timestamp: time::get_time().sec as u64,
}
}
@ -88,7 +87,7 @@ impl Event {
can_bubble: bool,
cancelable: bool) -> Temporary<Event> {
let event = Event::new_uninitialized(global).root();
event.deref().InitEvent(type_, can_bubble, cancelable);
event.InitEvent(type_, can_bubble, cancelable);
Temporary::from_rooted(*event)
}
@ -101,11 +100,11 @@ impl Event {
impl<'a> EventMethods for JSRef<'a, Event> {
fn EventPhase(self) -> u16 {
self.phase.deref().get() as u16
self.phase.get() as u16
}
fn Type(self) -> DOMString {
self.type_.deref().borrow().clone()
self.type_.borrow().clone()
}
fn GetTarget(self) -> Option<Temporary<EventTarget>> {
@ -117,30 +116,30 @@ impl<'a> EventMethods for JSRef<'a, Event> {
}
fn DefaultPrevented(self) -> bool {
self.canceled.deref().get()
self.canceled.get()
}
fn PreventDefault(self) {
if self.cancelable.deref().get() {
self.canceled.deref().set(true)
if self.cancelable.get() {
self.canceled.set(true)
}
}
fn StopPropagation(self) {
self.stop_propagation.deref().set(true);
self.stop_propagation.set(true);
}
fn StopImmediatePropagation(self) {
self.stop_immediate.deref().set(true);
self.stop_propagation.deref().set(true);
self.stop_immediate.set(true);
self.stop_propagation.set(true);
}
fn Bubbles(self) -> bool {
self.bubbles.deref().get()
self.bubbles.get()
}
fn Cancelable(self) -> bool {
self.cancelable.deref().get()
self.cancelable.get()
}
fn TimeStamp(self) -> u64 {
@ -151,22 +150,22 @@ impl<'a> EventMethods for JSRef<'a, Event> {
type_: DOMString,
bubbles: bool,
cancelable: bool) {
self.initialized.deref().set(true);
if self.dispatching.deref().get() {
self.initialized.set(true);
if self.dispatching.get() {
return;
}
self.stop_propagation.deref().set(false);
self.stop_immediate.deref().set(false);
self.canceled.deref().set(false);
self.trusted.deref().set(false);
self.stop_propagation.set(false);
self.stop_immediate.set(false);
self.canceled.set(false);
self.trusted.set(false);
self.target.clear();
*self.type_.deref().borrow_mut() = type_;
self.bubbles.deref().set(bubbles);
self.cancelable.deref().set(cancelable);
*self.type_.borrow_mut() = type_;
self.bubbles.set(bubbles);
self.cancelable.set(cancelable);
}
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>,
pseudo_target: Option<JSRef<'b, EventTarget>>,
event: JSRef<Event>) -> bool {
assert!(!event.deref().dispatching.deref().get());
assert!(!event.dispatching.get());
event.target.assign(Some(match pseudo_target {
Some(pseudo_target) => pseudo_target,
None => target.clone(),
}));
event.dispatching.deref().set(true);
event.dispatching.set(true);
let type_ = event.Type();
//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();
target_node.ancestors().map(|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!()
};
event.deref().phase.deref().set(PhaseCapturing);
event.phase.set(PhaseCapturing);
//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.
let _ = listener.HandleEvent_(**cur_target, event, ReportExceptions);
if event.deref().stop_immediate.deref().get() {
if event.stop_immediate.get() {
break;
}
}
event.deref().stop_propagation.deref().get()
event.stop_propagation.get()
}
None => false
};
@ -65,17 +65,17 @@ pub fn dispatch_event<'a, 'b>(target: JSRef<'a, EventTarget>,
}
/* at target */
if !event.deref().stop_propagation.deref().get() {
event.phase.deref().set(PhaseAtTarget);
if !event.stop_propagation.get() {
event.phase.set(PhaseAtTarget);
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 listener in listeners.iter() {
// Explicitly drop any exception on the floor.
let _ = listener.HandleEvent_(target, event, ReportExceptions);
if event.deref().stop_immediate.deref().get() {
if event.stop_immediate.get() {
break;
}
}
@ -83,23 +83,23 @@ pub fn dispatch_event<'a, 'b>(target: JSRef<'a, EventTarget>,
}
/* bubbling */
if event.deref().bubbles.deref().get() && !event.deref().stop_propagation.deref().get() {
event.deref().phase.deref().set(PhaseBubbling);
if event.bubbles.get() && !event.stop_propagation.get() {
event.phase.set(PhaseBubbling);
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) => {
event.deref().current_target.assign(Some(cur_target.deref().clone()));
event.current_target.assign(Some(cur_target.deref().clone()));
for listener in listeners.iter() {
// Explicitly drop any exception on the floor.
let _ = listener.HandleEvent_(**cur_target, event, ReportExceptions);
if event.deref().stop_immediate.deref().get() {
if event.stop_immediate.get() {
break;
}
}
event.deref().stop_propagation.deref().get()
event.stop_propagation.get()
}
None => false
};
@ -131,8 +131,8 @@ pub fn dispatch_event<'a, 'b>(target: JSRef<'a, EventTarget>,
let _ = chain.pop();
}
event.dispatching.deref().set(false);
event.phase.deref().set(PhaseNone);
event.dispatching.set(false);
event.phase.set(PhaseNone);
event.current_target.clear();
!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::error::{Fallible, InvalidState, report_pending_exception};
use dom::bindings::js::JSRef;
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector};
use dom::event::Event;
use dom::eventdispatcher::dispatch_event;
@ -70,7 +69,7 @@ pub struct EventListenerEntry {
pub struct EventTarget {
pub type_id: EventTargetTypeId,
reflector_: Reflector,
handlers: Traceable<RefCell<HashMap<DOMString, Vec<EventListenerEntry>>>>,
handlers: RefCell<HashMap<DOMString, Vec<EventListenerEntry>>>,
}
impl EventTarget {
@ -78,19 +77,19 @@ impl EventTarget {
EventTarget {
type_id: type_id,
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>> {
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()
})
}
pub fn get_listeners_for(&self, type_: &str, desired_phase: ListenerPhase)
-> 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);
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,
target: Option<JSRef<EventTarget>>,
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);
}
Ok(dispatch_event(self, target, event))
@ -131,7 +130,7 @@ impl<'a> EventTargetHelpers for JSRef<'a, EventTarget> {
fn set_inline_event_listener(self,
ty: DOMString,
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 idx = entries.iter().position(|&entry| {
match entry.listener {
@ -161,7 +160,7 @@ impl<'a> EventTargetHelpers for JSRef<'a, EventTarget> {
}
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);
entries.and_then(|entries| entries.iter().find(|entry| {
match entry.listener {
@ -224,7 +223,7 @@ impl<'a> EventTargetHelpers for JSRef<'a, EventTarget> {
}
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) {
match 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 phase = if capture { Capturing } else { Bubbling };
let new_entry = EventListenerEntry {
@ -256,7 +255,7 @@ impl<'a> EventTargetMethods for JSRef<'a, EventTarget> {
capture: bool) {
match 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);
for entry in entry.iter_mut() {
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::global::{GlobalRef, GlobalField};
use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::blob::Blob;
use dom::file::File;
@ -29,7 +28,7 @@ pub enum FormDatum {
#[jstraceable]
#[must_root]
pub struct FormData {
data: Traceable<RefCell<HashMap<DOMString, Vec<FormDatum>>>>,
data: RefCell<HashMap<DOMString, Vec<FormDatum>>>,
reflector_: Reflector,
global: GlobalField,
form: Option<JS<HTMLFormElement>>
@ -38,7 +37,7 @@ pub struct FormData {
impl FormData {
fn new_inherited(form: Option<JSRef<HTMLFormElement>>, global: &GlobalRef) -> FormData {
FormData {
data: Traceable::new(RefCell::new(HashMap::new())),
data: RefCell::new(HashMap::new()),
reflector_: Reflector::new(),
global: GlobalField::from_rooted(global),
form: form.map(|f| JS::from_rooted(f)),
@ -59,22 +58,22 @@ impl<'a> FormDataMethods for JSRef<'a, FormData> {
#[allow(unrooted_must_root)]
fn Append(self, name: DOMString, value: JSRef<Blob>, filename: Option<DOMString>) {
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());});
}
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()));});
}
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> {
if self.data.deref().borrow().contains_key_equiv(&name) {
match (*self.data.deref().borrow())[name][0].clone() {
if self.data.borrow().contains_key_equiv(&name) {
match (*self.data.borrow())[name][0].clone() {
StringData(ref s) => Some(eString(s.clone())),
FileData(ref f) => {
Some(eFile(f.clone()))
@ -86,16 +85,16 @@ impl<'a> FormDataMethods for JSRef<'a, FormData> {
}
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)]
fn Set(self, name: DOMString, value: JSRef<Blob>, filename: Option<DOMString>) {
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) {
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::global::Window;
use dom::bindings::js::{MutNullableJS, JSRef, Temporary, OptionalSettable};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector};
use dom::canvasrenderingcontext2d::CanvasRenderingContext2D;
use dom::document::Document;
@ -33,9 +32,9 @@ static DefaultHeight: u32 = 150;
#[must_root]
pub struct HTMLCanvasElement {
pub htmlelement: HTMLElement,
context: Traceable<MutNullableJS<CanvasRenderingContext2D>>,
width: Traceable<Cell<u32>>,
height: Traceable<Cell<u32>>,
context: MutNullableJS<CanvasRenderingContext2D>,
width: Cell<u32>,
height: Cell<u32>,
}
impl HTMLCanvasElementDerived for EventTarget {
@ -48,9 +47,9 @@ impl HTMLCanvasElement {
fn new_inherited(localName: DOMString, document: JSRef<Document>) -> HTMLCanvasElement {
HTMLCanvasElement {
htmlelement: HTMLElement::new_inherited(HTMLCanvasElementTypeId, localName, document),
context: Traceable::new(Default::default()),
width: Traceable::new(Cell::new(DefaultWidth)),
height: Traceable::new(Cell::new(DefaultHeight)),
context: Default::default(),
width: Cell::new(DefaultWidth),
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::{HTMLElementCast, HTMLIFrameElementDerived};
use dom::bindings::js::{JSRef, Temporary, OptionalRootable};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector};
use dom::document::Document;
use dom::element::{HTMLIFrameElementTypeId, Element};
@ -44,8 +43,8 @@ enum SandboxAllowance {
#[must_root]
pub struct HTMLIFrameElement {
pub htmlelement: HTMLElement,
pub size: Traceable<Cell<Option<IFrameSize>>>,
pub sandbox: Traceable<Cell<Option<u8>>>,
pub size: Cell<Option<IFrameSize>>,
pub sandbox: Cell<Option<u8>>,
}
impl HTMLIFrameElementDerived for EventTarget {
@ -69,7 +68,7 @@ pub trait HTMLIFrameElementHelpers {
impl<'a> HTMLIFrameElementHelpers for JSRef<'a, HTMLIFrameElement> {
fn is_sandboxed(self) -> bool {
self.sandbox.deref().get().is_some()
self.sandbox.get().is_some()
}
fn get_url(self) -> Option<Url> {
@ -103,12 +102,12 @@ impl<'a> HTMLIFrameElementHelpers for JSRef<'a, HTMLIFrameElement> {
let page = window.deref().page();
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,
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));
}
}
@ -117,8 +116,8 @@ impl HTMLIFrameElement {
fn new_inherited(localName: DOMString, document: JSRef<Document>) -> HTMLIFrameElement {
HTMLIFrameElement {
htmlelement: HTMLElement::new_inherited(HTMLIFrameElementTypeId, localName, document),
size: Traceable::new(Cell::new(None)),
sandbox: Traceable::new(Cell::new(None)),
size: Cell::new(None),
sandbox: Cell::new(None),
}
}
@ -151,14 +150,14 @@ impl<'a> HTMLIFrameElementMethods for JSRef<'a, HTMLIFrameElement> {
}
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 children = window.deref().page.children.deref().borrow();
let children = window.deref().page.children.borrow();
let child = children.iter().find(|child| {
child.subpage_id.unwrap() == size.subpage_id
});
child.and_then(|page| {
page.frame.deref().borrow().as_ref().map(|frame| {
page.frame.borrow().as_ref().map(|frame| {
Temporary::new(frame.window.clone())
})
})
@ -191,7 +190,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLIFrameElement> {
_ => AllowNothing
} as u8;
}
self.deref().sandbox.deref().set(Some(modes));
self.deref().sandbox.set(Some(modes));
}
if "src" == name.as_slice() {
@ -209,7 +208,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLIFrameElement> {
}
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::InheritTypes::{NodeCast, ElementCast, HTMLElementCast, HTMLImageElementDerived};
use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::trace::Untraceable;
use dom::bindings::utils::{Reflectable, Reflector};
use dom::document::Document;
use dom::element::{Element, HTMLImageElementTypeId};
@ -29,7 +28,7 @@ use std::cell::RefCell;
#[must_root]
pub struct HTMLImageElement {
pub htmlelement: HTMLElement,
image: Untraceable<RefCell<Option<Url>>>,
image: RefCell<Option<Url>>,
}
impl HTMLImageElementDerived for EventTarget {
@ -52,13 +51,13 @@ impl<'a> PrivateHTMLImageElementHelpers for JSRef<'a, HTMLImageElement> {
let image_cache = &window.image_cache_task;
match value {
None => {
*self.image.deref().borrow_mut() = None;
*self.image.borrow_mut() = None;
}
Some((src, base_url)) => {
let img_url = UrlParser::new().base_url(base_url).parse(src.as_slice());
// FIXME: handle URL parse errors more gracefully.
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
// handle.
@ -75,7 +74,7 @@ impl HTMLImageElement {
fn new_inherited(localName: DOMString, document: JSRef<Document>) -> HTMLImageElement {
HTMLImageElement {
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();
match UrlParser::new().base_url(&window.deref().page().get_url()).parse(href) {
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));
}
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) {
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("-->");
}
@ -82,11 +82,11 @@ fn serialize_text(text: JSRef<Text>, html: &mut String) {
"style" | "script" | "xmp" | "iframe" |
"noembed" | "noframes" | "plaintext" |
"noscript" if elem.deref().namespace == ns!(HTML)
=> html.push_str(text.deref().characterdata.data.deref().borrow().as_slice()),
_ => escape(text.deref().characterdata.data.deref().borrow().as_slice(), false, html)
=> html.push_str(text.deref().characterdata.data.borrow().as_slice()),
_ => 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(processing_instruction.deref().target.as_slice());
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("?>");
}
@ -120,7 +120,7 @@ fn serialize_elem(elem: JSRef<Element>, open_elements: &mut Vec<String>, html: &
match node.first_child().map(|child| child.root()) {
Some(ref child) if child.is_text() => {
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');
}
},

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 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));
}
}

View file

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

View file

@ -10,7 +10,6 @@ use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef;
use dom::bindings::global;
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::event::{Event, MouseEventTypeId};
use dom::eventtarget::EventTarget;
@ -24,15 +23,15 @@ use std::default::Default;
#[must_root]
pub struct MouseEvent {
pub mouseevent: UIEvent,
pub screen_x: Traceable<Cell<i32>>,
pub screen_y: Traceable<Cell<i32>>,
pub client_x: Traceable<Cell<i32>>,
pub client_y: Traceable<Cell<i32>>,
pub ctrl_key: Traceable<Cell<bool>>,
pub shift_key: Traceable<Cell<bool>>,
pub alt_key: Traceable<Cell<bool>>,
pub meta_key: Traceable<Cell<bool>>,
pub button: Traceable<Cell<i16>>,
pub screen_x: Cell<i32>,
pub screen_y: Cell<i32>,
pub client_x: Cell<i32>,
pub client_y: Cell<i32>,
pub ctrl_key: Cell<bool>,
pub shift_key: Cell<bool>,
pub alt_key: Cell<bool>,
pub meta_key: Cell<bool>,
pub button: Cell<i16>,
pub related_target: MutNullableJS<EventTarget>
}
@ -46,15 +45,15 @@ impl MouseEvent {
fn new_inherited() -> MouseEvent {
MouseEvent {
mouseevent: UIEvent::new_inherited(MouseEventTypeId),
screen_x: Traceable::new(Cell::new(0)),
screen_y: Traceable::new(Cell::new(0)),
client_x: Traceable::new(Cell::new(0)),
client_y: Traceable::new(Cell::new(0)),
ctrl_key: Traceable::new(Cell::new(false)),
shift_key: Traceable::new(Cell::new(false)),
alt_key: Traceable::new(Cell::new(false)),
meta_key: Traceable::new(Cell::new(false)),
button: Traceable::new(Cell::new(0)),
screen_x: Cell::new(0),
screen_y: Cell::new(0),
client_x: Cell::new(0),
client_y: Cell::new(0),
ctrl_key: Cell::new(false),
shift_key: Cell::new(false),
alt_key: Cell::new(false),
meta_key: Cell::new(false),
button: Cell::new(0),
related_target: Default::default(),
}
}
@ -82,7 +81,7 @@ impl MouseEvent {
button: i16,
relatedTarget: Option<JSRef<EventTarget>>) -> Temporary<MouseEvent> {
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,
ctrlKey, altKey, shiftKey, metaKey,
button, relatedTarget);
@ -107,39 +106,39 @@ impl MouseEvent {
impl<'a> MouseEventMethods for JSRef<'a, MouseEvent> {
fn ScreenX(self) -> i32 {
self.screen_x.deref().get()
self.screen_x.get()
}
fn ScreenY(self) -> i32 {
self.screen_y.deref().get()
self.screen_y.get()
}
fn ClientX(self) -> i32 {
self.client_x.deref().get()
self.client_x.get()
}
fn ClientY(self) -> i32 {
self.client_y.deref().get()
self.client_y.get()
}
fn CtrlKey(self) -> bool {
self.ctrl_key.deref().get()
self.ctrl_key.get()
}
fn ShiftKey(self) -> bool {
self.shift_key.deref().get()
self.shift_key.get()
}
fn AltKey(self) -> bool {
self.alt_key.deref().get()
self.alt_key.get()
}
fn MetaKey(self) -> bool {
self.meta_key.deref().get()
self.meta_key.get()
}
fn Button(self) -> i16 {
self.button.deref().get()
self.button.get()
}
fn GetRelatedTarget(self) -> Option<Temporary<EventTarget>> {
@ -164,15 +163,15 @@ impl<'a> MouseEventMethods for JSRef<'a, MouseEvent> {
relatedTargetArg: Option<JSRef<EventTarget>>) {
let uievent: JSRef<UIEvent> = UIEventCast::from_ref(self);
uievent.InitUIEvent(typeArg, canBubbleArg, cancelableArg, viewArg, detailArg);
self.screen_x.deref().set(screenXArg);
self.screen_y.deref().set(screenYArg);
self.client_x.deref().set(clientXArg);
self.client_y.deref().set(clientYArg);
self.ctrl_key.deref().set(ctrlKeyArg);
self.alt_key.deref().set(altKeyArg);
self.shift_key.deref().set(shiftKeyArg);
self.meta_key.deref().set(metaKeyArg);
self.button.deref().set(buttonArg);
self.screen_x.set(screenXArg);
self.screen_y.set(screenYArg);
self.client_x.set(clientXArg);
self.client_y.set(clientYArg);
self.ctrl_key.set(ctrlKeyArg);
self.alt_key.set(altKeyArg);
self.shift_key.set(shiftKeyArg);
self.meta_key.set(metaKeyArg);
self.button.set(buttonArg);
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::{OptionalSettable, TemporaryPushable, OptionalRootedRootable};
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::{Reflectable, Reflector, reflect_dom_object};
use dom::characterdata::CharacterData;
@ -53,7 +53,7 @@ use servo_util::geometry::Au;
use servo_util::str::{DOMString, null_str_as_empty};
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 libc;
use libc::uintptr_t;
@ -102,13 +102,13 @@ pub struct Node {
child_list: MutNullableJS<NodeList>,
/// A bitfield of flags for node items.
flags: Traceable<RefCell<NodeFlags>>,
flags: RefCell<NodeFlags>,
/// Layout information. Only the layout task may touch this data.
///
/// Must be sent back to the layout task to be destroyed when this
/// node is finalized.
pub layout_data: Untraceable<LayoutDataRef>,
pub layout_data: LayoutDataRef,
unique_id: RefCell<String>,
}
@ -189,6 +189,8 @@ pub struct LayoutDataRef {
pub data_cell: RefCell<Option<LayoutData>>,
}
untraceable!(LayoutDataRef)
impl LayoutDataRef {
pub fn new() -> LayoutDataRef {
LayoutDataRef {
@ -453,7 +455,7 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
}
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.
@ -512,38 +514,38 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
}
fn get_hover_state(self) -> bool {
self.flags.deref().borrow().contains(InHoverState)
self.flags.borrow().contains(InHoverState)
}
fn set_hover_state(self, state: bool) {
if state {
self.flags.deref().borrow_mut().insert(InHoverState);
self.flags.borrow_mut().insert(InHoverState);
} else {
self.flags.deref().borrow_mut().remove(InHoverState);
self.flags.borrow_mut().remove(InHoverState);
}
}
fn get_disabled_state(self) -> bool {
self.flags.deref().borrow().contains(InDisabledState)
self.flags.borrow().contains(InDisabledState)
}
fn set_disabled_state(self, state: bool) {
if state {
self.flags.deref().borrow_mut().insert(InDisabledState);
self.flags.borrow_mut().insert(InDisabledState);
} else {
self.flags.deref().borrow_mut().remove(InDisabledState);
self.flags.borrow_mut().remove(InDisabledState);
}
}
fn get_enabled_state(self) -> bool {
self.flags.deref().borrow().contains(InEnabledState)
self.flags.borrow().contains(InEnabledState)
}
fn set_enabled_state(self, state: bool) {
if state {
self.flags.deref().borrow_mut().insert(InEnabledState);
self.flags.borrow_mut().insert(InEnabledState);
} 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),
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()),
}
@ -1236,9 +1238,9 @@ impl Node {
let is_in_doc = parent.is_in_doc();
for kid in node.traverse_preorder() {
if is_in_doc {
kid.flags.deref().borrow_mut().insert(IsInDoc);
kid.flags.borrow_mut().insert(IsInDoc);
} else {
kid.flags.deref().borrow_mut().remove(IsInDoc);
kid.flags.borrow_mut().remove(IsInDoc);
}
}
}
@ -1325,7 +1327,7 @@ impl Node {
// Step 8.
parent.remove_child(node);
node.deref().flags.deref().borrow_mut().remove(IsInDoc);
node.deref().flags.borrow_mut().remove(IsInDoc);
// Step 9.
match suppress_observers {
@ -1362,7 +1364,7 @@ impl Node {
CommentNodeTypeId => {
let comment: JSRef<Comment> = CommentCast::to_ref(node).unwrap();
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)
},
DocumentNodeTypeId => {
@ -1386,14 +1388,14 @@ impl Node {
TextNodeTypeId => {
let text: JSRef<Text> = TextCast::to_ref(node).unwrap();
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)
},
ProcessingInstructionNodeTypeId => {
let pi: JSRef<ProcessingInstruction> = ProcessingInstructionCast::to_ref(node).unwrap();
let pi = pi.deref();
let pi = ProcessingInstruction::new(pi.target.clone(),
pi.characterdata.data.deref().borrow().clone(), *document);
pi.characterdata.data.borrow().clone(), *document);
NodeCast::from_temporary(pi)
},
}.root();
@ -1412,7 +1414,7 @@ impl Node {
DocumentNodeTypeId => {
let node_doc: JSRef<Document> = DocumentCast::to_ref(node).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());
},
ElementNodeTypeId(..) => {
@ -1449,7 +1451,7 @@ impl Node {
/// Sends layout data, if any, back to the layout task to be destroyed.
unsafe fn reap_layout_data(&mut self) {
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();
match layout_chan {
None => {}
@ -1660,7 +1662,7 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
self.wait_until_safe_to_modify_dom();
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
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 other_pi: JSRef<ProcessingInstruction> = ProcessingInstructionCast::to_ref(other).unwrap();
(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 {
let characterdata: JSRef<CharacterData> = CharacterDataCast::to_ref(node).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 {
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::global::Window;
use dom::bindings::js::{JS, JSRef, OptionalRootable, Temporary};
use dom::bindings::trace::Untraceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::document::Document;
use dom::node::{Node, NodeHelpers};
@ -334,7 +333,7 @@ impl<'a> PrivateTreeWalkerHelpers<'a> for JSRef<'a, TreeWalker> {
// "6. Return result."
match self.filter {
FilterNone => Ok(NodeFilterConstants::FILTER_ACCEPT),
FilterNative(f) => Ok((*f)(node)),
FilterNative(f) => Ok((f)(node)),
FilterJS(callback) => callback.AcceptNode_(self, node, RethrowExceptions)
}
}
@ -554,7 +553,7 @@ impl<'a> Iterator<JSRef<'a, Node>> for JSRef<'a, TreeWalker> {
#[jstraceable]
pub enum Filter {
FilterNone,
FilterNative(Untraceable<fn (node: JSRef<Node>) -> u16>),
FilterNative(fn (node: JSRef<Node>) -> u16),
FilterJS(NodeFilter)
}

View file

@ -10,7 +10,7 @@ use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef;
use dom::bindings::global;
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::event::{Event, EventTypeId, UIEventTypeId};
use dom::window::Window;
@ -24,7 +24,7 @@ use std::default::Default;
pub struct UIEvent {
pub event: Event,
view: MutNullableJS<Window>,
detail: Traceable<Cell<i32>>
detail: Cell<i32>
}
impl UIEventDerived for Event {
@ -38,7 +38,7 @@ impl UIEvent {
UIEvent {
event: Event::new_inherited(type_id),
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 {
self.detail.deref().get()
self.detail.get()
}
fn InitUIEvent(self,
@ -87,7 +87,7 @@ impl<'a> UIEventMethods for JSRef<'a, UIEvent> {
let event: JSRef<Event> = EventCast::from_ref(self);
event.InitEvent(type_, can_bubble, cancelable);
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::global::GlobalRef;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use servo_util::str::DOMString;
@ -24,14 +23,14 @@ use std::ascii::OwnedStrAsciiExt;
#[jstraceable]
#[must_root]
pub struct URLSearchParams {
data: Traceable<RefCell<HashMap<DOMString, Vec<DOMString>>>>,
data: RefCell<HashMap<DOMString, Vec<DOMString>>>,
reflector_: Reflector,
}
impl URLSearchParams {
fn new_inherited() -> URLSearchParams {
URLSearchParams {
data: Traceable::new(RefCell::new(HashMap::new())),
data: RefCell::new(HashMap::new()),
reflector_: Reflector::new(),
}
}
@ -51,8 +50,8 @@ impl URLSearchParams {
},
Some(eURLSearchParams(u)) => {
let u = u.root();
let mut map = usp.deref().data.deref().borrow_mut();
*map = u.data.deref().borrow().clone();
let mut map = usp.deref().data.borrow_mut();
*map = u.data.borrow().clone();
},
None => {}
}
@ -62,26 +61,26 @@ impl URLSearchParams {
impl<'a> URLSearchParamsMethods for JSRef<'a, URLSearchParams> {
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()));
self.update_steps();
}
fn Delete(self, name: DOMString) {
self.data.deref().borrow_mut().remove(&name);
self.data.borrow_mut().remove(&name);
self.update_steps();
}
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 {
self.data.deref().borrow().contains_key_equiv(&name)
self.data.borrow().contains_key_equiv(&name)
}
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();
}
}
@ -129,7 +128,7 @@ impl URLSearchParamsHelpers for URLSearchParams {
let encoding = encoding.unwrap_or(UTF_8 as EncodingRef);
let mut buf = vec!();
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);
for val in v.iter() {
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::global;
use dom::bindings::js::{MutNullableJS, JSRef, Temporary, OptionalSettable};
use dom::bindings::trace::{Traceable, Untraceable};
use dom::bindings::utils::{Reflectable, Reflector};
use dom::browsercontext::BrowserContext;
use dom::console::Console;
@ -60,7 +59,7 @@ pub struct TimerId(i32);
pub struct TimerHandle {
handle: TimerId,
pub data: TimerData,
cancel_chan: Untraceable<Option<Sender<()>>>,
cancel_chan: Option<Sender<()>>,
}
impl Hash for TimerId {
@ -86,10 +85,10 @@ pub struct Window {
location: MutNullableJS<Location>,
navigator: MutNullableJS<Navigator>,
pub image_cache_task: ImageCacheTask,
pub active_timers: Traceable<RefCell<HashMap<TimerId, TimerHandle>>>,
next_timer_handle: Traceable<Cell<i32>>,
pub compositor: Untraceable<Box<ScriptListener+'static>>,
pub browser_context: Traceable<RefCell<Option<BrowserContext>>>,
pub active_timers: RefCell<HashMap<TimerId, TimerHandle>>,
next_timer_handle: Cell<i32>,
pub compositor: Box<ScriptListener+'static>,
pub browser_context: RefCell<Option<BrowserContext>>,
pub page: Rc<Page>,
performance: MutNullableJS<Performance>,
pub navigationStart: u64,
@ -100,7 +99,7 @@ pub struct Window {
impl Window {
pub fn get_cx(&self) -> *mut JSContext {
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 {
@ -126,7 +125,7 @@ impl Drop for Window {
#[jstraceable]
pub struct TimerData {
pub is_interval: bool,
pub funval: Traceable<JSVal>,
pub funval: JSVal,
}
// http://www.whatwg.org/html/#atob
@ -250,7 +249,7 @@ impl<'a> WindowMethods for JSRef<'a, Window> {
}
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));
match timer_handle {
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>) {
*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.
@ -437,7 +436,7 @@ impl<'a> WindowHelpers for JSRef<'a, Window> {
fn handle_fire_timer(self, timer_id: TimerId, cx: *mut JSContext) {
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,
Some(timer_handle) => timer_handle.data,
};
@ -446,13 +445,13 @@ impl<'a> WindowHelpers for JSRef<'a, Window> {
with_compartment(cx, this_value, || {
let mut rval = NullValue();
unsafe {
JS_CallFunctionValue(cx, this_value, *data.funval,
JS_CallFunctionValue(cx, this_value, data.funval,
0, ptr::null_mut(), &mut rval);
}
});
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> {
fn set_timeout_or_interval(self, callback: JSVal, timeout: i32, is_interval: bool) -> i32 {
let timeout = cmp::max(0, timeout) as u64;
let handle = self.next_timer_handle.deref().get();
self.next_timer_handle.deref().set(handle + 1);
let handle = self.next_timer_handle.get();
self.next_timer_handle.set(handle + 1);
// Post a delayed message to the per-window timer task; it will dispatch 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 = TimerHandle {
handle: timer_id,
cancel_chan: Untraceable::new(Some(cancel_chan)),
cancel_chan: Some(cancel_chan),
data: TimerData {
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
}
}
@ -531,14 +530,14 @@ impl Window {
script_chan: script_chan,
control_chan: control_chan,
console: Default::default(),
compositor: Untraceable::new(compositor),
compositor: compositor,
page: page,
location: Default::default(),
navigator: Default::default(),
image_cache_task: image_cache_task,
active_timers: Traceable::new(RefCell::new(HashMap::new())),
next_timer_handle: Traceable::new(Cell::new(0)),
browser_context: Traceable::new(RefCell::new(None)),
active_timers: RefCell::new(HashMap::new()),
next_timer_handle: Cell::new(0),
browser_context: RefCell::new(None),
performance: Default::default(),
navigationStart: time::get_time().sec as u64,
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::global::{GlobalRef, GlobalField};
use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::trace::JSTraceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope;
use dom::eventtarget::{EventTarget, EventTargetHelpers, WorkerTypeId};
@ -18,7 +19,7 @@ use script_task::{ScriptChan, DOMMessage};
use servo_util::str::DOMString;
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::jsval::{JSVal, UndefinedValue};
use url::UrlParser;
@ -28,6 +29,7 @@ use std::cell::Cell;
use std::ptr;
pub struct TrustedWorkerAddress(pub *const c_void);
untraceable!(TrustedWorkerAddress)
#[jstraceable]
#[must_root]

View file

@ -4,7 +4,6 @@
use dom::bindings::codegen::Bindings::WorkerGlobalScopeBinding::WorkerGlobalScopeMethods;
use dom::bindings::error::{ErrorResult, Fallible, Syntax, Network, FailureUnknown};
use dom::bindings::trace::Untraceable;
use dom::bindings::global;
use dom::bindings::js::{MutNullableJS, JSRef, Temporary, OptionalSettable};
use dom::bindings::utils::{Reflectable, Reflector};
@ -35,9 +34,9 @@ pub enum WorkerGlobalScopeId {
#[must_root]
pub struct WorkerGlobalScope {
pub eventtarget: EventTarget,
worker_url: Untraceable<Url>,
js_context: Untraceable<Rc<Cx>>,
resource_task: Untraceable<ResourceTask>,
worker_url: Url,
js_context: Rc<Cx>,
resource_task: ResourceTask,
script_chan: ScriptChan,
location: MutNullableJS<WorkerLocation>,
navigator: MutNullableJS<WorkerNavigator>,
@ -52,9 +51,9 @@ impl WorkerGlobalScope {
script_chan: ScriptChan) -> WorkerGlobalScope {
WorkerGlobalScope {
eventtarget: EventTarget::new_inherited(WorkerGlobalScopeTypeId(type_id)),
worker_url: Untraceable::new(worker_url),
js_context: Untraceable::new(cx),
resource_task: Untraceable::new(resource_task),
worker_url: worker_url,
js_context: cx,
resource_task: resource_task,
script_chan: script_chan,
location: Default::default(),
navigator: Default::default(),
@ -67,11 +66,11 @@ impl WorkerGlobalScope {
}
pub fn resource_task<'a>(&'a self) -> &'a ResourceTask {
&*self.resource_task
& self.resource_task
}
pub fn get_url<'a>(&'a self) -> &'a Url {
&*self.worker_url
&self.worker_url
}
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> {
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.get().unwrap()
@ -95,7 +94,7 @@ impl<'a> WorkerGlobalScopeMethods for JSRef<'a, WorkerGlobalScope> {
fn ImportScripts(self, url_strings: Vec<DOMString>) -> ErrorResult {
let mut urls = Vec::with_capacity(url_strings.len());
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());
match url {
Ok(url) => urls.push(url),
@ -104,14 +103,14 @@ impl<'a> WorkerGlobalScopeMethods for JSRef<'a, WorkerGlobalScope> {
}
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),
Ok((metadata, bytes)) => {
(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) {
Ok(_) => (),
Err(_) => {

View file

@ -6,7 +6,6 @@ use dom::bindings::codegen::Bindings::WorkerLocationBinding;
use dom::bindings::codegen::Bindings::WorkerLocationBinding::WorkerLocationMethods;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::global::Worker;
use dom::bindings::trace::Untraceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::urlhelper::UrlHelper;
use dom::workerglobalscope::WorkerGlobalScope;
@ -19,14 +18,14 @@ use url::Url;
#[must_root]
pub struct WorkerLocation {
reflector_: Reflector,
url: Untraceable<Url>,
url: Url,
}
impl WorkerLocation {
fn new_inherited(url: Url) -> WorkerLocation {
WorkerLocation {
reflector_: Reflector::new(),
url: Untraceable::new(url),
url: url,
}
}
@ -39,15 +38,15 @@ impl WorkerLocation {
impl<'a> WorkerLocationMethods for JSRef<'a, WorkerLocation> {
fn Href(self) -> DOMString {
UrlHelper::Href(self.url.deref())
UrlHelper::Href(&self.url)
}
fn Search(self) -> DOMString {
UrlHelper::Search(self.url.deref())
UrlHelper::Search(&self.url)
}
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::js::{MutNullableJS, JS, JSRef, Temporary, OptionalRootedRootable};
use dom::bindings::str::ByteString;
use dom::bindings::trace::{Traceable, Untraceable};
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::document::Document;
use dom::event::Event;
@ -107,68 +106,68 @@ enum SyncOrAsync<'a> {
#[must_root]
pub struct XMLHttpRequest {
eventtarget: XMLHttpRequestEventTarget,
ready_state: Traceable<Cell<XMLHttpRequestState>>,
timeout: Traceable<Cell<u32>>,
with_credentials: Traceable<Cell<bool>>,
ready_state: Cell<XMLHttpRequestState>,
timeout: Cell<u32>,
with_credentials: Cell<bool>,
upload: JS<XMLHttpRequestUpload>,
response_url: DOMString,
status: Traceable<Cell<u16>>,
status_text: Traceable<RefCell<ByteString>>,
response: Traceable<RefCell<ByteString>>,
response_type: Traceable<Cell<XMLHttpRequestResponseType>>,
status: Cell<u16>,
status_text: RefCell<ByteString>,
response: RefCell<ByteString>,
response_type: Cell<XMLHttpRequestResponseType>,
response_xml: MutNullableJS<Document>,
response_headers: Untraceable<RefCell<ResponseHeaderCollection>>,
response_headers: RefCell<ResponseHeaderCollection>,
// Associated concepts
request_method: Untraceable<RefCell<Method>>,
request_url: Untraceable<RefCell<Option<Url>>>,
request_headers: Untraceable<RefCell<RequestHeaderCollection>>,
request_body_len: Traceable<Cell<uint>>,
sync: Traceable<Cell<bool>>,
upload_complete: Traceable<Cell<bool>>,
upload_events: Traceable<Cell<bool>>,
send_flag: Traceable<Cell<bool>>,
request_method: RefCell<Method>,
request_url: RefCell<Option<Url>>,
request_headers: RefCell<RequestHeaderCollection>,
request_body_len: Cell<uint>,
sync: Cell<bool>,
upload_complete: Cell<bool>,
upload_events: Cell<bool>,
send_flag: Cell<bool>,
global: GlobalField,
pinned_count: Traceable<Cell<uint>>,
timer: Untraceable<RefCell<Timer>>,
fetch_time: Traceable<Cell<i64>>,
timeout_pinned: Traceable<Cell<bool>>,
terminate_sender: Untraceable<RefCell<Option<Sender<Error>>>>,
pinned_count: Cell<uint>,
timer: RefCell<Timer>,
fetch_time: Cell<i64>,
timeout_pinned: Cell<bool>,
terminate_sender: RefCell<Option<Sender<Error>>>,
}
impl XMLHttpRequest {
fn new_inherited(global: &GlobalRef) -> XMLHttpRequest {
XMLHttpRequest {
eventtarget: XMLHttpRequestEventTarget::new_inherited(XMLHttpRequestTypeId),
ready_state: Traceable::new(Cell::new(Unsent)),
timeout: Traceable::new(Cell::new(0u32)),
with_credentials: Traceable::new(Cell::new(false)),
ready_state: Cell::new(Unsent),
timeout: Cell::new(0u32),
with_credentials: Cell::new(false),
upload: JS::from_rooted(XMLHttpRequestUpload::new(global)),
response_url: "".to_string(),
status: Traceable::new(Cell::new(0)),
status_text: Traceable::new(RefCell::new(ByteString::new(vec!()))),
response: Traceable::new(RefCell::new(ByteString::new(vec!()))),
response_type: Traceable::new(Cell::new(_empty)),
status: Cell::new(0),
status_text: RefCell::new(ByteString::new(vec!())),
response: RefCell::new(ByteString::new(vec!())),
response_type: Cell::new(_empty),
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_url: Untraceable::new(RefCell::new(None)),
request_headers: Untraceable::new(RefCell::new(RequestHeaderCollection::new())),
request_body_len: Traceable::new(Cell::new(0)),
sync: Traceable::new(Cell::new(false)),
send_flag: Traceable::new(Cell::new(false)),
request_method: RefCell::new(Get),
request_url: RefCell::new(None),
request_headers: RefCell::new(RequestHeaderCollection::new()),
request_body_len: Cell::new(0),
sync: Cell::new(false),
send_flag: Cell::new(false),
upload_complete: Traceable::new(Cell::new(false)),
upload_events: Traceable::new(Cell::new(false)),
upload_complete: Cell::new(false),
upload_events: Cell::new(false),
global: GlobalField::from_rooted(global),
pinned_count: Traceable::new(Cell::new(0)),
timer: Untraceable::new(RefCell::new(Timer::new().unwrap())),
fetch_time: Traceable::new(Cell::new(0)),
timeout_pinned: Traceable::new(Cell::new(false)),
terminate_sender: Untraceable::new(RefCell::new(None)),
pinned_count: Cell::new(0),
timer: RefCell::new(Timer::new().unwrap()),
fetch_time: Cell::new(0),
timeout_pinned: Cell::new(false),
terminate_sender: RefCell::new(None),
}
}
pub fn new(global: &GlobalRef) -> Temporary<XMLHttpRequest> {
@ -276,7 +275,7 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
}
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 {
@ -306,7 +305,7 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
Some(ExtensionMethod(ref t)) if t.as_slice() == "TRACK" => Err(Security),
Some(_) if method.is_token() => {
*self.request_method.deref().borrow_mut() = maybe_method.unwrap();
*self.request_method.borrow_mut() = maybe_method.unwrap();
// Step 6
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
};
// 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
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)
}
}
// XXXManishearth abort existing requests
// Step 12
*self.request_url.deref().borrow_mut() = Some(parsed_url);
*self.request_headers.deref().borrow_mut() = RequestHeaderCollection::new();
self.send_flag.deref().set(false);
*self.status_text.deref().borrow_mut() = ByteString::new(vec!());
self.status.deref().set(0);
*self.request_url.borrow_mut() = Some(parsed_url);
*self.request_headers.borrow_mut() = RequestHeaderCollection::new();
self.send_flag.set(false);
*self.status_text.borrow_mut() = ByteString::new(vec!());
self.status.set(0);
// Step 13
if self.ready_state.deref().get() != Opened {
if self.ready_state.get() != Opened {
self.change_ready_state(Opened);
}
Ok(())
@ -342,11 +341,11 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
}
fn Open_(self, method: ByteString, url: DOMString, async: bool,
_username: Option<DOMString>, _password: Option<DOMString>) -> ErrorResult {
self.sync.deref().set(!async);
self.sync.set(!async);
self.Open(method, url)
}
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
}
if !name.is_token() || !value.is_field_value() {
@ -371,7 +370,7 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
},
None => return Err(Syntax)
};
let mut collection = self.request_headers.deref().borrow_mut();
let mut collection = self.request_headers.borrow_mut();
// Steps 6,7
@ -410,20 +409,20 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
}
}
fn Timeout(self) -> u32 {
self.timeout.deref().get()
self.timeout.get()
}
fn SetTimeout(self, timeout: u32) -> ErrorResult {
if self.sync.deref().get() {
if self.sync.get() {
// FIXME: Not valid for a worker environment
Err(InvalidState)
} else {
self.timeout.deref().set(timeout);
if self.send_flag.deref().get() {
self.timeout.set(timeout);
if self.send_flag.get() {
if timeout == 0 {
self.cancel_timeout();
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 {
self.set_timeout(timeout - (progress * 1000) as u32);
} else {
@ -435,20 +434,20 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
}
}
fn WithCredentials(self) -> bool {
self.with_credentials.deref().get()
self.with_credentials.get()
}
fn SetWithCredentials(self, with_credentials: bool) {
self.with_credentials.deref().set(with_credentials);
self.with_credentials.set(with_credentials);
}
fn Upload(self) -> Temporary<XMLHttpRequestUpload> {
Temporary::new(self.upload)
}
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
}
let data = match *self.request_method.deref().borrow() {
let data = match *self.request_method.borrow() {
Get | Head => None, // Step 3
_ => 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));
// Step 6
self.upload_events.deref().set(false);
self.upload_events.set(false);
// Step 7
self.upload_complete.deref().set(match extracted {
self.upload_complete.set(match extracted {
None => true,
Some (ref v) if v.len() == 0 => true,
_ => false
});
let mut addr = None;
if !self.sync.deref().get() {
if !self.sync.get() {
// If one of the event handlers below aborts the fetch,
// the assertion in release_once() will fail since we haven't pinned it yet.
// 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 event_target: JSRef<EventTarget> = EventTargetCast::from_ref(upload_target);
if event_target.has_handlers() {
self.upload_events.deref().set(true);
self.upload_events.set(true);
}
// Step 9
self.send_flag.deref().set(true);
self.send_flag.set(true);
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));
}
}
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.
return Ok(());
}
let global = self.global.root();
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;
// Default headers
let request_headers = self.request_headers.deref();
let ref request_headers = self.request_headers;
if request_headers.borrow().content_type.is_none() {
let parameters = vec!((String::from_str("charset"), String::from_str("UTF-8")));
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("*/*"))
}
load_data.headers = (*self.request_headers.deref().borrow()).clone();
load_data.method = (*self.request_method.deref().borrow()).clone();
load_data.headers = (*self.request_headers.borrow()).clone();
load_data.method = (*self.request_method.borrow()).clone();
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
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
} else {
CORSMode
@ -547,25 +546,25 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
buf.push_str(format!("{:u}", p).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(),
format!("{}", req.origin)),
_ => {}
}
if self.sync.deref().get() {
if self.sync.get() {
return XMLHttpRequest::fetch(&mut Sync(self), resource_task, load_data,
terminate_receiver, cors_request);
} else {
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();
builder.spawn(proc() {
let _ = XMLHttpRequest::fetch(&mut Async(addr.unwrap(), script_chan),
resource_task, load_data, terminate_receiver, cors_request);
});
let timeout = self.timeout.deref().get();
let timeout = self.timeout.get();
if timeout > 0 {
self.set_timeout(timeout);
}
@ -573,22 +572,22 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
Ok(())
}
fn Abort(self) {
self.terminate_sender.deref().borrow().as_ref().map(|s| s.send_opt(Abort));
match self.ready_state.deref().get() {
Opened if self.send_flag.deref().get() => self.process_partial_response(ErroredMsg(Some(Abort))),
self.terminate_sender.borrow().as_ref().map(|s| s.send_opt(Abort));
match self.ready_state.get() {
Opened if self.send_flag.get() => 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 {
self.response_url.clone()
}
fn Status(self) -> u16 {
self.status.deref().get()
self.status.get()
}
fn StatusText(self) -> ByteString {
self.status_text.deref().borrow().clone()
self.status_text.borrow().clone()
}
fn GetResponseHeader(self, name: ByteString) -> Option<ByteString> {
self.filter_response_headers().iter().find(|h| {
@ -610,7 +609,7 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
ByteString::new(vec)
}
fn ResponseType(self) -> XMLHttpRequestResponseType {
self.response_type.deref().get()
self.response_type.get()
}
fn SetResponseType(self, response_type: XMLHttpRequestResponseType) -> ErrorResult {
match self.global {
@ -618,28 +617,28 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
=> return Ok(()),
_ => {}
}
match self.ready_state.deref().get() {
match self.ready_state.get() {
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(())
}
}
}
fn Response(self, cx: *mut JSContext) -> JSVal {
match self.response_type.deref().get() {
match self.response_type.get() {
_empty | Text => {
let ready_state = self.ready_state.deref().get();
let ready_state = self.ready_state.get();
if ready_state == XHRDone || ready_state == Loading {
self.text_response().to_jsval(cx)
} else {
"".to_string().to_jsval(cx)
}
},
_ if self.ready_state.deref().get() != XHRDone => NullValue(),
_ if self.ready_state.get() != XHRDone => NullValue(),
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 mut vp = UndefinedValue();
unsafe {
@ -652,14 +651,14 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> {
}
_ => {
// XXXManishearth handle other response types
self.response.deref().borrow().to_jsval(cx)
self.response.borrow().to_jsval(cx)
}
}
}
fn GetResponseText(self) -> Fallible<DOMString> {
match self.response_type.deref().get() {
match self.response_type.get() {
_empty | Text => {
match self.ready_state.deref().get() {
match self.ready_state.get() {
Loading | XHRDone => Ok(self.text_response()),
_ => Ok("".to_string())
}
@ -716,25 +715,25 @@ trait PrivateXMLHttpRequestHelpers {
impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> {
// Creates a trusted address to the object, and roots it. Always pair this with a release()
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());
}
let pinned_count = self.pinned_count.deref().get();
self.pinned_count.deref().set(pinned_count + 1);
let pinned_count = self.pinned_count.get();
self.pinned_count.set(pinned_count + 1);
TrustedXHRAddress(self.deref() as *const XMLHttpRequest as *const libc::c_void)
}
fn release_once(self) {
if self.sync.deref().get() {
if self.sync.get() {
// Lets us call this at various termination cases without having to
// check self.sync every time, since the pinning mechanism only is
// meaningful during an async fetch
return;
}
assert!(self.pinned_count.deref().get() > 0)
let pinned_count = self.pinned_count.deref().get();
self.pinned_count.deref().set(pinned_count - 1);
if self.pinned_count.deref().get() == 0 {
assert!(self.pinned_count.get() > 0)
let pinned_count = self.pinned_count.get();
self.pinned_count.set(pinned_count - 1);
if self.pinned_count.get() == 0 {
unsafe {
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) {
assert!(self.ready_state.deref().get() != rs)
self.ready_state.deref().set(rs);
assert!(self.ready_state.get() != rs)
self.ready_state.set(rs);
let global = self.global.root();
let event = Event::new(&global.root_ref(),
"readystatechange".to_string(),
@ -760,9 +759,9 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> {
// Part of step 13, send() (processing request end of file)
// Substep 1
self.upload_complete.deref().set(true);
self.upload_complete.set(true);
// 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("load".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)
// XXXManishearth handle errors, if any (substep 1)
// Substep 2
*self.status_text.deref().borrow_mut() = ByteString::new(status.reason().container_into_owned_bytes());
self.status.deref().set(status.code());
*self.status_text.borrow_mut() = ByteString::new(status.reason().container_into_owned_bytes());
self.status.set(status.code());
match headers {
Some(ref h) => {
*self.response_headers.deref().borrow_mut() = h.clone();
*self.response_headers.borrow_mut() = h.clone();
}
None => {}
};
// 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);
}
},
@ -789,13 +788,13 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> {
// XXXManishearth handle errors, if any (substep 1)
// 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);
}
// Substep 3
*self.response.deref().borrow_mut() = partial_response;
*self.response.borrow_mut() = partial_response;
// Substep 4
if !self.sync.deref().get() {
if !self.sync.get() {
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)
// 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
self.send_flag.deref().set(false);
self.send_flag.set(false);
self.change_ready_state(XHRDone);
// Subsubsteps 5-7
@ -818,7 +817,7 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> {
self.release_once();
},
ErroredMsg(e) => {
self.send_flag.deref().set(false);
self.send_flag.set(false);
// XXXManishearth set response to NetworkError
self.change_ready_state(XHRDone);
let errormsg = match e {
@ -828,7 +827,7 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> {
_ => unreachable!()
};
let upload_complete: &Cell<bool> = self.upload_complete.deref();
let upload_complete: &Cell<bool> = &self.upload_complete;
if !upload_complete.get() {
upload_complete.set(true);
self.dispatch_upload_progress_event("progress".to_string(), None);
@ -843,8 +842,8 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> {
self.release_once();
},
TimeoutMsg => {
match self.ready_state.deref().get() {
Opened if self.send_flag.deref().get() => self.process_partial_response(ErroredMsg(Some(Timeout))),
match self.ready_state.get() {
Opened if self.send_flag.get() => self.process_partial_response(ErroredMsg(Some(Timeout))),
Loading | HeadersReceived => self.process_partial_response(ErroredMsg(Some(Timeout))),
_ => self.release_once()
};
@ -855,7 +854,7 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> {
fn insert_trusted_header(self, name: String, value: String) {
// Insert a header without checking spec-compliance
// 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 mut reader = BufReader::new(value_bytes.as_slice());
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) {
let len = self.response.deref().borrow().len() as u64;
let total = self.response_headers.deref().borrow().content_length.map(|x| {x as u64});
let len = self.response.borrow().len() as u64;
let total = self.response_headers.borrow().content_length.map(|x| {x as u64});
self.dispatch_progress_event(false, type_, len, total);
}
fn set_timeout(self, timeout: u32) {
// Sets up the object to timeout in a given number of milliseconds
// 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));
let addr = unsafe {
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
self.release_once();
}
self.timeout_pinned.deref().set(true);
self.timeout_pinned.set(true);
let global = self.global.root();
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 () {
match oneshot.recv_opt() {
Ok(_) => {
@ -926,16 +925,16 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> {
}
fn cancel_timeout(self) {
// Cancels timeouts on the object, if any
if self.timeout_pinned.deref().get() {
self.timeout_pinned.deref().set(false);
if self.timeout_pinned.get() {
self.timeout_pinned.set(false);
self.release_once();
}
// 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 {
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) => {
for &(ref name, ref value) in x.parameters.iter() {
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
// 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 {
// http://fetch.spec.whatwg.org/#concept-response-header-list
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() {
"set-cookie" | "set-cookie2" => {},
// XXXManishearth additional CORS filtering goes here

View file

@ -492,7 +492,7 @@ pub fn parse_html(page: &Page,
for child in scriptnode.children() {
debug!("child = {:?}", child);
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);

View file

@ -5,7 +5,6 @@
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::InheritTypes::NodeCast;
use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable};
use dom::bindings::trace::{Traceable, Untraceable};
use dom::bindings::utils::GlobalStaticData;
use dom::document::{Document, DocumentHelpers};
use dom::element::Element;
@ -42,50 +41,50 @@ pub struct Page {
pub subpage_id: Option<SubpageId>,
/// 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.
pub frame: Traceable<RefCell<Option<Frame>>>,
pub frame: RefCell<Option<Frame>>,
/// 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.
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.
pub layout_join_port: Untraceable<RefCell<Option<Receiver<()>>>>,
pub layout_join_port: RefCell<Option<Receiver<()>>>,
/// 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.
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
/// TODO(tkuehn): this currently does not follow any particular caching policy
/// and simply caches pages forever (!). The bool indicates if reflow is required
/// 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.
pub resize_event: Untraceable<Cell<Option<WindowSizeData>>>,
pub resize_event: Cell<Option<WindowSizeData>>,
/// Pending scroll to fragment event, if any
pub fragment_name: RefCell<Option<String>>,
/// 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.
pub constellation_chan: Untraceable<ConstellationChan>,
pub constellation_chan: ConstellationChan,
// 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.
pub pending_reflows: Cell<int>,
@ -111,7 +110,7 @@ impl IterablePage for Rc<Page> {
}
fn find(&self, id: PipelineId) -> Option<Rc<Page>> {
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);
if found.is_some() { return found; }
}
@ -129,7 +128,7 @@ impl Page {
js_context: Rc<Cx>) -> Page {
let js_info = JSPageInfo {
dom_static: GlobalStaticData(),
js_context: Untraceable::new(js_context),
js_context: js_context,
};
let layout_rpc: Box<LayoutRPC> = {
let (rpc_send, rpc_recv) = channel();
@ -140,21 +139,21 @@ impl Page {
Page {
id: id,
subpage_id: subpage_id,
frame: Traceable::new(RefCell::new(None)),
layout_chan: Untraceable::new(layout_chan),
layout_rpc: Untraceable::new(layout_rpc),
layout_join_port: Untraceable::new(RefCell::new(None)),
damage: Traceable::new(RefCell::new(None)),
window_size: Traceable::new(Cell::new(window_size)),
js_info: Traceable::new(RefCell::new(Some(js_info))),
url: Untraceable::new(RefCell::new(None)),
next_subpage_id: Traceable::new(Cell::new(SubpageId(0))),
resize_event: Untraceable::new(Cell::new(None)),
frame: RefCell::new(None),
layout_chan: layout_chan,
layout_rpc: layout_rpc,
layout_join_port: RefCell::new(None),
damage: RefCell::new(None),
window_size: Cell::new(window_size),
js_info: RefCell::new(Some(js_info)),
url: RefCell::new(None),
next_subpage_id: Cell::new(SubpageId(0)),
resize_event: Cell::new(None),
fragment_name: RefCell::new(None),
last_reflow_id: Traceable::new(Cell::new(0)),
resource_task: Untraceable::new(resource_task),
constellation_chan: Untraceable::new(constellation_chan),
children: Traceable::new(RefCell::new(vec!())),
last_reflow_id: Cell::new(0),
resource_task: resource_task,
constellation_chan: constellation_chan,
children: RefCell::new(vec!()),
pending_reflows: Cell::new(0),
avoided_reflows: Cell::new(0),
}
@ -165,7 +164,7 @@ impl Page {
if damaged {
let frame = self.frame();
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 {
self.avoided_reflows.set(self.avoided_reflows.get() + 1);
}
@ -177,7 +176,7 @@ impl Page {
// doing a query reflow.
self.flush_layout(ReflowForDisplay);
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
}
@ -185,7 +184,6 @@ impl Page {
pub fn remove(&self, id: PipelineId) -> Option<Rc<Page>> {
let remove_idx = {
self.children
.deref()
.borrow_mut()
.iter_mut()
.enumerate()
@ -197,9 +195,9 @@ impl Page {
.map(|(idx, _)| 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 => {
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) {
found @ Some(_) => return found,
None => (), // keep going...
@ -215,7 +213,7 @@ impl Iterator<Rc<Page>> for PageIterator {
fn next(&mut self) -> Option<Rc<Page>> {
if !self.stack.is_empty() {
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());
}
Some(next.clone())
@ -227,33 +225,33 @@ impl Iterator<Rc<Page>> for PageIterator {
impl Page {
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>> {
self.js_info.deref().borrow()
self.js_info.borrow()
}
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)>> {
self.url.deref().borrow_mut()
self.url.borrow_mut()
}
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>> {
self.frame.deref().borrow_mut()
self.frame.borrow_mut()
}
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;
self.next_subpage_id.deref().set(SubpageId(id_num + 1));
self.next_subpage_id.set(SubpageId(id_num + 1));
subpage_id
}
@ -267,7 +265,7 @@ impl Page {
None => {},
Some(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 {
None => {}
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(),
level: level,
})
@ -297,7 +295,7 @@ impl Page {
/// Sends a ping to layout and waits for the response. The response will arrive when the
/// layout task has finished any pending request messages.
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() {
let join_port = replace(&mut *layout_join_port, None);
match join_port {
@ -355,15 +353,15 @@ impl Page {
// Layout will let us know when it's done.
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);
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);
let root: JSRef<Node> = NodeCast::from_ref(*root);
let mut damage = self.damage.deref().borrow_mut();
let window_size = self.window_size.deref().get();
let mut damage = self.damage.borrow_mut();
let window_size = self.window_size.get();
// Send new document and relevant styles to layout.
let reflow = box Reflow {
@ -378,7 +376,7 @@ impl Page {
id: last_reflow_id.get(),
};
let LayoutChan(ref chan) = *self.layout_chan;
let LayoutChan(ref chan) = self.layout_chan;
chan.send(ReflowMsg(reflow));
debug!("script: layout forked")
@ -450,5 +448,5 @@ pub struct JSPageInfo {
/// Global static data related to the DOM.
pub dom_static: GlobalStaticData,
/// 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();
for page in page.iter() {
// 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() {
let mut resize_event = page.resize_event.deref().get();
let mut resize_event = page.resize_event.get();
match resize_event.take() {
Some(size) => resizes.push((page.id, size)),
None => ()
}
page.resize_event.deref().set(None);
page.resize_event.set(None);
}
}
}
@ -457,7 +457,7 @@ impl ScriptTask {
FromConstellation(ResizeMsg(id, size)) => {
let mut page = self.page.borrow_mut();
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);
@ -594,15 +594,15 @@ impl ScriptTask {
whose parent has a PipelineId which does not correspond to a pipeline in the script
task's page tree. This is a bug.");
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),
LayoutChan(layout_chan.downcast_ref::<Sender<layout_interface::Msg>>().unwrap().clone()),
window_size,
parent_page.resource_task.deref().clone(),
parent_page.resource_task.clone(),
self.constellation_chan.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.
@ -622,9 +622,9 @@ impl ScriptTask {
let page = page.find(pipeline_id).expect(
"ScriptTask: received a load message for a layout channel that is not associated \
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 {
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;
}
@ -649,7 +649,7 @@ impl ScriptTask {
let mut page = self.page.borrow_mut();
let page = page.find(id).expect("Received resize message for PipelineId not associated
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() {
&Some((_, ref mut needs_reflow)) => *needs_reflow = true,
&None => (),
@ -866,7 +866,7 @@ impl ScriptTask {
let window = {
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();
if frame.is_some() {
@ -911,7 +911,7 @@ impl ScriptTask {
let page = get_page(&*self.page.borrow(), pipeline_id);
let frame = page.frame();
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 {
page.pending_reflows.set(page.pending_reflows.get() + 1);
} 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
// processed this message.
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));
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.
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);
}
}