use deno_core::v8::{self, HandleScope};
use serde::Deserialize;
use super::V8Value;
#[derive(Eq, Hash, PartialEq, Debug, Clone)]
pub struct Function(V8Value<FunctionTypeChecker>);
impl_v8!(Function, FunctionTypeChecker);
impl_checker!(FunctionTypeChecker, Function, is_function, |e| {
crate::Error::ValueNotCallable(e)
});
impl Function {
pub(crate) fn as_global(&self, scope: &mut HandleScope<'_>) -> v8::Global<v8::Function> {
self.0.as_global(scope)
}
#[must_use]
pub fn is_async(&self) -> bool {
let unsafe_f = unsafe { v8::Handle::get_unchecked(&self.0 .0) };
unsafe_f.is_async_function()
}
pub fn call<T>(
&self,
runtime: &mut crate::Runtime,
module_context: Option<&crate::ModuleHandle>,
args: &impl serde::ser::Serialize,
) -> Result<T, crate::Error>
where
T: serde::de::DeserializeOwned,
{
runtime.call_stored_function(module_context, self, args)
}
pub async fn call_async<T>(
&self,
runtime: &mut crate::Runtime,
module_context: Option<&crate::ModuleHandle>,
args: &impl serde::ser::Serialize,
) -> Result<T, crate::Error>
where
T: serde::de::DeserializeOwned,
{
runtime
.call_stored_function_async(module_context, self, args)
.await
}
pub fn call_immediate<T>(
&self,
runtime: &mut crate::Runtime,
module_context: Option<&crate::ModuleHandle>,
args: &impl serde::ser::Serialize,
) -> Result<T, crate::Error>
where
T: serde::de::DeserializeOwned,
{
runtime.call_stored_function_immediate(module_context, self, args)
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::{js_value::Promise, json_args, Module, Runtime, RuntimeOptions};
#[test]
fn test_function() {
let module = Module::new(
"test.js",
"
export const f = () => 42;
export const f2 = async () => 42;
",
);
let mut runtime = Runtime::new(RuntimeOptions::default()).unwrap();
let handle = runtime.load_module(&module).unwrap();
let f: Function = runtime.get_value(Some(&handle), "f").unwrap();
let value: usize = f.call(&mut runtime, Some(&handle), &json_args!()).unwrap();
assert_eq!(value, 42);
let f2: Function = runtime.get_value(Some(&handle), "f2").unwrap();
let value: Promise<usize> = f2
.call_immediate(&mut runtime, Some(&handle), &json_args!())
.unwrap();
let value = value.into_value(&mut runtime).unwrap();
assert_eq!(value, 42);
}
}