mirror of
https://github.com/W3SLAV/micropython.git
synced 2025-06-19 12:05:32 -04:00
webassembly: Add C-level finaliser to JsProxy object.
And clear the corresponding `proxy_js_ref[js_ref]` entry when the finaliser runs. This then allows the JavaScript side to (eventually) free the corresponding JavaScript object. Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
parent
c0ca4bb85f
commit
5c7a414574
@ -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) {
|
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]);
|
int arg0 = mp_obj_jsproxy_get_ref(args[0]);
|
||||||
n_args -= 1;
|
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) {
|
if (dest[0] == MP_OBJ_NULL) {
|
||||||
// Load attribute.
|
// Load attribute.
|
||||||
uint32_t out[PVN];
|
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);
|
dest[0] = proxy_convert_js_to_mp_obj_cside(out);
|
||||||
} else if (attr == MP_QSTR_new) {
|
} else if (attr == MP_QSTR_new) {
|
||||||
// Special case to handle construction of JS objects.
|
// 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_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;
|
o->ref = ref;
|
||||||
return MP_OBJ_FROM_PTR(o);
|
return MP_OBJ_FROM_PTR(o);
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,9 @@
|
|||||||
* THE SOFTWARE.
|
* 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.
|
// These constants should match the constants in proxy_c.c.
|
||||||
|
|
||||||
const PROXY_KIND_MP_EXCEPTION = -1;
|
const PROXY_KIND_MP_EXCEPTION = -1;
|
||||||
@ -57,6 +60,28 @@ class PythonError extends Error {
|
|||||||
|
|
||||||
function proxy_js_init() {
|
function proxy_js_init() {
|
||||||
globalThis.proxy_js_ref = [globalThis, undefined];
|
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) {
|
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");
|
Module.setValue(out + 4, js_obj._ref, "i32");
|
||||||
} else {
|
} else {
|
||||||
kind = PROXY_KIND_JS_OBJECT;
|
kind = PROXY_KIND_JS_OBJECT;
|
||||||
const id = proxy_js_ref.length;
|
const id = proxy_js_add_obj(js_obj);
|
||||||
proxy_js_ref[id] = js_obj;
|
|
||||||
Module.setValue(out + 4, id, "i32");
|
Module.setValue(out + 4, id, "i32");
|
||||||
}
|
}
|
||||||
Module.setValue(out + 0, kind, "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
|
js_obj instanceof PyProxyThenable
|
||||||
) {
|
) {
|
||||||
const kind = PROXY_KIND_JS_OBJECT;
|
const kind = PROXY_KIND_JS_OBJECT;
|
||||||
const id = proxy_js_ref.length;
|
const id = proxy_js_add_obj(js_obj);
|
||||||
proxy_js_ref[id] = js_obj;
|
|
||||||
Module.setValue(out + 4, id, "i32");
|
Module.setValue(out + 4, id, "i32");
|
||||||
Module.setValue(out + 0, kind, "i32");
|
Module.setValue(out + 0, kind, "i32");
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user