aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/bindings/js.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/bindings/js.rs')
-rw-r--r--components/script/dom/bindings/js.rs543
1 files changed, 148 insertions, 395 deletions
diff --git a/components/script/dom/bindings/js.rs b/components/script/dom/bindings/js.rs
index fc22078360f..400200c3df3 100644
--- a/components/script/dom/bindings/js.rs
+++ b/components/script/dom/bindings/js.rs
@@ -11,178 +11,32 @@
//!
//! Here is a brief overview of the important types:
//!
-//! - `JSRef<T>`: a freely-copyable reference to a rooted DOM object.
//! - `Root<T>`: a stack-based reference to a rooted DOM object.
//! - `JS<T>`: a reference to a DOM object that can automatically be traced by
//! the GC when encountered as a field of a Rust structure.
-//! - `Temporary<T>`: a reference to a DOM object that will remain rooted for
-//! the duration of its lifetime.
//!
-//! The rule of thumb is as follows:
+//! `JS<T>` does not allow access to their inner value without explicitly
+//! creating a stack-based root via the `root` method. This returns a `Root<T>`,
+//! which causes the JS-owned value to be uncollectable for the duration of the
+//! `Root` object's lifetime. A reference to the object can then be obtained
+//! from the `Root` object. These references are not allowed to outlive their
+//! originating `Root<T>`.
//!
-//! - All methods return `Temporary<T>`, to ensure the value remains alive
-//! until it is stored somewhere that is reachable by the GC.
-//! - All functions take `JSRef<T>` arguments, to ensure that they will remain
-//! uncollected for the duration of their usage.
-//! - All DOM structs contain `JS<T>` fields and derive the `JSTraceable`
-//! trait, to ensure that they are transitively marked as reachable by the GC
-//! if the enclosing value is reachable.
-//! - All methods for type `T` are implemented for `JSRef<T>`, to ensure that
-//! the self value will not be collected for the duration of the method call.
-//!
-//! Both `Temporary<T>` and `JS<T>` do not allow access to their inner value
-//! without explicitly creating a stack-based root via the `root` method
-//! through the `Rootable<T>` trait. This returns a `Root<T>`, which causes the
-//! JS-owned value to be uncollectable for the duration of the `Root` object's
-//! lifetime. A `JSRef<T>` can be obtained from a `Root<T>` by calling the `r`
-//! method. These `JSRef<T>` values are not allowed to outlive their
-//! originating `Root<T>`, to ensure that all interactions with the enclosed
-//! value only occur when said value is uncollectable, and will cause static
-//! lifetime errors if misused.
-//!
-//! Other miscellaneous helper traits:
-//!
-//! - `OptionalRootable` and `OptionalOptionalRootable`: make rooting `Option`
-//! values easy via a `root` method
-//! - `ResultRootable`: make rooting successful `Result` values easy
-//! - `TemporaryPushable`: allows mutating vectors of `JS<T>` with new elements
-//! of `JSRef`/`Temporary`
-//! - `RootedReference`: makes obtaining an `Option<JSRef<T>>` from an
-//! `Option<Root<T>>` easy
use dom::bindings::trace::JSTraceable;
-use dom::bindings::trace::RootedVec;
+use dom::bindings::trace::trace_reflector;
use dom::bindings::utils::{Reflector, Reflectable};
use dom::node::Node;
-use js::jsapi::JSObject;
-use js::jsval::JSVal;
+use js::jsapi::{JSObject, Heap, JSTracer};
+use js::jsval::{JSVal, UndefinedValue};
use layout_interface::TrustedNodeAddress;
use script_task::STACK_ROOTS;
use core::nonzero::NonZero;
-use libc;
use std::cell::{Cell, UnsafeCell};
use std::default::Default;
-use std::intrinsics::return_address;
-use std::marker::PhantomData;
use std::ops::Deref;
-/// An unrooted, JS-owned value. Must not be held across a GC.
-///
-/// This is used in particular to wrap pointers extracted from a reflector.
-#[must_root]
-pub struct Unrooted<T> {
- ptr: NonZero<*const T>
-}
-
-impl<T: Reflectable> Unrooted<T> {
- /// Create a new JS-owned value wrapped from a raw Rust pointer.
- pub unsafe fn from_raw(raw: *const T) -> Unrooted<T> {
- assert!(!raw.is_null());
- Unrooted {
- ptr: NonZero::new(raw)
- }
- }
-
- /// Create a new unrooted value from a `JS<T>`.
- #[allow(unrooted_must_root)]
- pub fn from_js(ptr: JS<T>) -> Unrooted<T> {
- Unrooted {
- ptr: ptr.ptr
- }
- }
-
- /// Create a new unrooted value from a `Temporary<T>`.
- #[allow(unrooted_must_root)]
- pub fn from_temporary(ptr: Temporary<T>) -> Unrooted<T> {
- Unrooted::from_js(ptr.inner)
- }
-
- /// Get the `Reflector` for this pointer.
- pub fn reflector<'a>(&'a self) -> &'a Reflector {
- unsafe {
- (**self.ptr).reflector()
- }
- }
-
- /// Returns an unsafe pointer to the interior of this object.
- pub unsafe fn unsafe_get(&self) -> *const T {
- *self.ptr
- }
-}
-
-impl<T: Reflectable> Rootable<T> for Unrooted<T> {
- /// Create a stack-bounded root for this value.
- fn root(&self) -> Root<T> {
- STACK_ROOTS.with(|ref collection| {
- let RootCollectionPtr(collection) = collection.get().unwrap();
- unsafe {
- Root::new(&*collection, self.ptr)
- }
- })
- }
-}
-
-impl<T> Copy for Unrooted<T> {}
-impl<T> Clone for Unrooted<T> {
- fn clone(&self) -> Unrooted<T> { *self }
-}
-
-/// 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 (i.e.
-/// `JS<T>` types) safely via the `JS<T>::assign` method or
-/// `OptionalSettable::assign` (for `Option<JS<T>>` fields).
-#[allow(unrooted_must_root)]
-pub struct Temporary<T> {
- inner: JS<T>,
- /// On-stack JS pointer to assuage conservative stack scanner
- _js_ptr: *mut JSObject,
-}
-
-impl<T> Clone for Temporary<T> {
- fn clone(&self) -> Temporary<T> {
- Temporary {
- inner: self.inner,
- _js_ptr: self._js_ptr,
- }
- }
-}
-
-impl<T> PartialEq for Temporary<T> {
- fn eq(&self, other: &Temporary<T>) -> bool {
- self.inner == other.inner
- }
-}
-
-impl<T: Reflectable> Temporary<T> {
- /// Create a new `Temporary` value from an unrooted value.
- #[allow(unrooted_must_root)]
- pub fn from_unrooted(unrooted: Unrooted<T>) -> Temporary<T> {
- Temporary {
- inner: JS { ptr: unrooted.ptr },
- _js_ptr: unrooted.reflector().get_jsobject(),
- }
- }
-
- /// Create a new `Temporary` value from a rooted value.
- #[allow(unrooted_must_root)]
- pub fn from_rooted<U: Assignable<T>>(root: U) -> Temporary<T> {
- let inner = JS::from_rooted(root);
- Temporary {
- inner: inner,
- _js_ptr: inner.reflector().get_jsobject(),
- }
- }
-}
-
-impl<T: Reflectable> Rootable<T> for Temporary<T> {
- /// Create a stack-bounded root for this value.
- fn root(&self) -> Root<T> {
- self.inner.root()
- }
-}
-
/// A traced reference to a DOM object. Must only be used as a field in other
/// DOM objects.
#[must_root]
@@ -198,6 +52,32 @@ impl<T> JS<T> {
}
}
}
+impl<T: Reflectable> JS<T> {
+ /// Root this JS-owned value to prevent its collection as garbage.
+ pub fn root(&self) -> Root<T> {
+ Root::new(self.ptr)
+ }
+ /// Create a JS<T> from a Root<T>
+ /// XXX Not a great API. Should be a call on Root<T> instead
+ pub fn from_rooted(root: &Root<T>) -> JS<T> {
+ JS {
+ ptr: unsafe { NonZero::new(&**root) }
+ }
+ }
+ /// Create a JS<T> from a &T
+ pub fn from_ref(obj: &T) -> JS<T> {
+ JS {
+ ptr: unsafe { NonZero::new(&*obj) }
+ }
+ }
+ /// Store an rooted value in this field. This is safe under the
+ /// assumption that JS<T> 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: Root<T>) {
+ self.ptr = val.ptr.clone();
+ }
+}
/// An unrooted reference to a DOM object for use in layout. `Layout*Helpers`
/// traits must be implemented on this.
@@ -208,7 +88,7 @@ pub struct LayoutJS<T> {
impl<T: Reflectable> LayoutJS<T> {
/// Get the reflector.
pub unsafe fn get_jsobject(&self) -> *mut JSObject {
- (**self.ptr).reflector().get_jsobject()
+ (**self.ptr).reflector().get_jsobject().get()
}
}
@@ -217,14 +97,12 @@ impl<T> Copy for JS<T> {}
impl<T> Copy for LayoutJS<T> {}
impl<T> PartialEq for JS<T> {
- #[allow(unrooted_must_root)]
fn eq(&self, other: &JS<T>) -> bool {
self.ptr == other.ptr
}
}
impl<T> PartialEq for LayoutJS<T> {
- #[allow(unrooted_must_root)]
fn eq(&self, other: &LayoutJS<T>) -> bool {
self.ptr == other.ptr
}
@@ -260,29 +138,6 @@ impl LayoutJS<Node> {
}
}
-impl<T: Reflectable> Rootable<T> for JS<T> {
- /// Root this JS-owned value to prevent its collection as garbage.
- fn root(&self) -> Root<T> {
- STACK_ROOTS.with(|ref collection| {
- let RootCollectionPtr(collection) = collection.get().unwrap();
- unsafe {
- Root::new(&*collection, self.ptr)
- }
- })
- }
-}
-
-impl<U: Reflectable> JS<U> {
- /// Create a `JS<T>` from any JS-managed pointer.
- pub fn from_rooted<T: Assignable<U>>(root: T) -> JS<U> {
- unsafe {
- root.get_js()
- }
- }
-}
-
-//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<T: Reflectable> Reflectable for JS<T> {
fn reflector<'a>(&'a self) -> &'a Reflector {
unsafe {
@@ -298,19 +153,50 @@ impl<T: Reflectable> Reflectable for JS<T> {
pub trait HeapGCValue: JSTraceable {
}
-impl HeapGCValue for JSVal {
+impl HeapGCValue for Heap<JSVal> {
}
impl<T: Reflectable> HeapGCValue for JS<T> {
}
-/// A holder that provides interior mutability for GC-managed values such as
-/// `JSVal` and `JS<T>`.
+/// A holder that provides interior mutability for GC-managed JSVals.
///
/// Must be used in place of traditional interior mutability to ensure proper
/// GC barriers are enforced.
#[must_root]
#[jstraceable]
+pub struct MutHeapJSVal {
+ val: UnsafeCell<Heap<JSVal>>,
+}
+
+impl MutHeapJSVal {
+ /// Create a new `MutHeapJSVal`.
+ pub fn new() -> MutHeapJSVal {
+ MutHeapJSVal {
+ val: UnsafeCell::new(Heap::default()),
+ }
+ }
+
+ /// Set this `MutHeapJSVal` to the given value, calling write barriers as
+ /// appropriate.
+ pub fn set(&self, val: JSVal) {
+ unsafe {
+ let cell = self.val.get();
+ (*cell).set(val);
+ }
+ }
+
+ /// Set the value in this `MutHeapJSVal`, calling read barriers as appropriate.
+ pub fn get(&self) -> JSVal {
+ unsafe { (*self.val.get()).get() }
+ }
+}
+
+
+/// A holder that provides interior mutability for GC-managed values such as
+/// `JS<T>`.
+#[must_root]
+#[jstraceable]
pub struct MutHeap<T: HeapGCValue+Copy> {
val: Cell<T>,
}
@@ -323,13 +209,12 @@ impl<T: HeapGCValue+Copy> MutHeap<T> {
}
}
- /// Set this `MutHeap` to the given value, calling write barriers as
- /// appropriate.
+ /// Set this `MutHeap` to the given value.
pub fn set(&self, val: T) {
self.val.set(val)
}
- /// Set the value in this `MutHeap`, calling read barriers as appropriate.
+ /// Set the value in this `MutHeap`.
pub fn get(&self) -> T {
self.val.get()
}
@@ -353,8 +238,7 @@ impl<T: HeapGCValue+Copy> MutNullableHeap<T> {
}
}
- /// Set this `MutNullableHeap` to the given value, calling write barriers
- /// as appropriate.
+ /// Set this `MutNullableHeap` to the given value.
pub fn set(&self, val: Option<T>) {
self.ptr.set(val);
}
@@ -368,14 +252,14 @@ impl<T: HeapGCValue+Copy> MutNullableHeap<T> {
impl<T: Reflectable> MutNullableHeap<JS<T>> {
/// Retrieve a copy of the current inner value. If it is `None`, it is
/// initialized with the result of `cb` first.
- pub fn or_init<F>(&self, cb: F) -> Temporary<T>
- where F: FnOnce() -> Temporary<T>
+ pub fn or_init<F>(&self, cb: F) -> Root<T>
+ where F: FnOnce() -> Root<T>
{
match self.get() {
- Some(inner) => Temporary::from_rooted(inner),
+ Some(inner) => Root::from_rooted(inner),
None => {
let inner = cb();
- self.set(Some(JS::from_rooted(inner.clone())));
+ self.set(Some(JS::from_rooted(&inner)));
inner
},
}
@@ -396,16 +280,6 @@ impl<T: HeapGCValue+Copy> Default for MutNullableHeap<T> {
}
}
-impl<T: Reflectable> JS<T> {
- /// Store an unrooted value in this field. This is safe under the
- /// assumption that JS<T> 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<T>) {
- *self = val.inner.clone();
- }
-}
-
impl<T: Reflectable> LayoutJS<T> {
/// Returns an unsafe pointer to the interior of this JS object. This is
/// the only method that be safely accessed from layout. (The fact that
@@ -419,129 +293,36 @@ impl<T: Reflectable> LayoutJS<T> {
pub trait RootedReference<T> {
/// Obtain a safe optional reference to the wrapped JS owned-value that
/// cannot outlive the lifetime of this root.
- fn r<'a>(&'a self) -> Option<JSRef<'a, T>>;
+ fn r<'a>(&'a self) -> Option<&'a T>;
}
impl<T: Reflectable> RootedReference<T> for Option<Root<T>> {
- fn r<'a>(&'a self) -> Option<JSRef<'a, T>> {
+ fn r<'a>(&'a self) -> Option<&'a T> {
self.as_ref().map(|root| root.r())
}
}
-/// Get an `Option<Option<JSRef<T>>>` out of an `Option<Option<Root<T>>>`
+/// Get an `Option<Option<&T>>` out of an `Option<Option<Root<T>>>`
pub trait OptionalRootedReference<T> {
/// Obtain a safe optional optional reference to the wrapped JS owned-value
/// that cannot outlive the lifetime of this root.
- fn r<'a>(&'a self) -> Option<Option<JSRef<'a, T>>>;
+ fn r<'a>(&'a self) -> Option<Option<&'a T>>;
}
impl<T: Reflectable> OptionalRootedReference<T> for Option<Option<Root<T>>> {
- fn r<'a>(&'a self) -> Option<Option<JSRef<'a, T>>> {
+ fn r<'a>(&'a self) -> Option<Option<&'a T>> {
self.as_ref().map(|inner| inner.r())
}
}
-/// Trait that allows extracting a `JS<T>` value from a variety of
-/// rooting-related containers, which in general is an unsafe operation since
-/// they can outlive the rooted lifetime of the original value.
-pub trait Assignable<T> {
- /// Extract an unrooted `JS<T>`.
- unsafe fn get_js(&self) -> JS<T>;
-}
-
-impl<T> Assignable<T> for JS<T> {
- unsafe fn get_js(&self) -> JS<T> {
- self.clone()
- }
-}
-
-impl<'a, T: Reflectable> Assignable<T> for JSRef<'a, T> {
- unsafe fn get_js(&self) -> JS<T> {
- JS {
- ptr: self.ptr
- }
- }
-}
-
-impl<T: Reflectable> Assignable<T> for Temporary<T> {
- unsafe fn get_js(&self) -> JS<T> {
- self.inner.clone()
- }
-}
-
-
-/// Root a rootable `Option` type (used for `Option<Temporary<T>>`)
-pub trait OptionalRootable<T> {
- /// Root the inner value, if it exists.
- fn root(&self) -> Option<Root<T>>;
-}
-
-impl<T: Reflectable, U: Rootable<T>> OptionalRootable<T> for Option<U> {
- fn root(&self) -> Option<Root<T>> {
- self.as_ref().map(|inner| inner.root())
- }
-}
-
-/// Root a rootable `Option<Option>` type (used for `Option<Option<JS<T>>>`)
-pub trait OptionalOptionalRootable<T> {
- /// Root the inner value, if it exists.
- fn root(&self) -> Option<Option<Root<T>>>;
-}
-
-impl<T: Reflectable, U: OptionalRootable<T>> OptionalOptionalRootable<T> for Option<U> {
- fn root(&self) -> Option<Option<Root<T>>> {
- self.as_ref().map(|inner| inner.root())
- }
-}
-
-/// Root a rootable `Result` type (any of `Temporary<T>` or `JS<T>`)
-pub trait ResultRootable<T,U> {
- /// Root the inner value, if it exists.
- fn root(self) -> Result<Root<T>, U>;
-}
-
-impl<T: Reflectable, U, V: Rootable<T>> ResultRootable<T, U> for Result<V, U> {
- fn root(self) -> Result<Root<T>, U> {
- self.map(|inner| inner.root())
- }
-}
-
-/// Root a rootable type.
-pub trait Rootable<T> {
- /// Root the value.
- fn root(&self) -> Root<T>;
-}
-
-
-/// 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<T> {
- /// Push a new value onto this container.
- fn push_unrooted(&mut self, val: &T);
- /// Insert a new value into this container.
- fn insert_unrooted(&mut self, index: usize, val: &T);
-}
-
-impl<T: Assignable<U>, U: Reflectable> TemporaryPushable<T> for Vec<JS<U>> {
- fn push_unrooted(&mut self, val: &T) {
- self.push(unsafe { val.get_js() });
- }
-
- fn insert_unrooted(&mut self, index: usize, val: &T) {
- self.insert(index, unsafe { val.get_js() });
- }
-}
-
-/// An opaque, LIFO rooting mechanism. This tracks roots and ensures that they
-/// are destructed in a LIFO order.
+/// A rooting mechanism for reflectors on the stack.
+/// LIFO is not required.
///
/// See also [*Exact Stack Rooting - Storing a GCPointer on the CStack*]
/// (https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Internals/GC/Exact_Stack_Rooting).
#[no_move]
pub struct RootCollection {
- roots: UnsafeCell<RootedVec<*mut JSObject>>,
+ roots: UnsafeCell<Vec<*const Reflector>>,
}
/// A pointer to a RootCollection, for use in global variables.
@@ -555,142 +336,114 @@ impl Clone for RootCollectionPtr {
impl RootCollection {
/// Create an empty collection of roots
pub fn new() -> RootCollection {
- let addr = unsafe {
- return_address() as *const libc::c_void
- };
-
RootCollection {
- roots: UnsafeCell::new(RootedVec::new_with_destination_address(addr)),
+ roots: UnsafeCell::new(vec!()),
}
}
- /// Track a stack-based root as a pointer to ensure LIFO root ordering.
- fn root<'b>(&self, untracked_js_ptr: *mut JSObject) {
+ /// Start tracking a stack-based root
+ fn root<'b>(&self, untracked_reflector: *const Reflector) {
unsafe {
- let roots = self.roots.get();
- (*roots).push(untracked_js_ptr);
- debug!(" rooting {:?}", untracked_js_ptr);
+ let mut roots = &mut *self.roots.get();
+ roots.push(untracked_reflector);
+ assert!(!(*untracked_reflector).get_jsobject().is_null())
}
}
- /// Stop tracking a stack-based root, asserting if LIFO root ordering has
- /// been violated
+ /// Stop tracking a stack-based root, asserting if the reflector isn't found
fn unroot<'b, T: Reflectable>(&self, rooted: &Root<T>) {
unsafe {
- let roots = self.roots.get();
- let unrooted = (*roots).pop().unwrap();
- debug!("unrooted {:?} (expecting {:?}", unrooted, rooted.js_ptr);
- assert!(unrooted == rooted.js_ptr);
+ let mut roots = &mut *self.roots.get();
+ let old_reflector = &*rooted.r().reflector();
+ match roots.iter().rposition(|r| *r == old_reflector) {
+ Some(idx) => {
+ roots.remove(idx);
+ },
+ None => panic!("Can't remove a root that was never rooted!")
+ }
}
}
}
+/// SM Callback that traces the rooted reflectors
+pub unsafe fn trace_roots(tracer: *mut JSTracer) {
+ STACK_ROOTS.with(|ref collection| {
+ let RootCollectionPtr(collection) = collection.get().unwrap();
+ let collection = &*(*collection).roots.get();
+ for root in collection.iter() {
+ trace_reflector(tracer, "reflector", &**root);
+ }
+ });
+}
+
/// A rooted reference to a DOM object.
///
/// 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. `Root`s cannot outlive the associated
-/// `RootCollection` object. Attempts to transfer ownership of a `Root` via
-/// moving will trigger dynamic unrooting failures due to incorrect ordering.
-#[no_move]
+/// `RootCollection` object.
pub struct Root<T: Reflectable> {
- /// List that ensures correct dynamic root ordering
- root_list: &'static RootCollection,
/// Reference to rooted value that must not outlive this container
ptr: NonZero<*const T>,
- /// On-stack JS pointer to assuage conservative stack scanner
- js_ptr: *mut JSObject,
+ /// List that ensures correct dynamic root ordering
+ root_list: *const RootCollection,
}
impl<T: Reflectable> Root<T> {
/// Create a new stack-bounded root for the provided JS-owned value.
- /// It cannot not outlive its associated `RootCollection`, and it contains
- /// a `JSRef` which cannot outlive this new `Root`.
- #[inline]
- fn new(roots: &'static RootCollection, unrooted: NonZero<*const T>)
- -> Root<T> {
- let js_ptr = unsafe {
- (**unrooted).reflector().get_jsobject()
- };
- roots.root(js_ptr);
- Root {
- root_list: roots,
- ptr: unrooted,
- js_ptr: js_ptr,
- }
+ /// It cannot not outlive its associated `RootCollection`, and it gives
+ /// out references which cannot outlive this new `Root`.
+ pub fn new(unrooted: NonZero<*const T>)
+ -> Root<T> {
+ STACK_ROOTS.with(|ref collection| {
+ let RootCollectionPtr(collection) = collection.get().unwrap();
+ unsafe { (*collection).root(&*(**unrooted).reflector()) }
+ Root {
+ ptr: unrooted,
+ root_list: collection,
+ }
+ })
}
- /// Obtain a safe reference to the wrapped JS owned-value that cannot
- /// outlive the lifetime of this root.
- pub fn r<'b>(&'b self) -> JSRef<'b, T> {
- JSRef {
- ptr: self.ptr,
- chain: PhantomData,
- }
+ /// Generate a new root from a reference
+ pub fn from_ref(unrooted: &T) -> Root<T> {
+ Root::new(unsafe { NonZero::new(&*unrooted) })
}
- /// Obtain an unsafe reference to the wrapped JS owned-value that can
+ /// Obtain a safe reference to the wrapped JS owned-value that cannot
/// outlive the lifetime of this root.
- ///
- /// DO NOT CALL.
- pub fn get_unsound_ref_forever<'b>(&self) -> JSRef<'b, T> {
- JSRef {
- ptr: self.ptr,
- chain: PhantomData,
- }
+ pub fn r<'a>(&'a self) -> &'a T {
+ &**self
}
-}
-impl<T: Reflectable> Drop for Root<T> {
- fn drop(&mut self) {
- self.root_list.unroot(self);
+ /// Don't use this. Don't make me find you.
+ pub fn get_unsound_ref_forever<'a, 'b>(&'a self) -> &'b T {
+ unsafe { &**self.ptr }
}
-}
-impl<'a, T: Reflectable> Deref for JSRef<'a, T> {
- type Target = T;
- fn deref<'b>(&'b self) -> &'b T {
- unsafe {
- &**self.ptr
- }
+ /// Generate a new root from a JS<T> reference
+ #[allow(unrooted_must_root)]
+ pub fn from_rooted(js: JS<T>) -> Root<T> {
+ js.root()
}
}
-/// A reference to a DOM object that is guaranteed to be alive. This is freely
-/// copyable.
-pub struct JSRef<'a, T> {
- ptr: NonZero<*const T>,
- chain: PhantomData<&'a ()>,
-}
-
-impl<'a, T> Copy for JSRef<'a, T> {}
-
-impl<'a, T> Clone for JSRef<'a, T> {
- fn clone(&self) -> JSRef<'a, T> {
- JSRef {
- ptr: self.ptr.clone(),
- chain: self.chain,
- }
+impl<T: Reflectable> Deref for Root<T> {
+ type Target = T;
+ fn deref<'a>(&'a self) -> &'a T {
+ unsafe { &**self.ptr.deref() }
}
}
-impl<'a, 'b, T> PartialEq<JSRef<'b, T>> for JSRef<'a, T> {
- fn eq(&self, other: &JSRef<T>) -> bool {
+impl<T: Reflectable> PartialEq for Root<T> {
+ fn eq(&self, other: &Root<T>) -> bool {
self.ptr == other.ptr
}
}
-impl<'a, T: Reflectable> JSRef<'a, T> {
- /// Returns the inner pointer directly.
- pub fn extended_deref(self) -> &'a T {
- unsafe {
- &**self.ptr
- }
+impl<T: Reflectable> Drop for Root<T> {
+ fn drop(&mut self) {
+ unsafe { (*self.root_list).unroot(self); }
}
}
-impl<'a, T: Reflectable> Reflectable for JSRef<'a, T> {
- fn reflector<'b>(&'b self) -> &'b Reflector {
- (**self).reflector()
- }
-}