use alloc::boxed::Box;
use core::ffi::c_int;
use rmquickjs_sys::{JS_Call, JS_PushArg, JSGCRef};
use crate::{Context, Error, Result, Value};
pub struct Function<'ctx> {
gc_ref: Box<JSGCRef>,
ctx: &'ctx Context,
}
impl Into<Value> for Function<'_> {
fn into(self) -> Value {
Value::from_raw(self.gc_ref.val)
}
}
impl<'ctx> Function<'ctx> {
pub(crate) fn new(gc_ref: Box<JSGCRef>, ctx: &'ctx Context) -> Self {
Self { gc_ref, ctx }
}
pub fn call(&self, args: &[Value]) -> Result<Value> {
unsafe {
for arg in args.iter().rev() {
JS_PushArg(self.ctx.as_ptr(), arg.into_raw());
}
JS_PushArg(self.ctx.as_ptr(), self.gc_ref.val);
JS_PushArg(self.ctx.as_ptr(), Value::null().into_raw());
let ret: Value = Value::from_raw(JS_Call(self.ctx.as_ptr(), args.len() as c_int));
if ret.is_exception() {
Err(Error {
message: ret.to_string(self.ctx),
exception: ret,
})
} else {
Ok(ret)
}
}
}
}