Skip to content

Commit 7c62fbe

Browse files
committed
webassembly/proxy_js: Promote Python thenable to a Promise.
Signed-off-by: Damien George <damien@micropython.org>
1 parent 3997532 commit 7c62fbe

3 files changed

Lines changed: 55 additions & 1 deletion

File tree

ports/webassembly/proxy_js.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,22 @@ function proxy_call_python(target, argumentsList) {
8989
if (argumentsList.length > 0) {
9090
Module._free(args);
9191
}
92-
return proxy_convert_mp_to_js_obj_jsside_with_free(value);
92+
const ret = proxy_convert_mp_to_js_obj_jsside_with_free(value);
93+
if (ret instanceof PyProxyThenable) {
94+
// In Python when an async function is called it creates the
95+
// corresponding "generator", which must then be executed at
96+
// the top level by an asyncio-like scheduler. In JavaScript
97+
// the semantics for async functions is that they are started
98+
// immediately (their non-async prefix code is executed immediately)
99+
// and only if they await do they return a Promise to delay the
100+
// execution of the remainder of the function.
101+
//
102+
// Emulate the JavaScript behaviour here by resolving the Python
103+
// async function. We assume that the caller who gets this
104+
// return is JavaScript.
105+
return Promise.resolve(ret);
106+
}
107+
return ret;
93108
}
94109

95110
function proxy_convert_js_to_mp_obj_jsside(js_obj, out) {
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Test using Python functions as JS callbacks.
2+
3+
const mp = await (await import(process.argv[2])).loadMicroPython();
4+
5+
globalThis.asyncTimeout = (ms) =>
6+
new Promise((resolve) => setTimeout(resolve, ms));
7+
8+
mp.runPython(`
9+
import js
10+
11+
def f0():
12+
print("f0 run")
13+
14+
async def f1():
15+
print("f1 run")
16+
17+
async def f2():
18+
print("f2 start")
19+
await js.asyncTimeout(0)
20+
print("f2 end")
21+
22+
async def f3():
23+
print("f3 start")
24+
await f2()
25+
print("f3 end")
26+
27+
js.setTimeout(f0, 0)
28+
js.setTimeout(f1, 50)
29+
js.setTimeout(f2, 100)
30+
js.setTimeout(f3, 150)
31+
`);
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
f0 run
2+
f1 run
3+
f2 start
4+
f2 end
5+
f3 start
6+
f2 start
7+
f2 end
8+
f3 end

0 commit comments

Comments
 (0)