Content-Length: 498097 | pFad | http://github.com/micropython/micropython/commit/a67e326cb9753f53e14a42b347133a571f972140

C5 webassembly/proxy_c: Ensure objs thrown into generators are exceptions. · micropython/micropython@a67e326 · GitHub
Skip to content

Commit a67e326

Browse files
committed
webassembly/proxy_c: Ensure objs thrown into generators are exceptions.
This commit defines a new `JsException` exception type which is used on the Python side to wrap JavaScript errors. That's then used when a JavaScript Promise is rejected, and the reason is then converted to a `JsException` for the Python side to handle. This new exception is exposed as `jsffi.JsException`. Signed-off-by: Damien George <damien@micropython.org>
1 parent 3f34be6 commit a67e326

File tree

5 files changed

+64
-0
lines changed

5 files changed

+64
-0
lines changed

Diff for: ports/webassembly/modjsffi.c

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ static const mp_rom_map_elem_t mp_module_jsffi_globals_table[] = {
7979
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_jsffi) },
8080

8181
{ MP_ROM_QSTR(MP_QSTR_JsProxy), MP_ROM_PTR(&mp_type_jsproxy) },
82+
{ MP_ROM_QSTR(MP_QSTR_JsException), MP_ROM_PTR(&mp_type_JsException) },
8283
{ MP_ROM_QSTR(MP_QSTR_create_proxy), MP_ROM_PTR(&mp_jsffi_create_proxy_obj) },
8384
{ MP_ROM_QSTR(MP_QSTR_to_js), MP_ROM_PTR(&mp_jsffi_to_js_obj) },
8485
{ MP_ROM_QSTR(MP_QSTR_async_timeout_ms), MP_ROM_PTR(&mp_jsffi_async_timeout_ms_obj) },

Diff for: ports/webassembly/proxy_c.c

+35
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ enum {
5858
PROXY_KIND_JS_PYPROXY = 7,
5959
};
6060

61+
MP_DEFINE_EXCEPTION(JsException, Exception)
62+
6163
void proxy_c_init(void) {
6264
MP_STATE_PORT(proxy_c_ref) = mp_obj_new_list(0, NULL);
6365
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) {
120122
} else if (mp_obj_is_jsproxy(obj)) {
121123
kind = PROXY_KIND_MP_JSPROXY;
122124
out[1] = mp_obj_jsproxy_get_ref(obj);
125+
} else if (mp_obj_get_type(obj) == &mp_type_JsException) {
126+
mp_obj_exception_t *exc = MP_OBJ_TO_PTR(obj);
127+
if (exc->args->len > 0 && mp_obj_is_jsproxy(exc->args->items[0])) {
128+
kind = PROXY_KIND_MP_JSPROXY;
129+
out[1] = mp_obj_jsproxy_get_ref(exc->args->items[0]);
130+
} else {
131+
kind = PROXY_KIND_MP_OBJECT;
132+
out[1] = proxy_c_add_obj(obj);
133+
}
123134
} else {
124135
if (mp_obj_is_callable(obj)) {
125136
kind = PROXY_KIND_MP_CALLABLE;
@@ -288,6 +299,24 @@ void proxy_c_to_js_get_dict(uint32_t c_ref, uint32_t *out) {
288299
out[1] = (uintptr_t)map->table;
289300
}
290301

302+
EM_JS(void, js_get_error_info, (int jsref, uint32_t * out_name, uint32_t * out_message), {
303+
const error = proxy_js_ref[jsref];
304+
proxy_convert_js_to_mp_obj_jsside(error.name, out_name);
305+
proxy_convert_js_to_mp_obj_jsside(error.message, out_message);
306+
});
307+
308+
mp_obj_t mp_obj_jsproxy_make_js_exception(mp_obj_t error) {
309+
uint32_t out_name[PVN];
310+
uint32_t out_message[PVN];
311+
js_get_error_info(mp_obj_jsproxy_get_ref(error), out_name, out_message);
312+
mp_obj_t args[3] = {
313+
error,
314+
proxy_convert_js_to_mp_obj_cside(out_name),
315+
proxy_convert_js_to_mp_obj_cside(out_message),
316+
};
317+
return mp_obj_new_exception_args(&mp_type_JsException, MP_ARRAY_SIZE(args), args);
318+
}
319+
291320
/******************************************************************************/
292321
// Bridge Python iterator to JavaScript iterator protocol.
293322

@@ -371,6 +400,12 @@ static mp_obj_t proxy_resume_execute(mp_obj_t self_in, mp_obj_t send_value, mp_o
371400
if (send_value == mp_const_none) {
372401
send_value = MP_OBJ_NULL;
373402
}
403+
// Ensure that the `throw_value` is a proper Python exception instance.
404+
if (mp_obj_is_jsproxy(throw_value)) {
405+
throw_value = mp_obj_jsproxy_make_js_exception(throw_value);
406+
} else {
407+
throw_value = mp_make_raise_obj(throw_value);
408+
}
374409
} else {
375410
throw_value = MP_OBJ_NULL;
376411
}

Diff for: ports/webassembly/proxy_c.h

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ typedef struct _mp_obj_jsproxy_t {
3737
} mp_obj_jsproxy_t;
3838

3939
extern const mp_obj_type_t mp_type_jsproxy;
40+
extern const mp_obj_type_t mp_type_JsException;
4041

4142
void proxy_c_init(void);
4243
mp_obj_t proxy_convert_js_to_mp_obj_cside(uint32_t *value);

Diff for: tests/ports/webassembly/await_error_handling.mjs

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Test await'ing on a JavaScript async function that throws a JavaScript Error.
2+
3+
const mp = await (await import(process.argv[2])).loadMicroPython();
4+
5+
globalThis.foo = async () => {
6+
console.log(2);
7+
throw Error("test");
8+
};
9+
10+
await mp.runPythonAsync(`
11+
import js, jsffi
12+
print(1)
13+
try:
14+
await js.foo()
15+
except jsffi.JsException as er:
16+
error = er
17+
print(error)
18+
print(3)
19+
`);
20+
21+
const error = mp.globals.get("error");
22+
console.log(error instanceof Error, error.name, error.message);

Diff for: tests/ports/webassembly/await_error_handling.mjs.exp

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
1
2+
2
3+
(<JsProxy 6>, 'Error', 'test')
4+
3
5+
true Error test

0 commit comments

Comments
 (0)








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/micropython/micropython/commit/a67e326cb9753f53e14a42b347133a571f972140

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy