Skip to content

Commit 80f9b92

Browse files
fix(jco): async return writing for caller memory
This commit fixes a bug where the memory for writing to was being retrieved too eagerly (@ trampoline fn binding time), and was not available properly when performing async `task.return`s.
1 parent 9e51031 commit 80f9b92

File tree

4 files changed

+44
-33
lines changed

4 files changed

+44
-33
lines changed

crates/js-component-bindgen/src/intrinsics/p3/async_task.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -303,12 +303,14 @@ impl AsyncTaskIntrinsic {
303303
let current_task_get_fn = Self::GetCurrentTask.name();
304304

305305
output.push_str(&format!("
306-
function {task_return_fn}(componentIdx, useDirectParams, memory, callbackFnIdx, liftFns) {{
307-
const params = [...arguments].slice(5);
306+
function {task_return_fn}(ctx) {{
307+
const {{ componentIdx, useDirectParams, getMemoryFn, callbackFnIdx, liftFns }} = ctx;
308+
const params = [...arguments].slice(1);
309+
const memory = getMemoryFn();
308310
{debug_log_fn}('[{task_return_fn}()] args', {{
309311
componentIdx,
310-
memory,
311312
callbackFnIdx,
313+
memory,
312314
liftFns,
313315
params,
314316
}});
@@ -326,18 +328,11 @@ impl AsyncTaskIntrinsic {
326328
}}
327329
328330
let liftCtx = {{ memory, useDirectParams, params }};
329-
if (useDirectParams) {{
330-
liftCtx.memory = memory;
331-
liftCtx.params = params;
332-
}} else {{
331+
if (!useDirectParams) {{
333332
liftCtx.storagePtr = params[0];
334333
liftCtx.storageLen = params[1];
335334
}}
336335
337-
if (memory && liftCtx.storageLen === undefined) {{
338-
throw new Error('storageLen must be provided if a memory is present');
339-
}}
340-
341336
const results = [];
342337
{debug_log_fn}('[{task_return_fn}()] lifting results out of memory', {{ liftCtx }});
343338
for (const liftFn of liftFns) {{

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

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1996,9 +1996,9 @@ impl<'a> Instantiator<'a, '_> {
19961996
}
19971997
let lift_fns_js = format!("[{}]", lift_fns.join(","));
19981998

1999-
let memory_js = memory
2000-
.map(|idx| format!("memory{}", idx.as_u32()))
2001-
.unwrap_or_else(|| "null".into());
1999+
let get_memory_fn_js = memory
2000+
.map(|idx| format!("() => memory{}", idx.as_u32()))
2001+
.unwrap_or_else(|| "() => null".into());
20022002
let component_idx = instance.as_u32();
20032003
let task_return_fn = self
20042004
.bindgen
@@ -2011,11 +2011,13 @@ impl<'a> Instantiator<'a, '_> {
20112011
self.src.js,
20122012
"const trampoline{i} = {task_return_fn}.bind(
20132013
null,
2014-
{component_idx},
2015-
{use_direct_params},
2016-
{memory_js},
2017-
{callback_fn_idx},
2018-
{lift_fns_js},
2014+
{{
2015+
componentIdx: {component_idx},
2016+
useDirectParams: {use_direct_params},
2017+
getMemoryFn: {get_memory_fn_js},
2018+
callbackFnIdx: {callback_fn_idx},
2019+
liftFns: {lift_fns_js},
2020+
}},
20192021
);",
20202022
);
20212023
}
Binary file not shown.

packages/jco/test/p3/async.js

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,16 @@ import { P3_COMPONENT_FIXTURES_DIR } from '../common.js';
1010
suite('Async (WASI P3)', () => {
1111
// see: https://github.com/bytecodealliance/jco/issues/1076
1212
test('incorrect task return params offloading', async () => {
13-
const componentPath = join(
14-
P3_COMPONENT_FIXTURES_DIR,
15-
'async-flat-param-adder.wasm'
16-
);
17-
13+
const name = 'async-flat-param-adder';
1814
const { instance, cleanup } = await setupAsyncTest({
1915
component: {
20-
name: 'async-flat-param-adder',
21-
path: componentPath,
16+
name,
17+
path: join(
18+
P3_COMPONENT_FIXTURES_DIR,
19+
`${name}.wasm`,
20+
),
2221
imports: new WASIShim().getImportObject(),
2322
},
24-
jco: {
25-
transpile: {
26-
extraArgs: {
27-
minify: false,
28-
}
29-
}
30-
}
3123
});
3224

3325
assert(instance.test3);
@@ -38,4 +30,26 @@ suite('Async (WASI P3)', () => {
3830

3931
await cleanup();
4032
});
33+
34+
// https://bytecodealliance.zulipchat.com/#narrow/channel/206238-general/topic/Should.20StringLift.20be.20emitted.20for.20async.20return.20values.3F/with/561133720
35+
test('simple string return', async () => {
36+
const name = 'async-simple-string-return';
37+
const { instance, cleanup } = await setupAsyncTest({
38+
component: {
39+
name,
40+
path: join(
41+
P3_COMPONENT_FIXTURES_DIR,
42+
`${name}.wasm`,
43+
),
44+
imports: new WASIShim().getImportObject(),
45+
},
46+
});
47+
48+
assert.typeOf(instance.asyncGetLiteral, 'function');
49+
50+
const result = await instance.asyncGetLiteral();
51+
assert.strictEqual(result, "literal");
52+
53+
await cleanup();
54+
});
4155
});

0 commit comments

Comments
 (0)