|
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