summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien George <damien@micropython.org>2024-05-06 12:26:20 +1000
committerDamien George <damien@micropython.org>2024-05-06 14:04:13 +1000
commit9da63a343e08c2a453ff32801bb0d9545e538497 (patch)
tree8a90c07778095d5cc90cbaab3668332c99a82cd9
parent9681a66c6b79a5f4721c74b756256336c47c9879 (diff)
webassembly/proxy_c: Reject promises with a PythonError instance.
The `reason` in a rejected promise should be an instance of `Error`. That leads to better error messages on the JavaScript side. Signed-off-by: Damien George <damien@micropython.org>
-rw-r--r--ports/webassembly/proxy_c.c11
-rw-r--r--tests/ports/webassembly/run_python_async_error.mjs11
-rw-r--r--tests/ports/webassembly/run_python_async_error.mjs.exp5
3 files changed, 25 insertions, 2 deletions
diff --git a/ports/webassembly/proxy_c.c b/ports/webassembly/proxy_c.c
index ebf670b56..9b32b6450 100644
--- a/ports/webassembly/proxy_c.c
+++ b/ports/webassembly/proxy_c.c
@@ -297,7 +297,14 @@ EM_JS(void, js_then_resolve, (uint32_t * ret_value, uint32_t * resolve, uint32_t
});
EM_JS(void, js_then_reject, (uint32_t * ret_value, uint32_t * resolve, uint32_t * reject), {
- const ret_value_js = proxy_convert_mp_to_js_obj_jsside(ret_value);
+ // The ret_value object should be a Python exception. Convert it to a
+ // JavaScript PythonError and pass it as the reason to reject the promise.
+ let ret_value_js;
+ try {
+ ret_value_js = proxy_convert_mp_to_js_obj_jsside(ret_value);
+ } catch(error) {
+ ret_value_js = error;
+ }
const resolve_js = proxy_convert_mp_to_js_obj_jsside(resolve);
const reject_js = proxy_convert_mp_to_js_obj_jsside(reject);
reject_js(ret_value_js);
@@ -359,7 +366,7 @@ static mp_obj_t proxy_resume_execute(mp_obj_t self_in, mp_obj_t send_value, mp_o
} else { // ret_kind == MP_VM_RETURN_EXCEPTION;
// Pass the exception through as an object to reject the promise (don't raise/throw it).
uint32_t out_ret_value[PVN];
- proxy_convert_mp_to_js_obj_cside(ret_value, out_ret_value);
+ proxy_convert_mp_to_js_exc_cside(ret_value, out_ret_value);
js_then_reject(out_ret_value, out_resolve, out_reject);
return mp_const_none;
}
diff --git a/tests/ports/webassembly/run_python_async_error.mjs b/tests/ports/webassembly/run_python_async_error.mjs
new file mode 100644
index 000000000..ce4db0ff0
--- /dev/null
+++ b/tests/ports/webassembly/run_python_async_error.mjs
@@ -0,0 +1,11 @@
+// Test raising an exception in async Python code running in runPythonAsync,
+// that the JavaScript-level promise is rejected with a PythonError.
+
+const mp = await (await import(process.argv[2])).loadMicroPython();
+
+try {
+ await mp.runPythonAsync("await fail");
+} catch (error) {
+ console.log(error.name, error.type);
+ console.log(error.message);
+}
diff --git a/tests/ports/webassembly/run_python_async_error.mjs.exp b/tests/ports/webassembly/run_python_async_error.mjs.exp
new file mode 100644
index 000000000..c77de4bb3
--- /dev/null
+++ b/tests/ports/webassembly/run_python_async_error.mjs.exp
@@ -0,0 +1,5 @@
+PythonError NameError
+Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+NameError: name 'fail' isn't defined
+