summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ports/webassembly/proxy_js.js17
-rw-r--r--tests/ports/webassembly/fun_py_callback_js.mjs31
-rw-r--r--tests/ports/webassembly/fun_py_callback_js.mjs.exp8
3 files changed, 55 insertions, 1 deletions
diff --git a/ports/webassembly/proxy_js.js b/ports/webassembly/proxy_js.js
index 7a0a1bbe8..1f60bf41e 100644
--- a/ports/webassembly/proxy_js.js
+++ b/ports/webassembly/proxy_js.js
@@ -89,7 +89,22 @@ function proxy_call_python(target, argumentsList) {
if (argumentsList.length > 0) {
Module._free(args);
}
- 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) {
+ // In Python when an async function is called it creates the
+ // corresponding "generator", which must then be executed at
+ // the top level by an asyncio-like scheduler. In JavaScript
+ // the semantics for async functions is that they are started
+ // immediately (their non-async prefix code is executed immediately)
+ // and only if they await do they return a Promise to delay the
+ // execution of the remainder of the function.
+ //
+ // Emulate the JavaScript behaviour here by resolving the Python
+ // async function. We assume that the caller who gets this
+ // return is JavaScript.
+ return Promise.resolve(ret);
+ }
+ return ret;
}
function proxy_convert_js_to_mp_obj_jsside(js_obj, out) {
diff --git a/tests/ports/webassembly/fun_py_callback_js.mjs b/tests/ports/webassembly/fun_py_callback_js.mjs
new file mode 100644
index 000000000..5541e7a46
--- /dev/null
+++ b/tests/ports/webassembly/fun_py_callback_js.mjs
@@ -0,0 +1,31 @@
+// Test using Python functions as JS callbacks.
+
+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")
+
+async def f1():
+ print("f1 run")
+
+async def f2():
+ print("f2 start")
+ await js.asyncTimeout(0)
+ print("f2 end")
+
+async def f3():
+ print("f3 start")
+ await f2()
+ print("f3 end")
+
+js.setTimeout(f0, 0)
+js.setTimeout(f1, 50)
+js.setTimeout(f2, 100)
+js.setTimeout(f3, 150)
+`);
diff --git a/tests/ports/webassembly/fun_py_callback_js.mjs.exp b/tests/ports/webassembly/fun_py_callback_js.mjs.exp
new file mode 100644
index 000000000..732062c84
--- /dev/null
+++ b/tests/ports/webassembly/fun_py_callback_js.mjs.exp
@@ -0,0 +1,8 @@
+f0 run
+f1 run
+f2 start
+f2 end
+f3 start
+f2 start
+f2 end
+f3 end