|
16 | 16 | #include <memory>
|
17 | 17 |
|
18 | 18 | struct node_napi_env__ : public napi_env__ {
|
19 |
| - explicit node_napi_env__(v8::Local<v8::Context> context): |
20 |
| - napi_env__(context) { |
| 19 | + explicit node_napi_env__(v8::Local<v8::Context> context, |
| 20 | + const std::string& module_filename): |
| 21 | + napi_env__(context), filename(module_filename) { |
21 | 22 | CHECK_NOT_NULL(node_env());
|
22 | 23 | }
|
23 | 24 |
|
@@ -52,6 +53,10 @@ struct node_napi_env__ : public napi_env__ {
|
52 | 53 | });
|
53 | 54 | });
|
54 | 55 | }
|
| 56 | + |
| 57 | + const char* GetFilename() const { return filename.c_str(); } |
| 58 | + |
| 59 | + std::string filename; |
55 | 60 | };
|
56 | 61 |
|
57 | 62 | typedef node_napi_env__* node_napi_env;
|
@@ -93,10 +98,11 @@ class BufferFinalizer : private Finalizer {
|
93 | 98 | };
|
94 | 99 | };
|
95 | 100 |
|
96 |
| -static inline napi_env NewEnv(v8::Local<v8::Context> context) { |
| 101 | +static inline napi_env |
| 102 | +NewEnv(v8::Local<v8::Context> context, const std::string& module_filename) { |
97 | 103 | node_napi_env result;
|
98 | 104 |
|
99 |
| - result = new node_napi_env__(context); |
| 105 | + result = new node_napi_env__(context, module_filename); |
100 | 106 | // TODO(addaleax): There was previously code that tried to delete the
|
101 | 107 | // napi_env when its v8::Context was garbage collected;
|
102 | 108 | // However, as long as N-API addons using this napi_env are in place,
|
@@ -579,16 +585,35 @@ void napi_module_register_by_symbol(v8::Local<v8::Object> exports,
|
579 | 585 | v8::Local<v8::Value> module,
|
580 | 586 | v8::Local<v8::Context> context,
|
581 | 587 | napi_addon_register_func init) {
|
| 588 | + node::Environment* node_env = node::Environment::GetCurrent(context); |
| 589 | + std::string module_filename = ""; |
582 | 590 | if (init == nullptr) {
|
583 |
| - node::Environment* node_env = node::Environment::GetCurrent(context); |
584 | 591 | CHECK_NOT_NULL(node_env);
|
585 | 592 | node_env->ThrowError(
|
586 | 593 | "Module has no declared entry point.");
|
587 | 594 | return;
|
588 | 595 | }
|
589 | 596 |
|
| 597 | + // We set `env->filename` from `module.filename` here, but we could just as |
| 598 | + // easily add a private property to `exports` in `process.dlopen`, which |
| 599 | + // receives the file name from JS, and retrieve *that* here. Thus, we are not |
| 600 | + // endorsing commonjs here by making use of `module.filename`. |
| 601 | + v8::Local<v8::Value> filename_js; |
| 602 | + v8::Local<v8::Object> modobj; |
| 603 | + if (module->ToObject(context).ToLocal(&modobj) && |
| 604 | + modobj->Get(context, node_env->filename_string()).ToLocal(&filename_js) && |
| 605 | + filename_js->IsString()) { |
| 606 | + node::Utf8Value filename(node_env->isolate(), filename_js); // Cast |
| 607 | + |
| 608 | + // Turn the absolute path into a URL. Currently the absolute path is always |
| 609 | + // a file system path. |
| 610 | + // TODO(gabrielschulhof): Pass the `filename` through unchanged if/when we |
| 611 | + // receive it as a URL already. |
| 612 | + module_filename = std::string("file://") + (*filename); |
| 613 | + } |
| 614 | + |
590 | 615 | // Create a new napi_env for this specific module.
|
591 |
| - napi_env env = v8impl::NewEnv(context); |
| 616 | + napi_env env = v8impl::NewEnv(context, module_filename); |
592 | 617 |
|
593 | 618 | napi_value _exports;
|
594 | 619 | env->CallIntoModule([&](napi_env env) {
|
@@ -1287,3 +1312,11 @@ napi_ref_threadsafe_function(napi_env env, napi_threadsafe_function func) {
|
1287 | 1312 | CHECK_NOT_NULL(func);
|
1288 | 1313 | return reinterpret_cast<v8impl::ThreadSafeFunction*>(func)->Ref();
|
1289 | 1314 | }
|
| 1315 | + |
| 1316 | +napi_status node_api_get_module_file_name(napi_env env, const char** result) { |
| 1317 | + CHECK_ENV(env); |
| 1318 | + CHECK_ARG(env, result); |
| 1319 | + |
| 1320 | + *result = static_cast<node_napi_env>(env)->GetFilename(); |
| 1321 | + return napi_clear_last_error(env); |
| 1322 | +} |
0 commit comments