Skip to content

Commit 4cf85d6

Browse files
fix(bindgen): impl async stream lower owned resources
1 parent 9074e03 commit 4cf85d6

4 files changed

Lines changed: 146 additions & 111 deletions

File tree

crates/js-component-bindgen/src/function_bindgen.rs

Lines changed: 135 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -2203,21 +2203,28 @@ impl Bindgen for FunctionBindgen<'_> {
22032203
} => {
22042204
let tid = tid.as_u32();
22052205
let rid = rid.as_u32();
2206-
if !imported {
2207-
if is_own {
2206+
2207+
match (imported, is_own) {
2208+
// Imported, owned host-provided resource
2209+
(_imported @ false, _owned @ true) => {
22082210
let empty_func = self
22092211
.intrinsic(Intrinsic::JsHelper(JsHelperIntrinsic::EmptyFunc));
22102212
uwriteln!(
2211-
self.src,
2212-
"var {handle} = {op}[{symbol_resource_handle}];
2213-
if (!{handle}) {{
2214-
throw new TypeError('Resource error: Not a valid \"{class_name}\" resource.');
2215-
}}
2216-
finalizationRegistry{tid}.unregister({op});
2217-
{op}[{symbol_dispose}] = {empty_func};
2218-
{op}[{symbol_resource_handle}] = undefined;",
2219-
);
2220-
} else {
2213+
self.src,
2214+
r#"
2215+
var {handle} = {op}[{symbol_resource_handle}];
2216+
if (!{handle}) {{
2217+
throw new TypeError('Resource error: Not a valid \"{class_name}\" resource.');
2218+
}}
2219+
finalizationRegistry{tid}.unregister({op});
2220+
{op}[{symbol_dispose}] = {empty_func};
2221+
{op}[{symbol_resource_handle}] = undefined;
2222+
"#,
2223+
);
2224+
}
2225+
2226+
// Imported, borrowed host-provdied resource
2227+
(_imported @ false, _owned @ false) => {
22212228
// When expecting a borrow, the JS resource provided will always be an own
22222229
// handle. This is because it is not possible for borrow handles to be passed
22232230
// back reentrantly.
@@ -2226,54 +2233,87 @@ impl Bindgen for FunctionBindgen<'_> {
22262233
ResourceIntrinsic::ResourceTableFlag,
22272234
));
22282235
let own_handle = format!("handle{}", self.tmp());
2229-
uwriteln!(self.src,
2230-
"var {own_handle} = {op}[{symbol_resource_handle}];
2231-
if (!{own_handle} || (handleTable{tid}[({own_handle} << 1) + 1] & {rsc_flag}) === 0) {{
2232-
throw new TypeError('Resource error: Not a valid \"{class_name}\" resource.');
2233-
}}
2234-
var {handle} = handleTable{tid}[({own_handle} << 1) + 1] & ~{rsc_flag};",
2235-
);
2236+
uwriteln!(
2237+
self.src,
2238+
r#"
2239+
var {own_handle} = {op}[{symbol_resource_handle}];
2240+
if (!{own_handle} || (handleTable{tid}[({own_handle} << 1) + 1] & {rsc_flag}) === 0) {{
2241+
throw new TypeError('Resource error: Not a valid \"{class_name}\" resource.');
2242+
}}
2243+
var {handle} = handleTable{tid}[({own_handle} << 1) + 1] & ~{rsc_flag};
2244+
"#,
2245+
);
22362246
}
2237-
} else {
2238-
// Imported resources may already have a handle if they were constructed
2239-
// by a component and then passed out.
2240-
uwriteln!(
2241-
self.src,
2242-
"if (!({op} instanceof {local_name})) {{
2243-
throw new TypeError('Resource error: Not a valid \"{class_name}\" resource.');
2244-
}}
2245-
var {handle} = {op}[{symbol_resource_handle}];",
2246-
);
2247-
// Otherwise, in hybrid bindgen we check for a Symbol.for('cabiRep')
2248-
// to get the resource rep.
2249-
// Fall back to assign a new rep in the capture table, when the imported
2250-
// resource was constructed externally.
2251-
let symbol_resource_rep = self.intrinsic(Intrinsic::SymbolResourceRep);
2252-
2253-
// Build the code to initialize the owned/borrowed resource handle
2254-
let handle_init_js = if is_own {
2247+
2248+
// Imported, owned guest-provided resource
2249+
(_imported @ true, _owned @ true) => {
2250+
// Imported resources may already have a handle if they were constructed
2251+
// by a component and then passed out.
2252+
//
2253+
// If the handle is not present, in hybrid bindgen we check for a Symbol.for('cabiRep')
2254+
// to get the resource rep.
2255+
//
2256+
// Fall back to assign a new rep in the capture table, when the imported
2257+
// resource was constructed externally.
2258+
let symbol_resource_rep =
2259+
self.intrinsic(Intrinsic::SymbolResourceRep);
22552260
let create_own_fn = self.intrinsic(Intrinsic::Resource(
22562261
ResourceIntrinsic::ResourceTableCreateOwn,
22572262
));
2258-
format!("{handle} = {create_own_fn}(handleTable{tid}, rep);")
2259-
} else {
2263+
2264+
uwriteln!(
2265+
self.src,
2266+
r#"
2267+
if (!({op} instanceof {local_name})) {{
2268+
throw new TypeError('Resource error: Not a valid \"{class_name}\" resource.');
2269+
}}
2270+
var {handle} = {op}[{symbol_resource_handle}];
2271+
if (!{handle}) {{
2272+
const rep = {op}[{symbol_resource_rep}] || ++captureCnt{rid};
2273+
captureTable{rid}.set(rep, {op});
2274+
{create_own_fn}(handleTable{tid}, rep);
2275+
}}
2276+
"#
2277+
);
2278+
}
2279+
2280+
// Imported, borrowed guest-provided resource
2281+
(_imported @ true, _owned @ false) => {
2282+
// Imported resources may already have a handle if they were constructed
2283+
// by a component and then passed out.
2284+
uwriteln!(
2285+
self.src,
2286+
r#"
2287+
if (!({op} instanceof {local_name})) {{
2288+
throw new TypeError('Resource error: Not a valid \"{class_name}\" resource.');
2289+
}}
2290+
var {handle} = {op}[{symbol_resource_handle}];
2291+
"#,
2292+
);
2293+
// Otherwise, in hybrid bindgen we check for a Symbol.for('cabiRep')
2294+
// to get the resource rep.
2295+
// Fall back to assign a new rep in the capture table, when the imported
2296+
// resource was constructed externally.
2297+
let symbol_resource_rep =
2298+
self.intrinsic(Intrinsic::SymbolResourceRep);
2299+
22602300
let scope_id = self.intrinsic(Intrinsic::ScopeId);
22612301
let create_borrow_fn = self.intrinsic(Intrinsic::Resource(
22622302
ResourceIntrinsic::ResourceTableCreateBorrow,
22632303
));
2264-
format!(
2304+
let handle_init_js = format!(
22652305
"{handle} = {create_borrow_fn}(handleTable{tid}, rep, {scope_id});"
2266-
)
2267-
};
2306+
);
22682307

2269-
uwriteln!(
2270-
self.src,
2271-
"if (!{handle}) {{
2308+
uwriteln!(
2309+
self.src,
2310+
"if (!{handle}) {{
22722311
const rep = {op}[{symbol_resource_rep}] || ++captureCnt{rid};
22732312
captureTable{rid}.set(rep, {op});
22742313
{handle_init_js}
22752314
}}"
2276-
);
2315+
);
2316+
}
22772317
}
22782318
}
22792319

