@@ -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+
262282void 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