|
15 | 15 | #include <memory>
|
16 | 16 |
|
17 | 17 | struct node_napi_env__ : public napi_env__ {
|
18 |
| - explicit node_napi_env__(v8::Local<v8::Context> context): |
19 |
| - napi_env__(context) { |
| 18 | + explicit node_napi_env__(v8::Local<v8::Context> context, |
| 19 | + const std::string& module_filename): |
| 20 | + napi_env__(context), filename(module_filename) { |
20 | 21 | CHECK_NOT_NULL(node_env());
|
21 | 22 | }
|
22 | 23 |
|
@@ -46,6 +47,10 @@ struct node_napi_env__ : public napi_env__ {
|
46 | 47 | });
|
47 | 48 | });
|
48 | 49 | }
|
| 50 | + |
| 51 | + const char* GetFilename() const { return filename.c_str(); } |
| 52 | + |
| 53 | + std::string filename; |
49 | 54 | };
|
50 | 55 |
|
51 | 56 | typedef node_napi_env__* node_napi_env;
|
@@ -87,10 +92,11 @@ class BufferFinalizer : private Finalizer {
|
87 | 92 | };
|
88 | 93 | };
|
89 | 94 |
|
90 |
| -static inline napi_env NewEnv(v8::Local<v8::Context> context) { |
| 95 | +static inline napi_env |
| 96 | +NewEnv(v8::Local<v8::Context> context, const std::string& module_filename) { |
91 | 97 | node_napi_env result;
|
92 | 98 |
|
93 |
| - result = new node_napi_env__(context); |
| 99 | + result = new node_napi_env__(context, module_filename); |
94 | 100 | // TODO(addaleax): There was previously code that tried to delete the
|
95 | 101 | // napi_env when its v8::Context was garbage collected;
|
96 | 102 | // However, as long as N-API addons using this napi_env are in place,
|
@@ -552,16 +558,30 @@ void napi_module_register_by_symbol(v8::Local<v8::Object> exports,
|
552 | 558 | v8::Local<v8::Value> module,
|
553 | 559 | v8::Local<v8::Context> context,
|
554 | 560 | napi_addon_register_func init) {
|
| 561 | + node::Environment* node_env = node::Environment::GetCurrent(context); |
| 562 | + std::string module_filename = ""; |
555 | 563 | if (init == nullptr) {
|
556 |
| - node::Environment* node_env = node::Environment::GetCurrent(context); |
557 | 564 | CHECK_NOT_NULL(node_env);
|
558 | 565 | node_env->ThrowError(
|
559 | 566 | "Module has no declared entry point.");
|
560 | 567 | return;
|
561 | 568 | }
|
562 | 569 |
|
| 570 | + // We set `env->filename` from `module.filename` here, but we could just as |
| 571 | + // easily add a private property to `exports` in `process.dlopen`, which |
| 572 | + // receives the file name from JS, and retrieve *that* here. Thus, we are not |
| 573 | + // endorsing commonjs here by making use of `module.filename`. |
| 574 | + v8::Local<v8::Value> filename_js; |
| 575 | + v8::Local<v8::Object> modobj; |
| 576 | + if (module->ToObject(context).ToLocal(&modobj) && |
| 577 | + modobj->Get(context, node_env->filename_string()).ToLocal(&filename_js) && |
| 578 | + filename_js->IsString()) { |
| 579 | + node::Utf8Value filename(node_env->isolate(), filename_js); // Cast |
| 580 | + module_filename = *filename; |
| 581 | + } |
| 582 | + |
563 | 583 | // Create a new napi_env for this specific module.
|
564 |
| - napi_env env = v8impl::NewEnv(context); |
| 584 | + napi_env env = v8impl::NewEnv(context, module_filename); |
565 | 585 |
|
566 | 586 | napi_value _exports;
|
567 | 587 | env->CallIntoModule([&](napi_env env) {
|
@@ -1257,3 +1277,11 @@ napi_ref_threadsafe_function(napi_env env, napi_threadsafe_function func) {
|
1257 | 1277 | CHECK_NOT_NULL(func);
|
1258 | 1278 | return reinterpret_cast<v8impl::ThreadSafeFunction*>(func)->Ref();
|
1259 | 1279 | }
|
| 1280 | + |
| 1281 | +napi_status node_api_get_module_file_name(napi_env env, const char** result) { |
| 1282 | + CHECK_ENV(env); |
| 1283 | + CHECK_ARG(env, result); |
| 1284 | + |
| 1285 | + *result = static_cast<node_napi_env>(env)->GetFilename(); |
| 1286 | + return napi_clear_last_error(env); |
| 1287 | +} |
0 commit comments