@@ -29,6 +29,7 @@ pub enum Resource {
2929 Constructor ( String ) ,
3030 Static ( String ) ,
3131 Method ( String ) ,
32+ Destructor ( String ) ,
3233}
3334
3435impl Resource {
@@ -38,6 +39,7 @@ impl Resource {
3839 Resource :: Constructor ( name) => format ! ( "[constructor]{name}" ) ,
3940 Resource :: Static ( name) => format ! ( "[static]{name}.{fn_name}" ) ,
4041 Resource :: Method ( name) => format ! ( "[method]{name}.{fn_name}" ) ,
42+ Resource :: Destructor ( name) => format ! ( "[dtor]{name}" ) ,
4143 }
4244 }
4345
@@ -65,6 +67,9 @@ impl Resource {
6567 fn_name. to_lower_camel_case( )
6668 )
6769 }
70+ Resource :: Destructor ( name) => {
71+ format ! ( "{}$dtor" , name. to_lower_camel_case( ) )
72+ }
6873 }
6974 }
7075}
@@ -190,7 +195,8 @@ pub fn componentize_bindgen(
190195 Resource :: None => None ,
191196 Resource :: Method ( name)
192197 | Resource :: Static ( name)
193- | Resource :: Constructor ( name) => Some ( name) ,
198+ | Resource :: Constructor ( name)
199+ | Resource :: Destructor ( name) => Some ( name) ,
194200 } )
195201 . or_default ( )
196202 . push ( item) ;
@@ -426,10 +432,12 @@ impl JsBindgen<'_> {
426432 }
427433 WorldItem :: Interface { id, stability : _ } => {
428434 let iface = & self . resolve . interfaces [ * id] ;
429- for id in iface. types . values ( ) {
430- if let TypeDefKind :: Resource = & self . resolve . types [ * id] . kind {
435+ let iface_name = interface_name ( self . resolve , * id) ;
436+ for ty_id in iface. types . values ( ) {
437+ if let TypeDefKind :: Resource = & self . resolve . types [ * ty_id] . kind {
431438 self . resource_directions
432- . insert ( * id, AbiVariant :: GuestExport ) ;
439+ . insert ( * ty_id, AbiVariant :: GuestExport ) ;
440+ self . resource_dtor_bindgen ( name. clone ( ) , iface_name. clone ( ) , * ty_id) ;
433441 }
434442 }
435443 for ( func_name, func) in & iface. functions {
@@ -991,6 +999,59 @@ impl JsBindgen<'_> {
991999 ) ) ;
9921000 }
9931001
1002+ fn resource_dtor_bindgen (
1003+ & mut self ,
1004+ export_name : String ,
1005+ iface_name : Option < String > ,
1006+ resource : TypeId ,
1007+ ) {
1008+ let resource_name = self . resolve . types [ resource] . name . as_ref ( ) . unwrap ( ) ;
1009+ let resource_name_camel = resource_name. to_lower_camel_case ( ) ;
1010+ let prefix = iface_name
1011+ . as_deref ( )
1012+ . map ( |name| format ! ( "{name}$" ) )
1013+ . unwrap_or_default ( ) ;
1014+ let symbol_dispose = self . intrinsic ( Intrinsic :: SymbolDispose ) ;
1015+ let symbol_resource_handle = self . intrinsic ( Intrinsic :: SymbolResourceHandle ) ;
1016+ let binding_name = format ! (
1017+ "export_{}" ,
1018+ binding_name( & format!( "{resource_name_camel}$dtor" ) , & iface_name)
1019+ ) ;
1020+
1021+ uwriteln ! (
1022+ self . src,
1023+ "
1024+ async function {binding_name}(rep) {{
1025+ const entry = repTable.get(rep);
1026+ if (!entry) return;
1027+ repTable.delete(rep);
1028+ const resource = entry.rep;
1029+ delete resource[{symbol_resource_handle}];
1030+ finalizationRegistry_export${prefix}{resource_name_camel}.unregister(resource);
1031+ if (resource[{symbol_dispose}]) resource[{symbol_dispose}]();
1032+ }}
1033+ "
1034+ ) ;
1035+
1036+ self . exports . push ( (
1037+ export_name,
1038+ BindingItem {
1039+ iface : true ,
1040+ iface_name,
1041+ binding_name,
1042+ resource : Resource :: Destructor ( resource_name. clone ( ) ) ,
1043+ name : resource_name. clone ( ) ,
1044+ func : CoreFn {
1045+ params : vec ! [ CoreTy :: I32 ] ,
1046+ ret : None ,
1047+ retptr : false ,
1048+ retsize : 0 ,
1049+ paramptr : false ,
1050+ } ,
1051+ } ,
1052+ ) ) ;
1053+ }
1054+
9941055 fn core_fn ( & self , func : & Function , sig : & WasmSignature ) -> CoreFn {
9951056 CoreFn {
9961057 retsize : if sig. retptr {
0 commit comments