/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::utils::{Reflector, Reflectable, cx_for_dom_object}; use dom::window::Window; use js::jsapi::{JSObject, JSContext, JS_AddObjectRoot, JS_RemoveObjectRoot}; use layout_interface::TrustedNodeAddress; use std::cast; use std::cell::RefCell; /// A type that represents a JS-owned value that is rooted for the lifetime of this value. /// Importantly, it requires explicit rooting in order to interact with the inner value. /// Can be assigned into JS-owned member fields (ie. JS types) safely via the /// `JS::assign` method or `OptionalAssignable::assign` (for Option> fields). pub struct Temporary { inner: JS, } impl Eq for Temporary { fn eq(&self, other: &Temporary) -> bool { self.inner == other.inner } } #[unsafe_destructor] impl Drop for Temporary { fn drop(&mut self) { let cx = cx_for_dom_object(&self.inner); unsafe { JS_RemoveObjectRoot(cx, self.inner.reflector().rootable()); } } } impl Temporary { /// Create a new Temporary value from a JS-owned value. pub fn new(inner: JS) -> Temporary { let cx = cx_for_dom_object(&inner); unsafe { JS_AddObjectRoot(cx, inner.reflector().rootable()); } Temporary { inner: inner, } } /// Create a new Temporary value from a rooted value. pub fn new_rooted<'a>(root: &JSRef<'a, T>) -> Temporary { Temporary::new(root.unrooted()) } /// Root this unrooted value. pub fn root<'a, 'b>(self, collection: &'a RootCollection) -> Root<'a, 'b, T> { collection.new_root(&self.inner) } unsafe fn inner(&self) -> JS { self.inner.clone() } //XXXjdm It would be lovely if this could be private. pub unsafe fn transmute(self) -> Temporary { cast::transmute(self) } } /// A rooted, JS-owned value. Must only be used as a field in other JS-owned types. pub struct JS { ptr: RefCell<*mut T> } impl Eq for JS { fn eq(&self, other: &JS) -> bool { self.ptr == other.ptr } } impl Clone for JS { #[inline] fn clone(&self) -> JS { JS { ptr: self.ptr.clone() } } } impl JS { /// Create a new JS-reflected DOM object; returns an Temporary type because the new value /// is not safe to use until it is rooted. pub fn new(obj: ~T, window: &JSRef, wrap_fn: extern "Rust" fn(*JSContext, &JSRef, ~T) -> JS) -> Temporary { Temporary::new(wrap_fn(window.get().get_cx(), window, obj)) } /// Create a new JS-owned value wrapped from a raw Rust pointer. pub unsafe fn from_raw(raw: *mut T) -> JS { JS { ptr: RefCell::new(raw) } } /// Create a new JS-owned value wrapped from an address known to be a Node pointer. pub unsafe fn from_trusted_node_address(inner: TrustedNodeAddress) -> JS { let TrustedNodeAddress(addr) = inner; JS { ptr: RefCell::new(addr as *mut T) } } /// Root this JS-owned value to prevent its collection as garbage. pub fn root<'a, 'b>(&self, collection: &'a RootCollection) -> Root<'a, 'b, T> { collection.new_root(self) } } //XXXjdm This is disappointing. This only gets called from trace hooks, in theory, // so it's safe to assume that self is rooted and thereby safe to access. impl Reflectable for JS { fn reflector<'a>(&'a self) -> &'a Reflector { unsafe { (*self.unsafe_get()).reflector() } } fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector { unsafe { (*self.unsafe_get()).mut_reflector() } } } impl JS { /// Returns an unsafe pointer to the interior of this JS object without touching the borrow /// flags. This is the only method that be safely accessed from layout. (The fact that this /// is unsafe is what necessitates the layout wrappers.) pub unsafe fn unsafe_get(&self) -> *mut T { cast::transmute_copy(&self.ptr) } /// Store an unrooted value in this field. This is safe under the assumption that JS /// values are only used as fields in DOM types that are reachable in the GC graph, /// so this unrooted value becomes transitively rooted for the lifetime of its new owner. pub fn assign(&mut self, val: Temporary) { *self = unsafe { val.inner() }; } } impl JS { //XXXjdm It would be lovely if this could be private. pub unsafe fn transmute(self) -> JS { cast::transmute(self) } pub unsafe fn transmute_copy(&self) -> JS { cast::transmute_copy(self) } } pub trait RootedReference { fn root_ref<'a>(&'a self) -> Option>; } impl<'a, 'b, T: Reflectable> RootedReference for Option> { fn root_ref<'a>(&'a self) -> Option> { self.as_ref().map(|root| root.root_ref()) } } // This trait should never be public; it allows access to unrooted values, and is thus // easy to misuse. /*definitely not public*/ trait Assignable { fn get_js(&self) -> JS; } impl Assignable for JS { fn get_js(&self) -> JS { self.clone() } } impl<'a, T> Assignable for JSRef<'a, T> { fn get_js(&self) -> JS { self.unrooted() } } // Assignable should not be exposed publically, since it's used to // extract unrooted values in a safe way WHEN USED CORRECTLY. impl Assignable for Temporary { fn get_js(&self) -> JS { unsafe { self.inner() } } } pub trait OptionalAssignable { fn assign(&mut self, val: Option); } impl, U: Reflectable> OptionalAssignable for Option> { fn assign(&mut self, val: Option) { *self = val.map(|val| val.get_js()); } } pub trait OptionalRootable { fn root<'a, 'b>(self, roots: &'a RootCollection) -> Option>; } impl OptionalRootable for Option> { fn root<'a, 'b>(self, roots: &'a RootCollection) -> Option> { self.map(|inner| inner.root(roots)) } } pub trait OptionalRootedRootable { fn root<'a, 'b>(&self, roots: &'a RootCollection) -> Option>; } impl OptionalRootedRootable for Option> { fn root<'a, 'b>(&self, roots: &'a RootCollection) -> Option> { self.as_ref().map(|inner| inner.root(roots)) } } pub trait ResultRootable { fn root<'a, 'b>(self, roots: &'a RootCollection) -> Result, U>; } impl ResultRootable for Result, U> { fn root<'a, 'b>(self, roots: &'a RootCollection) -> Result, U> { self.map(|inner| inner.root(roots)) } } /// Provides a facility to push unrooted values onto lists of rooted values. This is safe /// under the assumption that said lists are reachable via the GC graph, and therefore the /// new values are transitively rooted for the lifetime of their new owner. pub trait TemporaryPushable { fn push_unrooted(&mut self, val: Temporary); } impl TemporaryPushable for Vec> { fn push_unrooted(&mut self, val: Temporary) { unsafe { self.push(val.inner()) }; } } /// An opaque, LIFO rooting mechanism. pub struct RootCollection { roots: RefCell<~[*JSObject]>, } impl RootCollection { pub fn new() -> RootCollection { RootCollection { roots: RefCell::new(~[]), } } fn new_root<'a, 'b, T: Reflectable>(&'a self, unrooted: &JS) -> Root<'a, 'b, T> { Root::new(self, unrooted) } fn root<'a, 'b, T: Reflectable>(&self, unrooted: &Root<'a, 'b, T>) { self.root_raw(unrooted.js_ptr); } /// Root a raw JS pointer. pub fn root_raw(&self, unrooted: *JSObject) { let mut roots = self.roots.borrow_mut(); roots.push(unrooted); debug!(" rooting {:?}", unrooted); } fn unroot<'a, 'b, T: Reflectable>(&self, rooted: &Root<'a, 'b, T>) { self.unroot_raw(rooted.js_ptr); } /// Unroot a raw JS pointer. Must occur in reverse order to its rooting. pub fn unroot_raw(&self, rooted: *JSObject) { let mut roots = self.roots.borrow_mut(); debug!("unrooting {:?} (expecting {:?}", roots.last().unwrap(), rooted); assert!(*roots.last().unwrap() == rooted); roots.pop().unwrap(); } } /// A rooted JS value. The JS value is pinned for the duration of this object's lifetime; /// roots are additive, so this object's destruction will not invalidate other roots /// for the same JS value. Roots cannot outlive the associated RootCollection object. /// Attempts to transfer ownership of a Root via moving will trigger dynamic unrooting /// failures due to incorrect ordering. pub struct Root<'a, 'b, T> { /// List that ensures correct dynamic root ordering root_list: &'a RootCollection, /// Reference to rooted value that must not outlive this container jsref: JSRef<'b, T>, /// Pointer to underlying Rust data ptr: RefCell<*mut T>, /// On-stack JS pointer to assuage conservative stack scanner js_ptr: *JSObject, } impl<'a, 'b, T: Reflectable> Root<'a, 'b, T> { fn new(roots: &'a RootCollection, unrooted: &JS) -> Root<'a, 'b, T> { let root = Root { root_list: roots, jsref: JSRef { ptr: unrooted.ptr.clone(), chain: unsafe { cast::transmute_region(&()) }, }, ptr: unrooted.ptr.clone(), js_ptr: unrooted.reflector().get_jsobject(), }; roots.root(&root); root } pub fn get<'a>(&'a self) -> &'a T { unsafe { let borrow = self.ptr.borrow(); &**borrow } } pub fn get_mut<'a>(&'a mut self) -> &'a mut T { unsafe { let mut borrow = self.ptr.borrow_mut(); &mut **borrow } } pub fn root_ref<'b>(&'b self) -> JSRef<'b,T> { self.jsref.clone() } } #[unsafe_destructor] impl<'a, 'b, T: Reflectable> Drop for Root<'a, 'b, T> { fn drop(&mut self) { self.root_list.unroot(self); } } impl<'a, 'b, T: Reflectable> Reflectable for Root<'a, 'b, T> { fn reflector<'a>(&'a self) -> &'a Reflector { self.get().reflector() } fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector { self.get_mut().mut_reflector() } } impl<'a, 'b, T: Reflectable> Deref> for Root<'a, 'b, T> { fn deref<'c>(&'c self) -> &'c JSRef<'b, T> { &'a self.jsref } } impl<'a, 'b, T: Reflectable> DerefMut> for Root<'a, 'b, T> { fn deref_mut<'c>(&'c mut self) -> &'c mut JSRef<'b, T> { &'a mut self.jsref } } impl<'a, T: Reflectable> Deref for JSRef<'a, T> { fn deref<'b>(&'b self) -> &'b T { self.get() } } impl<'a, T: Reflectable> DerefMut for JSRef<'a, T> { fn deref_mut<'b>(&'b mut self) -> &'b mut T { self.get_mut() } } /// Encapsulates a reference to something that is guaranteed to be alive. This is freely copyable. pub struct JSRef<'a, T> { ptr: RefCell<*mut T>, chain: &'a (), } impl<'a, T> Clone for JSRef<'a, T> { fn clone(&self) -> JSRef<'a, T> { JSRef { ptr: self.ptr.clone(), chain: self.chain } } } impl<'a, T> Eq for JSRef<'a, T> { fn eq(&self, other: &JSRef) -> bool { self.ptr == other.ptr } } impl<'a,T> JSRef<'a,T> { pub fn get<'a>(&'a self) -> &'a T { unsafe { let borrow = self.ptr.borrow(); &**borrow } } pub fn get_mut<'a>(&'a mut self) -> &'a mut T { let mut borrowed = self.ptr.borrow_mut(); unsafe { &mut **borrowed } } //XXXjdm It would be lovely if this could be private. pub unsafe fn transmute<'b, To>(&'b self) -> &'b JSRef<'a, To> { cast::transmute(self) } //XXXjdm It would be lovely if this could be private. pub unsafe fn transmute_mut<'b, To>(&'b mut self) -> &'b mut JSRef<'a, To> { cast::transmute(self) } pub fn unrooted(&self) -> JS { JS { ptr: self.ptr.clone() } } } impl<'a, T: Reflectable> Reflectable for JSRef<'a, T> { fn reflector<'a>(&'a self) -> &'a Reflector { self.get().reflector() } fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector { self.get_mut().mut_reflector() } }