Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabriel Schulhof <gabriel.schulhof@intel.com>2021-02-03 10:07:34 +0300
committerGabriel Schulhof <gabriel.schulhof@intel.com>2021-02-10 10:34:30 +0300
commitad3ebed046ef457530b046f2a62313a7e16b7e29 (patch)
tree26a3e1308a5989eeb4c64dba0ffc99ece41ea784 /src/node_api.cc
parent79d44baae28d64e0a0ee1765df3eb637e429e7a6 (diff)
node-api: allow retrieval of add-on file name
Unlike JS-only modules, native add-ons are always associated with a dynamic shared object from which they are loaded. Being able to retrieve its absolute path is important to native-only add-ons, i.e. add-ons that are not themselves being loaded from a JS-only module located in the same package as the native add-on itself. Currently, the file name is obtained at environment construction time from the JS `module.filename`. Nevertheless, the presence of `module` is not required, because the file name could also be passed in via a private property added onto `exports` from the `process.dlopen` binding. As an attempt at future-proofing, the file name is provided as a URL, i.e. prefixed with the `file://` protocol. Fixes: https://github.com/nodejs/node-addon-api/issues/449 PR-URL: https://github.com/nodejs/node/pull/37195 Co-authored-by: Michael Dawson <mdawson@devrus.com> Reviewed-By: Michael Dawson <midawson@redhat.com>
Diffstat (limited to 'src/node_api.cc')
-rw-r--r--src/node_api.cc45
1 files changed, 39 insertions, 6 deletions
diff --git a/src/node_api.cc b/src/node_api.cc
index f1a5265b6a7..8dbf48d466d 100644
--- a/src/node_api.cc
+++ b/src/node_api.cc
@@ -15,8 +15,9 @@
#include <memory>
struct node_napi_env__ : public napi_env__ {
- explicit node_napi_env__(v8::Local<v8::Context> context):
- napi_env__(context) {
+ explicit node_napi_env__(v8::Local<v8::Context> context,
+ const std::string& module_filename):
+ napi_env__(context), filename(module_filename) {
CHECK_NOT_NULL(node_env());
}
@@ -46,6 +47,10 @@ struct node_napi_env__ : public napi_env__ {
});
});
}
+
+ const char* GetFilename() const { return filename.c_str(); }
+
+ std::string filename;
};
typedef node_napi_env__* node_napi_env;
@@ -87,10 +92,11 @@ class BufferFinalizer : private Finalizer {
};
};
-static inline napi_env NewEnv(v8::Local<v8::Context> context) {
+static inline napi_env
+NewEnv(v8::Local<v8::Context> context, const std::string& module_filename) {
node_napi_env result;
- result = new node_napi_env__(context);
+ result = new node_napi_env__(context, module_filename);
// 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,
@@ -552,16 +558,35 @@ void napi_module_register_by_symbol(v8::Local<v8::Object> exports,
v8::Local<v8::Value> module,
v8::Local<v8::Context> context,
napi_addon_register_func init) {
+ node::Environment* node_env = node::Environment::GetCurrent(context);
+ std::string module_filename = "";
if (init == nullptr) {
- node::Environment* node_env = node::Environment::GetCurrent(context);
CHECK_NOT_NULL(node_env);
node_env->ThrowError(
"Module has no declared entry point.");
return;
}
+ // We set `env->filename` from `module.filename` here, but we could just as
+ // easily add a private property to `exports` in `process.dlopen`, which
+ // receives the file name from JS, and retrieve *that* here. Thus, we are not
+ // endorsing commonjs here by making use of `module.filename`.
+ v8::Local<v8::Value> filename_js;
+ v8::Local<v8::Object> modobj;
+ if (module->ToObject(context).ToLocal(&modobj) &&
+ modobj->Get(context, node_env->filename_string()).ToLocal(&filename_js) &&
+ filename_js->IsString()) {
+ node::Utf8Value filename(node_env->isolate(), filename_js); // Cast
+
+ // Turn the absolute path into a URL. Currently the absolute path is always
+ // a file system path.
+ // TODO(gabrielschulhof): Pass the `filename` through unchanged if/when we
+ // receive it as a URL already.
+ module_filename = std::string("file://") + (*filename);
+ }
+
// Create a new napi_env for this specific module.
- napi_env env = v8impl::NewEnv(context);
+ napi_env env = v8impl::NewEnv(context, module_filename);
napi_value _exports;
env->CallIntoModule([&](napi_env env) {
@@ -1257,3 +1282,11 @@ napi_ref_threadsafe_function(napi_env env, napi_threadsafe_function func) {
CHECK_NOT_NULL(func);
return reinterpret_cast<v8impl::ThreadSafeFunction*>(func)->Ref();
}
+
+napi_status node_api_get_module_file_name(napi_env env, const char** result) {
+ CHECK_ENV(env);
+ CHECK_ARG(env, result);
+
+ *result = static_cast<node_napi_env>(env)->GetFilename();
+ return napi_clear_last_error(env);
+}