diff --git a/src/conversions.rs b/src/conversions.rs index a6065b055..9d91eb68b 100644 --- a/src/conversions.rs +++ b/src/conversions.rs @@ -42,6 +42,7 @@ use rust::{ToString, maybe_wrap_object_or_null_value}; use rust::{maybe_wrap_object_value, maybe_wrap_value}; use libc; use num_traits::{Bounded, Zero}; +use rust::{AsHandle, AsHandleMut}; use std::borrow::Cow; use std::rc::Rc; use std::{ptr, slice}; diff --git a/src/rust.rs b/src/rust.rs index 0c7520d82..bfbc2b28f 100644 --- a/src/rust.rs +++ b/src/rust.rs @@ -20,8 +20,8 @@ use consts::{JSCLASS_RESERVED_SLOTS_MASK, JSCLASS_GLOBAL_SLOT_COUNT}; use consts::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL}; use jsapi; use jsapi::{AutoIdVector, AutoObjectVector, CallArgs, CompartmentOptions, ContextFriendFields}; -use jsapi::{Evaluate2, Handle, HandleBase, HandleObject, HandleValue, Heap, HeapObjectPostBarrier}; -use jsapi::{HeapValuePostBarrier, InitSelfHostedCode, IsWindowSlow, JS_BeginRequest}; +use jsapi::{Evaluate2, Handle, HandleBase, HandleObject, HandleValue, HandleValueArray, Heap}; +use jsapi::{HeapObjectPostBarrier, HeapValuePostBarrier, InitSelfHostedCode, IsWindowSlow, JS_BeginRequest}; use jsapi::{JS_DefineFunctions, JS_DefineProperties, JS_DestroyRuntime, JS_EndRequest}; use jsapi::{JS_EnterCompartment, JS_EnumerateStandardClasses, JS_GetContext, JS_GlobalObjectTraceHook}; use jsapi::{JS_Init, JS_LeaveCompartment, JS_MayResolveStandardClass, JS_NewRuntime, JS_ResolveStandardClass}; @@ -270,6 +270,7 @@ impl RootKind for Value { } // Creates a C string literal `$str`. +#[macro_export] macro_rules! c_str { ($str:expr) => { concat!($str, "\0").as_ptr() as *const ::std::os::raw::c_char @@ -320,6 +321,50 @@ unsafe impl Trace for Heap { } } +pub trait AsHandle { + fn handle(&self) -> Handle; + + fn get(&self) -> T where T: Copy { + self.handle().get() + } +} + +/// Given the types `$T` and `$U`, implements the trait `AsHandle<$T>` for the type `$U`, where +/// `$U` is a newtype whose underlying type implements `AsHandle<$T>`. +#[macro_export] +macro_rules! derive_as_handle { + ($T:ty, $U:ty) => { + impl $crate::rust::AsHandle<$T> for $U { + fn handle(&self) -> $crate::jsapi::Handle<$T> { + self.0.handle() + } + } + } +} + +pub trait AsHandleMut : AsHandle { + fn handle_mut(&mut self) -> MutableHandle; + + fn set(&mut self, v: T) where T: Copy { + self.handle_mut().set(v) + } +} + +/// Given the types `$T` and `$U`, implements the trait `AsHandleMut<$T>` for the type `$U`, where +/// `$U` is a newtype whose underlying type implements `HandleMut<$T>`. +#[macro_export] +macro_rules! derive_as_handle_mut { + ($T:ty, $U:ty) => { + derive_as_handle($T, $U); + + impl $crate::rust::AsHandleMut<$T> for $U { + fn handle_mut(&self) -> $crate::jsapi::MutableHandle<$T> { + self.0.handle_mut() + } + } + } +} + impl Rooted { pub fn new_unrooted(initial: T) -> Rooted { Rooted { @@ -362,26 +407,6 @@ impl<'a, T> RootedGuard<'a, T> { root: root } } - - pub fn handle(&self) -> Handle { - unsafe { - Handle::from_marked_location(&self.root.ptr) - } - } - - pub fn handle_mut(&mut self) -> MutableHandle { - unsafe { - MutableHandle::from_marked_location(&mut self.root.ptr) - } - } - - pub fn get(&self) -> T where T: Copy { - self.root.ptr - } - - pub fn set(&mut self, v: T) { - self.root.ptr = v; - } } impl<'a, T> Deref for RootedGuard<'a, T> { @@ -405,6 +430,22 @@ impl<'a, T> Drop for RootedGuard<'a, T> { } } +impl<'a, T> AsHandle for RootedGuard<'a, T> { + fn handle(&self) -> Handle { + unsafe { + Handle::from_marked_location(&self.root.ptr) + } + } +} + +impl<'a, T> AsHandleMut for RootedGuard<'a, T> { + fn handle_mut(&mut self) -> MutableHandle { + unsafe { + MutableHandle::from_marked_location(&mut self.root.ptr) + } + } +} + #[macro_export] macro_rules! rooted { (in($cx:expr) let $name:ident = $init:expr) => { @@ -495,6 +536,22 @@ impl HandleValue { } } +impl HandleValueArray { + pub fn new() -> HandleValueArray { + HandleValueArray { + length_: 0, + elements_: ptr::null(), + } + } + + pub unsafe fn from_rooted_slice(values: &[Value]) -> HandleValueArray { + HandleValueArray { + length_: values.len(), + elements_: values.as_ptr() + } + } +} + const ConstNullValue: *mut JSObject = 0 as *mut JSObject; impl HandleObject { @@ -580,28 +637,9 @@ impl + Copy> Heap { ptr } - pub fn set(&mut self, v: T) { - unsafe { - let ptr = self.ptr.get(); - let prev = *ptr; - *ptr = v; - T::post_barrier(ptr, prev, v); - } - } - - pub fn get(&self) -> T { - unsafe { *self.ptr.get() } - } - pub fn get_unsafe(&self) -> *mut T { self.ptr.get() } - - pub fn handle(&self) -> Handle { - unsafe { - Handle::from_marked_location(self.ptr.get() as *const _) - } - } } impl + Copy> Clone for Heap @@ -645,6 +683,22 @@ impl + Copy + PartialEq> PartialEq for Heap { } } +impl + Copy> AsHandle for Heap { + fn handle(&self) -> Handle { + unsafe { + Handle::from_marked_location(self.ptr.get() as *const _) + } + } +} + +impl + Copy> AsHandleMut for Heap { + fn handle_mut(&mut self) -> MutableHandle { + unsafe { + MutableHandle::from_marked_location(self.ptr.get() as *mut _) + } + } +} + // ___________________________________________________________________________ // Implementations for various things in jsapi.rs diff --git a/tests/callback.rs b/tests/callback.rs index 115c2fdfb..582993010 100644 --- a/tests/callback.rs +++ b/tests/callback.rs @@ -17,7 +17,7 @@ use js::jsapi::JS_ReportError; use js::jsapi::OnNewGlobalHookOption; use js::jsapi::Value; use js::jsval::UndefinedValue; -use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS}; +use js::rust::{AsHandle, AsHandleMut, Runtime, SIMPLE_GLOBAL_CLASS}; use std::ffi::CStr; use std::ptr; diff --git a/tests/enumerate.rs b/tests/enumerate.rs index 08ccbaef7..3c8323c5c 100644 --- a/tests/enumerate.rs +++ b/tests/enumerate.rs @@ -14,6 +14,8 @@ use js::jsapi::JS_NewGlobalObject; use js::jsapi::JS_StringEqualsAscii; use js::jsapi::OnNewGlobalHookOption; use js::jsval::UndefinedValue; +use js::rust::AsHandle; +use js::rust::AsHandleMut; use js::rust::IdVector; use js::rust::Runtime; use js::rust::SIMPLE_GLOBAL_CLASS; diff --git a/tests/evaluate.rs b/tests/evaluate.rs index da3074e80..c0fa41006 100644 --- a/tests/evaluate.rs +++ b/tests/evaluate.rs @@ -9,7 +9,7 @@ use js::jsapi::CompartmentOptions; use js::jsapi::JS_NewGlobalObject; use js::jsapi::OnNewGlobalHookOption; use js::jsval::UndefinedValue; -use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS}; +use js::rust::{AsHandle, AsHandleMut, Runtime, SIMPLE_GLOBAL_CLASS}; use std::ptr; diff --git a/tests/panic.rs b/tests/panic.rs index 548f9ee48..6b924b2c8 100644 --- a/tests/panic.rs +++ b/tests/panic.rs @@ -14,7 +14,7 @@ use js::jsapi::OnNewGlobalHookOption; use js::jsapi::Value; use js::jsval::UndefinedValue; use js::panic::wrap_panic; -use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS}; +use js::rust::{AsHandle, AsHandleMut, Runtime, SIMPLE_GLOBAL_CLASS}; use std::ptr; use std::str; diff --git a/tests/stack_limit.rs b/tests/stack_limit.rs index b15f1b75c..0d90e2c82 100644 --- a/tests/stack_limit.rs +++ b/tests/stack_limit.rs @@ -9,7 +9,7 @@ use js::jsapi::CompartmentOptions; use js::jsapi::JS_NewGlobalObject; use js::jsapi::OnNewGlobalHookOption; use js::jsval::UndefinedValue; -use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS}; +use js::rust::{AsHandle, AsHandleMut, Runtime, SIMPLE_GLOBAL_CLASS}; use std::ptr; diff --git a/tests/typedarray.rs b/tests/typedarray.rs index cd2f127f3..c73b5ba1c 100644 --- a/tests/typedarray.rs +++ b/tests/typedarray.rs @@ -10,6 +10,8 @@ use js::jsapi::JSAutoCompartment; use js::jsapi::JS_NewGlobalObject; use js::jsapi::OnNewGlobalHookOption; use js::jsval::UndefinedValue; +use js::rust::AsHandle; +use js::rust::AsHandleMut; use js::rust::Runtime as Runtime_; use js::rust::SIMPLE_GLOBAL_CLASS; use js::typedarray::Uint32Array; diff --git a/tests/vec_conversion.rs b/tests/vec_conversion.rs index 95fdd2ae0..e9d755d92 100644 --- a/tests/vec_conversion.rs +++ b/tests/vec_conversion.rs @@ -15,7 +15,7 @@ use js::jsapi::JS_InitStandardClasses; use js::jsapi::JS_NewGlobalObject; use js::jsapi::OnNewGlobalHookOption; use js::jsval::UndefinedValue; -use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS}; +use js::rust::{AsHandle, AsHandleMut, Runtime, SIMPLE_GLOBAL_CLASS}; use std::ptr;