@@ -2291,48 +2331,61 @@ impl Bindgen for FunctionBindgen<'_> {
22912331
let lower_camel = resource_name.to_lower_camel_case();
22922332
let prefix = prefix.as_deref().unwrap_or("");
22932333

2294-
if !imported {
2295-
let local_rep = format!("localRep{}", self.tmp());
2296-
uwriteln!(
2297-
self.src,
2298-
"if (!({op} instanceof {upper_camel})) {{
2299-
throw new TypeError('Resource error: Not a valid \"{upper_camel}\" resource.');
2300-
}}
2301-
let {handle} = {op}[{symbol_resource_handle}];",
2302-
);
2334+
let symbol_resource_handle =
2335+
self.intrinsic(Intrinsic::SymbolResourceHandle);
23032336

2304-
if is_own {
2337+
let tmp = self.tmp();
2338+
match (imported, is_own) {
2339+
// imported owned/borrowed guest resource
2340+
(_imported @ true, _owned @ _) => {
2341+
uwrite!(
2342+
self.src,
2343+
r#"
2344+
var {handle} = {op}[{symbol_resource_handle}];
2345+
finalizationRegistry_import${prefix}{lower_camel}.unregister({op});
2346+
"#
2347+
);
2348+
}
2349+
2350+
// Not-imported, borrowed guest resource
2351+
(_imported @ false, _owned @ false) => {
2352+
let local_rep = format!("localRep{tmp}");
23052353
uwriteln!(
2306-
self.src,
2307-
"if ({handle} === undefined) {{
2308-
var {local_rep} = repCnt++;
2309-
repTable.set({local_rep}, {{ rep: {op}, own: true }});
2310-
{handle} = $resource_{prefix}new${lower_camel}({local_rep});
2311-
{op}[{symbol_resource_handle}] = {handle};
2312-
finalizationRegistry_export${prefix}{lower_camel}.register({op}, {handle}, {op});
2313-
}}
2314-
"
2315-
);
2316-
} else {
2354+
self.src,
2355+
r#"
2356+
if (!({op} instanceof {upper_camel})) {{
2357+
throw new TypeError('Resource error: Not a valid \"{upper_camel}\" resource.');
2358+
}}
2359+
let {handle} = {op}[{symbol_resource_handle}];
2360+
if ({handle} === undefined) {{
2361+
var {local_rep} = repCnt++;
2362+
repTable.set({local_rep}, {{ rep: {op}, own: false }});
2363+
{op}[{symbol_resource_handle}] = {local_rep};
2364+
}}
2365+
"#
2366+
);
2367+
}
2368+
2369+
// Not-imported, owned guest resource
2370+
(_imported @ false, _owned @ true) => {
2371+
let local_rep = format!("localRep{tmp}");
23172372
uwriteln!(
23182373
self.src,
2319-
"if ({handle} === undefined) {{
2320-
var {local_rep} = repCnt++;
2321-
repTable.set({local_rep}, {{ rep: {op}, own: false }});
2322-
{op}[{symbol_resource_handle}] = {local_rep};
2323-
}}
2324-
"
2374+
r#"
2375+
if (!({op} instanceof {upper_camel})) {{
2376+
throw new TypeError('Resource error: Not a valid \"{upper_camel}\" resource.');
2377+
}}
2378+
let {handle} = {op}[{symbol_resource_handle}];
2379+
if ({handle} === undefined) {{
2380+
var {local_rep} = repCnt++;
2381+
repTable.set({local_rep}, {{ rep: {op}, own: true }});
2382+
{handle} = $resource_{prefix}new${lower_camel}({local_rep});
2383+
{op}[{symbol_resource_handle}] = {handle};
2384+
finalizationRegistry_export${prefix}{lower_camel}.register({op}, {handle}, {op});
2385+
}}
2386+
"#
23252387
);
23262388
}
2327-
} else {
2328-
let symbol_resource_handle =
2329-
self.intrinsic(Intrinsic::SymbolResourceHandle);
2330-
uwrite!(
2331-
self.src,
2332-
"var {handle} = {op}[{symbol_resource_handle}];
2333-
finalizationRegistry_import${prefix}{lower_camel}.unregister({op});
2334-
"
2335-
);
23362389
}
23372390
}
23382391
}

