Bug 1421056 - Changes to the js Rust crate needed for Starling. r=till
authorNick Fitzgerald <fitzgen@gmail.com>
Mon, 27 Nov 2017 15:58:00 -0500
changeset 393916 bd70c8874a80aa2968f9c2e6275b2837f5bc6aae
parent 393915 d33ac0db7103cfd681798233a1521b18cb8e908f
child 393917 532ee04d1c93049fe8555cc1879686fed6097ca1
push id32985
push usercbrindusan@mozilla.com
push dateTue, 28 Nov 2017 09:51:26 +0000
treeherdermozilla-central@5b33b070378a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstill
bugs1421056
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1421056 - Changes to the js Rust crate needed for Starling. r=till Changes include: whitelisting more things in `bindgen`, exposing the builtin micro-task queue, and more conversion implementations.
js/rust/build.rs
js/rust/src/conversions.rs
js/rust/src/rust.rs
js/rust/tests/callback.rs
js/rust/tests/enumerate.rs
js/rust/tests/evaluate.rs
js/rust/tests/panic.rs
js/rust/tests/rooting.rs
js/rust/tests/runtime.rs
js/rust/tests/stack_limit.rs
js/rust/tests/typedarray.rs
js/rust/tests/vec_conversion.rs
--- a/js/rust/build.rs
+++ b/js/rust/build.rs
@@ -158,16 +158,17 @@ const WHITELIST_TYPES: &'static [&'stati
     "js::Class",
     "JS::CompartmentOptions",
     "JS::ContextOptions",
     "js::DOMCallbacks",
     "js::DOMProxyShadowsResult",
     "js::ESClass",
     "JS::ForOfIterator",
     "JS::Handle",
+    "JS::HandleFunction",
     "JS::HandleId",
     "JS::HandleObject",
     "JS::HandleString",
     "JS::HandleValue",
     "JS::HandleValueArray",
     "JS::IsAcceptableThis",
     "JSAutoCompartment",
     "JSAutoStructuredCloneBuffer",
@@ -221,16 +222,17 @@ const WHITELIST_TYPES: &'static [&'stati
     "JS::RootedObject",
     "JS::RootingContext",
     "JS::RootKind",
     "js::Scalar::Type",
     "JS::ServoSizes",
     "js::shadow::Object",
     "js::shadow::ObjectGroup",
     "JS::SourceBufferHolder",
+    "js::StackFormat",
     "JSStructuredCloneCallbacks",
     "JS::Symbol",
     "JS::SymbolCode",
     "JS::TraceKind",
     "JS::TransferableOwnership",
     "JS::Value",
     "JS::WarningReporter",
     "JS::shadow::Zone",
