summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorDamien George <damien@micropython.org>2024-05-07 11:33:05 +1000
committerDamien George <damien@micropython.org>2024-05-07 11:33:05 +1000
commitbe1ecb54e6be1ee5017a1a8aeca83d9e12ad16c9 (patch)
tree9e1ea086e00f87b02d5ba9025708969eaeab15dc
parentc056840ee8f7a154ff437a335eb4a83f14d47f0f (diff)
downloadmicropython-be1ecb54e6be1ee5017a1a8aeca83d9e12ad16c9.tar.gz
micropython-be1ecb54e6be1ee5017a1a8aeca83d9e12ad16c9.zip
webassembly/api: Resolve thenables returned from runPythonAsync.
JavaScript semantics are such that the caller of an async function does not need to await that function for it to run to completion. This commit makes that behaviour also apply to top-level async Python code run via `runPythonAsync()`. Signed-off-by: Damien George <damien@micropython.org>
-rw-r--r--ports/webassembly/api.js6
-rw-r--r--tests/ports/webassembly/run_python_async_no_await.mjs24
-rw-r--r--tests/ports/webassembly/run_python_async_no_await.mjs.exp6
3 files changed, 35 insertions, 1 deletions
diff --git a/ports/webassembly/api.js b/ports/webassembly/api.js
index f3245451e4..c00edf575f 100644
--- a/ports/webassembly/api.js
+++ b/ports/webassembly/api.js
@@ -152,7 +152,11 @@ export async function loadMicroPython(options) {
[buf, len, value],
);
Module._free(buf);
- return proxy_convert_mp_to_js_obj_jsside_with_free(value);
+ const ret = proxy_convert_mp_to_js_obj_jsside_with_free(value);
+ if (ret instanceof PyProxyThenable) {
+ return Promise.resolve(ret);
+ }
+ return ret;
},
replInit() {
Module.ccall("mp_js_repl_init", "null", ["null"]);
diff --git a/tests/ports/webassembly/run_python_async_no_await.mjs b/tests/ports/webassembly/run_python_async_no_await.mjs
new file mode 100644
index 0000000000..19462d6e7f
--- /dev/null
+++ b/tests/ports/webassembly/run_python_async_no_await.mjs
@@ -0,0 +1,24 @@
+// Test runPythonAsync() without await'ing it.
+
+const mp = await (await import(process.argv[2])).loadMicroPython();
+
+globalThis.p = new Promise((resolve, reject) => {
+ setTimeout(() => {
+ resolve(123);
+ console.log("setTimeout resolved");
+ }, 100);
+});
+
+console.log(1);
+
+const ret = mp.runPythonAsync(`
+import js
+print("py 1")
+print("resolved value:", await js.p)
+print("py 2")
+`);
+
+// `ret` should be a Promise.
+console.log(2, ret);
+
+// Here, the Python async code should continue to run until completed.
diff --git a/tests/ports/webassembly/run_python_async_no_await.mjs.exp b/tests/ports/webassembly/run_python_async_no_await.mjs.exp
new file mode 100644
index 0000000000..1dbf7f95f4
--- /dev/null
+++ b/tests/ports/webassembly/run_python_async_no_await.mjs.exp
@@ -0,0 +1,6 @@
+1
+2 Promise { <pending> }
+py 1
+setTimeout resolved
+resolved value: 123
+py 2