Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Finalizer for napi_create_function() #313

Closed
gabrielschulhof opened this issue Apr 28, 2018 · 8 comments
Closed

Finalizer for napi_create_function() #313

gabrielschulhof opened this issue Apr 28, 2018 · 8 comments
Assignees

Comments

@gabrielschulhof
Copy link
Collaborator

When using napi_create_object() and napi_create_function(), you cannot
specify a finalizer callback, which probably should be allowed since it
can be useful to have.

The omission of a napi_finalize for napi_create_function() is of particular concern IMO.

Re: nodejs/node#14256

@gabrielschulhof
Copy link
Collaborator Author

... because it prevents one from being able to associate dynamic data with a function.

OTOH, how often to we dynamically associate a native function with a JS function? Most often we do so from Init() and then never again.

@gabrielschulhof gabrielschulhof self-assigned this May 10, 2018
@gabrielschulhof
Copy link
Collaborator Author

@nodejs/n-api I think the reason we don't have napi_finalize on napi_create_function() and napi_define_class() is that native-backed JS functions live forever – at least on V8. Similarly, IIRC, the v8::FunctionTemplate also lives forever.

IMO this also means we should discourage function factories. Of course, we still may want to add finalizers for the sake of other engines.

@gabrielschulhof
Copy link
Collaborator Author

If we were to implement this, we couldn't really test it on V8.

@mhdawson
Copy link
Member

Unless the team from ChakraCore thinks this is important, I'd probably focus on other priorities as opposed to adding a new method with the additional signature.

@gabrielschulhof
Copy link
Collaborator Author

@kfarnung @digitalinfinity what do you think?

@digitalinfinity
Copy link
Contributor

I agree with the sentiment that it could be useful, but I'm also of the view that we should generally wait for module authors to say that something is impossible for them to implement in N-API without a new API. Or in other words, I'm in favor of kicking this can down the road until someone convinces us otherwise.

@gabrielschulhof
Copy link
Collaborator Author

If we sacrifice the ability to wrap a function, we can already accomplish this:

void delete_data(napi_env env, void* data, void* hint) {
  free(data);
}

NativeData* data = malloc(*data);
napi_value js_function;

assert(napi_create_function(env,
                            "someMethod",
                            NAPI_AUTO_LENGTH,
                            data,
                            &js_function) == napi_ok);
assert(napi_wrap(env, js_function, data, delete_data, NULL, NULL) == napi_ok);

@gabrielschulhof
Copy link
Collaborator Author

In the API working group meeting of 2018-08-09 we agreed to add an API for adding finalizers so that data associated with dynamically created functions can itself be freed when the function is finalized while at the same time advising potential bug reporters to rely on napi_wrap() until the new API becomes supported on all supported versions of Node.js.

Relying on napi_wrap(), although not ideal, should not be a big sacrifice because, although it sacrifices the ability to wrap a function, it is usually not functions that are wrapped, but rather objects which are either plain or constructed using functions.

gabrielschulhof pushed a commit to gabrielschulhof/node that referenced this issue Sep 3, 2018
Add `napi_add_finalizer()`, which provides the ability to attach data
to an arbitrary object and be notified when that object is garbage-
collected so as to have an opportunity to delete the data previously
attached.

This differs from `napi_wrap()` in that it does not use up the private
slot on the object, and is therefore neither removable, nor retrievable
after the call to `napi_add_finalizer()`. It is assumed that the data
is accessible by other means, yet it must be tied to the lifetime of
the object. This is the case for data passed to a dynamically created
function which is itself heap-allocated and must therefore be freed
along with the function.

Fixes: nodejs/abi-stable-node#313
targos pushed a commit to nodejs/node that referenced this issue Sep 14, 2018
Add `napi_add_finalizer()`, which provides the ability to attach data
to an arbitrary object and be notified when that object is garbage-
collected so as to have an opportunity to delete the data previously
attached.

This differs from `napi_wrap()` in that it does not use up the private
slot on the object, and is therefore neither removable, nor retrievable
after the call to `napi_add_finalizer()`. It is assumed that the data
is accessible by other means, yet it must be tied to the lifetime of
the object. This is the case for data passed to a dynamically created
function which is itself heap-allocated and must therefore be freed
along with the function.

Fixes: nodejs/abi-stable-node#313
PR-URL: #22244
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
targos pushed a commit to nodejs/node that referenced this issue Sep 19, 2018
Add `napi_add_finalizer()`, which provides the ability to attach data
to an arbitrary object and be notified when that object is garbage-
collected so as to have an opportunity to delete the data previously
attached.

This differs from `napi_wrap()` in that it does not use up the private
slot on the object, and is therefore neither removable, nor retrievable
after the call to `napi_add_finalizer()`. It is assumed that the data
is accessible by other means, yet it must be tied to the lifetime of
the object. This is the case for data passed to a dynamically created
function which is itself heap-allocated and must therefore be freed
along with the function.

Fixes: nodejs/abi-stable-node#313
PR-URL: #22244
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
targos pushed a commit to nodejs/node that referenced this issue Sep 20, 2018
Add `napi_add_finalizer()`, which provides the ability to attach data
to an arbitrary object and be notified when that object is garbage-
collected so as to have an opportunity to delete the data previously
attached.

This differs from `napi_wrap()` in that it does not use up the private
slot on the object, and is therefore neither removable, nor retrievable
after the call to `napi_add_finalizer()`. It is assumed that the data
is accessible by other means, yet it must be tied to the lifetime of
the object. This is the case for data passed to a dynamically created
function which is itself heap-allocated and must therefore be freed
along with the function.

Fixes: nodejs/abi-stable-node#313
PR-URL: #22244
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
gabrielschulhof pushed a commit to gabrielschulhof/node that referenced this issue Sep 2, 2019
Add `napi_add_finalizer()`, which provides the ability to attach data
to an arbitrary object and be notified when that object is garbage-
collected so as to have an opportunity to delete the data previously
attached.

This differs from `napi_wrap()` in that it does not use up the private
slot on the object, and is therefore neither removable, nor retrievable
after the call to `napi_add_finalizer()`. It is assumed that the data
is accessible by other means, yet it must be tied to the lifetime of
the object. This is the case for data passed to a dynamically created
function which is itself heap-allocated and must therefore be freed
along with the function.

Fixes: nodejs/abi-stable-node#313
PR-URL: nodejs#22244
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
BethGriggs pushed a commit to nodejs/node that referenced this issue Sep 19, 2019
Add `napi_add_finalizer()`, which provides the ability to attach data
to an arbitrary object and be notified when that object is garbage-
collected so as to have an opportunity to delete the data previously
attached.

This differs from `napi_wrap()` in that it does not use up the private
slot on the object, and is therefore neither removable, nor retrievable
after the call to `napi_add_finalizer()`. It is assumed that the data
is accessible by other means, yet it must be tied to the lifetime of
the object. This is the case for data passed to a dynamically created
function which is itself heap-allocated and must therefore be freed
along with the function.

Fixes: nodejs/abi-stable-node#313
PR-URL: #22244
Backport-PR-URL: #28296
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants