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