Skip to content

Commit edb60a3

Browse files
committed
Add weak callback for cleaning the js_object_cache
1 parent 405653f commit edb60a3

File tree

2 files changed

+27
-0
lines changed

2 files changed

+27
-0
lines changed

v8py/context.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ PyObject *context_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) {
114114

115115
void context_dealloc(context_c *self) {
116116
self->js_context.Reset();
117+
PyDict_Clear(self->js_object_cache);
117118
Py_DECREF(self->js_object_cache);
118119
Py_DECREF(self->scripts);
119120
Py_TYPE(self)->tp_free((PyObject *) self);

v8py/pyclass.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,9 +259,34 @@ Local<Function> py_class_get_constructor(py_class *self, Local<Context> context)
259259
return hs.Escape(function);
260260
}
261261

262+
void py_class_object_weak_callback(const WeakCallbackInfo<Persistent<Object>> &info) {
263+
HandleScope hs(isolate);
264+
Local<Object> js_object = info.GetParameter()->Get(isolate);
265+
266+
assert(js_object->GetInternalField(0) == IZ_DAT_OBJECT);
267+
PyObject *py_object = (PyObject *) js_object->GetInternalField(1).As<External>()->Value();
268+
PyObject *js_object_cache = (PyObject *) js_object->GetInternalField(2).As<External>()->Value();
269+
270+
if (PyDict_Size(js_object_cache) != 0) {
271+
if (PyMapping_HasKey(js_object_cache, py_object)) {
272+
PyObject_DelItem(js_object_cache, py_object);
273+
}
274+
}
275+
Py_DECREF(js_object_cache);
276+
277+
info.GetParameter()->Reset();
278+
delete info.GetParameter();
279+
}
280+
281+
262282
void py_class_init_js_object(Local<Object> js_object, PyObject *py_object, Local<Context> context) {
263283
js_object->SetInternalField(0, IZ_DAT_OBJECT);
264284
js_object->SetInternalField(1, External::New(isolate, py_object));
285+
// the v8::Context will get garbage collected before the JS objects,
286+
// so for the weak callback we keep a pointer to the object cache
287+
context_c *py_ctx = (context_c *)context->GetEmbedderData(CONTEXT_OBJECT_SLOT).As<External>()->Value();
288+
Py_INCREF(py_ctx->js_object_cache);
289+
js_object->SetInternalField(2, External::New(isolate, py_ctx->js_object_cache));
265290

266291
// find out if the object is supposed to inherit from Error
267292
// the information is in an internal field on the last prototype
@@ -280,6 +305,7 @@ void py_class_init_js_object(Local<Object> js_object, PyObject *py_object, Local
280305
}
281306

282307
Persistent<Object> *obj_handle = new Persistent<Object>(isolate, js_object);
308+
obj_handle->SetWeak(obj_handle, py_class_object_weak_callback, WeakCallbackType::kFinalizer);
283309

284310
context_set_cached_jsobject(context, py_object, js_object);
285311
}

0 commit comments

Comments
 (0)