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 }