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