8000
We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
There was an error while loading. Please reload this page.
1 parent 06b1273 commit 86b101cCopy full SHA for 86b101c
src/node_api.cc
@@ -712,6 +712,45 @@ bool FindWrapper(v8::Local<v8::Object> obj,
712
return true;
713
}
714
715
+static void DeleteEnv(napi_env env, void* data, void* hint) {
716
+ delete env;
717
+}
718
+
719
+napi_env GetEnv(v8::Local<v8::Context> context) {
720
+ napi_env result;
721
722
+ auto isolate = context->GetIsolate();
723
+ auto global = context->Global();
724
725
+ // In the case of the string for which we grab the private and the value of
726
+ // the private on the global object we can call .ToLocalChecked() directly
727
+ // because we need to stop hard if either of them is empty.
728
+ //
729
+ // Re https://github.com/nodejs/node/pull/14217#discussion_r128775149
730
+ auto key = v8::Private::ForApi(isolate,
731
+ v8::String::NewFromOneByte(isolate,
732
+ reinterpret_cast<const uint8_t*>("N-API Environment"),
733
+ v8::NewStringType::kInternalized).ToLocalChecked());
734
+ auto value = global->GetPrivate(context, key).ToLocalChecked();
735
736
+ if (value->IsExternal()) {
737
+ result = static_cast<napi_env>(value.As<v8::External>()->Value());
738
+ } else {
739
+ result = new napi_env__(isolate);
740
+ auto external = v8::External::New(isolate, result);
741
742
+ // We must also stop hard if the result of assigning the env to the global
743
+ // is either nothing or false.
744
+ CHECK(global->SetPrivate(context, key, external).FromJust());
745
746
+ // Create a self-destructing reference to external that will get rid of the
747
+ // napi_env when external goes out of scope.
748
+ Reference::New(result, external, 0, true, DeleteEnv, nullptr, nullptr);
749
+ }
750
751
+ return result;
752
753
754
} // end of namespace v8impl
755
756
// Intercepts the Node-V8 module registration callback. Converts parameters
@@ -723,9 +762,9 @@ void napi_module_register_cb(v8::Local<v8::Object> exports,
762
void* priv) {
763
napi_module* mod = static_cast<napi_module*>(priv);
764
- // Create a new napi_env for this module. Once module unloading is supported
- // we shall have to call delete on this object from there.
- napi_env env = new napi_env__(context->GetIsolate());
765
+ // Create a new napi_env for this module or reference one if a pre-existing
766
+ // one is found.
767
+ napi_env env = v8impl::GetEnv(context);
768
769
mod->nm_register_func(
770
env,
test/addons-napi/test_env_sharing/binding.gyp
@@ -0,0 +1,12 @@
1
+{
2
+ "targets": [
3
+ {
4
+ "target_name": "store_env",
5
+ "sources": [ "store_env.c" ]
6
+ },
7
8
+ "target_name": "compare_env",
9
+ "sources": [ "compare_env.c" ]
10
11
+ ]
12
test/addons-napi/test_env_sharing/compare_env.c
@@ -0,0 +1,22 @@
+#include <node_api.h>
+#include "../common.h"
+napi_value compare(napi_env env, napi_callback_info info) {
+ napi_value external;
+ size_t argc = 1;
+ void* data;
+ napi_value return_value;
+ NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &external, NULL, NULL));
+ NAPI_CALL(env, napi_get_value_external(env, external, &data));
+ NAPI_CALL(env, napi_get_boolean(env, ((napi_env)data) == env, &return_value));
13
14
+ return return_value;
15
16
17
+void Init(napi_env env, napi_value exports, napi_value module, void* context) {
18
+ napi_property_descriptor prop = DECLARE_NAPI_PROPERTY("exports", compare);
19
+ NAPI_CALL_RETURN_VOID(env, napi_define_properties(env, module, 1, &prop));
20
21
22
+NAPI_MODULE(compare_env, Init)
test/addons-napi/test_env_sharing/store_env.c
+ NAPI_CALL_RETURN_VOID(env,
+ napi_create_external(env, env, NULL, NULL, &external));
+ napi_set_named_property(env, module, "exports", external));
+NAPI_MODULE(store_env, Init)
test/addons-napi/test_env_sharing/test.js
@@ -0,0 +1,10 @@
+'use strict';
+const common = require('../../common');
+const storeEnv = require(`./build/${common.buildType}/store_env`);
+const compareEnv = require(`./build/${common.buildType}/compare_env`);
+const assert = require('assert');
+assert.strictEqual(compareEnv(storeEnv), true,
+ 'N-API environment pointers in two different modules have ' +
+ 'the same value');