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