Skip to content

Commit

Permalink
Introduce RootedTraceableBox.
Browse files Browse the repository at this point in the history
  • Loading branch information
Ms2ger committed Feb 16, 2017
1 parent 8c8eb41 commit f1605ab
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 0 deletions.
17 changes: 17 additions & 0 deletions components/script/dom/bindings/conversions.rs
Expand Up @@ -37,6 +37,7 @@ use dom::bindings::js::Root;
use dom::bindings::num::Finite;
use dom::bindings::reflector::{DomObject, Reflector};
use dom::bindings::str::{ByteString, DOMString, USVString};
use dom::bindings::trace::{JSTraceable, RootedTraceableBox};
use dom::bindings::utils::DOMClass;
use js;
pub use js::conversions::{FromJSValConvertible, ToJSValConvertible, ConversionResult};
Expand Down Expand Up @@ -117,6 +118,22 @@ impl <T: DomObject + IDLInterface> FromJSValConvertible for Root<T> {
}
}

impl <T: FromJSValConvertible + JSTraceable> FromJSValConvertible for RootedTraceableBox<T> {
type Config = T::Config;

unsafe fn from_jsval(cx: *mut JSContext,
value: HandleValue,
config: Self::Config)
-> Result<ConversionResult<Self>, ()> {
T::from_jsval(cx, value, config).map(|result| {
match result {
ConversionResult::Success(v) => ConversionResult::Success(RootedTraceableBox::new(v)),
ConversionResult::Failure(e) => ConversionResult::Failure(e),
}
})
}
}

/// Convert `id` to a `DOMString`, assuming it is string-valued.
///
/// Handling of invalid UTF-16 in strings depends on the relevant option.
Expand Down
55 changes: 55 additions & 0 deletions components/script/dom/bindings/trace.rs
Expand Up @@ -653,6 +653,61 @@ impl<'a, T: JSTraceable + 'static> Drop for RootedTraceable<'a, T> {
}
}

/// Roots any JSTraceable thing
///
/// If you have a valid DomObject, use Root.
/// If you have GC things like *mut JSObject or JSVal, use rooted!.
/// If you have an arbitrary number of DomObjects to root, use rooted_vec!.
/// If you know what you're doing, use this.
pub struct RootedTraceableBox<T: 'static + JSTraceable> {
ptr: *mut T,
}

unsafe impl<T: JSTraceable + 'static> JSTraceable for RootedTraceableBox<T> {
unsafe fn trace(&self, tracer: *mut JSTracer) {
(*self.ptr).trace(tracer);
}
}

impl<T: JSTraceable + 'static> RootedTraceableBox<T> {
/// Root a JSTraceable thing for the life of this RootedTraceable
pub fn new(traceable: T) -> RootedTraceableBox<T> {
let traceable = Box::into_raw(box traceable);
unsafe {
RootedTraceableSet::add(traceable);
}
RootedTraceableBox {
ptr: traceable,
}
}
}

impl<T: JSTraceable> Deref for RootedTraceableBox<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe {
&*self.ptr
}
}
}

impl<T: JSTraceable> DerefMut for RootedTraceableBox<T> {
fn deref_mut(&mut self) -> &mut T {
unsafe {
&mut *self.ptr
}
}
}

impl<T: JSTraceable + 'static> Drop for RootedTraceableBox<T> {
fn drop(&mut self) {
unsafe {
RootedTraceableSet::remove(self.ptr);
let _ = Box::from_raw(self.ptr);
}
}
}

/// A vector of items to be rooted with `RootedVec`.
/// Guaranteed to be empty when not rooted.
/// Usage: `rooted_vec!(let mut v);` or if you have an
Expand Down

0 comments on commit f1605ab

Please sign in to comment.