summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ports/webassembly/modjsffi.c1
-rw-r--r--ports/webassembly/proxy_c.c35
-rw-r--r--ports/webassembly/proxy_c.h1
-rw-r--r--tests/ports/webassembly/await_error_handling.mjs22
-rw-r--r--tests/ports/webassembly/await_error_handling.mjs.exp5
5 files changed, 64 insertions, 0 deletions
diff --git a/ports/webassembly/modjsffi.c b/ports/webassembly/modjsffi.c
index cb2f578f8..c77d899fb 100644
--- a/ports/webassembly/modjsffi.c
+++ b/ports/webassembly/modjsffi.c
@@ -79,6 +79,7 @@ static const mp_rom_map_elem_t mp_module_jsffi_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_jsffi) },
{ MP_ROM_QSTR(MP_QSTR_JsProxy), MP_ROM_PTR(&mp_type_jsproxy) },
+ { MP_ROM_QSTR(MP_QSTR_JsException), MP_ROM_PTR(&mp_type_JsException) },
{ MP_ROM_QSTR(MP_QSTR_create_proxy), MP_ROM_PTR(&mp_jsffi_create_proxy_obj) },
{ MP_ROM_QSTR(MP_QSTR_to_js), MP_ROM_PTR(&mp_jsffi_to_js_obj) },
{ MP_ROM_QSTR(MP_QSTR_async_timeout_ms), MP_ROM_PTR(&mp_jsffi_async_timeout_ms_obj) },
diff --git a/ports/webassembly/proxy_c.c b/ports/webassembly/proxy_c.c
index 4e2fdc8f2..3097d6d3a 100644
--- a/ports/webassembly/proxy_c.c
+++ b/ports/webassembly/proxy_c.c
@@ -58,6 +58,8 @@ enum {
PROXY_KIND_JS_PYPROXY = 7,
};
+MP_DEFINE_EXCEPTION(JsException, Exception)
+
void proxy_c_init(void) {
MP_STATE_PORT(proxy_c_ref) = mp_obj_new_list(0, NULL);
mp_obj_list_append(MP_STATE_PORT(proxy_c_ref), MP_OBJ_NULL);
@@ -120,6 +122,15 @@ void proxy_convert_mp_to_js_obj_cside(mp_obj_t obj, uint32_t *out) {
} else if (mp_obj_is_jsproxy(obj)) {
kind = PROXY_KIND_MP_JSPROXY;
out[1] = mp_obj_jsproxy_get_ref(obj);
+ } else if (mp_obj_get_type(obj) == &mp_type_JsException) {
+ mp_obj_exception_t *exc = MP_OBJ_TO_PTR(obj);
+ if (exc->args->len > 0 && mp_obj_is_jsproxy(exc->args->items[0])) {
+ kind = PROXY_KIND_MP_JSPROXY;
+ out[1] = mp_obj_jsproxy_get_ref(exc->args->items[0]);
+ } else {
+ kind = PROXY_KIND_MP_OBJECT;
+ out[1] = proxy_c_add_obj(obj);
+ }
} else {
if (mp_obj_is_callable(obj)) {
kind = PROXY_KIND_MP_CALLABLE;
@@ -288,6 +299,24 @@ void proxy_c_to_js_get_dict(uint32_t c_ref, uint32_t *out) {
out[1] = (uintptr_t)map->table;
}
+EM_JS(void, js_get_error_info, (int jsref, uint32_t * out_name, uint32_t * out_message), {
+ const error = proxy_js_ref[jsref];
+ proxy_convert_js_to_mp_obj_jsside(error.name, out_name);
+ proxy_convert_js_to_mp_obj_jsside(error.message, out_message);
+});
+
+mp_obj_t mp_obj_jsproxy_make_js_exception(mp_obj_t error) {
+ uint32_t out_name[PVN];
+ uint32_t out_message[PVN];
+ js_get_error_info(mp_obj_jsproxy_get_ref(error), out_name, out_message);
+ mp_obj_t args[3] = {
+ error,
+ proxy_convert_js_to_mp_obj_cside(out_name),
+ proxy_convert_js_to_mp_obj_cside(out_message),
+ };
+ return mp_obj_new_exception_args(&mp_type_JsException, MP_ARRAY_SIZE(args), args);
+}
+
/******************************************************************************/
// Bridge Python iterator to JavaScript iterator protocol.
@@ -371,6 +400,12 @@ static mp_obj_t proxy_resume_execute(mp_obj_t self_in, mp_obj_t send_value, mp_o
if (send_value == mp_const_none) {
send_value = MP_OBJ_NULL;
}
+ // Ensure that the `throw_value` is a proper Python exception instance.
+ if (mp_obj_is_jsproxy(throw_value)) {
+ throw_value = mp_obj_jsproxy_make_js_exception(throw_value);
+ } else {
+ throw_value = mp_make_raise_obj(throw_value);
+ }
} else {
throw_value = MP_OBJ_NULL;
}
diff --git a/ports/webassembly/proxy_c.h b/ports/webassembly/proxy_c.h
index 3e68d2504..751d14332 100644
--- a/ports/webassembly/proxy_c.h
+++ b/ports/webassembly/proxy_c.h
@@ -37,6 +37,7 @@ typedef struct _mp_obj_jsproxy_t {
} mp_obj_jsproxy_t;
extern const mp_obj_type_t mp_type_jsproxy;
+extern const mp_obj_type_t mp_type_JsException;
void proxy_c_init(void);
mp_obj_t proxy_convert_js_to_mp_obj_cside(uint32_t *value);
diff --git a/tests/ports/webassembly/await_error_handling.mjs b/tests/ports/webassembly/await_error_handling.mjs
new file mode 100644
index 000000000..067bc2513
--- /dev/null
+++ b/tests/ports/webassembly/await_error_handling.mjs
@@ -0,0 +1,22 @@
+// Test await'ing on a JavaScript async function that throws a JavaScript Error.
+
+const mp = await (await import(process.argv[2])).loadMicroPython();
+
+globalThis.foo = async () => {
+ console.log(2);
+ throw Error("test");
+};
+
+await mp.runPythonAsync(`
+import js, jsffi
+print(1)
+try:
+ await js.foo()
+except jsffi.JsException as er:
+ error = er
+print(error)
+print(3)
+`);
+
+const error = mp.globals.get("error");
+console.log(error instanceof Error, error.name, error.message);
diff --git a/tests/ports/webassembly/await_error_handling.mjs.exp b/tests/ports/webassembly/await_error_handling.mjs.exp
new file mode 100644
index 000000000..149f8914d
--- /dev/null
+++ b/tests/ports/webassembly/await_error_handling.mjs.exp
@@ -0,0 +1,5 @@
+1
+2
+(<JsProxy 6>, 'Error', 'test')
+3
+true Error test