Description
napi-inl.h
has a bunch of places where it allocates memory and leaves a // TODO ...
comment as to freeing it.
The following lists the places where the code allocates memory and leaves a TODO, and the solution for implementing the freeing of the memory:
- Creating a function
Use napi_wrap()
to associate the internal data with the function and provide a finalizer. - Filling out a function-valued property descriptor
Convert to anapi_value
-ed property descriptor where thenapi_value
is created using the code that creates functions, as modified above. - Filling out a function-valued or an accessor-valued instance property descriptor
After callingnapi_define_class()
, iterate over the property descriptors and, if any of them have theirmethor
,getter
, orsetter
field set to the callback provided by theObjectWrap
class, then attach a vector to the JavaScript class usingnapi_wrap()
and add deleters for the data of all the matching property descriptors. - Filling out an accessor-valued property descriptor.
No clear solution.
Normally the solution that applies to function-valued or accessor-valued instance property descriptors could also be used for accessor-valued property descriptors of plain objects, but plain objects are more likely to be wrapped by the user than class constructors, so using napi_wrap()
on them would take up a potentially valuable slot.
In N-API, before switching to v8::Private
for wrapping we used to do the wrapping by injecting an object into the prototype chain which had an internal slot, and then walking the prototype chain to find the object when asked to napi_unwrap()
. We could retain the napi_wrap()
slot on a plain object if we stored the deleters list in such an injected object, but retrieving the object becomes somewhat murky, because, as we walk the prototype chain looking for the injected object, the only way we can detect it is by the fact that it is a wrapped object. This does not tell us with certainty that the object was wrapped by us.
In N-API we solved the problem of identifying the object in the prototype chain which holds the wrapped data by maintaining a JavaScript class on the env
from which all such injected objects were derived. Thus, for each object encountered on the prototype chain we could check whether it was an instance of this class.
In node-addon-api maintaining such a class is untenable because we do not have the ability to attach classes to env
.
Another, perhaps cleaner, solution is to attach the data at a symbol-valued property on the object.
This problem would be rendered trivial by the napi_add_finalizer()
PR, but that code would not be available on all versions of Node.js supported by node-addon-api even once it lands.
So, the question remains: Where, on a plain object, to store the data created as part of defining accessor-valued properties, keeping in mind that this data is not visible to users?