From 3997532186016c14753098294e4f3fcfad77ac2f Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 29 Mar 2024 23:07:32 +1100 Subject: [PATCH] webassembly/proxy_c: Ensure return value of async fun is passed to JS. Signed-off-by: Damien George --- ports/webassembly/proxy_c.c | 9 +++-- tests/ports/webassembly/await_js_async_py.mjs | 35 +++++++++++++++++++ .../webassembly/await_js_async_py.mjs.exp | 12 +++++++ 3 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 tests/ports/webassembly/await_js_async_py.mjs create mode 100644 tests/ports/webassembly/await_js_async_py.mjs.exp diff --git a/ports/webassembly/proxy_c.c b/ports/webassembly/proxy_c.c index 1e4573ce0b..8d137f6271 100644 --- a/ports/webassembly/proxy_c.c +++ b/ports/webassembly/proxy_c.c @@ -289,10 +289,11 @@ void proxy_c_to_js_get_dict(uint32_t c_ref, uint32_t *out) { static const mp_obj_fun_builtin_var_t resume_obj; -EM_JS(void, js_then_resolve, (uint32_t * resolve, uint32_t * reject), { +EM_JS(void, js_then_resolve, (uint32_t * ret_value, uint32_t * resolve, uint32_t * reject), { + const ret_value_js = proxy_convert_mp_to_js_obj_jsside(ret_value); const resolve_js = proxy_convert_mp_to_js_obj_jsside(resolve); const reject_js = proxy_convert_mp_to_js_obj_jsside(reject); - resolve_js(null); + resolve_js(ret_value_js); }); EM_JS(void, js_then_reject, (uint32_t * resolve, uint32_t * reject), { @@ -321,7 +322,9 @@ static mp_obj_t proxy_resume_execute(mp_obj_t self_in, mp_obj_t value, mp_obj_t proxy_convert_mp_to_js_obj_cside(reject, out_reject); if (ret_kind == MP_VM_RETURN_NORMAL) { - js_then_resolve(out_resolve, out_reject); + uint32_t out_ret_value[PVN]; + proxy_convert_mp_to_js_obj_cside(ret_value, out_ret_value); + js_then_resolve(out_ret_value, out_resolve, out_reject); return mp_const_none; } else if (ret_kind == MP_VM_RETURN_YIELD) { // ret_value should be a JS thenable diff --git a/tests/ports/webassembly/await_js_async_py.mjs b/tests/ports/webassembly/await_js_async_py.mjs new file mode 100644 index 0000000000..953a7b783d --- /dev/null +++ b/tests/ports/webassembly/await_js_async_py.mjs @@ -0,0 +1,35 @@ +// Test JavaScript await'ing on Python async functions. + +const mp = await (await import(process.argv[2])).loadMicroPython(); + +globalThis.asyncTimeout = (ms) => + new Promise((resolve) => setTimeout(resolve, ms)); + +mp.runPython(` +import js + +def f0(): + print("f0 run") + return 1 + +async def f1(): + print("f1 run") + return 2 + +async def f2(): + print("f2 start") + await js.asyncTimeout(0) + print("f2 end") + return 3 + +async def f3(): + print("f3 start") + ret = await f2() + print("f3 end") + return ret + 1 +`); + +console.log("f0 return:", await mp.globals.get("f0")()); +console.log("f1 return:", await mp.globals.get("f1")()); +console.log("f2 return:", await mp.globals.get("f2")()); +console.log("f3 return:", await mp.globals.get("f3")()); diff --git a/tests/ports/webassembly/await_js_async_py.mjs.exp b/tests/ports/webassembly/await_js_async_py.mjs.exp new file mode 100644 index 0000000000..ab8cbabebb --- /dev/null +++ b/tests/ports/webassembly/await_js_async_py.mjs.exp @@ -0,0 +1,12 @@ +f0 run +f0 return: 1 +f1 run +f1 return: 2 +f2 start +f2 end +f2 return: 3 +f3 start +f2 start +f2 end +f3 end +f3 return: 4