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