@@ -3,6 +3,7 @@ use crate::encode;
33use crate :: Diagnostic ;
44use once_cell:: sync:: Lazy ;
55use proc_macro2:: { Ident , Literal , Span , TokenStream } ;
6+ use quote:: format_ident;
67use quote:: quote_spanned;
78use quote:: { quote, ToTokens } ;
89use std:: collections:: { HashMap , HashSet } ;
@@ -142,15 +143,15 @@ impl TryToTokens for ast::LinkToModule {
142143 let link_function_name = self . 0 . link_function_name ( 0 ) ;
143144 let name = Ident :: new ( & link_function_name, Span :: call_site ( ) ) ;
144145 let wasm_bindgen = & self . 0 . wasm_bindgen ;
145- let abi_ret = quote ! { < std:: string:: String as #wasm_bindgen:: convert:: FromWasmAbi >:: Abi } ;
146+ let abi_ret = quote ! { #wasm_bindgen :: convert :: WasmRet << std:: string:: String as #wasm_bindgen:: convert:: FromWasmAbi >:: Abi > } ;
146147 let extern_fn = extern_fn ( & name, & [ ] , & [ ] , & [ ] , abi_ret) ;
147148 ( quote ! {
148149 {
149150 #program
150151 #extern_fn
151152
152153 unsafe {
153- <std:: string:: String as #wasm_bindgen:: convert:: FromWasmAbi >:: from_abi( #name( ) )
154+ <std:: string:: String as #wasm_bindgen:: convert:: FromWasmAbi >:: from_abi( #name( ) . join ( ) )
154155 }
155156 }
156157 } )
@@ -401,7 +402,7 @@ impl ToTokens for ast::StructField {
401402 #[ cfg_attr( all( target_arch = "wasm32" , not( any( target_os = "emscripten" , target_os = "wasi" ) ) ) , no_mangle) ]
402403 #[ doc( hidden) ]
403404 pub unsafe extern "C" fn #getter( js: u32 )
404- -> < #ty as #wasm_bindgen:: convert:: IntoWasmAbi >:: Abi
405+ -> #wasm_bindgen :: convert :: WasmRet << #ty as #wasm_bindgen:: convert:: IntoWasmAbi >:: Abi >
405406 {
406407 use #wasm_bindgen:: __rt:: { WasmRefCell , assert_not_null} ;
407408 use #wasm_bindgen:: convert:: IntoWasmAbi ;
@@ -412,7 +413,7 @@ impl ToTokens for ast::StructField {
412413 let js = js as * mut WasmRefCell <#struct_name>;
413414 assert_not_null( js) ;
414415 let val = #val;
415- <#ty as IntoWasmAbi >:: into_abi( val)
416+ <#ty as IntoWasmAbi >:: into_abi( val) . into ( )
416417 }
417418 } ;
418419 } )
@@ -432,6 +433,9 @@ impl ToTokens for ast::StructField {
432433 return ;
433434 }
434435
436+ let abi = quote ! { <#ty as #wasm_bindgen:: convert:: FromWasmAbi >:: Abi } ;
437+ let ( args, names) = splat ( wasm_bindgen, & Ident :: new ( "val" , rust_name. span ( ) ) , & abi) ;
438+
435439 ( quote ! {
436440 #[ cfg( all( target_arch = "wasm32" , not( any( target_os = "emscripten" , target_os = "wasi" ) ) ) ) ]
437441 #[ automatically_derived]
@@ -440,13 +444,14 @@ impl ToTokens for ast::StructField {
440444 #[ doc( hidden) ]
441445 pub unsafe extern "C" fn #setter(
442446 js: u32 ,
443- val : <#ty as #wasm_bindgen :: convert :: FromWasmAbi > :: Abi ,
447+ # ( #args , ) *
444448 ) {
445449 use #wasm_bindgen:: __rt:: { WasmRefCell , assert_not_null} ;
446450 use #wasm_bindgen:: convert:: FromWasmAbi ;
447451
448452 let js = js as * mut WasmRefCell <#struct_name>;
449453 assert_not_null( js) ;
454+ let val = <#abi as #wasm_bindgen:: convert:: WasmAbi >:: join( #( #names) , * ) ;
450455 let val = <#ty as FromWasmAbi >:: from_abi( val) ;
451456 ( * js) . borrow_mut( ) . #rust_name = val;
452457 }
@@ -525,52 +530,61 @@ impl TryToTokens for ast::Export {
525530 elem,
526531 ..
527532 } ) => {
528- args . push ( quote ! {
529- # ident: <#elem as #wasm_bindgen :: convert :: RefMutFromWasmAbi > :: Abi
530- } ) ;
533+ let abi = quote ! { <#elem as #wasm_bindgen :: convert :: RefMutFromWasmAbi > :: Abi } ;
534+ let ( prim_args , prim_names ) = splat ( wasm_bindgen , & ident, & abi ) ;
535+ args . extend ( prim_args ) ;
531536 arg_conversions. push ( quote ! {
532537 let mut #ident = unsafe {
533538 <#elem as #wasm_bindgen:: convert:: RefMutFromWasmAbi >
534- :: ref_mut_from_abi( #ident)
539+ :: ref_mut_from_abi(
540+ <#abi as #wasm_bindgen:: convert:: WasmAbi >:: join( #( #prim_names) , * )
541+ )
535542 } ;
536543 let #ident = & mut * #ident;
537544 } ) ;
538545 }
539546 syn:: Type :: Reference ( syn:: TypeReference { elem, .. } ) => {
540547 if self . function . r#async {
541- args. push ( quote ! {
542- #ident: <#elem as #wasm_bindgen:: convert:: LongRefFromWasmAbi >:: Abi
543- } ) ;
548+ let abi =
549+ quote ! { <#elem as #wasm_bindgen:: convert:: LongRefFromWasmAbi >:: Abi } ;
550+ let ( prim_args, prim_names) = splat ( wasm_bindgen, & ident, & abi) ;
551+ args. extend ( prim_args) ;
544552 arg_conversions. push ( quote ! {
545553 let #ident = unsafe {
546554 <#elem as #wasm_bindgen:: convert:: LongRefFromWasmAbi >
547- :: long_ref_from_abi( #ident)
555+ :: long_ref_from_abi(
556+ <#abi as #wasm_bindgen:: convert:: WasmAbi >:: join( #( #prim_names) , * )
557+ )
548558 } ;
549559 let #ident = <<#elem as #wasm_bindgen:: convert:: LongRefFromWasmAbi >
550560 :: Anchor as core:: borrow:: Borrow <#elem>>
551561 :: borrow( & #ident) ;
552562 } ) ;
553563 } else {
554- args . push ( quote ! {
555- # ident: <#elem as #wasm_bindgen :: convert :: RefFromWasmAbi > :: Abi
556- } ) ;
564+ let abi = quote ! { <#elem as #wasm_bindgen :: convert :: RefFromWasmAbi > :: Abi } ;
565+ let ( prim_args , prim_names ) = splat ( wasm_bindgen , & ident, & abi ) ;
566+ args . extend ( prim_args ) ;
557567 arg_conversions. push ( quote ! {
558568 let #ident = unsafe {
559569 <#elem as #wasm_bindgen:: convert:: RefFromWasmAbi >
560- :: ref_from_abi( #ident)
570+ :: ref_from_abi(
571+ <#abi as #wasm_bindgen:: convert:: WasmAbi >:: join( #( #prim_names) , * )
572+ )
561573 } ;
562574 let #ident = & * #ident;
563575 } ) ;
564576 }
565577 }
566578 _ => {
567- args . push ( quote ! {
568- # ident: <#ty as #wasm_bindgen :: convert :: FromWasmAbi > :: Abi
569- } ) ;
579+ let abi = quote ! { <#ty as #wasm_bindgen :: convert :: FromWasmAbi > :: Abi } ;
580+ let ( prim_args , prim_names ) = splat ( wasm_bindgen , & ident, & abi ) ;
581+ args . extend ( prim_args ) ;
570582 arg_conversions. push ( quote ! {
571583 let #ident = unsafe {
572584 <#ty as #wasm_bindgen:: convert:: FromWasmAbi >
573- :: from_abi( #ident)
585+ :: from_abi(
586+ <#abi as #wasm_bindgen:: convert:: WasmAbi >:: join( #( #prim_names) , * )
587+ )
574588 } ;
575589 } ) ;
576590 }
@@ -642,7 +656,7 @@ impl TryToTokens for ast::Export {
642656 }
643657
644658 let projection = quote ! { <#ret_ty as #wasm_bindgen:: convert:: ReturnWasmAbi > } ;
645- let convert_ret = quote ! { #projection:: return_abi( #ret) } ;
659+ let convert_ret = quote ! { #projection:: return_abi( #ret) . into ( ) } ;
646660 let describe_ret = quote ! {
647661 <#ret_ty as WasmDescribe >:: describe( ) ;
648662 <#inner_ret_ty as WasmDescribe >:: describe( ) ;
@@ -664,7 +678,7 @@ impl TryToTokens for ast::Export {
664678 all( target_arch = "wasm32" , not( any( target_os = "emscripten" , target_os = "wasi" ) ) ) ,
665679 export_name = #export_name,
666680 ) ]
667- pub unsafe extern "C" fn #generated_name( #( #args) , * ) -> #projection:: Abi {
681+ pub unsafe extern "C" fn #generated_name( #( #args) , * ) -> #wasm_bindgen :: convert :: WasmRet <# projection:: Abi > {
668682 #start_check
669683
670684 let #ret = #call;
@@ -1147,10 +1161,11 @@ impl TryToTokens for ast::ImportFunction {
11471161 ) ,
11481162 } ;
11491163
1150- abi_argument_names. push ( name. clone ( ) ) ;
1151- abi_arguments. push ( quote ! {
1152- #name: <#ty as #wasm_bindgen:: convert:: IntoWasmAbi >:: Abi
1153- } ) ;
1164+ let abi = quote ! { <#ty as #wasm_bindgen:: convert:: IntoWasmAbi >:: Abi } ;
1165+ let ( prim_args, prim_names) = splat ( wasm_bindgen, & name, & abi) ;
1166+ abi_arguments. extend ( prim_args) ;
1167+ abi_argument_names. extend ( prim_names. iter ( ) . cloned ( ) ) ;
1168+
11541169 let var = if i == 0 && is_method {
11551170 quote ! { self }
11561171 } else {
@@ -1160,6 +1175,7 @@ impl TryToTokens for ast::ImportFunction {
11601175 arg_conversions. push ( quote ! {
11611176 let #name = <#ty as #wasm_bindgen:: convert:: IntoWasmAbi >
11621177 :: into_abi( #var) ;
1178+ let ( #( #prim_names) , * ) = <#abi as #wasm_bindgen:: convert:: WasmAbi >:: split( #name) ;
11631179 } ) ;
11641180 }
11651181 let abi_ret;
@@ -1173,12 +1189,13 @@ impl TryToTokens for ast::ImportFunction {
11731189 }
11741190 Some ( ref ty) => {
11751191 if self . function . r#async {
1176- abi_ret =
1177- quote ! { <js_sys:: Promise as #wasm_bindgen:: convert:: FromWasmAbi >:: Abi } ;
1192+ abi_ret = quote ! {
1193+ #wasm_bindgen:: convert:: WasmRet <<js_sys:: Promise as #wasm_bindgen:: convert:: FromWasmAbi >:: Abi >
1194+ } ;
11781195 let future = quote ! {
11791196 #wasm_bindgen_futures:: JsFuture :: from(
11801197 <js_sys:: Promise as #wasm_bindgen:: convert:: FromWasmAbi >
1181- :: from_abi( #ret_ident)
1198+ :: from_abi( #ret_ident. join ( ) )
11821199 ) . await
11831200 } ;
11841201 convert_ret = if self . catch {
@@ -1188,22 +1205,23 @@ impl TryToTokens for ast::ImportFunction {
11881205 } ;
11891206 } else {
11901207 abi_ret = quote ! {
1191- < #ty as #wasm_bindgen:: convert:: FromWasmAbi >:: Abi
1208+ #wasm_bindgen :: convert :: WasmRet << #ty as #wasm_bindgen:: convert:: FromWasmAbi >:: Abi >
11921209 } ;
11931210 convert_ret = quote ! {
11941211 <#ty as #wasm_bindgen:: convert:: FromWasmAbi >
1195- :: from_abi( #ret_ident)
1212+ :: from_abi( #ret_ident. join ( ) )
11961213 } ;
11971214 }
11981215 }
11991216 None => {
12001217 if self . function . r#async {
1201- abi_ret =
1202- quote ! { <js_sys:: Promise as #wasm_bindgen:: convert:: FromWasmAbi >:: Abi } ;
1218+ abi_ret = quote ! {
1219+ #wasm_bindgen:: convert:: WasmRet <<js_sys:: Promise as #wasm_bindgen:: convert:: FromWasmAbi >:: Abi >
1220+ } ;
12031221 let future = quote ! {
12041222 #wasm_bindgen_futures:: JsFuture :: from(
12051223 <js_sys:: Promise as #wasm_bindgen:: convert:: FromWasmAbi >
1206- :: from_abi( #ret_ident)
1224+ :: from_abi( #ret_ident. join ( ) )
12071225 ) . await
12081226 } ;
12091227 convert_ret = if self . catch {
@@ -1421,23 +1439,27 @@ impl ToTokens for ast::ImportStatic {
14211439 let shim_name = & self . shim ;
14221440 let vis = & self . vis ;
14231441 let wasm_bindgen = & self . wasm_bindgen ;
1442+
1443+ let abi_ret = quote ! {
1444+ #wasm_bindgen:: convert:: WasmRet <<#ty as #wasm_bindgen:: convert:: FromWasmAbi >:: Abi >
1445+ } ;
14241446 ( quote ! {
14251447 #[ automatically_derived]
14261448 #vis static #name: #wasm_bindgen:: JsStatic <#ty> = {
14271449 fn init( ) -> #ty {
14281450 #[ link( wasm_import_module = "__wbindgen_placeholder__" ) ]
14291451 #[ cfg( all( target_arch = "wasm32" , not( any( target_os = "emscripten" , target_os = "wasi" ) ) ) ) ]
14301452 extern "C" {
1431- fn #shim_name( ) -> <#ty as #wasm_bindgen :: convert :: FromWasmAbi > :: Abi ;
1453+ fn #shim_name( ) -> #abi_ret ;
14321454 }
14331455
14341456 #[ cfg( not( all( target_arch = "wasm32" , not( any( target_os = "emscripten" , target_os = "wasi" ) ) ) ) ) ]
1435- unsafe fn #shim_name( ) -> <#ty as wasm_bindgen :: convert :: FromWasmAbi > :: Abi {
1457+ unsafe fn #shim_name( ) -> #abi_ret {
14361458 panic!( "cannot access imported statics on non-wasm targets" )
14371459 }
14381460
14391461 unsafe {
1440- <#ty as #wasm_bindgen:: convert:: FromWasmAbi >:: from_abi( #shim_name( ) )
1462+ <#ty as #wasm_bindgen:: convert:: FromWasmAbi >:: from_abi( #shim_name( ) . join ( ) )
14411463 }
14421464 }
14431465 thread_local!( static _VAL: #ty = init( ) ; ) ;
@@ -1540,6 +1562,32 @@ fn extern_fn(
15401562 }
15411563}
15421564
1565+ /// Splats an argument with the given name and ABI type into 4 arguments, one
1566+ /// for each primitive that the ABI type splits into.
1567+ ///
1568+ /// Returns an `(args, names)` pair, where `args` is the list of arguments to
1569+ /// be inserted into the function signature, and `names` is a list of the names
1570+ /// of those arguments.
1571+ fn splat (
1572+ wasm_bindgen : & syn:: Path ,
1573+ name : & Ident ,
1574+ abi : & TokenStream ,
1575+ ) -> ( Vec < TokenStream > , Vec < Ident > ) {
1576+ let mut args = Vec :: new ( ) ;
1577+ let mut names = Vec :: new ( ) ;
1578+
1579+ for n in 1 ..=4 {
1580+ let arg_name = format_ident ! ( "{name}_{n}" ) ;
1581+ let prim_name = format_ident ! ( "Prim{n}" ) ;
1582+ args. push ( quote ! {
1583+ #arg_name: <#abi as #wasm_bindgen:: convert:: WasmAbi >:: #prim_name
1584+ } ) ;
1585+ names. push ( arg_name) ;
1586+ }
1587+
1588+ ( args, names)
1589+ }
1590+
15431591/// Converts `span` into a stream of tokens, and attempts to ensure that `input`
15441592/// has all the appropriate span information so errors in it point to `span`.
15451593fn respan ( input : TokenStream , span : & dyn ToTokens ) -> TokenStream {
0 commit comments