• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2025 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 "native_api_internal.h"
17 #include "native_engine/native_async_hook_context.h"
18 #include "native_engine/native_utils.h"
19 #include "native_engine/impl/ark/ark_native_engine.h"
20 
21 using panda::Local;
22 using panda::StringRef;
23 
24 static constexpr int32_t MAX_THREAD_SAFE_COUNT = 128;
25 
napi_module_register(napi_module * mod)26 NAPI_EXTERN void napi_module_register(napi_module* mod)
27 {
28     if (mod == nullptr) {
29         HILOG_ERROR("mod is nullptr");
30         return;
31     }
32 
33     NativeModuleManager* moduleManager = NativeModuleManager::GetInstance();
34     NativeModule module;
35 
36     module.version = mod->nm_version;
37     module.fileName = mod->nm_filename;
38     module.name = mod->nm_modname;
39     module.flags = mod->nm_flags;
40     module.registerCallback = (RegisterCallback)mod->nm_register_func;
41 
42     moduleManager->Register(&module);
43 }
44 
napi_module_with_js_register(napi_module_with_js * mod)45 NAPI_EXTERN void napi_module_with_js_register(napi_module_with_js* mod)
46 {
47     if (mod == nullptr) {
48         HILOG_ERROR("mod is nullptr");
49         return;
50     }
51 
52     NativeModuleManager* moduleManager = NativeModuleManager::GetInstance();
53     NativeModule module;
54 
55     module.version = mod->nm_version;
56     module.fileName = mod->nm_filename;
57     module.name = mod->nm_modname;
58     module.registerCallback = (RegisterCallback)mod->nm_register_func;
59     module.getJSCode = (GetJSCodeCallback)mod->nm_get_js_code;
60     module.getABCCode = (GetJSCodeCallback)mod->nm_get_abc_code;
61 
62     moduleManager->Register(&module);
63 }
64 
napi_fatal_error(const char * location,size_t location_len,const char * message,size_t message_len)65 NAPI_EXTERN NAPI_NO_RETURN void napi_fatal_error(const char* location,
66                                                  size_t location_len,
67                                                  const char* message,
68                                                  size_t message_len)
69 {
70     (void)location_len;
71     (void)message_len;
72     HILOG_FATAL("FATAL ERROR: %{public}s %{public}s\n", location, message);
73 }
74 
napi_create_limit_runtime(napi_env env,napi_env * result_env)75 NAPI_EXTERN napi_status napi_create_limit_runtime(napi_env env, napi_env* result_env)
76 {
77     CHECK_ENV(env);
78     CHECK_ARG(env, result_env);
79 
80     auto engine = reinterpret_cast<NativeEngine*>(env);
81     if (!engine->IsMainEnvContext()) {
82         HILOG_FATAL("multi-context does not support this interface");
83     }
84 
85     auto result = engine->CreateRuntime(true);
86     *result_env = reinterpret_cast<napi_env>(result);
87 
88     return napi_clear_last_error(env);
89 }
90 
napi_fatal_exception(napi_env env,napi_value err)91 NAPI_EXTERN napi_status napi_fatal_exception(napi_env env, napi_value err)
92 {
93     NAPI_PREAMBLE(env);
94     CHECK_ENV(env);
95     CHECK_ARG(env, err);
96 
97     auto exceptionValue = LocalValueFromJsValue(err);
98     auto ecmaVm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
99     RETURN_STATUS_IF_FALSE(env, exceptionValue->IsError(ecmaVm), napi_invalid_arg);
100 
101     auto engine = reinterpret_cast<NativeEngine*>(env);
102     engine->TriggerFatalException(exceptionValue);
103     return napi_ok;
104 }
105 
106 // 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)107 NAPI_EXTERN napi_status napi_create_async_work(napi_env env,
108                                                napi_value async_resource,
109                                                napi_value async_resource_name,
110                                                napi_async_execute_callback execute,
111                                                napi_async_complete_callback complete,
112                                                void* data,
113                                                napi_async_work* result)
114 {
115     CHECK_ENV(env);
116     CHECK_ARG(env, async_resource_name);
117     CHECK_ARG(env, execute);
118     CHECK_ARG(env, complete);
119     CHECK_ARG(env, result);
120 
121     SWITCH_CONTEXT(env);
122     auto ecmaVm = engine->GetEcmaVm();
123     auto asyncResource = LocalValueFromJsValue(async_resource);
124     auto asyncResourceName = LocalValueFromJsValue(async_resource_name);
125     auto asyncExecute = reinterpret_cast<NativeAsyncExecuteCallback>(execute);
126     auto asyncComplete = reinterpret_cast<NativeAsyncCompleteCallback>(complete);
127     (void)asyncResource;
128     (void)asyncResourceName;
129     char name[64] = {0}; // 64:NAME_BUFFER_SIZE
130     if (!(asyncResourceName->IsNull() || asyncResourceName->IsUndefined())) {
131         panda::Local<panda::StringRef> nativeString(asyncResourceName);
132         int copied = nativeString->WriteUtf8(ecmaVm, name, 63, true) - 1;  // 63:NAME_BUFFER_SIZE
133         name[copied] = '\0';
134     }
135     auto asyncWork  = new NativeAsyncWork(engine, asyncExecute, asyncComplete, name, data);
136     *result = reinterpret_cast<napi_async_work>(asyncWork);
137     return napi_status::napi_ok;
138 }
139 
napi_delete_async_work(napi_env env,napi_async_work work)140 NAPI_EXTERN napi_status napi_delete_async_work(napi_env env, napi_async_work work)
141 {
142     CHECK_ENV(env);
143     CHECK_ARG(env, work);
144 
145     auto asyncWork = reinterpret_cast<NativeAsyncWork*>(work);
146     delete asyncWork;
147     asyncWork = nullptr;
148 
149     return napi_status::napi_ok;
150 }
151 
napi_queue_async_work(napi_env env,napi_async_work work)152 NAPI_EXTERN napi_status napi_queue_async_work(napi_env env, napi_async_work work)
153 {
154     CHECK_ENV(env);
155     CHECK_ARG(env, work);
156 
157     auto asyncWork = reinterpret_cast<NativeAsyncWork*>(work);
158 
159     asyncWork->Queue(reinterpret_cast<NativeEngine*>(env));
160     return napi_status::napi_ok;
161 }
162 
napi_cancel_async_work(napi_env env,napi_async_work work)163 NAPI_EXTERN napi_status napi_cancel_async_work(napi_env env, napi_async_work work)
164 {
165     CHECK_ENV(env);
166     CHECK_ARG(env, work);
167 
168     auto asyncWork = reinterpret_cast<NativeAsyncWork*>(work);
169 
170     asyncWork->Cancel(reinterpret_cast<NativeEngine*>(env));
171     return napi_status::napi_ok;
172 }
173 
174 // Version management
napi_get_node_version(napi_env env,const napi_node_version ** version)175 NAPI_EXTERN napi_status napi_get_node_version(napi_env env, const napi_node_version** version)
176 {
177     (void)version;
178     return napi_status::napi_ok;
179 }
180 
181 // Return the current libuv event loop for a given environment
napi_get_uv_event_loop(napi_env env,struct uv_loop_s ** loop)182 NAPI_EXTERN napi_status napi_get_uv_event_loop(napi_env env, struct uv_loop_s** loop)
183 {
184     CHECK_ENV(env);
185     CHECK_ARG(env, loop);
186 
187     auto engine = reinterpret_cast<NativeEngine*>(env);
188     if (!NativeEngine::IsAlive(engine)) {
189         HILOG_ERROR("napi_env has been destroyed!");
190         return napi_status::napi_generic_failure;
191     }
192 
193     if (!engine->IsMainEnvContext()) {
194         HILOG_ERROR("multi-context does not support obtain uv looper");
195         return napi_set_last_error(env, napi_invalid_arg);
196     }
197     *loop = engine->GetUVLoop();
198 
199     return napi_status::napi_ok;
200 }
201 
napi_add_env_cleanup_hook(napi_env env,void (* fun)(void * arg),void * arg)202 NAPI_EXTERN napi_status napi_add_env_cleanup_hook(napi_env env, void (*fun)(void* arg), void* arg)
203 {
204     CHECK_ENV(env);
205     CHECK_ARG(env, fun);
206     WEAK_CROSS_THREAD_CHECK(env);
207 
208     auto engine = reinterpret_cast<NativeEngine*>(env);
209     engine->AddCleanupHook(fun, arg);
210 
211     return napi_clear_last_error(env);
212 }
213 
napi_remove_env_cleanup_hook(napi_env env,void (* fun)(void * arg),void * arg)214 NAPI_EXTERN napi_status napi_remove_env_cleanup_hook(napi_env env, void (*fun)(void* arg), void* arg)
215 {
216     CHECK_ENV(env);
217     CHECK_ARG(env, fun);
218     WEAK_CROSS_THREAD_CHECK(env);
219 
220     auto engine = reinterpret_cast<NativeEngine*>(env);
221     engine->RemoveCleanupHook(fun, arg);
222 
223     return napi_clear_last_error(env);
224 }
225 
226 using CleanupHook = void (*)(void* arg);
227 using AsyncCleanupHook = void (*)(void* arg, void (*)(void*), void*);
228 
229 struct AsyncCleanupHookInfo final {
230     napi_env env_;
231     AsyncCleanupHook fun_;
232     void* arg_;
233     bool started_ = false;
234     // Use a self-reference to make sure the storage is kept alive while the
235     // cleanup hook is registered but not yet finished.
236     std::shared_ptr<AsyncCleanupHookInfo> self_;
237 };
238 
239 // Opaque type that is basically an alias for `shared_ptr<AsyncCleanupHookInfo>`
240 // (but not publicly so for easier ABI/API changes). In particular,
241 // std::shared_ptr does not generally maintain a consistent ABI even on a
242 // specific platform.
243 struct ACHHandle final {
244     std::shared_ptr<AsyncCleanupHookInfo> info_;
245 };
246 
247 struct DeleteACHHandle {
operator ()DeleteACHHandle248     void operator()(ACHHandle* handle) const
249     {
250         delete handle;
251     };
252 };
253 using AsyncCleanupHookHandle = std::unique_ptr<ACHHandle, DeleteACHHandle>;
254 
FinishAsyncCleanupHook(void * arg)255 static void FinishAsyncCleanupHook(void* arg)
256 {
257     HILOG_INFO("%{public}s, start.", __func__);
258     AsyncCleanupHookInfo* info = static_cast<AsyncCleanupHookInfo*>(arg);
259     std::shared_ptr<AsyncCleanupHookInfo> keep_alive = info->self_;
260     auto engine = reinterpret_cast<NativeEngine*>(info->env_);
261     engine->DecreaseWaitingRequestCounter();
262     info->self_.reset();
263     HILOG_INFO("%{public}s, end.", __func__);
264 }
265 
RunAsyncCleanupHook(void * arg)266 static void RunAsyncCleanupHook(void* arg)
267 {
268     HILOG_INFO("%{public}s, start.", __func__);
269     AsyncCleanupHookInfo* info = static_cast<AsyncCleanupHookInfo*>(arg);
270     auto engine = reinterpret_cast<NativeEngine*>(info->env_);
271     engine->IncreaseWaitingRequestCounter();
272     info->started_ = true;
273     info->fun_(info->arg_, FinishAsyncCleanupHook, info);
274     HILOG_INFO("%{public}s, end.", __func__);
275 }
276 
AddEnvironmentCleanupHook(napi_env env,AsyncCleanupHook fun,void * arg)277 static AsyncCleanupHookHandle AddEnvironmentCleanupHook(napi_env env, AsyncCleanupHook fun, void* arg)
278 {
279     HILOG_INFO("%{public}s, start.", __func__);
280     auto info = std::make_shared<AsyncCleanupHookInfo>();
281     info->env_ = env;
282     info->fun_ = fun;
283     info->arg_ = arg;
284     info->self_ = info;
285     auto engine = reinterpret_cast<NativeEngine*>(env);
286     engine->AddCleanupHook(RunAsyncCleanupHook, info.get());
287     HILOG_INFO("%{public}s, end.", __func__);
288     return AsyncCleanupHookHandle(new ACHHandle { info });
289 }
290 
RemoveEnvironmentCleanupHook(AsyncCleanupHookHandle handle)291 static void RemoveEnvironmentCleanupHook(AsyncCleanupHookHandle handle)
292 {
293     if (handle->info_->started_) {
294         return;
295     }
296     handle->info_->self_.reset();
297     auto engine = reinterpret_cast<NativeEngine*>(handle->info_->env_);
298     engine->RemoveCleanupHook(RunAsyncCleanupHook, handle->info_.get());
299 }
300 
301 struct napi_async_cleanup_hook_handle__ {
napi_async_cleanup_hook_handle__napi_async_cleanup_hook_handle__302     napi_async_cleanup_hook_handle__(napi_env env, napi_async_cleanup_hook user_hook, void* user_data)
303         : env_(env), user_hook_(user_hook), user_data_(user_data)
304     {
305         handle_ = AddEnvironmentCleanupHook(env, Hook, this);
306     }
307 
~napi_async_cleanup_hook_handle__napi_async_cleanup_hook_handle__308     ~napi_async_cleanup_hook_handle__()
309     {
310         RemoveEnvironmentCleanupHook(std::move(handle_));
311         if (done_cb_ != nullptr) {
312             done_cb_(done_data_);
313         }
314     }
315 
Hooknapi_async_cleanup_hook_handle__316     static void Hook(void* data, void (*done_cb)(void*), void* done_data)
317     {
318         auto handle = static_cast<napi_async_cleanup_hook_handle__*>(data);
319         handle->done_cb_ = done_cb;
320         handle->done_data_ = done_data;
321         handle->user_hook_(handle, handle->user_data_);
322     }
323 
324     AsyncCleanupHookHandle handle_;
325     napi_env env_ = nullptr;
326     napi_async_cleanup_hook user_hook_ = nullptr;
327     void* user_data_ = nullptr;
328     void (*done_cb_)(void*) = nullptr;
329     void* done_data_ = nullptr;
330 };
331 
napi_add_async_cleanup_hook(napi_env env,napi_async_cleanup_hook hook,void * arg,napi_async_cleanup_hook_handle * remove_handle)332 NAPI_EXTERN napi_status napi_add_async_cleanup_hook(
333     napi_env env, napi_async_cleanup_hook hook, void* arg, napi_async_cleanup_hook_handle* remove_handle)
334 {
335     CHECK_ENV(env);
336     CHECK_ARG(env, hook);
337     CROSS_THREAD_CHECK(env);
338 
339     napi_async_cleanup_hook_handle__* handle = new napi_async_cleanup_hook_handle__(env, hook, arg);
340 
341     if (remove_handle != nullptr)
342         *remove_handle = handle;
343 
344     return napi_clear_last_error(env);
345 }
346 
napi_remove_async_cleanup_hook(napi_async_cleanup_hook_handle remove_handle)347 NAPI_EXTERN napi_status napi_remove_async_cleanup_hook(napi_async_cleanup_hook_handle remove_handle)
348 {
349     if (remove_handle == nullptr) {
350         return napi_invalid_arg;
351     }
352 
353     delete remove_handle;
354     return napi_ok;
355 }
356 
357 // 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)358 NAPI_EXTERN napi_status napi_create_threadsafe_function(napi_env env, napi_value func, napi_value async_resource,
359     napi_value async_resource_name, size_t max_queue_size, size_t initial_thread_count, void* thread_finalize_data,
360     napi_finalize thread_finalize_cb, void* context, napi_threadsafe_function_call_js call_js_cb,
361     napi_threadsafe_function* result)
362 {
363     CHECK_ENV(env);
364     CHECK_ARG(env, async_resource_name);
365     RETURN_STATUS_IF_FALSE(
366         env, initial_thread_count > 0 && initial_thread_count <= MAX_THREAD_SAFE_COUNT, napi_invalid_arg);
367     CHECK_ARG(env, result);
368     if (func == nullptr) {
369         CHECK_ARG(env, call_js_cb);
370     }
371 
372     SWITCH_CONTEXT(env);
373     auto finalizeCallback = reinterpret_cast<NativeFinalize>(thread_finalize_cb);
374     auto callJsCallback = reinterpret_cast<NativeThreadSafeFunctionCallJs>(call_js_cb);
375     auto safeAsyncWork = engine->CreateSafeAsyncWork(func, async_resource, async_resource_name, max_queue_size,
376         initial_thread_count, thread_finalize_data, finalizeCallback, context, callJsCallback);
377     CHECK_ENV(safeAsyncWork);
378 
379     auto ret = safeAsyncWork->Init();
380     if (ret) {
381         *result = reinterpret_cast<napi_threadsafe_function>(safeAsyncWork);
382     } else {
383         return napi_status::napi_generic_failure;
384     }
385 
386     return napi_status::napi_ok;
387 }
388 
napi_call_threadsafe_function(napi_threadsafe_function func,void * data,napi_threadsafe_function_call_mode is_blocking)389 NAPI_EXTERN napi_status napi_call_threadsafe_function(
390     napi_threadsafe_function func, void* data, napi_threadsafe_function_call_mode is_blocking)
391 {
392     CHECK_ENV(func);
393 
394     auto safeAsyncWork = reinterpret_cast<NativeSafeAsyncWork*>(func);
395     auto callMode = static_cast<NativeThreadSafeFunctionCallMode>(is_blocking);
396 
397     napi_status status = napi_status::napi_ok;
398     auto code = safeAsyncWork->Send(data, callMode);
399     switch (code) {
400         case SafeAsyncCode::SAFE_ASYNC_OK:
401             status = napi_status::napi_ok;
402             break;
403         case SafeAsyncCode::SAFE_ASYNC_QUEUE_FULL:
404             status = napi_status::napi_queue_full;
405             break;
406         case SafeAsyncCode::SAFE_ASYNC_INVALID_ARGS:
407             status = napi_status::napi_invalid_arg;
408             break;
409         case SafeAsyncCode::SAFE_ASYNC_CLOSED:
410             status = napi_status::napi_closing;
411             break;
412         case SafeAsyncCode::SAFE_ASYNC_FAILED:
413             status = napi_status::napi_generic_failure;
414             break;
415         default:
416             HILOG_FATAL("this branch is unreachable, code is %{public}d", code);
417             break;
418     }
419 
420     return status;
421 }
422 
napi_acquire_threadsafe_function(napi_threadsafe_function func)423 NAPI_EXTERN napi_status napi_acquire_threadsafe_function(napi_threadsafe_function func)
424 {
425     CHECK_ENV(func);
426 
427     auto safeAsyncWork = reinterpret_cast<NativeSafeAsyncWork*>(func);
428 
429     auto ret = safeAsyncWork->Acquire();
430     if (ret != SafeAsyncCode::SAFE_ASYNC_OK) {
431         return napi_status::napi_generic_failure;
432     }
433 
434     return napi_status::napi_ok;
435 }
436 
napi_release_threadsafe_function(napi_threadsafe_function func,napi_threadsafe_function_release_mode mode)437 NAPI_EXTERN napi_status napi_release_threadsafe_function(
438     napi_threadsafe_function func, napi_threadsafe_function_release_mode mode)
439 {
440     CHECK_ENV(func);
441 
442     auto safeAsyncWork = reinterpret_cast<NativeSafeAsyncWork*>(func);
443     auto releaseMode = static_cast<NativeThreadSafeFunctionReleaseMode>(mode);
444 
445     auto ret = safeAsyncWork->Release(releaseMode);
446     if (ret != SafeAsyncCode::SAFE_ASYNC_OK) {
447         return napi_status::napi_generic_failure;
448     }
449 
450     return napi_status::napi_ok;
451 }
452 
napi_get_threadsafe_function_context(napi_threadsafe_function func,void ** result)453 NAPI_EXTERN napi_status napi_get_threadsafe_function_context(napi_threadsafe_function func, void** result)
454 {
455     CHECK_ENV(func);
456     CHECK_ENV(result);
457 
458     auto safeAsyncWork = reinterpret_cast<NativeSafeAsyncWork*>(func);
459     *result = safeAsyncWork->GetContext();
460 
461     return napi_status::napi_ok;
462 }
463 
napi_ref_threadsafe_function(napi_env env,napi_threadsafe_function func)464 NAPI_EXTERN napi_status napi_ref_threadsafe_function(napi_env env, napi_threadsafe_function func)
465 {
466     CHECK_ENV(env);
467     CHECK_ARG(env, func);
468 
469     auto safeAsyncWork = reinterpret_cast<NativeSafeAsyncWork*>(func);
470     auto ret = safeAsyncWork->Ref();
471     if (!ret) {
472         return napi_status::napi_generic_failure;
473     }
474 
475     return napi_status::napi_ok;
476 }
477 
napi_unref_threadsafe_function(napi_env env,napi_threadsafe_function func)478 NAPI_EXTERN napi_status napi_unref_threadsafe_function(napi_env env, napi_threadsafe_function func)
479 {
480     CHECK_ENV(env);
481     CHECK_ARG(env, func);
482 
483     auto safeAsyncWork = reinterpret_cast<NativeSafeAsyncWork*>(func);
484     auto ret = safeAsyncWork->Unref();
485     if (!ret) {
486         return napi_status::napi_generic_failure;
487     }
488 
489     return napi_status::napi_ok;
490 }
491 
napi_async_init(napi_env env,napi_value async_resource,napi_value async_resource_name,napi_async_context * result)492 NAPI_EXTERN napi_status napi_async_init(
493     napi_env env, napi_value async_resource, napi_value async_resource_name, napi_async_context* result)
494 {
495     CHECK_ENV(env);
496     CHECK_ARG(env, async_resource_name);
497     CHECK_ARG(env, result);
498 
499     SWITCH_CONTEXT(env);
500     auto ecmaVm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
501     panda::Local<panda::ObjectRef> resource;
502     bool isExternalResource;
503     if (async_resource != nullptr) {
504         auto nativeValue = LocalValueFromJsValue(async_resource);
505         resource = nativeValue->ToObject(ecmaVm);
506         isExternalResource = true;
507     } else {
508         resource = panda::ObjectRef::New(ecmaVm);
509         isExternalResource = false;
510     }
511 
512     auto nativeValue = LocalValueFromJsValue(async_resource_name);
513     auto resourceName = nativeValue->ToString(ecmaVm);
514 
515     auto asyncContext = new NativeAsyncHookContext(reinterpret_cast<NativeEngine*>(env),
516                                                    resource,
517                                                    resourceName,
518                                                    isExternalResource);
519 
520     *result = reinterpret_cast<napi_async_context>(asyncContext);
521 
522     return napi_clear_last_error(env);
523 }
524 
napi_async_destroy(napi_env env,napi_async_context async_context)525 NAPI_EXTERN napi_status napi_async_destroy(napi_env env, napi_async_context async_context)
526 {
527     CHECK_ENV(env);
528     CHECK_ARG(env, async_context);
529 
530     NativeAsyncHookContext* nativeAsyncContext = reinterpret_cast<NativeAsyncHookContext*>(async_context);
531 
532     delete nativeAsyncContext;
533 
534     return napi_clear_last_error(env);
535 }
536 
napi_open_callback_scope(napi_env env,napi_value,napi_async_context async_context_handle,napi_callback_scope * result)537 NAPI_EXTERN napi_status napi_open_callback_scope(
538     napi_env env, napi_value, napi_async_context async_context_handle, napi_callback_scope* result)
539 {
540     CHECK_ENV(env);
541     CHECK_ARG(env, result);
542 
543     NativeAsyncHookContext* nodeAsyncContext = reinterpret_cast<NativeAsyncHookContext*>(async_context_handle);
544 
545     *result = reinterpret_cast<napi_callback_scope>(nodeAsyncContext->OpenCallbackScope());
546 
547     return napi_clear_last_error(env);
548 }
549 
napi_close_callback_scope(napi_env env,napi_callback_scope scope)550 NAPI_EXTERN napi_status napi_close_callback_scope(napi_env env, napi_callback_scope scope)
551 {
552     CHECK_ENV(env);
553     CHECK_ARG(env, scope);
554 
555     auto ret = NativeAsyncHookContext::CloseCallbackScope(reinterpret_cast<NativeEngine*>(env),
556                                                           reinterpret_cast<NativeCallbackScope*>(scope));
557     if (ret == CALLBACK_SCOPE_MISMATCH) {
558         return napi_callback_scope_mismatch;
559     } else if (ret != CALLBACK_SCOPE_OK) {
560         return napi_invalid_arg;
561     }
562 
563     return napi_clear_last_error(env);
564 }
565 
napi_set_instance_data(napi_env env,void * data,napi_finalize finalize_cb,void * finalize_hint)566 NAPI_EXTERN napi_status napi_set_instance_data(
567     napi_env env, void* data, napi_finalize finalize_cb, void* finalize_hint)
568 {
569     CHECK_ENV(env);
570     CROSS_THREAD_CHECK(env);
571     auto engine = reinterpret_cast<NativeEngine*>(env);
572     auto callback = reinterpret_cast<NativeFinalize>(finalize_cb);
573     engine->SetInstanceData(data, callback, finalize_hint);
574     return napi_clear_last_error(env);
575 }
576 
napi_get_instance_data(napi_env env,void ** data)577 NAPI_EXTERN napi_status napi_get_instance_data(napi_env env, void** data)
578 {
579     CHECK_ENV(env);
580     CHECK_ARG(env, data);
581     CROSS_THREAD_CHECK(env);
582     auto engine = reinterpret_cast<NativeEngine*>(env);
583     engine->GetInstanceData(data);
584     return napi_clear_last_error(env);
585 }
586 
node_api_get_module_file_name(napi_env env,const char ** result)587 NAPI_EXTERN napi_status node_api_get_module_file_name(napi_env env, const char** result)
588 {
589     CHECK_ENV(env);
590     CHECK_ARG(env, result);
591     auto engine = reinterpret_cast<NativeEngine*>(env);
592     *result = engine->GetModuleFileName();
593     HILOG_INFO("%{public}s, napi called fileName : %{public}s", __func__, *result);
594     return napi_clear_last_error(env);
595 }
596 
napi_make_callback(napi_env env,napi_async_context async_context,napi_value recv,napi_value func,size_t argc,const napi_value * argv,napi_value * result)597 NAPI_EXTERN napi_status napi_make_callback(napi_env env,
598                                            napi_async_context async_context,
599                                            napi_value recv,
600                                            napi_value func,
601                                            size_t argc,
602                                            const napi_value* argv,
603                                            napi_value* result)
604 {
605     NAPI_PREAMBLE(env);
606     CHECK_ARG(env, func);
607     CHECK_ARG(env, recv);
608     if (argc > 0) {
609         CHECK_ARG(env, argv);
610     }
611     SWITCH_CONTEXT(env);
612     auto vm = engine->GetEcmaVm();
613     RETURN_STATUS_IF_FALSE(env, reinterpret_cast<panda::JSValueRef *>(recv)->IsObject(vm), napi_object_expected);
614     RETURN_STATUS_IF_FALSE(env, reinterpret_cast<panda::JSValueRef *>(func)->IsFunction(vm), napi_function_expected);
615     panda::JSValueRef* Obj = reinterpret_cast<panda::JSValueRef *>(recv);
616     panda::FunctionRef* funRef = reinterpret_cast<panda::FunctionRef *>(func);
617     panda::JSValueRef* callBackRst;
618     if (async_context == nullptr) {
619         callBackRst = MakeCallback(engine, funRef, Obj,
620                                    argc, reinterpret_cast<panda::JSValueRef* const*>(argv), nullptr);
621     } else {
622         NativeAsyncHookContext* nativeAsyncContext = reinterpret_cast<NativeAsyncHookContext*>(async_context);
623         callBackRst = nativeAsyncContext->MakeCallback(funRef, Obj,
624                                                        reinterpret_cast<panda::JSValueRef* const*>(argv), argc);
625     }
626     if (tryCatch.HasCaught()) {
627         HILOG_ERROR("print exception info: ");
628         panda::JSNApi::PrintExceptionInfo(vm);
629         return napi_set_last_error(env, napi_pending_exception);
630     }
631     if (result) {
632         *result = reinterpret_cast<napi_value>(callBackRst);
633     }
634     return GET_RETURN_STATUS(env);
635 }
636 
napi_set_module_validate_callback(napi_module_validate_callback check_callback)637 NAPI_EXTERN napi_status napi_set_module_validate_callback(napi_module_validate_callback check_callback)
638 {
639     CHECK_ENV(check_callback);
640 
641     if (ArkNativeEngine::SetModuleValidateCallback(check_callback)) {
642         return napi_ok;
643     }
644     return napi_generic_failure;
645 }