@@ -10,7 +10,7 @@ use proc_macro2::{Delimiter, Ident, Span, TokenStream, TokenTree};
10
10
use quote:: ToTokens ;
11
11
use syn:: parse:: { Parse , ParseStream , Result as SynResult } ;
12
12
use syn:: spanned:: Spanned ;
13
- use syn:: Lit ;
13
+ use syn:: { ItemFn , Lit , ReturnType } ;
14
14
15
15
thread_local ! ( static ATTRS : AttributeParseState = Default :: default ( ) ) ;
16
16
@@ -80,6 +80,7 @@ macro_rules! attrgen {
80
80
( variadic, Variadic ( Span ) ) ,
81
81
( typescript_custom_section, TypescriptCustomSection ( Span ) ) ,
82
82
( skip_typescript, SkipTypescript ( Span ) ) ,
83
+ ( main, Main ( Span ) ) ,
83
84
( start, Start ( Span ) ) ,
84
85
( skip, Skip ( Span ) ) ,
85
86
( typescript_type, TypeScriptType ( Span , String , Span ) ) ,
@@ -933,6 +934,13 @@ impl<'a> MacroParse<(Option<BindgenAttrs>, &'a mut TokenStream)> for syn::Item {
933
934
) -> Result < ( ) , Diagnostic > {
934
935
match self {
935
936
syn:: Item :: Fn ( mut f) => {
937
+ let opts = opts. unwrap_or_default ( ) ;
938
+
939
+ if opts. main ( ) . is_some ( ) {
940
+ opts. check_used ( ) ;
941
+ return main ( f, tokens) ;
942
+ }
943
+
936
944
let no_mangle = f
937
945
. attrs
938
946
. iter ( )
@@ -951,7 +959,6 @@ impl<'a> MacroParse<(Option<BindgenAttrs>, &'a mut TokenStream)> for syn::Item {
951
959
// `dead_code` warning. So, add `#[allow(dead_code)]` before it to avoid that.
952
960
tokens. extend ( quote:: quote! { #[ allow( dead_code) ] } ) ;
953
961
f. to_tokens ( tokens) ;
954
- let opts = opts. unwrap_or_default ( ) ;
955
962
if opts. start ( ) . is_some ( ) {
956
963
if f. sig . generics . params . len ( ) > 0 {
957
964
bail_span ! ( & f. sig. generics, "the start function cannot have generics" , ) ;
@@ -1689,6 +1696,59 @@ pub fn link_to(opts: BindgenAttrs) -> Result<ast::LinkToModule, Diagnostic> {
1689
1696
Ok ( ast:: LinkToModule ( program) )
1690
1697
}
1691
1698
1699
+ fn main ( mut f : ItemFn , tokens : & mut TokenStream ) -> Result < ( ) , Diagnostic > {
1700
+ if f. sig . ident != "main" {
1701
+ bail_span ! ( & f. sig. ident, "the main function has to be called main" ) ;
1702
+ }
1703
+ if let Some ( constness) = f. sig . constness {
1704
+ bail_span ! ( & constness, "the main function cannot be const" ) ;
1705
+ }
1706
+ if !f. sig . generics . params . is_empty ( ) {
1707
+ bail_span ! ( & f. sig. generics, "the main function cannot have generics" ) ;
1708
+ }
1709
+ if !f. sig . inputs . is_empty ( ) {
1710
+ bail_span ! ( & f. sig. inputs, "the main function cannot have arguments" ) ;
1711
+ }
1712
+
1713
+ let r#return = f. sig . output ;
1714
+ f. sig . output = ReturnType :: Default ;
1715
+ let body = f. block ;
1716
+
1717
+ if f. sig . asyncness . take ( ) . is_some ( ) {
1718
+ f. block = Box :: new (
1719
+ syn:: parse2 ( quote:: quote! {
1720
+ {
1721
+ async fn __wasm_bindgen_generated_main( ) #r#return #body
1722
+ wasm_bindgen_futures:: spawn_local(
1723
+ async move {
1724
+ use wasm_bindgen:: __rt:: Main ;
1725
+ let __ret = __wasm_bindgen_generated_main( ) ;
1726
+ ( & mut wasm_bindgen:: __rt:: MainWrapper ( Some ( __ret. await ) ) ) . __wasm_bindgen_main( )
1727
+ } ,
1728
+ )
1729
+ }
1730
+ } )
1731
+ . unwrap ( ) ,
1732
+ ) ;
1733
+ } else {
1734
+ f. block = Box :: new (
1735
+ syn:: parse2 ( quote:: quote! {
1736
+ {
1737
+ fn __wasm_bindgen_generated_main( ) #r#return #body
1738
+ use wasm_bindgen:: __rt:: Main ;
1739
+ let __ret = __wasm_bindgen_generated_main( ) ;
1740
+ ( & mut wasm_bindgen:: __rt:: MainWrapper ( Some ( __ret) ) ) . __wasm_bindgen_main( )
1741
+ }
1742
+ } )
1743
+ . unwrap ( ) ,
1744
+ ) ;
1745
+ }
1746
+
1747
+ f. to_tokens ( tokens) ;
1748
+
1749
+ Ok ( ( ) )
1750
+ }
1751
+
1692
1752
#[ cfg( test) ]
1693
1753
mod tests {
1694
1754
#[ test]
0 commit comments