@@ -58,6 +58,8 @@ pub struct ExportedClass {
58
58
typescript : String ,
59
59
has_constructor : bool ,
60
60
wrap_needed : bool ,
61
+ /// Map from field name to type as a string plus whether it has a setter
62
+ typescript_fields : HashMap < String , ( String , bool ) > ,
61
63
}
62
64
63
65
const INITIAL_HEAP_VALUES : & [ & str ] = & [ "undefined" , "null" , "true" , "false" ] ;
@@ -638,6 +640,19 @@ impl<'a> Context<'a> {
638
640
ts_dst. push_str ( " free(): void;" ) ;
639
641
dst. push_str ( & class. contents ) ;
640
642
ts_dst. push_str ( & class. typescript ) ;
643
+
644
+ let mut fields = class. typescript_fields . keys ( ) . collect :: < Vec < _ > > ( ) ;
645
+ fields. sort ( ) ; // make sure we have deterministic output
646
+ for name in fields {
647
+ let ( ty, readonly) = & class. typescript_fields [ name] ;
648
+ if * readonly {
649
+ ts_dst. push_str ( "readonly " ) ;
650
+ }
651
+ ts_dst. push_str ( name) ;
652
+ ts_dst. push_str ( ": " ) ;
653
+ ts_dst. push_str ( ty) ;
654
+ ts_dst. push_str ( ";\n " ) ;
655
+ }
641
656
dst. push_str ( "}\n " ) ;
642
657
ts_dst. push_str ( "}\n " ) ;
643
658
@@ -1913,14 +1928,15 @@ impl<'a> Context<'a> {
1913
1928
& format ! ( "wasm.{}" , wasm_name) ,
1914
1929
ExportedShim :: Named ( & wasm_name) ,
1915
1930
) ;
1931
+ let ret_ty = j2r. ret_ty . clone ( ) ;
1916
1932
let exported = require_class ( & mut self . exported_classes , class) ;
1917
1933
let docs = format_doc_comments ( & export. comments , Some ( raw_docs) ) ;
1918
1934
match export. kind {
1919
1935
AuxExportKind :: Getter { .. } => {
1920
- exported. push ( & docs , name, "get " , & js, & ts ) ;
1936
+ exported. push_field ( name, & js, Some ( & ret_ty ) , true ) ;
1921
1937
}
1922
1938
AuxExportKind :: Setter { .. } => {
1923
- exported. push ( & docs , name, "set " , & js, & ts ) ;
1939
+ exported. push_field ( name, & js, None , false ) ;
1924
1940
}
1925
1941
AuxExportKind :: StaticFunction { .. } => {
1926
1942
exported. push ( & docs, name, "static " , & js, & ts) ;
@@ -1983,7 +1999,7 @@ impl<'a> Context<'a> {
1983
1999
bail ! (
1984
2000
"NPM dependencies have been specified in `{}` but \
1985
2001
this is only compatible with the `bundler` and `nodejs` targets",
1986
- path. display( ) ,
2002
+ path. display( ) ,
1987
2003
) ;
1988
2004
}
1989
2005
@@ -2164,6 +2180,31 @@ impl ExportedClass {
2164
2180
self . typescript . push_str ( ts) ;
2165
2181
self . typescript . push_str ( "\n " ) ;
2166
2182
}
2183
+
2184
+ /// Used for adding a field to a class, mainly to ensure that TypeScript
2185
+ /// generation is handled specially.
2186
+ ///
2187
+ /// Note that the `ts` is optional and it's expected to just be the field
2188
+ /// type, not the full signature. It's currently only available on getters,
2189
+ /// but there currently has to always be at least a getter.
2190
+ fn push_field ( & mut self , field : & str , js : & str , ts : Option < & str > , getter : bool ) {
2191
+ if getter {
2192
+ self . contents . push_str ( "get " ) ;
2193
+ } else {
2194
+ self . contents . push_str ( "set " ) ;
2195
+ }
2196
+ self . contents . push_str ( field) ;
2197
+ self . contents . push_str ( js) ;
2198
+ self . contents . push_str ( "\n " ) ;
2199
+ let ( ty, has_setter) = self
2200
+ . typescript_fields
2201
+ . entry ( field. to_string ( ) )
2202
+ . or_insert_with ( Default :: default) ;
2203
+ if let Some ( ts) = ts {
2204
+ * ty = ts. to_string ( ) ;
2205
+ }
2206
+ * has_setter = * has_setter || !getter;
2207
+ }
2167
2208
}
2168
2209
2169
2210
#[ test]
0 commit comments