summaryrefslogtreecommitdiff
path: root/src/node_api.cc
diff options
context:
space:
mode:
authorGabriel Schulhof <gabriel.schulhof@intel.com>2019-07-14 17:21:13 -0700
committerGabriel Schulhof <gabriel.schulhof@intel.com>2019-07-25 16:53:07 -0700
commit5030e81ce305cc6bc5a1e17dd0ef8a9c761f035b (patch)
tree5678055a6286b9e8a452b83b05398b5fad51ee5b /src/node_api.cc
parente9ea8eaf7a77cf9b6f164cef92283c5eb99688cc (diff)
downloadandroid-node-v8-5030e81ce305cc6bc5a1e17dd0ef8a9c761f035b.tar.gz
android-node-v8-5030e81ce305cc6bc5a1e17dd0ef8a9c761f035b.tar.bz2
android-node-v8-5030e81ce305cc6bc5a1e17dd0ef8a9c761f035b.zip
n-api: add APIs for per-instance state management
Adds `napi_set_instance_data()` and `napi_get_instance_data()`, which allow native addons to store their data on and retrieve their data from `napi_env`. `napi_set_instance_data()` accepts a finalizer which is called when the `node::Environment()` is destroyed. This entails rendering the `napi_env` local to each add-on. Fixes: https://github.com/nodejs/abi-stable-node/issues/378 PR-URL: https://github.com/nodejs/node/pull/28682 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Diffstat (limited to 'src/node_api.cc')
-rw-r--r--src/node_api.cc74
1 files changed, 23 insertions, 51 deletions
diff --git a/src/node_api.cc b/src/node_api.cc
index a9f26e551d..4947293063 100644
--- a/src/node_api.cc
+++ b/src/node_api.cc
@@ -46,9 +46,9 @@ class BufferFinalizer : private Finalizer {
v8::HandleScope handle_scope(finalizer->_env->isolate);
v8::Context::Scope context_scope(finalizer->_env->context());
- NapiCallIntoModuleThrow(finalizer->_env, [&]() {
+ finalizer->_env->CallIntoModuleThrow([&](napi_env env) {
finalizer->_finalize_callback(
- finalizer->_env,
+ env,
finalizer->_finalize_data,
finalizer->_finalize_hint);
});
@@ -59,44 +59,22 @@ class BufferFinalizer : private Finalizer {
}
};
-static inline napi_env GetEnv(v8::Local<v8::Context> context) {
+static inline napi_env NewEnv(v8::Local<v8::Context> context) {
node_napi_env result;
- auto isolate = context->GetIsolate();
- auto global = context->Global();
-
- // In the case of the string for which we grab the private and the value of
- // the private on the global object we can call .ToLocalChecked() directly
- // because we need to stop hard if either of them is empty.
- //
- // Re https://github.com/nodejs/node/pull/14217#discussion_r128775149
- auto value = global->GetPrivate(context, NAPI_PRIVATE_KEY(context, env))
- .ToLocalChecked();
-
- if (value->IsExternal()) {
- result = static_cast<node_napi_env>(value.As<v8::External>()->Value());
- } else {
- result = new node_napi_env__(context);
- auto external = v8::External::New(isolate, result);
-
- // We must also stop hard if the result of assigning the env to the global
- // is either nothing or false.
- CHECK(global->SetPrivate(context, NAPI_PRIVATE_KEY(context, env), external)
- .FromJust());
-
- // TODO(addaleax): There was previously code that tried to delete the
- // napi_env when its v8::Context was garbage collected;
- // However, as long as N-API addons using this napi_env are in place,
- // the Context needs to be accessible and alive.
- // Ideally, we'd want an on-addon-unload hook that takes care of this
- // once all N-API addons using this napi_env are unloaded.
- // For now, a per-Environment cleanup hook is the best we can do.
- result->node_env()->AddCleanupHook(
- [](void* arg) {
- static_cast<napi_env>(arg)->Unref();
- },
- static_cast<void*>(result));
- }
+ result = new node_napi_env__(context);
+ // TODO(addaleax): There was previously code that tried to delete the
+ // napi_env when its v8::Context was garbage collected;
+ // However, as long as N-API addons using this napi_env are in place,
+ // the Context needs to be accessible and alive.
+ // Ideally, we'd want an on-addon-unload hook that takes care of this
+ // once all N-API addons using this napi_env are unloaded.
+ // For now, a per-Environment cleanup hook is the best we can do.
+ result->node_env()->AddCleanupHook(
+ [](void* arg) {
+ static_cast<napi_env>(arg)->Unref();
+ },
+ static_cast<void*>(result));
return result;
}
@@ -325,7 +303,7 @@ class ThreadSafeFunction : public node::AsyncResource {
v8::Local<v8::Function>::New(env->isolate, ref);
js_callback = v8impl::JsValueFromV8LocalValue(js_cb);
}
- NapiCallIntoModuleThrow(env, [&]() {
+ env->CallIntoModuleThrow([&](napi_env env) {
call_js_cb(env, js_callback, context, data);
});
}
@@ -346,7 +324,7 @@ class ThreadSafeFunction : public node::AsyncResource {
v8::HandleScope scope(env->isolate);
if (finalize_cb) {
CallbackScope cb_scope(this);
- NapiCallIntoModuleThrow(env, [&]() {
+ env->CallIntoModuleThrow([&](napi_env env) {
finalize_cb(env, finalize_data, context);
});
}
@@ -481,10 +459,10 @@ void napi_module_register_by_symbol(v8::Local<v8::Object> exports,
// Create a new napi_env for this module or reference one if a pre-existing
// one is found.
- napi_env env = v8impl::GetEnv(context);
+ napi_env env = v8impl::NewEnv(context);
napi_value _exports;
- NapiCallIntoModuleThrow(env, [&]() {
+ env->CallIntoModuleThrow([&](napi_env env) {
_exports = init(env, v8impl::JsValueFromV8LocalValue(exports));
});
@@ -889,15 +867,9 @@ class Work : public node::AsyncResource, public node::ThreadPoolWork {
CallbackScope callback_scope(this);
- // We have to back up the env here because the `NAPI_CALL_INTO_MODULE` macro
- // makes use of it after the call into the module completes, but the module
- // may have deallocated **this**, and along with it the place where _env is
- // stored.
- napi_env env = _env;
-
- NapiCallIntoModule(env, [&]() {
- _complete(_env, ConvertUVErrorCode(status), _data);
- }, [env](v8::Local<v8::Value> local_err) {
+ _env->CallIntoModule([&](napi_env env) {
+ _complete(env, ConvertUVErrorCode(status), _data);
+ }, [](napi_env env, v8::Local<v8::Value> local_err) {
// If there was an unhandled exception in the complete callback,
// report it as a fatal exception. (There is no JavaScript on the
// callstack that can possibly handle it.)