diff options
| -rw-r--r-- | ports/webassembly/objjsproxy.c | 24 | ||||
| -rw-r--r-- | ports/webassembly/proxy_js.js | 31 |
2 files changed, 49 insertions, 6 deletions
diff --git a/ports/webassembly/objjsproxy.c b/ports/webassembly/objjsproxy.c index 05fe71516..5c09e003f 100644 --- a/ports/webassembly/objjsproxy.c +++ b/ports/webassembly/objjsproxy.c @@ -234,6 +234,22 @@ static mp_obj_t jsproxy_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const } } +EM_JS(void, proxy_js_free_obj, (int js_ref), { + if (js_ref >= PROXY_JS_REF_NUM_STATIC) { + proxy_js_ref[js_ref] = undefined; + if (js_ref < proxy_js_ref_next) { + proxy_js_ref_next = js_ref; + } + } +}); + +static mp_obj_t jsproxy___del__(mp_obj_t self_in) { + mp_obj_jsproxy_t *self = MP_OBJ_TO_PTR(self_in); + proxy_js_free_obj(self->ref); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(jsproxy___del___obj, jsproxy___del__); + static mp_obj_t jsproxy_reflect_construct(size_t n_args, const mp_obj_t *args) { int arg0 = mp_obj_jsproxy_get_ref(args[0]); n_args -= 1; @@ -274,7 +290,11 @@ void mp_obj_jsproxy_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] == MP_OBJ_NULL) { // Load attribute. uint32_t out[PVN]; - if (lookup_attr(self->ref, qstr_str(attr), out)) { + if (attr == MP_QSTR___del__) { + // For finaliser. + dest[0] = MP_OBJ_FROM_PTR(&jsproxy___del___obj); + dest[1] = self_in; + } else if (lookup_attr(self->ref, qstr_str(attr), out)) { dest[0] = proxy_convert_js_to_mp_obj_cside(out); } else if (attr == MP_QSTR_new) { // Special case to handle construction of JS objects. @@ -515,7 +535,7 @@ MP_DEFINE_CONST_OBJ_TYPE( ); mp_obj_t mp_obj_new_jsproxy(int ref) { - mp_obj_jsproxy_t *o = mp_obj_malloc(mp_obj_jsproxy_t, &mp_type_jsproxy); + mp_obj_jsproxy_t *o = mp_obj_malloc_with_finaliser(mp_obj_jsproxy_t, &mp_type_jsproxy); o->ref = ref; return MP_OBJ_FROM_PTR(o); } diff --git a/ports/webassembly/proxy_js.js b/ports/webassembly/proxy_js.js index 2a34f01a7..20f13f1d7 100644 --- a/ports/webassembly/proxy_js.js +++ b/ports/webassembly/proxy_js.js @@ -24,6 +24,9 @@ * THE SOFTWARE. */ +// Number of static entries at the start of proxy_js_ref. +const PROXY_JS_REF_NUM_STATIC = 2; + // These constants should match the constants in proxy_c.c. const PROXY_KIND_MP_EXCEPTION = -1; @@ -57,6 +60,28 @@ class PythonError extends Error { function proxy_js_init() { globalThis.proxy_js_ref = [globalThis, undefined]; + globalThis.proxy_js_ref_next = PROXY_JS_REF_NUM_STATIC; +} + +// js_obj cannot be undefined +function proxy_js_add_obj(js_obj) { + // Search for the first free slot in proxy_js_ref. + while (proxy_js_ref_next < proxy_js_ref.length) { + if (proxy_js_ref[proxy_js_ref_next] === undefined) { + // Free slot found, reuse it. + const id = proxy_js_ref_next; + ++proxy_js_ref_next; + proxy_js_ref[id] = js_obj; + return id; + } + ++proxy_js_ref_next; + } + + // No free slots, so grow proxy_js_ref by one (append at the end of the array). + const id = proxy_js_ref.length; + proxy_js_ref[id] = js_obj; + proxy_js_ref_next = proxy_js_ref.length; + return id; } function proxy_call_python(target, argumentsList) { @@ -147,8 +172,7 @@ function proxy_convert_js_to_mp_obj_jsside(js_obj, out) { Module.setValue(out + 4, js_obj._ref, "i32"); } else { kind = PROXY_KIND_JS_OBJECT; - const id = proxy_js_ref.length; - proxy_js_ref[id] = js_obj; + const id = proxy_js_add_obj(js_obj); Module.setValue(out + 4, id, "i32"); } Module.setValue(out + 0, kind, "i32"); @@ -161,8 +185,7 @@ function proxy_convert_js_to_mp_obj_jsside_force_double_proxy(js_obj, out) { js_obj instanceof PyProxyThenable ) { const kind = PROXY_KIND_JS_OBJECT; - const id = proxy_js_ref.length; - proxy_js_ref[id] = js_obj; + const id = proxy_js_add_obj(js_obj); Module.setValue(out + 4, id, "i32"); Module.setValue(out + 0, kind, "i32"); } else { |
