n-api: delete callback bundle via reference
We should strive to use weak persistent references consistently throughout the code, since using `v8::Persistent` directly results in having to change many sites in the code when the way we use it changes. N-API uses `v8impl::Reference` internally when maintaining a weak persistent reference is necessary. So far, `v8impl::CallbackBundle` was using `v8::Persistent` directly in order to weakly reference the JS function backed by a N-API callback. The change introduced here reduces `v8impl::CallbackBundle` to a simple structure and uses a `v8impl::Reference` to weakly reference the N-API callback with which it is associated. The structure is freed by the `napi_finalize` callback of the `v8impl::Reference`. This brings N-API use of `v8::Persistent` completely under the `v8impl::Reference` umbrella, rendering our use of weak references consistent. PR-URL: https://github.com/nodejs/node/pull/29479 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Anna Henningsen <anna@addaleax.net>
This commit is contained in:
parent
ab05d43083
commit
1f4f2b488e
@ -379,27 +379,10 @@ inline static napi_status Unwrap(napi_env env,
|
||||
// Ref: benchmark/misc/function_call
|
||||
// Discussion (incl. perf. data): https://github.com/nodejs/node/pull/21072
|
||||
struct CallbackBundle {
|
||||
// Bind the lifecycle of `this` C++ object to a JavaScript object.
|
||||
// We never delete a CallbackBundle C++ object directly.
|
||||
void BindLifecycleTo(v8::Isolate* isolate, v8::Local<v8::Value> target) {
|
||||
handle.Reset(isolate, target);
|
||||
handle.SetWeak(this, WeakCallback, v8::WeakCallbackType::kParameter);
|
||||
}
|
||||
|
||||
napi_env env; // Necessary to invoke C++ NAPI callback
|
||||
void* cb_data; // The user provided callback data
|
||||
napi_callback function_or_getter;
|
||||
napi_callback setter;
|
||||
v8impl::Persistent<v8::Value> handle; // Die with this JavaScript object
|
||||
|
||||
private:
|
||||
static void WeakCallback(v8::WeakCallbackInfo<CallbackBundle> const& info) {
|
||||
// Use the "WeakCallback mechanism" to delete the C++ `bundle` object.
|
||||
// This will be called when the v8::External containing `this` pointer
|
||||
// is being GC-ed.
|
||||
CallbackBundle* bundle = info.GetParameter();
|
||||
delete bundle;
|
||||
}
|
||||
};
|
||||
|
||||
// Base class extended by classes that wrap V8 function and property callback
|
||||
@ -580,6 +563,11 @@ class SetterCallbackWrapper
|
||||
const v8::Local<v8::Value>& _value;
|
||||
};
|
||||
|
||||
static void DeleteCallbackBundle(napi_env env, void* data, void* hint) {
|
||||
CallbackBundle* bundle = static_cast<CallbackBundle*>(data);
|
||||
delete bundle;
|
||||
}
|
||||
|
||||
// Creates an object to be made available to the static function callback
|
||||
// wrapper, used to retrieve the native callback function and data pointer.
|
||||
static
|
||||
@ -591,7 +579,7 @@ v8::Local<v8::Value> CreateFunctionCallbackData(napi_env env,
|
||||
bundle->cb_data = data;
|
||||
bundle->env = env;
|
||||
v8::Local<v8::Value> cbdata = v8::External::New(env->isolate, bundle);
|
||||
bundle->BindLifecycleTo(env->isolate, cbdata);
|
||||
Reference::New(env, cbdata, 0, true, DeleteCallbackBundle, bundle, nullptr);
|
||||
|
||||
return cbdata;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user