зеркало из https://github.com/mozilla/gecko-dev.git
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.
This commit is contained in:
Родитель
a02f536d6d
Коммит
f73f7eecaf
|
@ -163,6 +163,7 @@ const WHITELIST_TYPES: &'static [&'static str] = &[
|
|||
"js::ESClass",
|
||||
"JS::ForOfIterator",
|
||||
"JS::Handle",
|
||||
"JS::HandleFunction",
|
||||
"JS::HandleId",
|
||||
"JS::HandleObject",
|
||||
"JS::HandleString",
|
||||
|
@ -226,6 +227,7 @@ const WHITELIST_TYPES: &'static [&'static str] = &[
|
|||
"js::shadow::Object",
|
||||
"js::shadow::ObjectGroup",
|
||||
"JS::SourceBufferHolder",
|
||||
"js::StackFormat",
|
||||
"JSStructuredCloneCallbacks",
|
||||
"JS::Symbol",
|
||||
"JS::SymbolCode",
|
||||
|
@ -254,6 +256,7 @@ const WHITELIST_VARS: &'static [&'static str] = &[
|
|||
/// Functions we want to generate bindings to.
|
||||
const WHITELIST_FUNCTIONS: &'static [&'static str] = &[
|
||||
"INTERNED_STRING_TO_JSID",
|
||||
"ExceptionStackOrNull",
|
||||
"JS_AddExtraGCRootsTracer",
|
||||
"JS_AddInterruptCallback",
|
||||
"JS::AddPromiseReactions",
|
||||
|
@ -261,7 +264,9 @@ const WHITELIST_FUNCTIONS: &'static [&'static str] = &[
|
|||
"JS_AlreadyHasOwnPropertyById",
|
||||
"JS_AtomizeAndPinString",
|
||||
"js::AssertSameCompartment",
|
||||
"JS::BuildStackString",
|
||||
"JS::Call",
|
||||
"JS_CallFunctionName",
|
||||
"JS_CallFunctionValue",
|
||||
"JS::CallOriginalPromiseThen",
|
||||
"JS::CallOriginalPromiseResolve",
|
||||
|
@ -288,6 +293,7 @@ const WHITELIST_FUNCTIONS: &'static [&'static str] = &[
|
|||
"JS_GetObjectPrototype",
|
||||
"JS_GetObjectRuntime",
|
||||
"JS_GetOwnPropertyDescriptorById",
|
||||
"JS::GetPromiseResult",
|
||||
"JS::GetPromiseState",
|
||||
"JS_GetPropertyDescriptorById",
|
||||
"js::GetPropertyKeys",
|
||||
|
@ -322,6 +328,7 @@ const WHITELIST_FUNCTIONS: &'static [&'static str] = &[
|
|||
"JS_EnumerateStandardClasses",
|
||||
"JS_ErrorFromException",
|
||||
"JS_FireOnNewGlobalObject",
|
||||
"JS_free",
|
||||
"JS_GC",
|
||||
"JS_GetArrayBufferData",
|
||||
"JS_GetArrayBufferViewType",
|
||||
|
@ -386,11 +393,13 @@ const WHITELIST_FUNCTIONS: &'static [&'static str] = &[
|
|||
"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",
|
||||
|
@ -408,6 +417,7 @@ const WHITELIST_FUNCTIONS: &'static [&'static str] = &[
|
|||
"JS_SetParallelParsingEnabled",
|
||||
"JS_SetPendingException",
|
||||
"js::SetPreserveWrapperCallback",
|
||||
"JS::SetPromiseRejectionTrackerCallback",
|
||||
"JS_SetPrototype",
|
||||
"js::SetWindowProxy",
|
||||
"js::SetWindowProxyClass",
|
||||
|
@ -416,6 +426,7 @@ const WHITELIST_FUNCTIONS: &'static [&'static str] = &[
|
|||
"JS_SetWrapObjectCallbacks",
|
||||
"JS_ShutDown",
|
||||
"JS_SplicePrototype",
|
||||
"js::StopDrainingJobQueue",
|
||||
"JS_StrictPropertyStub",
|
||||
"JS_StringEqualsAscii",
|
||||
"JS_StringHasLatin1Chars",
|
||||
|
@ -449,6 +460,8 @@ const WHITELIST_FUNCTIONS: &'static [&'static str] = &[
|
|||
"js::UnwrapUint32Array",
|
||||
"js::UnwrapUint8Array",
|
||||
"js::UnwrapUint8ClampedArray",
|
||||
"js::UseInternalJobQueues",
|
||||
"JS_ValueToFunction",
|
||||
];
|
||||
|
||||
/// Types that should be treated as an opaque blob of bytes whenever they show
|
||||
|
|
|
@ -102,6 +102,17 @@ pub enum ConversionResult<T> {
|
|||
}
|
||||
|
||||
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 {
|
||||
|
@ -137,6 +148,53 @@ pub enum ConversionBehavior {
|
|||
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>, ()>
|
||||
|
@ -677,3 +735,55 @@ impl ToJSValConvertible for Heap<*mut JSObject> {
|
|||
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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,7 +84,11 @@ impl Runtime {
|
|||
}
|
||||
|
||||
/// 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(());
|
||||
}
|
||||
|
@ -177,6 +181,10 @@ impl Runtime {
|
|||
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));
|
||||
|
@ -1098,3 +1106,126 @@ pub unsafe fn maybe_wrap_value(cx: *mut JSContext, rval: JS::MutableHandleValue)
|
|||
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 _,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ 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();
|
||||
|
|
|
@ -21,7 +21,7 @@ use std::ptr;
|
|||
|
||||
#[test]
|
||||
fn enumerate() {
|
||||
let rt = Runtime::new().unwrap();
|
||||
let rt = Runtime::new(false).unwrap();
|
||||
let cx = rt.cx();
|
||||
|
||||
unsafe {
|
||||
|
|
|
@ -15,7 +15,7 @@ use std::ptr;
|
|||
|
||||
#[test]
|
||||
fn evaluate() {
|
||||
let rt = Runtime::new().unwrap();
|
||||
let rt = Runtime::new(false).unwrap();
|
||||
let cx = rt.cx();
|
||||
|
||||
unsafe {
|
||||
|
|
|
@ -15,7 +15,7 @@ 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();
|
||||
|
|
|
@ -17,7 +17,7 @@ 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();
|
||||
|
|
|
@ -13,7 +13,7 @@ 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;
|
||||
|
@ -28,7 +28,7 @@ fn runtime() {
|
|||
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) {
|
||||
|
|
|
@ -15,7 +15,7 @@ use std::ptr;
|
|||
|
||||
#[test]
|
||||
fn stack_limit() {
|
||||
let rt = Runtime::new().unwrap();
|
||||
let rt = Runtime::new(false).unwrap();
|
||||
let cx = rt.cx();
|
||||
|
||||
unsafe {
|
||||
|
|
|
@ -14,7 +14,7 @@ use std::ptr;
|
|||
|
||||
#[test]
|
||||
fn typedarray() {
|
||||
let rt = Runtime_::new().unwrap();
|
||||
let rt = Runtime_::new(false).unwrap();
|
||||
let cx = rt.cx();
|
||||
|
||||
unsafe {
|
||||
|
@ -72,7 +72,7 @@ fn typedarray() {
|
|||
#[test]
|
||||
#[should_panic]
|
||||
fn typedarray_update_panic() {
|
||||
let rt = Runtime_::new().unwrap();
|
||||
let rt = Runtime_::new(false).unwrap();
|
||||
let cx = rt.cx();
|
||||
|
||||
unsafe {
|
||||
|
|
|
@ -30,7 +30,7 @@ fn assert_is_array(cx: *mut js::jsapi::root::JSContext,
|
|||
|
||||
#[test]
|
||||
fn vec_conversion() {
|
||||
let rt = Runtime::new().unwrap();
|
||||
let rt = Runtime::new(false).unwrap();
|
||||
let cx = rt.cx();
|
||||
|
||||
let h_option = OnNewGlobalHookOption::FireOnNewGlobalHook;
|
||||
|
|
Загрузка…
Ссылка в новой задаче