@@ -249,24 +251,27 @@ const WHITELIST_VARS: &'static [&'static
     "JS::NullHandleValue",
     "JS::TrueHandleValue",
     "JS::UndefinedHandleValue",
 ];
 
 /// Functions we want to generate bindings to.
 const WHITELIST_FUNCTIONS: &'static [&'static str] = &[
     "INTERNED_STRING_TO_JSID",
+    "ExceptionStackOrNull",
     "JS_AddExtraGCRootsTracer",
     "JS_AddInterruptCallback",
     "JS::AddPromiseReactions",
     "js::AddRawValueRoot",
     "JS_AlreadyHasOwnPropertyById",
     "JS_AtomizeAndPinString",
     "js::AssertSameCompartment",
+    "JS::BuildStackString",
     "JS::Call",
+    "JS_CallFunctionName",
     "JS_CallFunctionValue",
     "JS::CallOriginalPromiseThen",
     "JS::CallOriginalPromiseResolve",
     "JS::CallOriginalPromiseReject",
     "JS::CompileFunction",
     "JS::Construct",
     "JS::ContextOptionsRef",
     "JS_CopyPropertiesFrom",
@@ -283,16 +288,17 @@ const WHITELIST_FUNCTIONS: &'static [&'s
     "js::GetFunctionNativeReserved",
     "JS_GetFunctionPrototype",
     "js::GetGlobalForObjectCrossCompartment",
     "JS_GetIteratorPrototype",
     "js::GetObjectProto",
     "JS_GetObjectPrototype",
     "JS_GetObjectRuntime",
     "JS_GetOwnPropertyDescriptorById",
+    "JS::GetPromiseResult",
     "JS::GetPromiseState",
     "JS_GetPropertyDescriptorById",
     "js::GetPropertyKeys",
     "JS_GetPrototype",
     "JS_GetRuntime",
     "js::GetStaticPrototype",
     "JS_HasOwnPropertyById",
     "JS_HasProperty",
@@ -317,16 +323,17 @@ const WHITELIST_FUNCTIONS: &'static [&'s
     "JS::DisableIncrementalGC",
     "js::Dump.*",
     "JS_EncodeStringToUTF8",
     "JS_EndRequest",
     "JS_EnterCompartment",
     "JS_EnumerateStandardClasses",
     "JS_ErrorFromException",
     "JS_FireOnNewGlobalObject",
+    "JS_free",
     "JS_GC",
     "JS_GetArrayBufferData",
     "JS_GetArrayBufferViewType",
     "JS_GetFloat32ArrayData",
     "JS_GetFloat64ArrayData",
     "JS_GetFunctionObject",
     "JS_GetGCParameter",
     "JS_GetInt16ArrayData",
@@ -381,21 +388,23 @@ const WHITELIST_FUNCTIONS: &'static [&'s
     "JS_NewUint8Array",
     "JS_NewUint8ClampedArray",
     "js::ObjectClassName",
     "JS_ObjectIsDate",
     "JS_ParseJSON",
     "JS_ReadBytes",
     "JS_ReadStructuredClone",
     "JS_ReadUint32Pair",
+    "JS_RemoveExtraGCRootsTracer",
     "js::RemoveRawValueRoot",
     "JS_ReportErrorASCII",
     "JS_ReportErrorNumberUTF8",
     "JS_RequestInterruptCallback",
     "JS_ResolveStandardClass",
+    "js::RunJobs",
     "JS_SameValue",
     "js::SetDOMCallbacks",
     "js::SetDOMProxyInformation",
     "JS::SetEnqueuePromiseJobCallback",
     "js::SetFunctionNativeReserved",
     "JS_SetGCCallback",
     "JS::SetGCSliceCallback",
     "JS_SetGCParameter",
@@ -403,24 +412,26 @@ const WHITELIST_FUNCTIONS: &'static [&'s
     "JS::SetGetIncumbentGlobalCallback",
     "JS_SetGlobalJitCompilerOption",
     "JS_SetImmutablePrototype",
     "JS_SetNativeStackQuota",
     "JS_SetOffthreadIonCompilationEnabled",
     "JS_SetParallelParsingEnabled",
     "JS_SetPendingException",
     "js::SetPreserveWrapperCallback",
+    "JS::SetPromiseRejectionTrackerCallback",
     "JS_SetPrototype",
     "js::SetWindowProxy",
     "js::SetWindowProxyClass",
     "JS_SetProperty",
     "JS_SetReservedSlot",
     "JS_SetWrapObjectCallbacks",
     "JS_ShutDown",
     "JS_SplicePrototype",
+    "js::StopDrainingJobQueue",
     "JS_StrictPropertyStub",
     "JS_StringEqualsAscii",
     "JS_StringHasLatin1Chars",
     "JS_WrapObject",
     "JS_WrapValue",
     "JS_WriteBytes",
     "JS_WriteStructuredClone",
     "JS_WriteUint32Pair",
@@ -444,16 +455,18 @@ const WHITELIST_FUNCTIONS: &'static [&'s
     "js::UnwrapFloat64Array",
     "js::UnwrapInt16Array",
     "js::UnwrapInt32Array",
     "js::UnwrapInt8Array",
     "js::UnwrapUint16Array",
     "js::UnwrapUint32Array",
     "js::UnwrapUint8Array",
     "js::UnwrapUint8ClampedArray",
+    "js::UseInternalJobQueues",
+    "JS_ValueToFunction",
 ];
 
 /// Types that should be treated as an opaque blob of bytes whenever they show
 /// up within a whitelisted type.
 ///
 /// These are types which are too tricky for bindgen to handle, and/or use C++
 /// features that don't have an equivalent in rust, such as partial template
 /// specialization.
