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