@@ -2,6 +2,22 @@ use crate::descriptor::{Descriptor, Function};
2
2
use crate :: js:: Context ;
3
3
use failure:: { bail, Error } ;
4
4
5
+ pub struct JsArgument {
6
+ pub optional : bool ,
7
+ pub name : String ,
8
+ pub type_ : String ,
9
+ }
10
+
11
+ impl JsArgument {
12
+ fn required ( name : String , type_ : String ) -> Self {
13
+ Self { optional : false , name, type_ }
14
+ }
15
+
16
+ fn optional ( name : String , type_ : String ) -> Self {
17
+ Self { optional : true , name, type_ }
18
+ }
19
+ }
20
+
5
21
/// Helper struct for manufacturing a shim in JS used to translate JS types to
6
22
/// Rust, aka pass from JS back into Rust
7
23
pub struct Js2Rust < ' a , ' b : ' a > {
@@ -12,7 +28,7 @@ pub struct Js2Rust<'a, 'b: 'a> {
12
28
rust_arguments : Vec < String > ,
13
29
14
30
/// Arguments and their types to the JS shim.
15
- pub js_arguments : Vec < ( String , String ) > ,
31
+ pub js_arguments : Vec < JsArgument > ,
16
32
17
33
/// Conversions that happen before we invoke the wasm function, such as
18
34
/// converting a string to a ptr/length pair.
@@ -173,7 +189,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
173
189
174
190
if let Some ( kind) = arg. vector_kind ( ) {
175
191
self . js_arguments
176
- . push ( ( name. clone ( ) , kind. js_ty ( ) . to_string ( ) ) ) ;
192
+ . push ( JsArgument :: required ( name. clone ( ) , kind. js_ty ( ) . to_string ( ) ) ) ;
177
193
178
194
let func = self . cx . pass_to_wasm_function ( kind) ?;
179
195
let val = if optional {
@@ -221,7 +237,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
221
237
}
222
238
223
239
if arg. is_anyref ( ) {
224
- self . js_arguments . push ( ( name. clone ( ) , "any" . to_string ( ) ) ) ;
240
+ self . js_arguments . push ( JsArgument :: required ( name. clone ( ) , "any" . to_string ( ) ) ) ;
225
241
if self . cx . config . anyref {
226
242
if optional {
227
243
self . cx . expose_add_to_anyref_table ( ) ?;
@@ -250,7 +266,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
250
266
251
267
if arg. is_wasm_native ( ) {
252
268
self . js_arguments
253
- . push ( ( name. clone ( ) , "number | undefined " . to_string ( ) ) ) ;
269
+ . push ( JsArgument :: optional ( name. clone ( ) , "number" . to_string ( ) ) ) ;
254
270
255
271
if self . cx . config . debug {
256
272
self . cx . expose_assert_num ( ) ;
@@ -272,7 +288,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
272
288
273
289
if arg. is_abi_as_u32 ( ) {
274
290
self . js_arguments
275
- . push ( ( name. clone ( ) , "number | undefined " . to_string ( ) ) ) ;
291
+ . push ( JsArgument :: optional ( name. clone ( ) , "number" . to_string ( ) ) ) ;
276
292
277
293
if self . cx . config . debug {
278
294
self . cx . expose_assert_num ( ) ;
@@ -299,7 +315,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
299
315
} ;
300
316
self . cx . expose_uint32_memory ( ) ;
301
317
self . js_arguments
302
- . push ( ( name. clone ( ) , "BigInt | undefined " . to_string ( ) ) ) ;
318
+ . push ( JsArgument :: optional ( name. clone ( ) , "BigInt" . to_string ( ) ) ) ;
303
319
self . prelude ( & format ! (
304
320
"
305
321
{f}[0] = isLikeNone({name}) ? BigInt(0) : {name};
@@ -320,7 +336,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
320
336
match * arg {
321
337
Descriptor :: Boolean => {
322
338
self . js_arguments
323
- . push ( ( name. clone ( ) , "boolean | undefined " . to_string ( ) ) ) ;
339
+ . push ( JsArgument :: optional ( name. clone ( ) , "boolean" . to_string ( ) ) ) ;
324
340
if self . cx . config . debug {
325
341
self . cx . expose_assert_bool ( ) ;
326
342
self . prelude ( & format ! (
@@ -337,21 +353,21 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
337
353
}
338
354
Descriptor :: Char => {
339
355
self . js_arguments
340
- . push ( ( name. clone ( ) , "string | undefined " . to_string ( ) ) ) ;
356
+ . push ( JsArgument :: optional ( name. clone ( ) , "string" . to_string ( ) ) ) ;
341
357
self . rust_arguments . push ( format ! (
342
358
"isLikeNone({0}) ? 0xFFFFFF : {0}.codePointAt(0)" ,
343
359
name
344
360
) ) ;
345
361
}
346
362
Descriptor :: Enum { hole } => {
347
363
self . js_arguments
348
- . push ( ( name. clone ( ) , "number | undefined " . to_string ( ) ) ) ;
364
+ . push ( JsArgument :: optional ( name. clone ( ) , "number" . to_string ( ) ) ) ;
349
365
self . rust_arguments
350
366
. push ( format ! ( "isLikeNone({0}) ? {1} : {0}" , name, hole) ) ;
351
367
}
352
368
Descriptor :: RustStruct ( ref s) => {
353
369
self . js_arguments
354
- . push ( ( name. clone ( ) , format ! ( "{} | undefined" , s ) ) ) ;
370
+ . push ( JsArgument :: optional ( name. clone ( ) , s . to_string ( ) ) ) ;
355
371
self . prelude ( & format ! ( "let ptr{} = 0;" , i) ) ;
356
372
self . prelude ( & format ! ( "if (!isLikeNone({0})) {{" , name) ) ;
357
373
self . assert_class ( & name, s) ;
@@ -371,7 +387,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
371
387
}
372
388
373
389
if let Some ( s) = arg. rust_struct ( ) {
374
- self . js_arguments . push ( ( name. clone ( ) , s. to_string ( ) ) ) ;
390
+ self . js_arguments . push ( JsArgument :: required ( name. clone ( ) , s. to_string ( ) ) ) ;
375
391
self . assert_class ( & name, s) ;
376
392
self . assert_not_moved ( & name) ;
377
393
if arg. is_by_ref ( ) {
@@ -385,7 +401,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
385
401
}
386
402
387
403
if arg. number ( ) . is_some ( ) {
388
- self . js_arguments . push ( ( name. clone ( ) , "number" . to_string ( ) ) ) ;
404
+ self . js_arguments . push ( JsArgument :: required ( name. clone ( ) , "number" . to_string ( ) ) ) ;
389
405
390
406
if self . cx . config . debug {
391
407
self . cx . expose_assert_num ( ) ;
@@ -403,7 +419,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
403
419
self . cx . expose_uint64_cvt_shim ( )
404
420
} ;
405
421
self . cx . expose_uint32_memory ( ) ;
406
- self . js_arguments . push ( ( name. clone ( ) , "BigInt" . to_string ( ) ) ) ;
422
+ self . js_arguments . push ( JsArgument :: required ( name. clone ( ) , "BigInt" . to_string ( ) ) ) ;
407
423
self . prelude ( & format ! (
408
424
"
409
425
{f}[0] = {name};
@@ -420,7 +436,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
420
436
}
421
437
422
438
if arg. is_ref_anyref ( ) {
423
- self . js_arguments . push ( ( name. clone ( ) , "any" . to_string ( ) ) ) ;
439
+ self . js_arguments . push ( JsArgument :: required ( name. clone ( ) , "any" . to_string ( ) ) ) ;
424
440
if self . cx . config . anyref {
425
441
self . anyref_args . push ( ( self . rust_arguments . len ( ) , false ) ) ;
426
442
self . rust_arguments . push ( name) ;
@@ -440,7 +456,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
440
456
match * arg {
441
457
Descriptor :: Boolean => {
442
458
self . js_arguments
443
- . push ( ( name. clone ( ) , "boolean" . to_string ( ) ) ) ;
459
+ . push ( JsArgument :: required ( name. clone ( ) , "boolean" . to_string ( ) ) ) ;
444
460
if self . cx . config . debug {
445
461
self . cx . expose_assert_bool ( ) ;
446
462
self . prelude ( & format ! (
@@ -453,7 +469,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
453
469
self . rust_arguments . push ( format ! ( "{}" , name) ) ;
454
470
}
455
471
Descriptor :: Char => {
456
- self . js_arguments . push ( ( name. clone ( ) , "string" . to_string ( ) ) ) ;
472
+ self . js_arguments . push ( JsArgument :: required ( name. clone ( ) , "string" . to_string ( ) ) ) ;
457
473
self . rust_arguments . push ( format ! ( "{}.codePointAt(0)" , name) )
458
474
}
459
475
_ => bail ! (
@@ -735,7 +751,11 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
735
751
let mut ret: String = self
736
752
. js_arguments
737
753
. iter ( )
738
- . map ( |a| format ! ( "@param {{{}}} {}\n " , a. 1 , a. 0 ) )
754
+ . map ( |a| if a. optional {
755
+ format ! ( "@param {{{} | undefined}} {}\n " , a. type_, a. name)
756
+ } else {
757
+ format ! ( "@param {{{}}} {}\n " , a. type_, a. name)
758
+ } )
739
759
. collect ( ) ;
740
760
ret. push_str ( & format ! ( "@returns {{{}}}" , self . ret_ty) ) ;
741
761
ret
@@ -759,7 +779,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
759
779
let js_args = self
760
780
. js_arguments
761
781
. iter ( )
762
- . map ( |s| & s. 0 [ ..] )
782
+ . map ( |s| & s. name [ ..] )
763
783
. collect :: < Vec < _ > > ( )
764
784
. join ( ", " ) ;
765
785
let mut js = format ! ( "{}({}) {{\n " , prefix, js_args) ;
@@ -788,7 +808,11 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
788
808
let ts_args = self
789
809
. js_arguments
790
810
. iter ( )
791
- . map ( |s| format ! ( "{}: {}" , s. 0 , s. 1 ) )
811
+ . map ( |s| if s. optional {
812
+ format ! ( "{}?: {}" , s. name, s. type_)
813
+ } else {
814
+ format ! ( "{}: {}" , s. name, s. type_)
815
+ } )
792
816
. collect :: < Vec < _ > > ( )
793
817
. join ( ", " ) ;
794
818
let mut ts = if prefix. is_empty ( ) {
0 commit comments