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
25 using panda::Local;
26 using panda::StringRef;
27
28 static constexpr int32_t MAX_THREAD_SAFE_COUNT = 128;
29
napi_module_register(napi_module * mod)30 NAPI_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
napi_module_with_js_register(napi_module_with_js * mod)49 NAPI_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
napi_fatal_error(const char * location,size_t location_len,const char * message,size_t message_len)69 NAPI_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
napi_create_limit_runtime(napi_env env,napi_env * result_env)79 NAPI_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
napi_fatal_exception(napi_env env,napi_value err)92 NAPI_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
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)108 NAPI_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 int 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
napi_delete_async_work(napi_env env,napi_async_work work)141 NAPI_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
napi_queue_async_work(napi_env env,napi_async_work work)153 NAPI_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
napi_cancel_async_work(napi_env env,napi_async_work work)164 NAPI_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
napi_get_node_version(napi_env env,const napi_node_version ** version)176 NAPI_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
napi_get_uv_event_loop(napi_env env,struct uv_loop_s ** loop)183 NAPI_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
napi_add_env_cleanup_hook(napi_env env,void (* fun)(void * arg),void * arg)198 NAPI_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
napi_remove_env_cleanup_hook(napi_env env,void (* fun)(void * arg),void * arg)210 NAPI_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
222 using CleanupHook = void (*)(void* arg);
223 using AsyncCleanupHook = void (*)(void* arg, void (*)(void*), void*);
224
225 struct 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.
239 struct ACHHandle final {
240 std::shared_ptr<AsyncCleanupHookInfo> info_;
241 };
242
243 struct DeleteACHHandle {
operator ()DeleteACHHandle244 void operator()(ACHHandle* handle) const
245 {
246 delete handle;
247 };
248 };
249 using AsyncCleanupHookHandle = std::unique_ptr<ACHHandle, DeleteACHHandle>;
250
FinishAsyncCleanupHook(void * arg)251 static 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
RunAsyncCleanupHook(void * arg)262 static 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
AddEnvironmentCleanupHook(napi_env env,AsyncCleanupHook fun,void * arg)273 static 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
RemoveEnvironmentCleanupHook(AsyncCleanupHookHandle handle)287 static 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
297 struct napi_async_cleanup_hook_handle__ {
napi_async_cleanup_hook_handle__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
~napi_async_cleanup_hook_handle__napi_async_cleanup_hook_handle__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
Hooknapi_async_cleanup_hook_handle__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
napi_add_async_cleanup_hook(napi_env env,napi_async_cleanup_hook hook,void * arg,napi_async_cleanup_hook_handle * remove_handle)328 NAPI_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
napi_remove_async_cleanup_hook(napi_async_cleanup_hook_handle remove_handle)343 NAPI_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
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)354 NAPI_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
napi_call_threadsafe_function(napi_threadsafe_function func,void * data,napi_threadsafe_function_call_mode is_blocking)386 NAPI_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
napi_acquire_threadsafe_function(napi_threadsafe_function func)420 NAPI_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
napi_release_threadsafe_function(napi_threadsafe_function func,napi_threadsafe_function_release_mode mode)434 NAPI_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
napi_get_threadsafe_function_context(napi_threadsafe_function func,void ** result)450 NAPI_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
napi_ref_threadsafe_function(napi_env env,napi_threadsafe_function func)461 NAPI_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
napi_unref_threadsafe_function(napi_env env,napi_threadsafe_function func)475 NAPI_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
napi_async_init(napi_env env,napi_value async_resource,napi_value async_resource_name,napi_async_context * result)489 NAPI_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
napi_async_destroy(napi_env env,napi_async_context async_context)521 NAPI_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
napi_open_callback_scope(napi_env env,napi_value,napi_async_context async_context_handle,napi_callback_scope * result)533 NAPI_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
napi_close_callback_scope(napi_env env,napi_callback_scope scope)546 NAPI_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
napi_set_instance_data(napi_env env,void * data,napi_finalize finalize_cb,void * finalize_hint)562 NAPI_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
napi_get_instance_data(napi_env env,void ** data)573 NAPI_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
node_api_get_module_file_name(napi_env env,const char ** result)583 NAPI_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
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)593 NAPI_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