@@ -31,6 +31,7 @@ pub enum Resource {
3131 Constructor ( String ) ,
3232 Static ( String ) ,
3333 Method ( String ) ,
34+ Destructor ( String ) ,
3435}
3536
3637impl Resource {
@@ -40,6 +41,7 @@ impl Resource {
4041 Resource :: Constructor ( name) => format ! ( "[constructor]{name}" ) ,
4142 Resource :: Static ( name) => format ! ( "[static]{name}.{fn_name}" ) ,
4243 Resource :: Method ( name) => format ! ( "[method]{name}.{fn_name}" ) ,
44+ Resource :: Destructor ( name) => format ! ( "[dtor]{name}" ) ,
4345 }
4446 }
4547
@@ -67,6 +69,9 @@ impl Resource {
6769 fn_name. to_lower_camel_case( )
6870 )
6971 }
72+ Resource :: Destructor ( name) => {
73+ format ! ( "{}$dtor" , name. to_lower_camel_case( ) )
74+ }
7075 }
7176 }
7277}
@@ -193,7 +198,8 @@ pub fn componentize_bindgen(
193198 Resource :: None => None ,
194199 Resource :: Method ( name)
195200 | Resource :: Static ( name)
196- | Resource :: Constructor ( name) => Some ( name) ,
201+ | Resource :: Constructor ( name)
202+ | Resource :: Destructor ( name) => Some ( name) ,
197203 } )
198204 . or_default ( )
199205 . push ( item) ;
@@ -439,10 +445,12 @@ impl JsBindgen<'_> {
439445 id, stability : _, ..
440446 } => {
441447 let iface = & self . resolve . interfaces [ * id] ;
442- for id in iface. types . values ( ) {
443- if let TypeDefKind :: Resource = & self . resolve . types [ * id] . kind {
448+ let iface_name = interface_name ( self . resolve , * id) ;
449+ for ty_id in iface. types . values ( ) {
450+ if let TypeDefKind :: Resource = & self . resolve . types [ * ty_id] . kind {
444451 self . resource_directions
445- . insert ( * id, AbiVariant :: GuestExport ) ;
452+ . insert ( * ty_id, AbiVariant :: GuestExport ) ;
453+ self . resource_dtor_bindgen ( name. clone ( ) , iface_name. clone ( ) , * ty_id) ;
446454 }
447455 }
448456 for ( func_name, func) in & iface. functions {
@@ -1030,6 +1038,59 @@ impl JsBindgen<'_> {
10301038 ) ) ;
10311039 }
10321040
1041+ fn resource_dtor_bindgen (
1042+ & mut self ,
1043+ export_name : String ,
1044+ iface_name : Option < String > ,
1045+ resource : TypeId ,
1046+ ) {
1047+ let resource_name = self . resolve . types [ resource] . name . as_ref ( ) . unwrap ( ) ;
1048+ let resource_name_camel = resource_name. to_lower_camel_case ( ) ;
1049+ let prefix = iface_name
1050+ . as_deref ( )
1051+ . map ( |name| format ! ( "{name}$" ) )
1052+ . unwrap_or_default ( ) ;
1053+ let symbol_dispose = self . intrinsic ( Intrinsic :: SymbolDispose ) ;
1054+ let symbol_resource_handle = self . intrinsic ( Intrinsic :: SymbolResourceHandle ) ;
1055+ let binding_name = format ! (
1056+ "export_{}" ,
1057+ binding_name( & format!( "{resource_name_camel}$dtor" ) , & iface_name)
1058+ ) ;
1059+
1060+ uwriteln ! (
1061+ self . src,
1062+ "
1063+ async function {binding_name}(rep) {{
1064+ const entry = repTable.get(rep);
1065+ if (!entry) return;
1066+ repTable.delete(rep);
1067+ const resource = entry.rep;
1068+ delete resource[{symbol_resource_handle}];
1069+ finalizationRegistry_export${prefix}{resource_name_camel}.unregister(resource);
1070+ if (resource[{symbol_dispose}]) resource[{symbol_dispose}]();
1071+ }}
1072+ "
1073+ ) ;
1074+
1075+ self . exports . push ( (
1076+ export_name,
1077+ BindingItem {
1078+ iface : true ,
1079+ iface_name,
1080+ binding_name,
1081+ resource : Resource :: Destructor ( resource_name. clone ( ) ) ,
1082+ name : resource_name. clone ( ) ,
1083+ func : CoreFn {
1084+ params : vec ! [ CoreTy :: I32 ] ,
1085+ ret : None ,
1086+ retptr : false ,
1087+ retsize : 0 ,
1088+ paramptr : false ,
1089+ } ,
1090+ } ,
1091+ ) ) ;
1092+ }
1093+
10331094 fn core_fn ( & self , func : & Function , sig : & WasmSignature ) -> CoreFn {
10341095 CoreFn {
10351096 retsize : if sig. retptr {
0 commit comments