@@ -1980,77 +1980,104 @@ impl Bindgen for FunctionBindgen<'_> {
19801980 . intrinsic ( Intrinsic :: Resource ( ResourceIntrinsic :: ResourceTableRemove ) ) ;
19811981 let rsc_flag = self
19821982 . intrinsic ( Intrinsic :: Resource ( ResourceIntrinsic :: ResourceTableFlag ) ) ;
1983- if !imported {
1984- let symbol_resource_handle =
1985- self . intrinsic ( Intrinsic :: SymbolResourceHandle ) ;
1986-
1987- uwriteln ! (
1988- self . src,
1989- "var {rsc} = new.target === {local_name} ? this : Object.create({local_name}.prototype);"
1990- ) ;
1983+ let symbol_resource_handle =
1984+ self . intrinsic ( Intrinsic :: SymbolResourceHandle ) ;
1985+ let empty_func =
1986+ self . intrinsic ( Intrinsic :: JsHelper ( JsHelperIntrinsic :: EmptyFunc ) ) ;
19911987
1992- if is_own {
1993- // Sending an own handle out to JS as a return value - set up finalizer and disposal.
1994- let empty_func = self
1995- . intrinsic ( Intrinsic :: JsHelper ( JsHelperIntrinsic :: EmptyFunc ) ) ;
1996- uwriteln ! ( self . src,
1997- "Object.defineProperty({rsc}, {symbol_resource_handle}, {{ writable: true, value: {handle} }});
1998- finalizationRegistry{tid}.register({rsc}, {handle}, {rsc});" ) ;
1999- if let Some ( dtor) = dtor_name {
1988+ match ( imported, is_own) {
1989+ // Non-imported owned resource
1990+ ( _imported @ false , _owned @ true ) => {
1991+ let dtor_setup_js = if let Some ( dtor) = dtor_name {
20001992 // The Symbol.dispose function gets disabled on drop, so we can rely on the own handle remaining valid.
2001- uwriteln ! (
2002- self . src ,
2003- " Object.defineProperty({rsc}, {symbol_dispose}, {{ writable: true, value: function () {{
1993+ format ! (
1994+ r#" ,
1995+ Object.defineProperty({rsc}, {symbol_dispose}, {{ writable: true, value: function () {{
20041996 finalizationRegistry{tid}.unregister({rsc});
20051997 {rsc_table_remove}(handleTable{tid}, {handle});
20061998 {rsc}[{symbol_dispose}] = {empty_func};
20071999 {rsc}[{symbol_resource_handle}] = undefined;
20082000 {dtor}(handleTable{tid}[({handle} << 1) + 1] & ~{rsc_flag});
2009- }}}});"
2010- ) ;
2001+ }}}});
2002+ "#
2003+ )
20112004 } else {
20122005 // Set up Symbol.dispose for borrows to allow its call, even though it does nothing.
2013- uwriteln ! (
2014- self . src,
2015- "Object.defineProperty({rsc}, {symbol_dispose}, {{ writable: true, value: {empty_func} }});" ,
2016- ) ;
2017- }
2018- } else {
2006+ format ! (
2007+ "Object.defineProperty({rsc}, {symbol_dispose}, {{ writable: true, value: {empty_func} }});"
2008+ )
2009+ } ;
2010+
2011+ // Sending an own handle out to JS as a return value - set up finalizer and disposal.
2012+ uwriteln ! (
2013+ self . src,
2014+ r#"
2015+ var {rsc} = new.target === {local_name} ? this : Object.create({local_name}.prototype);
2016+ Object.defineProperty({rsc}, {symbol_resource_handle}, {{ writable: true, value: {handle} }});
2017+ finalizationRegistry{tid}.register({rsc}, {handle}, {rsc});
2018+ {dtor_setup_js}
2019+ "#
2020+ ) ;
2021+ }
2022+
2023+ // Non-imported borrowed resource
2024+ ( _imported @ false , _owned @ false ) => {
20192025 // Borrow handles of local resources have rep handles, which we carry through here.
20202026 uwriteln ! (
20212027 self . src,
20222028 "Object.defineProperty({rsc}, {symbol_resource_handle}, {{ writable: true, value: {handle} }});"
20232029 ) ;
20242030 }
2025- } else {
2026- let rep = format ! ( "rep{}" , self . tmp( ) ) ;
2027- // Imported handles either lift as instance capture from a previous lowering,
2028- // or we create a new JS class to represent it.
2029- let symbol_resource_rep = self . intrinsic ( Intrinsic :: SymbolResourceRep ) ;
2030- let symbol_resource_handle =
2031- self . intrinsic ( Intrinsic :: SymbolResourceHandle ) ;
20322031
2033- uwriteln ! (
2034- self . src,
2035- r#"
2032+ // Imported owned resource
2033+ ( _imported @ true , _owned @ true ) => {
2034+ let rep = format ! ( "rep{}" , self . tmp( ) ) ;
2035+ // Imported handles either lift as instance capture from a previous lowering,
2036+ // or we create a new JS class to represent it.
2037+ let symbol_resource_rep =
2038+ self . intrinsic ( Intrinsic :: SymbolResourceRep ) ;
2039+ let symbol_resource_handle =
2040+ self . intrinsic ( Intrinsic :: SymbolResourceHandle ) ;
2041+
2042+ uwriteln ! (
2043+ self . src,
2044+ r#"
20362045 var {rep} = handleTable{tid}[({handle} << 1) + 1] & ~{rsc_flag};
20372046 var {rsc} = captureTable{rid}.get({rep});
20382047 if (!{rsc}) {{
20392048 {rsc} = Object.create({local_name}.prototype);
20402049 Object.defineProperty({rsc}, {symbol_resource_handle}, {{ writable: true, value: {handle} }});
20412050 Object.defineProperty({rsc}, {symbol_resource_rep}, {{ writable: true, value: {rep} }});
2051+ }} else {{
2052+ captureTable{rid}.delete({rep});
20422053 }}
2054+ // NOTE: owned lifting is a transfer to JS, so existing own handle must be dropped
2055+ {rsc_table_remove}(handleTable{tid}, {handle});
20432056 "# ,
2044- ) ;
2057+ ) ;
2058+ }
2059+
2060+ // Imported borrowed resource
2061+ ( _imported @ true , _owned @ false ) => {
2062+ let rep = format ! ( "rep{}" , self . tmp( ) ) ;
2063+ // Imported handles either lift as instance capture from a previous lowering,
2064+ // or we create a new JS class to represent it.
2065+ let symbol_resource_rep =
2066+ self . intrinsic ( Intrinsic :: SymbolResourceRep ) ;
2067+ let symbol_resource_handle =
2068+ self . intrinsic ( Intrinsic :: SymbolResourceHandle ) ;
20452069
2046- if is_own {
2047- // An own lifting is a transfer to JS, so existing own handle is implicitly dropped.
20482070 uwriteln ! (
20492071 self . src,
2050- "else {{
2051- captureTable{rid}.delete({rep});
2052- }}
2053- {rsc_table_remove}(handleTable{tid}, {handle});"
2072+ r#"
2073+ var {rep} = handleTable{tid}[({handle} << 1) + 1] & ~{rsc_flag};
2074+ var {rsc} = captureTable{rid}.get({rep});
2075+ if (!{rsc}) {{
2076+ {rsc} = Object.create({local_name}.prototype);
2077+ Object.defineProperty({rsc}, {symbol_resource_handle}, {{ writable: true, value: {handle} }});
2078+ Object.defineProperty({rsc}, {symbol_resource_rep}, {{ writable: true, value: {rep} }});
2079+ }}
2080+ "# ,
20542081 ) ;
20552082 }
20562083 }
@@ -2080,52 +2107,78 @@ impl Bindgen for FunctionBindgen<'_> {
20802107 let prefix = prefix. as_deref ( ) . unwrap_or ( "" ) ;
20812108 let lower_camel = resource_name. to_lower_camel_case ( ) ;
20822109
2083- if !imported {
2084- if is_own {
2085- uwriteln ! (
2086- self . src,
2087- "var {rsc} = repTable.get($resource_{prefix}rep${lower_camel}({handle})).rep;"
2088- ) ;
2110+ match ( imported, is_own) {
2111+ // Non-imported, owned guest resource
2112+ ( _imported @ false , _owned @ true ) => {
20892113 uwrite ! (
20902114 self . src,
20912115 r#"
2116+ const {rsc} = repTable.get($resource_{prefix}rep${lower_camel}({handle})).rep;
20922117 repTable.delete({handle});
20932118 delete {rsc}[{symbol_resource_handle}];
20942119 finalizationRegistry_export${prefix}{lower_camel}.unregister({rsc});
20952120 "#
20962121 ) ;
2097- } else {
2098- uwriteln ! ( self . src, "var {rsc} = repTable.get({handle}).rep;" ) ;
20992122 }
2100- } else {
2101- let upper_camel = resource_name. to_upper_camel_case ( ) ;
21022123
2103- uwrite ! (
2104- self . src,
2105- r#"
2106- var {rsc} = new.target === import_{prefix}{upper_camel} ? this : Object.create(import_{prefix}{upper_camel}.prototype);
2107- Object.defineProperty({rsc}, {symbol_resource_handle}, {{ writable: true, value: {handle} }});
2108- "#
2109- ) ;
2124+ // Non-imported, borrowed guest resource
2125+ ( _imported @ false , _owned @ false ) => {
2126+ uwriteln ! ( self . src, "const {rsc} = repTable.get({handle}).rep;" ) ;
2127+ }
21102128
2111- uwriteln ! (
2112- self . src,
2113- "finalizationRegistry_import${prefix}{lower_camel}.register({rsc}, {handle}, {rsc});" ,
2114- ) ;
2129+ // Imported, owned guest resource
2130+ ( _imported @ true , _owned @ true ) => {
2131+ let upper_camel = resource_name. to_upper_camel_case ( ) ;
21152132
2116- if !is_own {
2117- let cur_resource_borrows = self . intrinsic ( Intrinsic :: Resource (
2118- ResourceIntrinsic :: CurResourceBorrows ,
2119- ) ) ;
2120- uwriteln ! (
2133+ uwrite ! (
2134+ self . src,
2135+ r#"
2136+ let {rsc};
2137+ if (new.target === import_{prefix}{upper_camel}) {{
2138+ {rsc} = this;
2139+ }} else {{
2140+ {rsc} = Object.create(import_{prefix}{upper_camel}.prototype);
2141+ }}
2142+ Object.defineProperty({rsc}, {symbol_resource_handle}, {{ writable: true, value: {handle} }});
2143+ finalizationRegistry_import${prefix}{lower_camel}.register({rsc}, {handle}, {rsc});
2144+ "#
2145+ ) ;
2146+ }
2147+
2148+ // Imported, borrowed guest resource
2149+ ( _imported @ true , _owned @ false ) => {
2150+ let upper_camel = resource_name. to_upper_camel_case ( ) ;
2151+
2152+ uwrite ! (
21212153 self . src,
2122- "{cur_resource_borrows}.push({{ rsc: {rsc}, drop: $resource_import${prefix}drop${lower_camel} }});"
2154+ r#"
2155+ let {rsc};
2156+ if (new.target === import_{prefix}{upper_camel}) {{
2157+ {rsc} = this;
2158+ }} else {{
2159+ {rsc} = Object.create(import_{prefix}{upper_camel}.prototype);
2160+ }}
2161+ Object.defineProperty({rsc}, {symbol_resource_handle}, {{ writable: true, value: {handle} }});
2162+ finalizationRegistry_import${prefix}{lower_camel}.register({rsc}, {handle}, {rsc});
2163+ "#
21232164 ) ;
2124- self . clear_resource_borrows = true ;
2165+
2166+ // TODO(fix): should this be similar to host and *not* be here, but apply no matter what?
2167+ if !is_own {
2168+ let cur_resource_borrows = self . intrinsic ( Intrinsic :: Resource (
2169+ ResourceIntrinsic :: CurResourceBorrows ,
2170+ ) ) ;
2171+ uwriteln ! (
2172+ self . src,
2173+ "{cur_resource_borrows}.push({{ rsc: {rsc}, drop: $resource_import${prefix}drop${lower_camel} }});"
2174+ ) ;
2175+ self . clear_resource_borrows = true ;
2176+ }
21252177 }
21262178 }
21272179 }
21282180 }
2181+
21292182 results. push ( rsc) ;
21302183 }
21312184
0 commit comments