crates/js-component-bindgen/src/intrinsics/lower.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -925,8 +925,9 @@ impl LowerIntrinsic {
925925
}
926926

927927
Self::LowerFlatOwn => {
928-
let debug_log_fn = Intrinsic::DebugLog.name();
929928
let lower_flat_own_fn = self.name();
929+
let debug_log_fn = Intrinsic::DebugLog.name();
930+
let lower_u32_fn = Self::LowerFlatU32.name();
930931

931932
output.push_str(&format!(
932933
r#"
@@ -941,11 +942,12 @@ impl LowerIntrinsic {
941942
throw new Error(`component index mismatch (expected [${{componentIdx}}], lift called from [${{ctx.componentIdx}}])`);
942943
}}
943944
944-
console.log("PARAMS?", [...arguments]);
945-
946945
const obj = ctx.vals[0];
947946
if (obj === undefined || obj === null) {{ throw new Error('missing resource'); }}
948-
lowerFn(obj);
947+
const handle = lowerFn(obj);
948+
949+
ctx.vals[0] = handle;
950+
{lower_u32_fn}(ctx);
949951
}};
950952
}}
951953
"#

crates/js-component-bindgen/src/intrinsics/resource.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,6 @@ pub enum ResourceIntrinsic {
6161
ResourceTransferBorrowValidLifting,
6262
ResourceTransferOwn,
6363
CurResourceBorrows,
64-
65-
/// Monotonically increasing ID that is used for lowered resource reps
66-
LoweredResourceRepId,
6764
}
6865

6966
impl ResourceIntrinsic {
@@ -86,7 +83,6 @@ impl ResourceIntrinsic {
8683
Self::ResourceTransferBorrowValidLifting.name(),
8784
Self::ResourceTransferOwn.name(),
8885
Self::CurResourceBorrows.name(),
89-
Self::LoweredResourceRepId.name(),
9086
]
9187
}
9288

@@ -104,7 +100,6 @@ impl ResourceIntrinsic {
104100
Self::ResourceTransferBorrowValidLifting => "resourceTransferBorrowValidLifting",
105101
Self::ResourceTransferOwn => "resourceTransferOwn",
106102
Self::CurResourceBorrows => "curResourceBorrows",
107-
Self::LoweredResourceRepId => "LOWERED_RESOURCE_REP",
108103
}
109104
}
110105

@@ -257,11 +252,6 @@ impl ResourceIntrinsic {
257252
let name = self.name();
258253
output.push_str(&format!("let {name} = [];"));
259254
}
260-
261-
Self::LoweredResourceRepId => {
262-
let name = self.name();
263-
output.push_str(&format!("const {name} = 1;"));
264-
}
265255
}
266256
}
267257
}

0 commit comments

Comments
 (0)