1use super::private::IntoJsFunctionSealed;
4use super::{IntoJsFunctionCopied, UnsafeIntoJsFunction};
5use crate::interop::{JsRest, TryFromJsArgument};
6use crate::{Context, NativeFunction, TryIntoJsResult};
7use std::cell::RefCell;
8
9#[derive(Debug, Copy, Clone)]
12pub struct ContextArgToken;
13
14macro_rules! impl_into_js_function {
15 ($($id: ident: $t: ident),*) => {
16 impl<$($t,)* R, T> IntoJsFunctionSealed<($($t,)*), R> for T
17 where
18 $($t: for<'a> TryFromJsArgument<'a> + 'static,)*
19 R: TryIntoJsResult,
20 T: FnMut($($t,)*) -> R + 'static
21 {}
22
23 impl<$($t,)* R, T> IntoJsFunctionSealed<($($t,)* ContextArgToken,), R> for T
24 where
25 $($t: for<'a> TryFromJsArgument<'a> + 'static,)*
26 R: TryIntoJsResult,
27 T: FnMut($($t,)* &mut Context) -> R + 'static
28 {}
29
30 impl<$($t,)* R, T> IntoJsFunctionSealed<($($t,)* JsRest<'_>,), R> for T
31 where
32 $($t: for<'a> TryFromJsArgument<'a> + 'static,)*
33 R: TryIntoJsResult,
34 T: FnMut($($t,)* JsRest<'_>) -> R + 'static
35 {}
36
37 impl<$($t,)* R, T> IntoJsFunctionSealed<($($t,)* JsRest<'_>, ContextArgToken), R> for T
38 where
39 $($t: for<'a> TryFromJsArgument<'a> + 'static,)*
40 R: TryIntoJsResult,
41 T: FnMut($($t,)* JsRest<'_>, &mut Context) -> R + 'static
42 {}
43
44 impl<$($t,)* R, T> UnsafeIntoJsFunction<($($t,)*), R> for T
45 where
46 $($t: for<'a> TryFromJsArgument<'a> + 'static,)*
47 R: TryIntoJsResult,
48 T: FnMut($($t,)*) -> R + 'static,
49 {
50 #[allow(unused_variables)]
51 unsafe fn into_js_function_unsafe(self, _context: &mut Context) -> NativeFunction {
52 let s = RefCell::new(self);
53 unsafe {
54 NativeFunction::from_closure(move |this, args, ctx| {
55 let rest = args;
56 $(
57 let ($id, rest) = $t::try_from_js_argument(this, rest, ctx)?;
58 )*
59 match s.try_borrow_mut() {
60 Ok(mut r) => r( $($id,)* ).try_into_js_result(ctx),
61 Err(_) => {
62 Err($crate::js_error!("recursive calls to this function not supported"))
63 }
64 }
65 })
66 }
67 }
68 }
69
70 impl<$($t,)* R, T> UnsafeIntoJsFunction<($($t,)* JsRest<'_>,), R> for T
71 where
72 $($t: for<'a> TryFromJsArgument<'a> + 'static,)*
73 R: TryIntoJsResult,
74 T: FnMut($($t,)* JsRest<'_>) -> R + 'static,
75 {
76 #[allow(unused_variables)]
77 unsafe fn into_js_function_unsafe(self, _context: &mut Context) -> NativeFunction {
78 let s = RefCell::new(self);
79 unsafe {
80 NativeFunction::from_closure(move |this, args, ctx| {
81 let rest = args;
82 $(
83 let ($id, rest) = $t::try_from_js_argument(this, rest, ctx)?;
84 )*
85 match s.try_borrow_mut() {
86 Ok(mut r) => r( $($id,)* rest.into() ).try_into_js_result(ctx),
87 Err(_) => {
88 Err($crate::js_error!("recursive calls to this function not supported"))
89 }
90 }
91 })
92 }
93 }
94 }
95
96 impl<$($t,)* R, T> UnsafeIntoJsFunction<($($t,)* ContextArgToken,), R> for T
97 where
98 $($t: for<'a> TryFromJsArgument<'a> + 'static,)*
99 R: TryIntoJsResult,
100 T: FnMut($($t,)* &mut Context) -> R + 'static,
101 {
102 #[allow(unused_variables)]
103 unsafe fn into_js_function_unsafe(self, _context: &mut Context) -> NativeFunction {
104 let s = RefCell::new(self);
105 unsafe {
106 NativeFunction::from_closure(move |this, args, ctx| {
107 let rest = args;
108 $(
109 let ($id, rest) = $t::try_from_js_argument(this, rest, ctx)?;
110 )*
111 let r = s.borrow_mut()( $($id,)* ctx);
112 r.try_into_js_result(ctx)
113 })
114 }
115 }
116 }
117
118 impl<$($t,)* R, T> UnsafeIntoJsFunction<($($t,)* JsRest<'_>, ContextArgToken), R> for T
119 where
120 $($t: for<'a> TryFromJsArgument<'a> + 'static,)*
121 R: TryIntoJsResult,
122 T: FnMut($($t,)* JsRest<'_>, &mut Context) -> R + 'static,
123 {
124 #[allow(unused_variables)]
125 unsafe fn into_js_function_unsafe(self, _context: &mut Context) -> NativeFunction {
126 let s = RefCell::new(self);
127 unsafe {
128 NativeFunction::from_closure(move |this, args, ctx| {
129 let rest = args;
130 $(
131 let ($id, rest) = $t::try_from_js_argument(this, rest, ctx)?;
132 )*
133 let r = s.borrow_mut()( $($id,)* rest.into(), ctx);
134 r.try_into_js_result(ctx)
135 })
136 }
137 }
138 }
139
140 impl<$($t,)* R, T> IntoJsFunctionCopied<($($t,)*), R> for T
142 where
143 $($t: for<'a> TryFromJsArgument<'a> + 'static,)*
144 R: TryIntoJsResult,
145 T: Fn($($t,)*) -> R + 'static + Copy,
146 {
147 #[allow(unused_variables)]
148 fn into_js_function_copied(self, _context: &mut Context) -> NativeFunction {
149 let s = self;
150 NativeFunction::from_copy_closure(move |this, args, ctx| {
151 let rest = args;
152 $(
153 let ($id, rest) = $t::try_from_js_argument(this, rest, ctx)?;
154 )*
155 let r = s( $($id,)* );
156 r.try_into_js_result(ctx)
157 })
158 }
159 }
160
161 impl<$($t,)* R, T> IntoJsFunctionCopied<($($t,)* JsRest<'_>,), R> for T
162 where
163 $($t: for<'a> TryFromJsArgument<'a> + 'static,)*
164 R: TryIntoJsResult,
165 T: Fn($($t,)* JsRest<'_>) -> R + 'static + Copy,
166 {
167 #[allow(unused_variables)]
168 fn into_js_function_copied(self, _context: &mut Context) -> NativeFunction {
169 let s = self;
170 NativeFunction::from_copy_closure(move |this, args, ctx| {
171 let rest = args;
172 $(
173 let ($id, rest) = $t::try_from_js_argument(this, rest, ctx)?;
174 )*
175 let r = s( $($id,)* rest.into() );
176 r.try_into_js_result(ctx)
177 })
178 }
179 }
180
181 impl<$($t,)* R, T> IntoJsFunctionCopied<($($t,)* ContextArgToken,), R> for T
182 where
183 $($t: for<'a> TryFromJsArgument<'a> + 'static,)*
184 R: TryIntoJsResult,
185 T: Fn($($t,)* &mut Context) -> R + 'static + Copy,
186 {
187 #[allow(unused_variables)]
188 fn into_js_function_copied(self, _context: &mut Context) -> NativeFunction {
189 let s = self;
190 NativeFunction::from_copy_closure(move |this, args, ctx| {
191 let rest = args;
192 $(
193 let ($id, rest) = $t::try_from_js_argument(this, rest, ctx)?;
194 )*
195 let r = s( $($id,)* ctx);
196 r.try_into_js_result(ctx)
197 })
198 }
199 }
200
201 impl<$($t,)* R, T> IntoJsFunctionCopied<($($t,)* JsRest<'_>, ContextArgToken), R> for T
202 where
203 $($t: for<'a> TryFromJsArgument<'a> + 'static,)*
204 R: TryIntoJsResult,
205 T: Fn($($t,)* JsRest<'_>, &mut Context) -> R + 'static + Copy,
206 {
207 #[allow(unused_variables)]
208 fn into_js_function_copied(self, _context: &mut Context) -> NativeFunction {
209 let s = self;
210 NativeFunction::from_copy_closure(move |this, args, ctx| {
211 let rest = args;
212 $(
213 let ($id, rest) = $t::try_from_js_argument(this, rest, ctx)?;
214 )*
215 let r = s( $($id,)* rest.into(), ctx);
216 r.try_into_js_result(ctx)
217 })
218 }
219 }
220 };
221}
222
223impl_into_js_function!();
228impl_into_js_function!(a: A);
229impl_into_js_function!(a: A, b: B);
230impl_into_js_function!(a: A, b: B, c: C);
231impl_into_js_function!(a: A, b: B, c: C, d: D);
232impl_into_js_function!(a: A, b: B, c: C, d: D, e: E);
233impl_into_js_function!(a: A, b: B, c: C, d: D, e: E, f: F);
234impl_into_js_function!(a: A, b: B, c: C, d: D, e: E, f: F, g: G);
235impl_into_js_function!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H);
236impl_into_js_function!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I);
237impl_into_js_function!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J);
238impl_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);
239impl_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);