--- a/js/rust/src/conversions.rs
+++ b/js/rust/src/conversions.rs
@@ -97,16 +97,27 @@ pub trait ToJSValConvertible {
 pub enum ConversionResult<T> {
     /// Everything went fine.
     Success(T),
     /// Conversion failed, without a pending exception.
     Failure(Cow<'static, str>),
 }
 
 impl<T> ConversionResult<T> {
+    /// Map a function over the `Success` value.
+    pub fn map<F, U>(self, mut f: F) -> ConversionResult<U>
+    where
+        F: FnMut(T) -> U
+    {
+        match self {
+            ConversionResult::Success(t) => ConversionResult::Success(f(t)),
+            ConversionResult::Failure(e) => ConversionResult::Failure(e),
+        }
+    }
+
     /// Returns Some(value) if it is `ConversionResult::Success`.
     pub fn get_success_value(&self) -> Option<&T> {
         match *self {
             ConversionResult::Success(ref v) => Some(v),
             _ => None,
         }
     }
 }
@@ -132,16 +143,63 @@ pub enum ConversionBehavior {
     /// Wrap into the integer's range.
     Default,
     /// Throw an exception.
     EnforceRange,
     /// Clamp into the integer's range.
     Clamp,
 }
 
+/// Use `T` with `ConversionBehavior::Default` but without requiring any
+/// `Config` associated type.
+pub struct Default<T>(pub T);
+
+impl<T> FromJSValConvertible for Default<T>
+where
+    T: FromJSValConvertible<Config = ConversionBehavior>
+{
+    type Config = ();
+    unsafe fn from_jsval(cx: *mut JSContext, val: JS::HandleValue, _: ())
+                         -> Result<ConversionResult<Self>, ()> {
+        T::from_jsval(cx, val, ConversionBehavior::Default).map(|conv| conv.map(Default))
+    }
+}
+
+/// Use `T` with `ConversionBehavior::EnforceRange` but without requiring any
+/// `Config` associated type.
+pub struct EnforceRange<T>(pub T);
+
+impl<T> FromJSValConvertible for EnforceRange<T>
+    where
+    T: FromJSValConvertible<Config = ConversionBehavior>
+{
+    type Config = ();
+    unsafe fn from_jsval(cx: *mut JSContext, val: JS::HandleValue, _: ())
+                         -> Result<ConversionResult<Self>, ()> {
+        T::from_jsval(cx, val, ConversionBehavior::EnforceRange)
+            .map(|conv| conv.map(EnforceRange))
+    }
+}
+
+/// Use `T` with `ConversionBehavior::Clamp` but without requiring any `Config`
+/// associated type.
+pub struct Clamp<T>(pub T);
+
+impl<T> FromJSValConvertible for Clamp<T>
+    where
+    T: FromJSValConvertible<Config = ConversionBehavior>
+{
+    type Config = ();
+    unsafe fn from_jsval(cx: *mut JSContext, val: JS::HandleValue, _: ())
+                         -> Result<ConversionResult<Self>, ()> {
+        T::from_jsval(cx, val, ConversionBehavior::Clamp)
+            .map(|conv| conv.map(Clamp))
+    }
+}
+
 /// Try to cast the number to a smaller type, but
 /// if it doesn't fit, it will return an error.
 unsafe fn enforce_range<D>(cx: *mut JSContext, d: f64) -> Result<ConversionResult<D>, ()>
     where D: Bounded + As<f64>,
           f64: As<D>
 {
     if d.is_infinite() {
         throw_type_error(cx, "value out of range in an EnforceRange argument");
@@ -672,8 +730,60 @@ impl ToJSValConvertible for NonZero<*mut
 // https://heycam.github.io/webidl/#es-object
 impl ToJSValConvertible for Heap<*mut JSObject> {
     #[inline]
     unsafe fn to_jsval(&self, cx: *mut JSContext, rval: JS::MutableHandleValue) {
         rval.set(ObjectOrNullValue(self.get()));
         maybe_wrap_object_or_null_value(cx, rval);
     }
 }
+
+// JSFunction
+
+impl ToJSValConvertible for *mut JSFunction {
+    #[inline]
+    unsafe fn to_jsval(&self, cx: *mut JSContext, rval: JS::MutableHandleValue) {
+        rval.set(ObjectOrNullValue(*self as *mut JSObject));
+        maybe_wrap_object_or_null_value(cx, rval);
+    }
+}
+
+#[cfg(feature = "nonzero")]
+impl ToJSValConvertible for NonZero<*mut JSFunction> {
+    #[inline]
+    unsafe fn to_jsval(&self, cx: *mut JSContext, rval: JS::MutableHandleValue) {
+        use rust::maybe_wrap_object_value;
+        rval.set(ObjectValue(self.get() as *mut JSObject));
+        maybe_wrap_object_value(cx, rval);
+    }
+}
+
+impl ToJSValConvertible for Heap<*mut JSFunction> {
+    #[inline]
+    unsafe fn to_jsval(&self, cx: *mut JSContext, rval: JS::MutableHandleValue) {
+        rval.set(ObjectOrNullValue(self.get() as *mut JSObject));
+        maybe_wrap_object_or_null_value(cx, rval);
+    }
+}
+
+impl ToJSValConvertible for JS::Handle<*mut JSFunction> {
+    #[inline]
+    unsafe fn to_jsval(&self, cx: *mut JSContext, rval: JS::MutableHandleValue) {
+        rval.set(ObjectOrNullValue(self.get() as *mut JSObject));
+        maybe_wrap_object_or_null_value(cx, rval);
+    }
+}
+
+impl FromJSValConvertible for *mut JSFunction {
+    type Config = ();
+
+    unsafe fn from_jsval(cx: *mut JSContext,
+                         val: JS::HandleValue,
+                         _: ())
+                         -> Result<ConversionResult<Self>, ()> {
+        let func = JS_ValueToFunction(cx, val);
+        if func.is_null() {
+            Ok(ConversionResult::Failure("value is not a function".into()))
+        } else {
+            Ok(ConversionResult::Success(func))
+        }
+    }
+}
--- a/js/rust/src/rust.rs
+++ b/js/rust/src/rust.rs
@@ -79,17 +79,21 @@ impl Runtime {
         let cx = CONTEXT.with(|context| {
             context.get()
         });
         assert!(!cx.is_null());
         cx
     }
 
     /// Creates a new `JSContext`.
-    pub fn new() -> Result<Runtime, ()> {
+    ///
+    /// * `use_internal_job_queue`: If `true`, then SpiderMonkey's internal
+    /// micro-task job queue is used. If `false`, then it is up to you to
+    /// implement micro-tasks yourself.
+    pub fn new(use_internal_job_queue: bool) -> Result<Runtime, ()> {
         if SHUT_DOWN.load(Ordering::SeqCst) {
             return Err(());
         }
 
         OUTSTANDING_RUNTIMES.fetch_add(1, Ordering::SeqCst);
 
         unsafe {
             #[derive(Debug)]
@@ -172,16 +176,20 @@ impl Runtime {
             (*opts).set_ion_(true);
             (*opts).set_nativeRegExp_(true);
 
             CONTEXT.with(|context| {
                 assert!(context.get().is_null());
                 context.set(js_context);
             });
 
+            if use_internal_job_queue {
+                assert!(js::UseInternalJobQueues(js_context, false));
+            }
+
             JS::InitSelfHostedCode(js_context);
 
             JS::SetWarningReporter(js_context, Some(report_warning));
 
             JS_BeginRequest(js_context);
 
             Ok(Runtime {
                 cx: js_context,
@@ -1093,8 +1101,131 @@ pub unsafe fn maybe_wrap_object_or_null_
 #[inline]
 pub unsafe fn maybe_wrap_value(cx: *mut JSContext, rval: JS::MutableHandleValue) {
     if rval.is_string() {
         assert!(JS_WrapValue(cx, rval));
     } else if rval.is_object() {
         maybe_wrap_object_value(cx, rval);
     }
 }
+
+/// Equivalents of the JS_FN* macros.
+impl JSFunctionSpec {
+    pub fn js_fs(name: *const ::std::os::raw::c_char,
+                 func: JSNative,
+                 nargs: u16,
+                 flags: u16) -> JSFunctionSpec {
+        JSFunctionSpec {
+            name: name,
+            call: JSNativeWrapper {
+                op: func,
+                info: ptr::null(),
+            },
+            nargs: nargs,
+            flags: flags,
+            selfHostedName: 0 as *const _,
+        }
+    }
+
+    pub fn js_fn(name: *const ::std::os::raw::c_char,
+                 func: JSNative,
+                 nargs: u16,
+                 flags: u16) -> JSFunctionSpec {
+        JSFunctionSpec {
+            name: name,
+            call: JSNativeWrapper {
+                op: func,
+                info: ptr::null(),
+            },
+            nargs: nargs,
+            flags: flags,
+            selfHostedName: 0 as *const _,
+        }
+    }
+
+    pub const NULL: JSFunctionSpec = JSFunctionSpec {
+        name: 0 as *const _,
+        call: JSNativeWrapper {
+            op: None,
+            info: 0 as *const _,
+        },
+        nargs: 0,
+        flags: 0,
+        selfHostedName: 0 as *const _,
+    };
+}
+
+/// Equivalents of the JS_PS* macros.
+impl JSPropertySpec {
+    pub fn getter(name: *const ::std::os::raw::c_char, flags: u8, func: JSNative)
+                        -> JSPropertySpec {
+        debug_assert_eq!(flags & !(JSPROP_ENUMERATE | JSPROP_PERMANENT), 0);
+        JSPropertySpec {
+            name: name,
+            flags: flags,
+            __bindgen_anon_1: JSPropertySpec__bindgen_ty_1 {
+                accessors: JSPropertySpec__bindgen_ty_1__bindgen_ty_1 {
+                    getter: JSPropertySpec__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1 {
+                        native: JSNativeWrapper {
+                            op: func,
+                            info: ptr::null(),
+                        },
+                    },
+                    setter: JSPropertySpec__bindgen_ty_1__bindgen_ty_1__bindgen_ty_2 {
+                        native: JSNativeWrapper {
+                            op: None,
+                            info: ptr::null(),
+                        },
+                    }
+                }
+            }
+        }
+    }
+
+    pub fn getter_setter(name: *const ::std::os::raw::c_char,
+                         flags: u8,
+                         g_f: JSNative,
+                         s_f: JSNative)
+                         -> JSPropertySpec {
+        debug_assert_eq!(flags & !(JSPROP_ENUMERATE | JSPROP_PERMANENT), 0);
+        JSPropertySpec {
+            name: name,
+            flags: flags,
+            __bindgen_anon_1: JSPropertySpec__bindgen_ty_1 {
+                accessors: JSPropertySpec__bindgen_ty_1__bindgen_ty_1 {
+                    getter: JSPropertySpec__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1 {
+                        native: JSNativeWrapper {
+                            op: g_f,
+                            info: ptr::null(),
+                        },
+                    },
+                    setter: JSPropertySpec__bindgen_ty_1__bindgen_ty_1__bindgen_ty_2 {
+                        native: JSNativeWrapper {
+                            op: s_f,
+                            info: ptr::null(),
+                        },
+                    }
+                }
+            }
+        }
+    }
+
+    pub const NULL: JSPropertySpec = JSPropertySpec {
+        name: 0 as *const _,
+        flags: 0,
+        __bindgen_anon_1: JSPropertySpec__bindgen_ty_1{
+            accessors: JSPropertySpec__bindgen_ty_1__bindgen_ty_1 {
+                getter: JSPropertySpec__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1 {
+                    native: JSNativeWrapper {
+                        op: None,
+                        info: 0 as *const _,
+                    },
+                },
+                setter: JSPropertySpec__bindgen_ty_1__bindgen_ty_1__bindgen_ty_2 {
+                    native: JSNativeWrapper {
+                        op: None,
+                        info: 0 as *const _,
+                    },
+                }
+            }
+        }
+    };
+}
--- a/js/rust/tests/callback.rs
+++ b/js/rust/tests/callback.rs
@@ -20,17 +20,17 @@ use js::jsval::UndefinedValue;
 use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS};
 
 use std::ffi::CStr;
 use std::ptr;
 use std::str;
 
 #[test]
 fn callback() {
-    let runtime = Runtime::new().unwrap();
+    let runtime = Runtime::new(false).unwrap();
     let context = runtime.cx();
     let h_option = OnNewGlobalHookOption::FireOnNewGlobalHook;
     let c_option = CompartmentOptions::default();
 
     unsafe {
         let global = JS_NewGlobalObject(context, &SIMPLE_GLOBAL_CLASS, ptr::null_mut(), h_option, &c_option);
         rooted!(in(context) let global_root = global);
         let global = global_root.handle();
--- a/js/rust/tests/enumerate.rs
+++ b/js/rust/tests/enumerate.rs
@@ -16,17 +16,17 @@ use js::jsapi::root::JS::OnNewGlobalHook
 use js::jsval::UndefinedValue;
 use js::rust::IdVector;
 use js::rust::Runtime;
 use js::rust::SIMPLE_GLOBAL_CLASS;
 use std::ptr;
 
 #[test]
 fn enumerate() {
-    let rt = Runtime::new().unwrap();
+    let rt = Runtime::new(false).unwrap();
     let cx = rt.cx();
 
     unsafe {
         rooted!(in(cx) let global =
             JS_NewGlobalObject(cx, &SIMPLE_GLOBAL_CLASS, ptr::null_mut(),
                                OnNewGlobalHookOption::FireOnNewGlobalHook,
                                &CompartmentOptions::default())
         );
--- a/js/rust/tests/evaluate.rs
+++ b/js/rust/tests/evaluate.rs
@@ -10,17 +10,17 @@ use js::jsapi::root::JS_NewGlobalObject;
 use js::jsapi::root::JS::OnNewGlobalHookOption;
 use js::jsval::UndefinedValue;
 use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS};
 
 use std::ptr;
 
 #[test]
 fn evaluate() {
-    let rt = Runtime::new().unwrap();
+    let rt = Runtime::new(false).unwrap();
     let cx = rt.cx();
 
     unsafe {
 
         rooted!(in(cx) let global =
             JS_NewGlobalObject(cx, &SIMPLE_GLOBAL_CLASS, ptr::null_mut(),
                                OnNewGlobalHookOption::FireOnNewGlobalHook,
                                &CompartmentOptions::default())
--- a/js/rust/tests/panic.rs
+++ b/js/rust/tests/panic.rs
@@ -10,17 +10,17 @@ use js::jsval::UndefinedValue;
 use js::panic::wrap_panic;
 use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS};
 use std::ptr;
 use std::str;
 
 #[test]
 #[should_panic]
 fn panic() {
-    let runtime = Runtime::new().unwrap();
+    let runtime = Runtime::new(false).unwrap();
     let context = runtime.cx();
     let h_option = JS::OnNewGlobalHookOption::FireOnNewGlobalHook;
     let c_option = JS::CompartmentOptions::default();
 
     unsafe {
         let global = JS_NewGlobalObject(context, &SIMPLE_GLOBAL_CLASS,
                                         ptr::null_mut(), h_option, &c_option);
         rooted!(in(context) let global_root = global);
--- a/js/rust/tests/rooting.rs
+++ b/js/rust/tests/rooting.rs
@@ -12,17 +12,17 @@ extern crate libc;
 
 use js::jsapi::*;
 use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS, define_methods};
 use std::ptr;
 
 #[test]
 fn rooting() {
     unsafe {
-        let runtime = Runtime::new().unwrap();
+        let runtime = Runtime::new(false).unwrap();
         JS_SetGCZeal(runtime.cx(), 2, 1);
 
         let cx = runtime.cx();
         let h_option = JS::OnNewGlobalHookOption::FireOnNewGlobalHook;
         let c_option = JS::CompartmentOptions::default();
 
         rooted!(in(cx) let global = JS_NewGlobalObject(cx,
                                                        &SIMPLE_GLOBAL_CLASS,
--- a/js/rust/tests/runtime.rs
+++ b/js/rust/tests/runtime.rs
@@ -8,32 +8,32 @@ extern crate libc;
 
 use js::jsapi::*;
 use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS};
 use std::ptr;
 
 #[test]
 fn runtime() {
     unsafe {
-        let runtime = Runtime::new().unwrap();
+        let runtime = Runtime::new(false).unwrap();
 
         let cx = runtime.cx();
         let h_option = JS::OnNewGlobalHookOption::FireOnNewGlobalHook;
         let c_option = JS::CompartmentOptions::default();
 
         rooted!(in(cx) let global = JS_NewGlobalObject(cx,
                                                        &SIMPLE_GLOBAL_CLASS,
                                                        ptr::null_mut(),
                                                        h_option,
                                                        &c_option));
         let _ac = js::ac::AutoCompartment::with_obj(cx, global.get());
         rooted!(in(cx) let _object = JS_NewObject(cx, &CLASS as *const _));
     }
 
-    assert!(Runtime::new().is_err());
+    assert!(Runtime::new(false).is_err());
 }
 
 unsafe extern fn finalize(_fop: *mut JSFreeOp, _object: *mut JSObject) {
     assert!(!Runtime::get().is_null());
 }
 
 static CLASS_OPS: JSClassOps = JSClassOps {
     addProperty: None,
--- a/js/rust/tests/stack_limit.rs
+++ b/js/rust/tests/stack_limit.rs
@@ -10,17 +10,17 @@ use js::jsapi::root::JS_NewGlobalObject;
 use js::jsapi::root::JS::OnNewGlobalHookOption;
 use js::jsval::UndefinedValue;
 use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS};
 
 use std::ptr;
 
 #[test]
 fn stack_limit() {
-    let rt = Runtime::new().unwrap();
+    let rt = Runtime::new(false).unwrap();
     let cx = rt.cx();
 
     unsafe {
         let h_option = OnNewGlobalHookOption::FireOnNewGlobalHook;
         let c_option = CompartmentOptions::default();
         let global = JS_NewGlobalObject(cx, &SIMPLE_GLOBAL_CLASS,
                                         ptr::null_mut(), h_option, &c_option);
         rooted!(in(cx) let global_root = global);
--- a/js/rust/tests/typedarray.rs
+++ b/js/rust/tests/typedarray.rs
@@ -9,17 +9,17 @@ use js::jsapi::*;
 use js::jsval::UndefinedValue;
 use js::rust::Runtime as Runtime_;
 use js::rust::SIMPLE_GLOBAL_CLASS;
 use js::typedarray::{CreateWith, Uint32Array};
 use std::ptr;
 
 #[test]
 fn typedarray() {
-    let rt = Runtime_::new().unwrap();
+    let rt = Runtime_::new(false).unwrap();
     let cx = rt.cx();
 
     unsafe {
         rooted!(in(cx) let global =
             JS_NewGlobalObject(cx, &SIMPLE_GLOBAL_CLASS, ptr::null_mut(),
                                JS::OnNewGlobalHookOption::FireOnNewGlobalHook,
                                &JS::CompartmentOptions::default())
         );
@@ -67,17 +67,17 @@ fn typedarray() {
         typedarray!(in(cx) let view: ArrayBufferView = rval.get());
         assert_eq!(view.unwrap().get_array_type(), js::jsapi::js::Scalar::Type::Uint32);
     }
 }
 
 #[test]
 #[should_panic]
 fn typedarray_update_panic() {
-    let rt = Runtime_::new().unwrap();
+    let rt = Runtime_::new(false).unwrap();
     let cx = rt.cx();
 
     unsafe {
         rooted!(in(cx) let global =
             JS_NewGlobalObject(cx, &SIMPLE_GLOBAL_CLASS, ptr::null_mut(),
                                JS::OnNewGlobalHookOption::FireOnNewGlobalHook,
                                &JS::CompartmentOptions::default())
         );
--- a/js/rust/tests/vec_conversion.rs
+++ b/js/rust/tests/vec_conversion.rs
@@ -25,17 +25,17 @@ fn assert_is_array(cx: *mut js::jsapi::r
     assert!(unsafe {
         js::jsapi::root::JS_IsArrayObject(cx, val, &mut is_array as *mut _)
     });
     assert!(is_array);
 }
 
 #[test]
 fn vec_conversion() {
-    let rt = Runtime::new().unwrap();
+    let rt = Runtime::new(false).unwrap();
     let cx = rt.cx();
 
     let h_option = OnNewGlobalHookOption::FireOnNewGlobalHook;
     let c_option = CompartmentOptions::default();
 
     unsafe {
         let global = JS_NewGlobalObject(cx, &SIMPLE_GLOBAL_CLASS,
                                         ptr::null_mut(), h_option, &c_option);