diff options
| author | Damien George <damien@micropython.org> | 2024-05-06 12:26:20 +1000 |
|---|---|---|
| committer | Damien George <damien@micropython.org> | 2024-05-06 14:04:13 +1000 |
| commit | 9da63a343e08c2a453ff32801bb0d9545e538497 (patch) | |
| tree | 8a90c07778095d5cc90cbaab3668332c99a82cd9 | |
| parent | 9681a66c6b79a5f4721c74b756256336c47c9879 (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.c | 11 | ||||
| -rw-r--r-- | tests/ports/webassembly/run_python_async_error.mjs | 11 | ||||
| -rw-r--r-- | tests/ports/webassembly/run_python_async_error.mjs.exp | 5 |
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 + |
