@@ -10,7 +10,7 @@ use proc_macro2::{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 , MacroDelimiter } ;
13
+ use syn:: { ItemFn , Lit , MacroDelimiter , ReturnType } ;
14
14
15
15
use crate :: ClassMarker ;
16
16
@@ -83,6 +83,7 @@ macro_rules! attrgen {
83
83
( typescript_custom_section, TypescriptCustomSection ( Span ) ) ,
84
84
( skip_typescript, SkipTypescript ( Span ) ) ,
85
85
( skip_jsdoc, SkipJsDoc ( Span ) ) ,
86
+ ( main, Main ( Span ) ) ,
86
87
( start, Start ( Span ) ) ,
87
88
( wasm_bindgen, WasmBindgen ( Span , syn:: Path ) ) ,
88
89
( wasm_bindgen_futures, WasmBindgenFutures ( Span , syn:: Path ) ) ,
@@ -949,6 +950,19 @@ impl<'a> MacroParse<(Option<BindgenAttrs>, &'a mut TokenStream)> for syn::Item {
949
950
) -> Result < ( ) , Diagnostic > {
950
951
match self {
951
952
syn:: Item :: Fn ( mut f) => {
953
+ let opts = opts. unwrap_or_default ( ) ;
954
+ if let Some ( path) = opts. wasm_bindgen ( ) {
955
+ program. wasm_bindgen = path. clone ( ) ;
956
+ }
957
+ if let Some ( path) = opts. wasm_bindgen_futures ( ) {
958
+ program. wasm_bindgen_futures = path. clone ( ) ;
959
+ }
960
+
961
+ if opts. main ( ) . is_some ( ) {
962
+ opts. check_used ( ) ;
963
+ return main ( program, f, tokens) ;
964
+ }
965
+
952
966
let no_mangle = f
953
967
. attrs
954
968
. iter ( )
@@ -966,13 +980,6 @@ impl<'a> MacroParse<(Option<BindgenAttrs>, &'a mut TokenStream)> for syn::Item {
966
980
// `dead_code` warning. So, add `#[allow(dead_code)]` before it to avoid that.
967
981
tokens. extend ( quote:: quote! { #[ allow( dead_code) ] } ) ;
968
982
f. to_tokens ( tokens) ;
969
- let opts = opts. unwrap_or_default ( ) ;
970
- if let Some ( path) = opts. wasm_bindgen ( ) {
971
- program. wasm_bindgen = path. clone ( ) ;
972
- }
973
- if let Some ( path) = opts. wasm_bindgen_futures ( ) {
974
- program. wasm_bindgen_futures = path. clone ( ) ;
975
- }
976
983
if opts. start ( ) . is_some ( ) {
977
984
if f. sig . generics . params . len ( ) > 0 {
978
985
bail_span ! ( & f. sig. generics, "the start function cannot have generics" , ) ;
@@ -1740,6 +1747,62 @@ pub fn link_to(opts: BindgenAttrs) -> Result<ast::LinkToModule, Diagnostic> {
1740
1747
Ok ( ast:: LinkToModule ( program) )
1741
1748
}
1742
1749
1750
+ fn main ( program : & ast:: Program , mut f : ItemFn , tokens : & mut TokenStream ) -> Result < ( ) , Diagnostic > {
1751
+ if f. sig . ident != "main" {
1752
+ bail_span ! ( & f. sig. ident, "the main function has to be called main" ) ;
1753
+ }
1754
+ if let Some ( constness) = f. sig . constness {
1755
+ bail_span ! ( & constness, "the main function cannot be const" ) ;
1756
+ }
1757
+ if !f. sig . generics . params . is_empty ( ) {
1758
+ bail_span ! ( & f. sig. generics, "the main function cannot have generics" ) ;
1759
+ }
1760
+ if !f. sig . inputs . is_empty ( ) {
1761
+ bail_span ! ( & f. sig. inputs, "the main function cannot have arguments" ) ;
1762
+ }
1763
+
1764
+ let r#return = f. sig . output ;
1765
+ f. sig . output = ReturnType :: Default ;
1766
+ let body = f. block ;
1767
+
1768
+ let wasm_bindgen = & program. wasm_bindgen ;
1769
+ let wasm_bindgen_futures = & program. wasm_bindgen_futures ;
1770
+
1771
+ if f. sig . asyncness . take ( ) . is_some ( ) {
1772
+ f. block = Box :: new (
1773
+ syn:: parse2 ( quote:: quote! {
1774
+ {
1775
+ async fn __wasm_bindgen_generated_main( ) #r#return #body
1776
+ #wasm_bindgen_futures:: spawn_local(
1777
+ async move {
1778
+ use #wasm_bindgen:: __rt:: Main ;
1779
+ let __ret = __wasm_bindgen_generated_main( ) ;
1780
+ ( & mut & mut & mut #wasm_bindgen:: __rt:: MainWrapper ( Some ( __ret. await ) ) ) . __wasm_bindgen_main( )
1781
+ } ,
1782
+ )
1783
+ }
1784
+ } )
1785
+ . unwrap ( ) ,
1786
+ ) ;
1787
+ } else {
1788
+ f. block = Box :: new (
1789
+ syn:: parse2 ( quote:: quote! {
1790
+ {
1791
+ fn __wasm_bindgen_generated_main( ) #r#return #body
1792
+ use #wasm_bindgen:: __rt:: Main ;
1793
+ let __ret = __wasm_bindgen_generated_main( ) ;
1794
+ ( & mut & mut & mut #wasm_bindgen:: __rt:: MainWrapper ( Some ( __ret) ) ) . __wasm_bindgen_main( )
1795
+ }
1796
+ } )
1797
+ . unwrap ( ) ,
1798
+ ) ;
1799
+ }
1800
+
1801
+ f. to_tokens ( tokens) ;
1802
+
1803
+ Ok ( ( ) )
1804
+ }
1805
+
1743
1806
#[ cfg( test) ]
1744
1807
mod tests {
1745
1808
#[ test]
0 commit comments