use super::private::IntoJsFunctionSealed;
use super::{IntoJsFunctionCopied, UnsafeIntoJsFunction};
use crate::interop::{JsRest, TryFromJsArgument};
use crate::{Context, JsError, NativeFunction, TryIntoJsResult, js_string};
use std::cell::RefCell;
#[derive(Debug, Copy, Clone)]
pub struct ContextArgToken;
macro_rules! impl_into_js_function {
($($id: ident: $t: ident),*) => {
impl<$($t,)* R, T> IntoJsFunctionSealed<($($t,)*), R> for T
where
$($t: for<'a> TryFromJsArgument<'a> + 'static,)*
R: TryIntoJsResult,
T: FnMut($($t,)*) -> R + 'static
{}
impl<$($t,)* R, T> IntoJsFunctionSealed<($($t,)* ContextArgToken,), R> for T
where
$($t: for<'a> TryFromJsArgument<'a> + 'static,)*
R: TryIntoJsResult,
T: FnMut($($t,)* &mut Context) -> R + 'static
{}
impl<$($t,)* R, T> IntoJsFunctionSealed<($($t,)* JsRest<'_>,), R> for T
where
$($t: for<'a> TryFromJsArgument<'a> + 'static,)*
R: TryIntoJsResult,
T: FnMut($($t,)* JsRest<'_>) -> R + 'static
{}
impl<$($t,)* R, T> IntoJsFunctionSealed<($($t,)* JsRest<'_>, ContextArgToken), R> for T
where
$($t: for<'a> TryFromJsArgument<'a> + 'static,)*
R: TryIntoJsResult,
T: FnMut($($t,)* JsRest<'_>, &mut Context) -> R + 'static
{}
impl<$($t,)* R, T> UnsafeIntoJsFunction<($($t,)*), R> for T
where
$($t: for<'a> TryFromJsArgument<'a> + 'static,)*
R: TryIntoJsResult,
T: FnMut($($t,)*) -> R + 'static,
{
#[allow(unused_variables)]
unsafe fn into_js_function_unsafe(self, _context: &mut Context) -> NativeFunction {
let s = RefCell::new(self);
unsafe {
NativeFunction::from_closure(move |this, args, ctx| {
let rest = args;
$(
let ($id, rest) = $t::try_from_js_argument(this, rest, ctx)?;
)*
match s.try_borrow_mut() {
Ok(mut r) => r( $($id,)* ).try_into_js_result(ctx),
Err(_) => {
Err(JsError::from_opaque(js_string!("recursive calls to this function not supported").into()))
}
}
})
}
}
}
impl<$($t,)* R, T> UnsafeIntoJsFunction<($($t,)* JsRest<'_>,), R> for T
where
$($t: for<'a> TryFromJsArgument<'a> + 'static,)*
R: TryIntoJsResult,
T: FnMut($($t,)* JsRest<'_>) -> R + 'static,
{
#[allow(unused_variables)]
unsafe fn into_js_function_unsafe(self, _context: &mut Context) -> NativeFunction {
let s = RefCell::new(self);
unsafe {
NativeFunction::from_closure(move |this, args, ctx| {
let rest = args;
$(
let ($id, rest) = $t::try_from_js_argument(this, rest, ctx)?;
)*
match s.try_borrow_mut() {
Ok(mut r) => r( $($id,)* rest.into() ).try_into_js_result(ctx),
Err(_) => {
Err(JsError::from_opaque(js_string!("recursive calls to this function not supported").into()))
}
}
})
}
}
}
impl<$($t,)* R, T> UnsafeIntoJsFunction<($($t,)* ContextArgToken,), R> for T
where
$($t: for<'a> TryFromJsArgument<'a> + 'static,)*
R: TryIntoJsResult,
T: FnMut($($t,)* &mut Context) -> R + 'static,
{
#[allow(unused_variables)]
unsafe fn into_js_function_unsafe(self, _context: &mut Context) -> NativeFunction {
let s = RefCell::new(self);
unsafe {
NativeFunction::from_closure(move |this, args, ctx| {
let rest = args;
$(
let ($id, rest) = $t::try_from_js_argument(this, rest, ctx)?;
)*
let r = s.borrow_mut()( $($id,)* ctx);
r.try_into_js_result(ctx)
})
}
}
}
impl<$($t,)* R, T> UnsafeIntoJsFunction<($($t,)* JsRest<'_>, ContextArgToken), R> for T
where
$($t: for<'a> TryFromJsArgument<'a> + 'static,)*
R: TryIntoJsResult,
T: FnMut($($t,)* JsRest<'_>, &mut Context) -> R + 'static,
{
#[allow(unused_variables)]
unsafe fn into_js_function_unsafe(self, _context: &mut Context) -> NativeFunction {
let s = RefCell::new(self);
unsafe {
NativeFunction::from_closure(move |this, args, ctx| {
let rest = args;
$(
let ($id, rest) = $t::try_from_js_argument(this, rest, ctx)?;
)*
let r = s.borrow_mut()( $($id,)* rest.into(), ctx);
r.try_into_js_result(ctx)
})
}
}
}
impl<$($t,)* R, T> IntoJsFunctionCopied<($($t,)*), R> for T
where
$($t: for<'a> TryFromJsArgument<'a> + 'static,)*
R: TryIntoJsResult,
T: Fn($($t,)*) -> R + 'static + Copy,
{
#[allow(unused_variables)]
fn into_js_function_copied(self, _context: &mut Context) -> NativeFunction {
let s = self;
NativeFunction::from_copy_closure(move |this, args, ctx| {
let rest = args;
$(
let ($id, rest) = $t::try_from_js_argument(this, rest, ctx)?;
)*
let r = s( $($id,)* );
r.try_into_js_result(ctx)
})
}
}
impl<$($t,)* R, T> IntoJsFunctionCopied<($($t,)* JsRest<'_>,), R> for T
where
$($t: for<'a> TryFromJsArgument<'a> + 'static,)*
R: TryIntoJsResult,
T: Fn($($t,)* JsRest<'_>) -> R + 'static + Copy,
{
#[allow(unused_variables)]
fn into_js_function_copied(self, _context: &mut Context) -> NativeFunction {
let s = self;
NativeFunction::from_copy_closure(move |this, args, ctx| {
let rest = args;
$(
let ($id, rest) = $t::try_from_js_argument(this, rest, ctx)?;
)*
let r = s( $($id,)* rest.into() );
r.try_into_js_result(ctx)
})
}
}
impl<$($t,)* R, T> IntoJsFunctionCopied<($($t,)* ContextArgToken,), R> for T
where
$($t: for<'a> TryFromJsArgument<'a> + 'static,)*
R: TryIntoJsResult,
T: Fn($($t,)* &mut Context) -> R + 'static + Copy,
{
#[allow(unused_variables)]
fn into_js_function_copied(self, _context: &mut Context) -> NativeFunction {
let s = self;
NativeFunction::from_copy_closure(move |this, args, ctx| {
let rest = args;
$(
let ($id, rest) = $t::try_from_js_argument(this, rest, ctx)?;
)*
let r = s( $($id,)* ctx);
r.try_into_js_result(ctx)
})
}
}
impl<$($t,)* R, T> IntoJsFunctionCopied<($($t,)* JsRest<'_>, ContextArgToken), R> for T
where
$($t: for<'a> TryFromJsArgument<'a> + 'static,)*
R: TryIntoJsResult,
T: Fn($($t,)* JsRest<'_>, &mut Context) -> R + 'static + Copy,
{
#[allow(unused_variables)]
fn into_js_function_copied(self, _context: &mut Context) -> NativeFunction {
let s = self;
NativeFunction::from_copy_closure(move |this, args, ctx| {
let rest = args;
$(
let ($id, rest) = $t::try_from_js_argument(this, rest, ctx)?;
)*
let r = s( $($id,)* rest.into(), ctx);
r.try_into_js_result(ctx)
})
}
}
};
}
impl_into_js_function!();
impl_into_js_function!(a: A);
impl_into_js_function!(a: A, b: B);
impl_into_js_function!(a: A, b: B, c: C);
impl_into_js_function!(a: A, b: B, c: C, d: D);
impl_into_js_function!(a: A, b: B, c: C, d: D, e: E);
impl_into_js_function!(a: A, b: B, c: C, d: D, e: E, f: F);
impl_into_js_function!(a: A, b: B, c: C, d: D, e: E, f: F, g: G);
impl_into_js_function!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H);
impl_into_js_function!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I);
impl_into_js_function!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J);
impl_into_js_function!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K);
impl_into_js_function!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L);