feat(gobject, closure): wrap GObject with GC-able C++ wrapper to fix closures reference loop #375
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Instead of storing pointer to GObject directly in JS Object, store a
C++ GC-able wrapper class.
Replace a Persistent in Closure with a TracedReference. Then, keep track
of created Closure in GObjectWrapper. When GObjectWrapper is traced by
cppgc, trace those reference to tell cppgc they're still alive.
By not creating a Persistent, we prevent a reference loop where the
Persistent holds function, holds JS wrapper, holds GObject, holds
Persistent. When TracedReference, evetually the whole loop will not be
traced by cppgc, allowing the whole loop to be dropped.
This approach is inspired by PyGObject and utilize V8's Oilpan (also called cppgc), C++ garbage collector integrated with V8. This, however, means cutting support for NodeJS older than version 20.6. That said, NodeJS 18 has just became end-of-life (not counting commercial support), so maybe it's not that bad, compared to not leaking memory?
TODO:
gobject.cc(seeFIXMEin the code). Also consider movingGObjectWrapperclass declaration togobject.h.