1use proc_macro2::TokenStream;
8use quote::quote;
9use syn::punctuated::Punctuated;
10use syn::{Abi, Block, Error, FnArg, Generics, ItemFn, Result, parse_quote, parse2};
11
12use crate::attribute::krate::crate_from_attributes;
13use crate::function::wrapper::impl_wrapper_fn;
14use crate::utils::new_token;
15
16pub(crate) mod inner;
17pub(crate) mod parameter;
18pub(crate) mod wrapper;
19
20pub(crate) fn impl_js_fn(mut function: ItemFn) -> Result<ItemFn> {
22 let ion = &crate_from_attributes(&mut function.attrs);
23
24 let ident = &function.sig.ident;
25 let (wrapper, _) = impl_wrapper_fn(ion, function.clone(), None, false, &ident.to_string())?;
26
27 check_abi(&mut function)?;
28 set_signature(&mut function);
29
30 function.attrs.clear();
31 function.block = impl_fn_body(ion, &wrapper)?;
32
33 Ok(function)
34}
35
36pub(crate) fn check_abi(function: &mut ItemFn) -> Result<()> {
37 match &function.sig.abi {
38 None => function.sig.abi = Some(parse_quote!(extern "C")),
39 Some(Abi { name: None, .. }) => {}
40 Some(Abi { name: Some(abi), .. }) if abi.value() == "C" => {}
41 Some(Abi { name: Some(non_c_abi), .. }) => return Err(Error::new_spanned(non_c_abi, "Expected C ABI")),
42 }
43 Ok(())
44}
45
46pub(crate) fn set_signature(function: &mut ItemFn) {
47 function.sig.unsafety = Some(new_token![unsafe]);
48 function.sig.generics = Generics::default();
49 function.sig.inputs = Punctuated::from_iter::<[FnArg; 3]>([
50 parse_quote!(cx: *mut ::mozjs::jsapi::JSContext),
51 parse_quote!(argc: ::core::primitive::u32),
52 parse_quote!(vp: *mut ::mozjs::jsval::JSVal),
53 ]);
54 function.sig.output = parse_quote!(-> ::core::primitive::bool);
55}
56
57pub(crate) fn impl_fn_body(ion: &TokenStream, wrapper: &ItemFn) -> Result<Box<Block>> {
58 parse2(quote!({
59 #wrapper
60
61 let cx = &#ion::Context::new_unchecked(cx);
62 let args = &mut #ion::Arguments::new(cx, argc, vp);
63
64 let result = ::std::panic::catch_unwind(::std::panic::AssertUnwindSafe(|| wrapper(cx, args)));
65 #ion::function::__handle_native_function_result(cx, result)
66 }))
67}