use std::convert::TryFrom;
use std::marker::PhantomData;
use crate::support::MapFnFrom;
use crate::support::MapFnTo;
use crate::support::ToCFn;
use crate::support::UnitType;
use crate::support::{int, Opaque};
use crate::CallbackScope;
use crate::Context;
use crate::Function;
use crate::HandleScope;
use crate::Local;
use crate::Name;
use crate::Object;
use crate::Value;
extern "C" {
fn v8__Function__New(
context: *const Context,
callback: FunctionCallback,
) -> *const Function;
fn v8__Function__NewWithData(
context: *const Context,
callback: FunctionCallback,
data: *const Value,
) -> *const Function;
fn v8__Function__Call(
this: *const Function,
context: *const Context,
recv: *const Value,
argc: int,
argv: *const *const Value,
) -> *const Value;
fn v8__FunctionCallbackInfo__GetReturnValue(
info: *const FunctionCallbackInfo,
) -> *mut Value;
fn v8__FunctionCallbackInfo__This(
this: *const FunctionCallbackInfo,
) -> *const Object;
fn v8__FunctionCallbackInfo__Length(this: *const FunctionCallbackInfo)
-> int;
fn v8__FunctionCallbackInfo__GetArgument(
this: *const FunctionCallbackInfo,
i: int,
) -> *const Value;
fn v8__FunctionCallbackInfo__Data(
this: *const FunctionCallbackInfo,
) -> *const Value;
fn v8__PropertyCallbackInfo__GetReturnValue(
this: *const PropertyCallbackInfo,
) -> *mut Value;
fn v8__PropertyCallbackInfo__This(
this: *const PropertyCallbackInfo,
) -> *const Object;
fn v8__ReturnValue__Set(this: *mut ReturnValue, value: *const Value);
fn v8__ReturnValue__Get(this: *const ReturnValue) -> *const Value;
}
#[repr(C)]
pub struct ReturnValue<'cb>(*mut Value, PhantomData<&'cb ()>);
impl<'cb> ReturnValue<'cb> {
fn from_function_callback_info(info: *const FunctionCallbackInfo) -> Self {
let slot = unsafe { v8__FunctionCallbackInfo__GetReturnValue(info) };
Self(slot, PhantomData)
}
fn from_property_callback_info(info: *const PropertyCallbackInfo) -> Self {
let slot = unsafe { v8__PropertyCallbackInfo__GetReturnValue(info) };
Self(slot, PhantomData)
}
pub fn set(&mut self, value: Local<Value>) {
unsafe { v8__ReturnValue__Set(&mut *self, &*value) }
}
pub fn get<'s>(&self, scope: &mut HandleScope<'s>) -> Local<'s, Value> {
unsafe { scope.cast_local(|_| v8__ReturnValue__Get(self)) }.unwrap()
}
}
#[repr(C)]
pub struct FunctionCallbackInfo {
implicit_args: *mut Opaque,
values: *const Value,
length: int,
}
#[repr(C)]
pub struct PropertyCallbackInfo {
args: *mut Opaque,
}
pub struct FunctionCallbackArguments<'s> {
info: *const FunctionCallbackInfo,
phantom: PhantomData<&'s ()>,
}
impl<'s> FunctionCallbackArguments<'s> {
fn from_function_callback_info(info: *const FunctionCallbackInfo) -> Self {
Self {
info,
phantom: PhantomData,
}
}
pub fn this(&self) -> Local<'s, Object> {
unsafe {
Local::from_raw(v8__FunctionCallbackInfo__This(self.info)).unwrap()
}
}
pub fn data(&self) -> Option<Local<'s, Value>> {
unsafe { Local::from_raw(v8__FunctionCallbackInfo__Data(self.info)) }
}
pub fn length(&self) -> int {
unsafe {
let length = (*self.info).length;
debug_assert_eq!(length, v8__FunctionCallbackInfo__Length(self.info));
length
}
}
pub fn get(&self, i: int) -> Local<'s, Value> {
unsafe {
Local::from_raw(v8__FunctionCallbackInfo__GetArgument(self.info, i))
.unwrap()
}
}
}
pub struct PropertyCallbackArguments<'s> {
info: *const PropertyCallbackInfo,
phantom: PhantomData<&'s ()>,
}
impl<'s> PropertyCallbackArguments<'s> {
fn from_property_callback_info(info: *const PropertyCallbackInfo) -> Self {
Self {
info,
phantom: PhantomData,
}
}
pub fn this(&self) -> Local<'s, Object> {
unsafe {
Local::from_raw(v8__PropertyCallbackInfo__This(self.info)).unwrap()
}
}
}
pub type FunctionCallback = extern "C" fn(*const FunctionCallbackInfo);
impl<F> MapFnFrom<F> for FunctionCallback
where
F: UnitType + Fn(&mut HandleScope, FunctionCallbackArguments, ReturnValue),
{
fn mapping() -> Self {
let f = |info: *const FunctionCallbackInfo| {
let scope = &mut unsafe { CallbackScope::new(&*info) };
let args = FunctionCallbackArguments::from_function_callback_info(info);
let rv = ReturnValue::from_function_callback_info(info);
(F::get())(scope, args, rv);
};
f.to_c_fn()
}
}
pub type AccessorNameGetterCallback<'s> =
extern "C" fn(Local<'s, Name>, *const PropertyCallbackInfo);
impl<F> MapFnFrom<F> for AccessorNameGetterCallback<'_>
where
F: UnitType
+ Fn(&mut HandleScope, Local<Name>, PropertyCallbackArguments, ReturnValue),
{
fn mapping() -> Self {
let f = |key: Local<Name>, info: *const PropertyCallbackInfo| {
let scope = &mut unsafe { CallbackScope::new(&*info) };
let args = PropertyCallbackArguments::from_property_callback_info(info);
let rv = ReturnValue::from_property_callback_info(info);
(F::get())(scope, key, args, rv);
};
f.to_c_fn()
}
}
impl Function {
pub fn new<'s>(
scope: &mut HandleScope<'s>,
callback: impl MapFnTo<FunctionCallback>,
) -> Option<Local<'s, Function>> {
unsafe {
scope.cast_local(|sd| {
v8__Function__New(sd.get_current_context(), callback.map_fn_to())
})
}
}
pub fn new_with_data<'s>(
scope: &mut HandleScope<'s>,
data: Local<Value>,
callback: impl MapFnTo<FunctionCallback>,
) -> Option<Local<'s, Function>> {
unsafe {
scope.cast_local(|sd| {
v8__Function__NewWithData(
sd.get_current_context(),
callback.map_fn_to(),
&*data,
)
})
}
}
pub fn call<'s>(
&self,
scope: &mut HandleScope<'s>,
recv: Local<Value>,
args: &[Local<Value>],
) -> Option<Local<'s, Value>> {
let args = Local::slice_into_raw(args);
let argc = int::try_from(args.len()).unwrap();
let argv = args.as_ptr();
unsafe {
scope.cast_local(|sd| {
v8__Function__Call(self, sd.get_current_context(), &*recv, argc, argv)
})
}
}
}