|
12 | 12 | #include <memory>
|
13 | 13 |
|
14 | 14 | struct node_napi_env__ : public napi_env__ {
|
15 |
| - explicit node_napi_env__(v8::Local<v8::Context> context): |
16 |
| - napi_env__(context) { |
| 15 | + explicit node_napi_env__(v8::Local<v8::Context> context, |
| 16 | + const std::string& module_filename): |
| 17 | + napi_env__(context), filename(module_filename) { |
17 | 18 | CHECK_NOT_NULL(node_env());
|
18 | 19 | }
|
19 | 20 |
|
@@ -43,6 +44,10 @@ struct node_napi_env__ : public napi_env__ {
|
43 | 44 | });
|
44 | 45 | });
|
45 | 46 | }
|
| 47 | + |
| 48 | + const char* GetFilename() const { return filename.c_str(); } |
| 49 | + |
| 50 | + std::string filename; |
46 | 51 | };
|
47 | 52 |
|
48 | 53 | typedef node_napi_env__* node_napi_env;
|
@@ -84,10 +89,11 @@ class BufferFinalizer : private Finalizer {
|
84 | 89 | };
|
85 | 90 | };
|
86 | 91 |
|
87 |
| -static inline napi_env NewEnv(v8::Local<v8::Context> context) { |
| 92 | +static inline napi_env |
| 93 | +NewEnv(v8::Local<v8::Context> context, const std::string& module_filename) { |
88 | 94 | node_napi_env result;
|
89 | 95 |
|
90 |
| - result = new node_napi_env__(context); |
| 96 | + result = new node_napi_env__(context, module_filename); |
91 | 97 | // TODO(addaleax): There was previously code that tried to delete the
|
92 | 98 | // napi_env when its v8::Context was garbage collected;
|
93 | 99 | // However, as long as N-API addons using this napi_env are in place,
|
@@ -454,16 +460,35 @@ void napi_module_register_by_symbol(v8::Local<v8::Object> exports,
|
454 | 460 | v8::Local<v8::Value> module,
|
455 | 461 | v8::Local<v8::Context> context,
|
456 | 462 | napi_addon_register_func init) {
|
| 463 | + node::Environment* node_env = node::Environment::GetCurrent(context); |
| 464 | + std::string module_filename = ""; |
457 | 465 | if (init == nullptr) {
|
458 |
| - node::Environment* node_env = node::Environment::GetCurrent(context); |
459 | 466 | CHECK_NOT_NULL(node_env);
|
460 | 467 | node_env->ThrowError(
|
461 | 468 | "Module has no declared entry point.");
|
462 | 469 | return;
|
463 | 470 | }
|
464 | 471 |
|
| 472 | + // We set `env->filename` from `module.filename` here, but we could just as |
| 473 | + // easily add a private property to `exports` in `process.dlopen`, which |
| 474 | + // receives the file name from JS, and retrieve *that* here. Thus, we are not |
| 475 | + // endorsing commonjs here by making use of `module.filename`. |
| 476 | + v8::Local<v8::Value> filename_js; |
| 477 | + v8::Local<v8::Object> modobj; |
| 478 | + if (module->ToObject(context).ToLocal(&modobj) && |
| 479 | + modobj->Get(context, node_env->filename_string()).ToLocal(&filename_js) && |
| 480 | + filename_js->IsString()) { |
| 481 | + node::Utf8Value filename(node_env->isolate(), filename_js); // Cast |
| 482 | + |
| 483 | + // Turn the absolute path into a URL. Currently the absolute path is always |
| 484 | + // a file system path. |
| 485 | + // TODO(gabrielschulhof): Pass the `filename` through unchanged if/when we |
| 486 | + // receive it as a URL already. |
| 487 | + module_filename = std::string("file://") + (*filename); |
| 488 | + } |
| 489 | + |
465 | 490 | // Create a new napi_env for this specific module.
|
466 |
| - napi_env env = v8impl::NewEnv(context); |
| 491 | + napi_env env = v8impl::NewEnv(context, module_filename); |
467 | 492 |
|
468 | 493 | napi_value _exports;
|
469 | 494 | env->CallIntoModule([&](napi_env env) {
|
@@ -1154,3 +1179,11 @@ napi_ref_threadsafe_function(napi_env env, napi_threadsafe_function func) {
|
1154 | 1179 | CHECK_NOT_NULL(func);
|
1155 | 1180 | return reinterpret_cast<v8impl::ThreadSafeFunction*>(func)->Ref();
|
1156 | 1181 | }
|
| 1182 | + |
| 1183 | +napi_status node_api_get_module_file_name(napi_env env, const char** result) { |
| 1184 | + CHECK_ENV(env); |
| 1185 | + CHECK_ARG(env, result); |
| 1186 | + |
| 1187 | + *result = static_cast<node_napi_env>(env)->GetFilename(); |
| 1188 | + return napi_clear_last_error(env); |
| 1189 | +} |
0 commit comments