use crate::js_error::JsResult;
use crate::js_value::JSValue;
use mozjs::rooted;
pub fn to_js_host_call(value: &JSValue) -> JSValue {
value.clone()
}
pub fn from_js_host_call(value: &JSValue) -> JsResult<JSValue> {
Ok(value.clone())
}
pub fn to_js_host_fn_result(result: JsResult<JSValue>) -> JSValue {
result.unwrap_or(JSValue::UNDEFINED)
}
pub unsafe fn call_method_on_object(
cx: *mut mozjs::jsapi::JSContext,
obj: *mut mozjs::jsapi::JSObject,
method_name: &str,
args: &[mozjs::jsapi::Value],
) -> mozjs::jsapi::Value {
if cx.is_null() || obj.is_null() {
return mozjs::jsval::UndefinedValue();
}
let wrapped_cx =
unsafe { mozjs::context::JSContext::from_ptr(::std::ptr::NonNull::new_unchecked(cx)) };
let c_method = ::std::ffi::CString::new(method_name).unwrap_or_default();
let mut method_val = mozjs::jsval::UndefinedValue();
rooted!(&in(wrapped_cx) let obj_root = obj);
unsafe {
mozjs::jsapi::JS_GetProperty(
cx,
obj_root.handle().into(),
c_method.as_ptr(),
mozjs::jsapi::MutableHandle::<mozjs::jsapi::Value> {
_phantom_0: ::std::marker::PhantomData,
ptr: &mut method_val,
},
);
}
if !method_val.is_object() {
return mozjs::jsval::UndefinedValue();
}
let global = unsafe { mozjs::jsapi::CurrentGlobalOrNull(cx) };
if global.is_null() {
return mozjs::jsval::UndefinedValue();
}
rooted!(&in(wrapped_cx) let cb_val_root = method_val);
rooted!(&in(wrapped_cx) let global_root = global);
let call_args = if args.is_empty() {
mozjs::jsapi::HandleValueArray::empty()
} else {
mozjs::jsapi::HandleValueArray {
length_: args.len(),
elements_: args.as_ptr(),
}
};
let mut rval = mozjs::jsval::UndefinedValue();
let rval_h = mozjs::jsapi::MutableHandle::<mozjs::jsapi::Value> {
_phantom_0: ::std::marker::PhantomData,
ptr: &mut rval,
};
unsafe {
mozjs::jsapi::JS_CallFunctionValue(
cx,
global_root.handle().into(),
cb_val_root.handle().into(),
&call_args,
rval_h,
);
}
unsafe {
mozjs::jsapi::JS_ClearPendingException(cx);
}
rval
}