• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "napi/native_node_api.h"
17 #include "native_api_internal.h"
18 #include "native_engine/native_engine.h"
19 #include "utils/log.h"
20 
21 static constexpr int32_t MAX_THREAD_SAFE_COUNT = 128;
22 
napi_module_register(napi_module * mod)23 NAPI_EXTERN void napi_module_register(napi_module* mod)
24 {
25     if (mod == nullptr) {
26         HILOG_ERROR("mod is nullptr");
27         return;
28     }
29 
30     NativeModuleManager* moduleManager = NativeModuleManager::GetInstance();
31     NativeModule module;
32 
33     module.version = mod->nm_version;
34     module.fileName = mod->nm_filename;
35     module.name = mod->nm_modname;
36     module.registerCallback = (RegisterCallback)mod->nm_register_func;
37 
38     moduleManager->Register(&module);
39 }
40 
napi_fatal_error(const char * location,size_t location_len,const char * message,size_t message_len)41 NAPI_EXTERN NAPI_NO_RETURN void napi_fatal_error(const char* location,
42                                                  size_t location_len,
43                                                  const char* message,
44                                                  size_t message_len)
45 {
46     (void)location_len;
47     (void)message_len;
48     HILOG_FATAL("FATAL ERROR: %{public}s %{public}s\n", location, message);
49     abort();
50 }
51 
napi_fatal_exception(napi_env env,napi_value err)52 NAPI_INNER_EXTERN napi_status napi_fatal_exception(napi_env env, napi_value err)
53 {
54     HILOG_INFO("%{public}s, start.", __func__);
55     CHECK_ENV(env);
56     CHECK_ARG(env, err);
57 
58     auto engine = reinterpret_cast<NativeEngine*>(env);
59     auto jsError = reinterpret_cast<NativeValue*>(err);
60     if (engine->TriggerFatalException(jsError)) {
61         HILOG_INFO("%{public}s, end.", __func__);
62         return napi_status::napi_ok;
63     } else {
64         HILOG_INFO("%{public}s, end.", __func__);
65         exit(1);
66         return napi_status::napi_ok;
67     }
68 }
69 
70 // Methods to manage simple async operations
napi_create_async_work(napi_env env,napi_value async_resource,napi_value async_resource_name,napi_async_execute_callback execute,napi_async_complete_callback complete,void * data,napi_async_work * result)71 NAPI_EXTERN napi_status napi_create_async_work(napi_env env,
72                                                napi_value async_resource,
73                                                napi_value async_resource_name,
74                                                napi_async_execute_callback execute,
75                                                napi_async_complete_callback complete,
76                                                void* data,
77                                                napi_async_work* result)
78 {
79     CHECK_ENV(env);
80     CHECK_ARG(env, async_resource_name);
81     CHECK_ARG(env, execute);
82     CHECK_ARG(env, complete);
83     CHECK_ARG(env, result);
84 
85     auto engine = reinterpret_cast<NativeEngine*>(env);
86     auto asyncResource = reinterpret_cast<NativeValue*>(async_resource);
87     auto asyncResourceName = reinterpret_cast<NativeValue*>(async_resource_name);
88     auto asyncExecute = reinterpret_cast<NativeAsyncExecuteCallback>(execute);
89     auto asyncComplete = reinterpret_cast<NativeAsyncCompleteCallback>(complete);
90 
91     auto asyncWork = engine->CreateAsyncWork(asyncResource, asyncResourceName, asyncExecute, asyncComplete, data);
92 
93     *result = reinterpret_cast<napi_async_work>(asyncWork);
94     return napi_status::napi_ok;
95 }
96 
napi_delete_async_work(napi_env env,napi_async_work work)97 NAPI_EXTERN napi_status napi_delete_async_work(napi_env env, napi_async_work work)
98 {
99     CHECK_ENV(env);
100     CHECK_ARG(env, work);
101 
102     auto asyncWork = reinterpret_cast<NativeAsyncWork*>(work);
103 
104     delete asyncWork;
105     asyncWork = nullptr;
106 
107     return napi_status::napi_ok;
108 }
109 
napi_queue_async_work(napi_env env,napi_async_work work)110 NAPI_EXTERN napi_status napi_queue_async_work(napi_env env, napi_async_work work)
111 {
112     CHECK_ENV(env);
113     CHECK_ARG(env, work);
114 
115     auto asyncWork = reinterpret_cast<NativeAsyncWork*>(work);
116 
117     asyncWork->Queue();
118     return napi_status::napi_ok;
119 }
120 
napi_cancel_async_work(napi_env env,napi_async_work work)121 NAPI_EXTERN napi_status napi_cancel_async_work(napi_env env, napi_async_work work)
122 {
123     CHECK_ENV(env);
124     CHECK_ARG(env, work);
125 
126     auto asyncWork = reinterpret_cast<NativeAsyncWork*>(work);
127 
128     asyncWork->Cancel();
129     return napi_status::napi_ok;
130 }
131 
132 // Version management
napi_get_node_version(napi_env env,const napi_node_version ** version)133 NAPI_EXTERN napi_status napi_get_node_version(napi_env env, const napi_node_version** version)
134 {
135     (void)version;
136     return napi_status::napi_ok;
137 }
138 
139 // Return the current libuv event loop for a given environment
napi_get_uv_event_loop(napi_env env,struct uv_loop_s ** loop)140 NAPI_EXTERN napi_status napi_get_uv_event_loop(napi_env env, struct uv_loop_s** loop)
141 {
142     CHECK_ENV(env);
143     CHECK_ARG(env, loop);
144 
145     auto engine = reinterpret_cast<NativeEngine*>(env);
146     *loop = engine->GetUVLoop();
147 
148     return napi_status::napi_ok;
149 }
150 
napi_add_env_cleanup_hook(napi_env env,void (* fun)(void * arg),void * arg)151 NAPI_INNER_EXTERN napi_status napi_add_env_cleanup_hook(napi_env env, void (*fun)(void* arg), void* arg)
152 {
153     CHECK_ENV(env);
154     CHECK_ARG(env, fun);
155 
156     auto engine = reinterpret_cast<NativeEngine*>(env);
157     engine->AddCleanupHook(fun, arg);
158 
159     return napi_clear_last_error(env);
160 }
161 
napi_remove_env_cleanup_hook(napi_env env,void (* fun)(void * arg),void * arg)162 NAPI_INNER_EXTERN napi_status napi_remove_env_cleanup_hook(napi_env env, void (*fun)(void* arg), void* arg)
163 {
164     CHECK_ENV(env);
165     CHECK_ARG(env, fun);
166 
167     auto engine = reinterpret_cast<NativeEngine*>(env);
168     engine->RemoveCleanupHook(fun, arg);
169 
170     return napi_clear_last_error(env);
171 }
172 
173 using CleanupHook = void (*)(void* arg);
174 using AsyncCleanupHook = void (*)(void* arg, void (*)(void*), void*);
175 
176 struct AsyncCleanupHookInfo final {
177     napi_env env_;
178     AsyncCleanupHook fun_;
179     void* arg_;
180     bool started_ = false;
181     // Use a self-reference to make sure the storage is kept alive while the
182     // cleanup hook is registered but not yet finished.
183     std::shared_ptr<AsyncCleanupHookInfo> self_;
184 };
185 
186 // Opaque type that is basically an alias for `shared_ptr<AsyncCleanupHookInfo>`
187 // (but not publicly so for easier ABI/API changes). In particular,
188 // std::shared_ptr does not generally maintain a consistent ABI even on a
189 // specific platform.
190 struct ACHHandle final {
191     std::shared_ptr<AsyncCleanupHookInfo> info_;
192 };
193 
194 struct DeleteACHHandle {
operator ()DeleteACHHandle195     void operator()(ACHHandle* handle) const
196     {
197         delete handle;
198     };
199 };
200 using AsyncCleanupHookHandle = std::unique_ptr<ACHHandle, DeleteACHHandle>;
201 
FinishAsyncCleanupHook(void * arg)202 static void FinishAsyncCleanupHook(void* arg)
203 {
204     HILOG_INFO("%{public}s, start.", __func__);
205     AsyncCleanupHookInfo* info = static_cast<AsyncCleanupHookInfo*>(arg);
206     std::shared_ptr<AsyncCleanupHookInfo> keep_alive = info->self_;
207     auto engine = reinterpret_cast<NativeEngine*>(info->env_);
208     engine->DecreaseWaitingRequestCounter();
209     info->self_.reset();
210     HILOG_INFO("%{public}s, end.", __func__);
211 }
212 
RunAsyncCleanupHook(void * arg)213 static void RunAsyncCleanupHook(void* arg)
214 {
215     HILOG_INFO("%{public}s, start.", __func__);
216     AsyncCleanupHookInfo* info = static_cast<AsyncCleanupHookInfo*>(arg);
217     auto engine = reinterpret_cast<NativeEngine*>(info->env_);
218     engine->IncreaseWaitingRequestCounter();
219     info->started_ = true;
220     info->fun_(info->arg_, FinishAsyncCleanupHook, info);
221     HILOG_INFO("%{public}s, end.", __func__);
222 }
223 
AddEnvironmentCleanupHook(napi_env env,AsyncCleanupHook fun,void * arg)224 static AsyncCleanupHookHandle AddEnvironmentCleanupHook(napi_env env, AsyncCleanupHook fun, void* arg)
225 {
226     HILOG_INFO("%{public}s, start.", __func__);
227     auto info = std::make_shared<AsyncCleanupHookInfo>();
228     info->env_ = env;
229     info->fun_ = fun;
230     info->arg_ = arg;
231     info->self_ = info;
232     auto engine = reinterpret_cast<NativeEngine*>(env);
233     engine->AddCleanupHook(RunAsyncCleanupHook, info.get());
234     HILOG_INFO("%{public}s, end.", __func__);
235     return AsyncCleanupHookHandle(new ACHHandle { info });
236 }
237 
RemoveEnvironmentCleanupHook(AsyncCleanupHookHandle handle)238 static void RemoveEnvironmentCleanupHook(AsyncCleanupHookHandle handle)
239 {
240     HILOG_INFO("%{public}s, start.", __func__);
241     if (handle->info_->started_) {
242         return;
243     }
244     handle->info_->self_.reset();
245     auto engine = reinterpret_cast<NativeEngine*>(handle->info_->env_);
246     engine->RemoveCleanupHook(RunAsyncCleanupHook, handle->info_.get());
247     HILOG_INFO("%{public}s, end.", __func__);
248 }
249 
250 struct napi_async_cleanup_hook_handle__ {
napi_async_cleanup_hook_handle__napi_async_cleanup_hook_handle__251     napi_async_cleanup_hook_handle__(napi_env env, napi_async_cleanup_hook user_hook, void* user_data)
252         : env_(env), user_hook_(user_hook), user_data_(user_data)
253     {
254         HILOG_INFO("%{public}s, start.", __func__);
255         handle_ = AddEnvironmentCleanupHook(env, Hook, this);
256         HILOG_INFO("%{public}s, end.", __func__);
257     }
258 
~napi_async_cleanup_hook_handle__napi_async_cleanup_hook_handle__259     ~napi_async_cleanup_hook_handle__()
260     {
261         HILOG_INFO("%{public}s, start.", __func__);
262         RemoveEnvironmentCleanupHook(std::move(handle_));
263         if (done_cb_ != nullptr) {
264             done_cb_(done_data_);
265         }
266         HILOG_INFO("%{public}s, end.", __func__);
267     }
268 
Hooknapi_async_cleanup_hook_handle__269     static void Hook(void* data, void (*done_cb)(void*), void* done_data)
270     {
271         HILOG_INFO("%{public}s, start.", __func__);
272         auto handle = static_cast<napi_async_cleanup_hook_handle__*>(data);
273         handle->done_cb_ = done_cb;
274         handle->done_data_ = done_data;
275         handle->user_hook_(handle, handle->user_data_);
276         HILOG_INFO("%{public}s, end.", __func__);
277     }
278 
279     AsyncCleanupHookHandle handle_;
280     napi_env env_ = nullptr;
281     napi_async_cleanup_hook user_hook_ = nullptr;
282     void* user_data_ = nullptr;
283     void (*done_cb_)(void*) = nullptr;
284     void* done_data_ = nullptr;
285 };
286 
napi_add_async_cleanup_hook(napi_env env,napi_async_cleanup_hook hook,void * arg,napi_async_cleanup_hook_handle * remove_handle)287 NAPI_INNER_EXTERN napi_status napi_add_async_cleanup_hook(
288     napi_env env, napi_async_cleanup_hook hook, void* arg, napi_async_cleanup_hook_handle* remove_handle)
289 {
290     CHECK_ENV(env);
291     CHECK_ARG(env, hook);
292 
293     napi_async_cleanup_hook_handle__* handle = new napi_async_cleanup_hook_handle__(env, hook, arg);
294 
295     if (remove_handle != nullptr)
296         *remove_handle = handle;
297 
298     return napi_clear_last_error(env);
299 }
300 
napi_remove_async_cleanup_hook(napi_async_cleanup_hook_handle remove_handle)301 NAPI_INNER_EXTERN napi_status napi_remove_async_cleanup_hook(napi_async_cleanup_hook_handle remove_handle)
302 {
303     if (remove_handle == nullptr) {
304         return napi_invalid_arg;
305     }
306 
307     delete remove_handle;
308     return napi_ok;
309 }
310 
311 // Methods to manager threadsafe
napi_create_threadsafe_function(napi_env env,napi_value func,napi_value async_resource,napi_value async_resource_name,size_t max_queue_size,size_t initial_thread_count,void * thread_finalize_data,napi_finalize thread_finalize_cb,void * context,napi_threadsafe_function_call_js call_js_cb,napi_threadsafe_function * result)312 NAPI_EXTERN napi_status napi_create_threadsafe_function(napi_env env, napi_value func, napi_value async_resource,
313     napi_value async_resource_name, size_t max_queue_size, size_t initial_thread_count, void* thread_finalize_data,
314     napi_finalize thread_finalize_cb, void* context, napi_threadsafe_function_call_js call_js_cb,
315     napi_threadsafe_function* result)
316 {
317     CHECK_ENV(env);
318     CHECK_ARG(env, async_resource_name);
319     RETURN_STATUS_IF_FALSE(env, max_queue_size >= 0, napi_invalid_arg);
320     RETURN_STATUS_IF_FALSE(
321         env, initial_thread_count > 0 && initial_thread_count <= MAX_THREAD_SAFE_COUNT, napi_invalid_arg);
322     CHECK_ARG(env, result);
323     if (func == nullptr) {
324         CHECK_ARG(env, call_js_cb);
325     }
326 
327     auto engine = reinterpret_cast<NativeEngine*>(env);
328     auto jsFunc = reinterpret_cast<NativeValue*>(func);
329     auto asyncResource = reinterpret_cast<NativeValue*>(async_resource);
330     auto asyncResourceName = reinterpret_cast<NativeValue*>(async_resource_name);
331     auto finalizeCallback = reinterpret_cast<NativeFinalize>(thread_finalize_cb);
332     auto callJsCallback = reinterpret_cast<NativeThreadSafeFunctionCallJs>(call_js_cb);
333     auto safeAsyncWork = engine->CreateSafeAsyncWork(jsFunc, asyncResource, asyncResourceName, max_queue_size,
334         initial_thread_count, thread_finalize_data, finalizeCallback, context, callJsCallback);
335     CHECK_ENV(safeAsyncWork);
336 
337     auto ret = safeAsyncWork->Init();
338     if (ret) {
339         *result = reinterpret_cast<napi_threadsafe_function>(safeAsyncWork);
340     } else {
341         return napi_status::napi_generic_failure;
342     }
343 
344     return napi_status::napi_ok;
345 }
346 
napi_call_threadsafe_function(napi_threadsafe_function func,void * data,napi_threadsafe_function_call_mode is_blocking)347 NAPI_EXTERN napi_status napi_call_threadsafe_function(
348     napi_threadsafe_function func, void* data, napi_threadsafe_function_call_mode is_blocking)
349 {
350     CHECK_ENV(func);
351 
352     auto safeAsyncWork = reinterpret_cast<NativeSafeAsyncWork*>(func);
353     auto callMode = static_cast<NativeThreadSafeFunctionCallMode>(is_blocking);
354 
355     napi_status status = napi_status::napi_ok;
356     auto code = safeAsyncWork->Send(data, callMode);
357     switch (code) {
358         case SafeAsyncCode::SAFE_ASYNC_QUEUE_FULL:
359             status = napi_status::napi_queue_full;
360             break;
361         case SafeAsyncCode::SAFE_ASYNC_INVALID_ARGS:
362             status = napi_status::napi_invalid_arg;
363             break;
364         case SafeAsyncCode::SAFE_ASYNC_CLOSED:
365             status = napi_status::napi_closing;
366             break;
367         case SafeAsyncCode::SAFE_ASYNC_FAILED:
368             status = napi_status::napi_generic_failure;
369             break;
370         default:
371             status = napi_status::napi_ok;
372             break;
373     }
374 
375     return status;
376 }
377 
napi_acquire_threadsafe_function(napi_threadsafe_function func)378 NAPI_EXTERN napi_status napi_acquire_threadsafe_function(napi_threadsafe_function func)
379 {
380     CHECK_ENV(func);
381 
382     auto safeAsyncWork = reinterpret_cast<NativeSafeAsyncWork*>(func);
383 
384     auto ret = safeAsyncWork->Acquire();
385     if (ret != SafeAsyncCode::SAFE_ASYNC_OK) {
386         return napi_status::napi_generic_failure;
387     }
388 
389     return napi_status::napi_ok;
390 }
391 
napi_release_threadsafe_function(napi_threadsafe_function func,napi_threadsafe_function_release_mode mode)392 NAPI_EXTERN napi_status napi_release_threadsafe_function(
393     napi_threadsafe_function func, napi_threadsafe_function_release_mode mode)
394 {
395     CHECK_ENV(func);
396 
397     auto safeAsyncWork = reinterpret_cast<NativeSafeAsyncWork*>(func);
398     auto releaseMode = static_cast<NativeThreadSafeFunctionReleaseMode>(mode);
399 
400     auto ret = safeAsyncWork->Release(releaseMode);
401     if (ret != SafeAsyncCode::SAFE_ASYNC_OK) {
402         return napi_status::napi_generic_failure;
403     }
404 
405     return napi_status::napi_ok;
406 }
407 
napi_get_threadsafe_function_context(napi_threadsafe_function func,void ** result)408 NAPI_EXTERN napi_status napi_get_threadsafe_function_context(napi_threadsafe_function func, void** result)
409 {
410     CHECK_ENV(func);
411     CHECK_ENV(result);
412 
413     auto safeAsyncWork = reinterpret_cast<NativeSafeAsyncWork*>(func);
414     *result = safeAsyncWork->GetContext();
415 
416     return napi_status::napi_ok;
417 }
418 
napi_ref_threadsafe_function(napi_env env,napi_threadsafe_function func)419 NAPI_EXTERN napi_status napi_ref_threadsafe_function(napi_env env, napi_threadsafe_function func)
420 {
421     CHECK_ENV(env);
422     CHECK_ARG(env, func);
423 
424     auto safeAsyncWork = reinterpret_cast<NativeSafeAsyncWork*>(func);
425     auto ret = safeAsyncWork->Ref();
426     if (!ret) {
427         return napi_status::napi_generic_failure;
428     }
429 
430     return napi_status::napi_ok;
431 }
432 
napi_unref_threadsafe_function(napi_env env,napi_threadsafe_function func)433 NAPI_EXTERN napi_status napi_unref_threadsafe_function(napi_env env, napi_threadsafe_function func)
434 {
435     CHECK_ENV(env);
436     CHECK_ARG(env, func);
437 
438     auto safeAsyncWork = reinterpret_cast<NativeSafeAsyncWork*>(func);
439     auto ret = safeAsyncWork->Unref();
440     if (!ret) {
441         return napi_status::napi_generic_failure;
442     }
443 
444     return napi_status::napi_ok;
445 }
446 
napi_async_init(napi_env env,napi_value async_resource,napi_value async_resource_name,napi_async_context * result)447 NAPI_INNER_EXTERN napi_status napi_async_init(
448     napi_env env, napi_value async_resource, napi_value async_resource_name, napi_async_context* result)
449 {
450     CHECK_ENV(env);
451     CHECK_ARG(env, async_resource_name);
452     CHECK_ARG(env, result);
453 
454     auto asyncResource = reinterpret_cast<NativeValue*>(async_resource);
455     auto asyncResourceName = reinterpret_cast<NativeValue*>(async_resource_name);
456 
457     auto async_context = new NativeAsyncContext();
458     async_context->asyncResource = asyncResource;
459     async_context->asyncResourceName = asyncResourceName;
460 
461     *result = reinterpret_cast<napi_async_context>(async_context);
462 
463     return napi_clear_last_error(env);
464 }
465 
napi_async_destroy(napi_env env,napi_async_context async_context)466 NAPI_INNER_EXTERN napi_status napi_async_destroy(napi_env env, napi_async_context async_context)
467 {
468     CHECK_ENV(env);
469     CHECK_ARG(env, async_context);
470 
471     NativeAsyncContext* native_async_context = reinterpret_cast<NativeAsyncContext*>(async_context);
472 
473     delete native_async_context;
474 
475     return napi_clear_last_error(env);
476 }
477 
napi_open_callback_scope(napi_env env,napi_value,napi_async_context async_context_handle,napi_callback_scope * result)478 NAPI_INNER_EXTERN napi_status napi_open_callback_scope(
479     napi_env env, napi_value, napi_async_context async_context_handle, napi_callback_scope* result)
480 {
481     CHECK_ENV(env);
482     CHECK_ARG(env, result);
483 
484     auto engine = reinterpret_cast<NativeEngine*>(env);
485     auto callbackScopeManager = engine->GetCallbackScopeManager();
486     CHECK_ARG(env, callbackScopeManager);
487 
488     auto callbackScope = callbackScopeManager->Open(engine);
489     callbackScopeManager->IncrementOpenCallbackScopes();
490 
491     *result = reinterpret_cast<napi_callback_scope>(callbackScope);
492 
493     return napi_clear_last_error(env);
494 }
495 
napi_close_callback_scope(napi_env env,napi_callback_scope scope)496 NAPI_INNER_EXTERN napi_status napi_close_callback_scope(napi_env env, napi_callback_scope scope)
497 {
498     CHECK_ENV(env);
499     CHECK_ARG(env, scope);
500 
501     auto engine = reinterpret_cast<NativeEngine*>(env);
502     auto callbackScopeManager = engine->GetCallbackScopeManager();
503     CHECK_ARG(env, callbackScopeManager);
504     size_t count = callbackScopeManager->GetOpenCallbackScopes();
505     if (count == 0) {
506         return napi_callback_scope_mismatch;
507     }
508     callbackScopeManager->DecrementOpenCallbackScopes();
509 
510     auto callbackScope = reinterpret_cast<NativeCallbackScope*>(scope);
511     callbackScopeManager->Close(callbackScope);
512 
513     return napi_clear_last_error(env);
514 }
515 
napi_set_instance_data(napi_env env,void * data,napi_finalize finalize_cb,void * finalize_hint)516 NAPI_INNER_EXTERN napi_status napi_set_instance_data(
517     napi_env env, void* data, napi_finalize finalize_cb, void* finalize_hint)
518 {
519     HILOG_INFO("%{public}s", __func__);
520     CHECK_ENV(env);
521     auto engine = reinterpret_cast<NativeEngine*>(env);
522     auto callback = reinterpret_cast<NativeFinalize>(finalize_cb);
523     engine->SetInstanceData(data, callback, finalize_hint);
524     return napi_clear_last_error(env);
525 }
526 
napi_get_instance_data(napi_env env,void ** data)527 NAPI_INNER_EXTERN napi_status napi_get_instance_data(napi_env env, void** data)
528 {
529     HILOG_INFO("%{public}s", __func__);
530     CHECK_ENV(env);
531     CHECK_ARG(env, data);
532     auto engine = reinterpret_cast<NativeEngine*>(env);
533     engine->GetInstanceData(data);
534     return napi_clear_last_error(env);
535 }
536 
node_api_get_module_file_name(napi_env env,const char ** result)537 NAPI_INNER_EXTERN napi_status node_api_get_module_file_name(napi_env env, const char** result)
538 {
539     HILOG_INFO("%{public}s", __func__);
540     CHECK_ENV(env);
541     CHECK_ARG(env, result);
542     auto engine = reinterpret_cast<NativeEngine*>(env);
543     *result = engine->GetModuleFileName();
544     HILOG_INFO("%{public}s, napi called fileName : %{public}s", __func__, *result);
545     return napi_clear_last_error(env);
546 }