@@ -3,6 +3,7 @@ use crate::encode;
3
3
use crate :: Diagnostic ;
4
4
use once_cell:: sync:: Lazy ;
5
5
use proc_macro2:: { Ident , Literal , Span , TokenStream } ;
6
+ use quote:: format_ident;
6
7
use quote:: quote_spanned;
7
8
use quote:: { quote, ToTokens } ;
8
9
use std:: collections:: { HashMap , HashSet } ;
@@ -142,15 +143,15 @@ impl TryToTokens for ast::LinkToModule {
142
143
let link_function_name = self . 0 . link_function_name ( 0 ) ;
143
144
let name = Ident :: new ( & link_function_name, Span :: call_site ( ) ) ;
144
145
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 > } ;
146
147
let extern_fn = extern_fn ( & name, & [ ] , & [ ] , & [ ] , abi_ret) ;
147
148
( quote ! {
148
149
{
149
150
#program
150
151
#extern_fn
151
152
152
153
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 ( ) )
154
155
}
155
156
}
156
157
} )
@@ -401,7 +402,7 @@ impl ToTokens for ast::StructField {
401
402
#[ cfg_attr( all( target_arch = "wasm32" , not( any( target_os = "emscripten" , target_os = "wasi" ) ) ) , no_mangle) ]
402
403
#[ doc( hidden) ]
403
404
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 >
405
406
{
406
407
use #wasm_bindgen:: __rt:: { WasmRefCell , assert_not_null} ;
407
408
use #wasm_bindgen:: convert:: IntoWasmAbi ;
@@ -412,7 +413,7 @@ impl ToTokens for ast::StructField {
412
413
let js = js as * mut WasmRefCell <#struct_name>;
413
414
assert_not_null( js) ;
414
415
let val = #val;
415
- <#ty as IntoWasmAbi >:: into_abi( val)
416
+ <#ty as IntoWasmAbi >:: into_abi( val) . into ( )
416
417
}
417
418
} ;
418
419
} )
@@ -432,6 +433,9 @@ impl ToTokens for ast::StructField {
432
433
return ;
433
434
}
434
435
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
+
435
439
( quote ! {
436
440
#[ cfg( all( target_arch = "wasm32" , not( any( target_os = "emscripten" , target_os = "wasi" ) ) ) ) ]
437
441
#[ automatically_derived]
@@ -440,13 +444,14 @@ impl ToTokens for ast::StructField {
440
444
#[ doc( hidden) ]
441
445
pub unsafe extern "C" fn #setter(
442
446
js: u32 ,
443
- val : <#ty as #wasm_bindgen :: convert :: FromWasmAbi > :: Abi ,
447
+ # ( #args , ) *
444
448
) {
445
449
use #wasm_bindgen:: __rt:: { WasmRefCell , assert_not_null} ;
446
450
use #wasm_bindgen:: convert:: FromWasmAbi ;
447
451
448
452
let js = js as * mut WasmRefCell <#struct_name>;
449
453
assert_not_null( js) ;
454
+ let val = <#abi as #wasm_bindgen:: convert:: WasmAbi >:: join( #( #names) , * ) ;
450
455
let val = <#ty as FromWasmAbi >:: from_abi( val) ;
451
456
( * js) . borrow_mut( ) . #rust_name = val;
452
457
}
@@ -525,52 +530,61 @@ impl TryToTokens for ast::Export {
525
530
elem,
526
531
..
527
532
} ) => {
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 ) ;
531
536
arg_conversions. push ( quote ! {
532
537
let mut #ident = unsafe {
533
538
<#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
+ )
535
542
} ;
536
543
let #ident = & mut * #ident;
537
544
} ) ;
538
545
}
539
546
syn:: Type :: Reference ( syn:: TypeReference { elem, .. } ) => {
540
547
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) ;
544
552
arg_conversions. push ( quote ! {
545
553
let #ident = unsafe {
546
554
<#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
+ )
548
558
} ;
549
559
let #ident = <<#elem as #wasm_bindgen:: convert:: LongRefFromWasmAbi >
550
560
:: Anchor as core:: borrow:: Borrow <#elem>>
551
561
:: borrow( & #ident) ;
552
562
} ) ;
553
563
} 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 ) ;
557
567
arg_conversions. push ( quote ! {
558
568
let #ident = unsafe {
559
569
<#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
+ )
561
573
} ;
562
574
let #ident = & * #ident;
563
575
} ) ;
564
576
}
565
577
}
566
578
_ => {
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 ) ;
570
582
arg_conversions. push ( quote ! {
571
583
let #ident = unsafe {
572
584
<#ty as #wasm_bindgen:: convert:: FromWasmAbi >
573
- :: from_abi( #ident)
585
+ :: from_abi(
586
+ <#abi as #wasm_bindgen:: convert:: WasmAbi >:: join( #( #prim_names) , * )
587
+ )
574
588
} ;
575
589
} ) ;
576
590
}
@@ -642,7 +656,7 @@ impl TryToTokens for ast::Export {
642
656
}
643
657
644
658
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 ( ) } ;
646
660
let describe_ret = quote ! {
647
661
<#ret_ty as WasmDescribe >:: describe( ) ;
648
662
<#inner_ret_ty as WasmDescribe >:: describe( ) ;
@@ -664,7 +678,7 @@ impl TryToTokens for ast::Export {
664
678
all( target_arch = "wasm32" , not( any( target_os = "emscripten" , target_os = "wasi" ) ) ) ,
665
679
export_name = #export_name,
666
680
) ]
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 > {
668
682
#start_check
669
683
670
684
let #ret = #call;
@@ -1147,10 +1161,11 @@ impl TryToTokens for ast::ImportFunction {
1147
1161
) ,
1148
1162
} ;
1149
1163
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
+
1154
1169
let var = if i == 0 && is_method {
1155
1170
quote ! { self }
1156
1171
} else {
@@ -1160,6 +1175,7 @@ impl TryToTokens for ast::ImportFunction {
1160
1175
arg_conversions. push ( quote ! {
1161
1176
let #name = <#ty as #wasm_bindgen:: convert:: IntoWasmAbi >
1162
1177
:: into_abi( #var) ;
1178
+ let ( #( #prim_names) , * ) = <#abi as #wasm_bindgen:: convert:: WasmAbi >:: split( #name) ;
1163
1179
} ) ;
1164
1180
}
1165
1181
let abi_ret;
@@ -1173,12 +1189,13 @@ impl TryToTokens for ast::ImportFunction {
1173
1189
}
1174
1190
Some ( ref ty) => {
1175
1191
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
+ } ;
1178
1195
let future = quote ! {
1179
1196
#wasm_bindgen_futures:: JsFuture :: from(
1180
1197
<js_sys:: Promise as #wasm_bindgen:: convert:: FromWasmAbi >
1181
- :: from_abi( #ret_ident)
1198
+ :: from_abi( #ret_ident. join ( ) )
1182
1199
) . await
1183
1200
} ;
1184
1201
convert_ret = if self . catch {
@@ -1188,22 +1205,23 @@ impl TryToTokens for ast::ImportFunction {
1188
1205
} ;
1189
1206
} else {
1190
1207
abi_ret = quote ! {
1191
- < #ty as #wasm_bindgen:: convert:: FromWasmAbi >:: Abi
1208
+ #wasm_bindgen :: convert :: WasmRet << #ty as #wasm_bindgen:: convert:: FromWasmAbi >:: Abi >
1192
1209
} ;
1193
1210
convert_ret = quote ! {
1194
1211
<#ty as #wasm_bindgen:: convert:: FromWasmAbi >
1195
- :: from_abi( #ret_ident)
1212
+ :: from_abi( #ret_ident. join ( ) )
1196
1213
} ;
1197
1214
}
1198
1215
}
1199
1216
None => {
1200
1217
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
+ } ;
1203
1221
let future = quote ! {
1204
1222
#wasm_bindgen_futures:: JsFuture :: from(
1205
1223
<js_sys:: Promise as #wasm_bindgen:: convert:: FromWasmAbi >
1206
- :: from_abi( #ret_ident)
1224
+ :: from_abi( #ret_ident. join ( ) )
1207
1225
) . await
1208
1226
} ;
1209
1227
convert_ret = if self . catch {
@@ -1421,23 +1439,27 @@ impl ToTokens for ast::ImportStatic {
1421
1439
let shim_name = & self . shim ;
1422
1440
let vis = & self . vis ;
1423
1441
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
+ } ;
1424
1446
( quote ! {
1425
1447
#[ automatically_derived]
1426
1448
#vis static #name: #wasm_bindgen:: JsStatic <#ty> = {
1427
1449
fn init( ) -> #ty {
1428
1450
#[ link( wasm_import_module = "__wbindgen_placeholder__" ) ]
1429
1451
#[ cfg( all( target_arch = "wasm32" , not( any( target_os = "emscripten" , target_os = "wasi" ) ) ) ) ]
1430
1452
extern "C" {
1431
- fn #shim_name( ) -> <#ty as #wasm_bindgen :: convert :: FromWasmAbi > :: Abi ;
1453
+ fn #shim_name( ) -> #abi_ret ;
1432
1454
}
1433
1455
1434
1456
#[ 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 {
1436
1458
panic!( "cannot access imported statics on non-wasm targets" )
1437
1459
}
1438
1460
1439
1461
unsafe {
1440
- <#ty as #wasm_bindgen:: convert:: FromWasmAbi >:: from_abi( #shim_name( ) )
1462
+ <#ty as #wasm_bindgen:: convert:: FromWasmAbi >:: from_abi( #shim_name( ) . join ( ) )
1441
1463
}
1442
1464
}
1443
1465
thread_local!( static _VAL: #ty = init( ) ; ) ;
@@ -1540,6 +1562,32 @@ fn extern_fn(
1540
1562
}
1541
1563
}
1542
1564
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
+
1543
1591
/// Converts `span` into a stream of tokens, and attempts to ensure that `input`
1544
1592
/// has all the appropriate span information so errors in it point to `span`.
1545
1593
fn respan ( input : TokenStream , span : & dyn ToTokens ) -> TokenStream {
0 commit comments