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
25using panda::Local;
26using panda::StringRef;
27
28static constexpr int32_t MAX_THREAD_SAFE_COUNT = 128;
29
30NAPI_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
49NAPI_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
69NAPI_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
79NAPI_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
92NAPI_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
108NAPI_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        uint32_t 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
141NAPI_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
153NAPI_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
164NAPI_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
176NAPI_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
183NAPI_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
198NAPI_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
210NAPI_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
222using CleanupHook = void (*)(void* arg);
223using AsyncCleanupHook = void (*)(void* arg, void (*)(void*), void*);
224
225struct 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.
239struct ACHHandle final {
240    std::shared_ptr<AsyncCleanupHookInfo> info_;
241};
242
243struct DeleteACHHandle {
244    void operator()(ACHHandle* handle) const
245    {
246        delete handle;
247    };
248};
249using AsyncCleanupHookHandle = std::unique_ptr<ACHHandle, DeleteACHHandle>;
250
251static 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
262static 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
273static 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
287static 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
297struct 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
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
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
328NAPI_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
343NAPI_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
354NAPI_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
386NAPI_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
420NAPI_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
434NAPI_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
450NAPI_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
461NAPI_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
475NAPI_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
489NAPI_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
521NAPI_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
533NAPI_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
546NAPI_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
562NAPI_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
573NAPI_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
583NAPI_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
593NAPI_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