@@ -21,6 +21,44 @@ fn unit_tuple() -> Type {
21
21
parse_quote ! { ( ) }
22
22
}
23
23
24
+ struct Func {
25
+ name : Ident ,
26
+ args : Vec < ( Ident , Type ) > ,
27
+ return_type : Type ,
28
+ returns_value : bool ,
29
+ }
30
+
31
+ impl Func {
32
+ fn from_item ( func : & ForeignItemFn ) -> Result < Func , Error > {
33
+ let name = func. sig . ident . clone ( ) ;
34
+
35
+ let mut args = func. sig . inputs . iter ( ) ;
36
+ let _this_arg = args. next ( ) . expect ( "Expected a this argument" ) ;
37
+
38
+ let args = args
39
+ . map ( |arg| match arg {
40
+ FnArg :: Typed ( arg) => match * arg. pat {
41
+ Pat :: Ident ( ref pat) => Ok ( ( pat. ident . clone ( ) , ( * arg. ty ) . clone ( ) ) ) ,
42
+ _ => Err ( Error :: new ( arg. span ( ) , "Expected an Ident argument" ) ) ,
43
+ } ,
44
+ _ => Err ( Error :: new ( arg. span ( ) , "Expected a typed argument" ) ) ,
45
+ } )
46
+ . collect :: < Result < Vec < _ > , _ > > ( ) ?;
47
+
48
+ let ( return_type, returns_value) = match & func. sig . output {
49
+ ReturnType :: Default => ( unit_tuple ( ) , false ) ,
50
+ ReturnType :: Type ( _, ty) => ( ( * * ty) . clone ( ) , true ) ,
51
+ } ;
52
+
53
+ Ok ( Func {
54
+ name,
55
+ args,
56
+ return_type,
57
+ returns_value,
58
+ } )
59
+ }
60
+ }
61
+
24
62
pub ( crate ) fn bitwarden_wasm_ipc_channel_internal (
25
63
_args : TokenStream ,
26
64
item : TokenStream ,
@@ -29,60 +67,21 @@ pub(crate) fn bitwarden_wasm_ipc_channel_internal(
29
67
30
68
// Validate the ABI
31
69
match input. abi . name {
32
- Some ( ref name) if name. value ( ) == "C" => { /* OK */ }
33
- _ => {
34
- return Err ( Error :: new ( input. abi . span ( ) , "Only C ABI is supported" ) ) ;
35
- }
36
- }
70
+ Some ( ref name) if name. value ( ) == "C" => Ok ( ( ) ) ,
71
+ _ => Err ( Error :: new ( input. abi . span ( ) , "Only C ABI is supported" ) ) ,
72
+ } ?;
37
73
38
- // Check that all the items are tagged as ` #[wasm_bindgen]`, and collect the type ident and function signatures
74
+ // Check that the extern mod is marked with #[wasm_bindgen]
39
75
get_bindgen_attr ( & input, & input. attrs ) ?;
40
76
41
77
let mut ident = None ;
42
78
let mut functions = Vec :: new ( ) ;
43
79
44
- struct Func {
45
- name : Ident ,
46
- args : Vec < ( Ident , Type ) > ,
47
- return_type : Type ,
48
- returns_value : bool ,
49
- }
50
-
51
- impl Func {
52
- fn from_item ( func : & ForeignItemFn ) -> Result < Func , Error > {
53
- let name = func. sig . ident . clone ( ) ;
54
-
55
- let mut args = func. sig . inputs . iter ( ) ;
56
- let _this_arg = args. next ( ) . expect ( "Expected a self argument" ) ;
57
-
58
- let args = args
59
- . map ( |arg| match arg {
60
- FnArg :: Typed ( arg) => {
61
- let name = match * arg. pat {
62
- Pat :: Ident ( ref pat) => pat. ident . clone ( ) ,
63
- _ => Err ( Error :: new ( arg. span ( ) , "Expected an Ident argument" ) ) ?,
64
- } ;
65
- Ok ( ( name, ( * arg. ty ) . clone ( ) ) )
66
- }
67
- _ => Err ( Error :: new ( arg. span ( ) , "Expected a typed argument" ) ) ,
68
- } )
69
- . collect :: < Result < Vec < _ > , _ > > ( ) ?;
70
-
71
- let ( return_type, returns_value) = match & func. sig . output {
72
- ReturnType :: Default => ( unit_tuple ( ) , false ) ,
73
- ReturnType :: Type ( _, ty) => ( ( * * ty) . clone ( ) , true ) ,
74
- } ;
75
-
76
- Ok ( Func {
77
- name,
78
- args,
79
- return_type,
80
- returns_value,
81
- } )
82
- }
83
- }
84
-
85
80
// Collect and parse the items (one type + multiple functions)
81
+ // For functions that return a value, we need to change the return type to JsValue in the
82
+ // #[wasm_bindgen] extern block, as only types that implement JsCast can be returned.
83
+ // The functions in the Channel struct will return the original values, and just use
84
+ // `serde_wasm_bindgen::from_value`.
86
85
for item in & mut input. items {
87
86
match item {
88
87
ForeignItem :: Type ( typ) => {
@@ -99,8 +98,8 @@ pub(crate) fn bitwarden_wasm_ipc_channel_internal(
99
98
}
100
99
ForeignItem :: Fn ( func) => {
101
100
if let Ok ( _bindgen) = get_bindgen_attr ( & func, & func. attrs ) {
101
+ // Collect the function info first, then modify the function return type
102
102
functions. push ( Func :: from_item ( func) ?) ;
103
-
104
103
if let ReturnType :: Type ( _, ty) = & mut func. sig . output {
105
104
* ty = parse_quote ! { :: wasm_bindgen:: JsValue } ;
106
105
}
@@ -164,24 +163,23 @@ pub(crate) fn bitwarden_wasm_ipc_channel_internal(
164
163
165
164
let matches = functions. iter ( ) . map ( |f| {
166
165
let name = & f. name ;
167
- let args1 = f. args . iter ( ) . map ( |( ident, _) | {
166
+ let args : Vec < _ > = f. args . iter ( ) . map ( |( ident, _) | {
168
167
quote:: quote! { #ident }
169
- } ) ;
170
- let args2 = args1. clone ( ) ;
168
+ } ) . collect ( ) ;
171
169
172
170
if f. returns_value {
173
171
// TODO: Should these return a result?
174
172
quote:: quote! {
175
- #channel_command_ident:: #name { _internal_respond_to, #( #args1 ) , * } => {
176
- let result = self . #name( #( #args2 ) , * ) . await ;
173
+ #channel_command_ident:: #name { _internal_respond_to, #( #args ) , * } => {
174
+ let result = self . #name( #( #args ) , * ) . await ;
177
175
let result = serde_wasm_bindgen:: from_value( result) . expect( "Couldn't convert to value" ) ;
178
176
_internal_respond_to. send( result) . expect( "Failed to send response" ) ;
179
177
}
180
178
}
181
179
} else {
182
180
quote:: quote! {
183
- #channel_command_ident:: #name { _internal_respond_to, #( #args1 ) , * } => {
184
- self . #name( #( #args2 ) , * ) . await ;
181
+ #channel_command_ident:: #name { _internal_respond_to, #( #args ) , * } => {
182
+ self . #name( #( #args ) , * ) . await ;
185
183
_internal_respond_to. send( ( ) ) . expect( "Failed to send response" ) ;
186
184
}
187
185
}
0 commit comments