summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ports/webassembly/objjsproxy.c24
-rw-r--r--ports/webassembly/proxy_js.js31
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 {