1 /*
2  * Copyright (c) 2021-2022 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 "ark_native_engine.h"
17 
18 #ifdef ENABLE_HITRACE
19 #include <sys/prctl.h>
20 #endif
21 
22 #include <sstream>
23 #include "ark_native_deferred.h"
24 #if !defined(is_arkui_x) && defined(OHOS_PLATFORM)
25 #include "unwinder.h"
26 #endif
27 #include "ark_native_reference.h"
28 #include "native_engine/native_property.h"
29 #include "native_engine/native_utils.h"
30 #include "native_sendable.h"
31 #include "securec.h"
32 #include "utils/file.h"
33 #include "utils/log.h"
34 #if !defined(PREVIEW) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
35 #include "parameters.h"
36 #include <uv.h>
37 #endif
38 #ifdef ENABLE_CONTAINER_SCOPE
39 #include "core/common/container_scope.h"
40 #endif
41 #if defined(ENABLE_EVENT_HANDLER)
42 #include "event_handler.h"
43 #endif
44 #ifdef ENABLE_HITRACE
45 #include "hitrace/trace.h"
46 #include "hitrace_meter.h"
47 #include "parameter.h"
48 #include "musl_preinit_common.h"
49 #include "memory_trace.h"
50 
51 // LCOV_EXCL_START
52 struct alignas(8) HookJsConfig { // 8 is 8 bit
53     int32_t jsStackReport = 0;
54     uint8_t maxJsStackDepth = 0;
55     bool jsFpUnwind = false;
56     char filterNapiName[64] = { "" };
57 };
58 
59 class BlockHookScope {
60 public:
BlockHookScope()61     BlockHookScope()
62     {
63         previousState_ = __set_hook_flag(false);
64     }
~BlockHookScope()65     ~BlockHookScope()
66     {
67         __set_hook_flag(previousState_);
68     }
69 private:
70     bool previousState_ {true};
71 };
72 
73 static HookJsConfig* g_hookJsConfig = nullptr;
74 static std::once_flag g_hookOnceFlag;
75 static std::string JS_CALL_STACK_DEPTH_SEP = ","; // ',' is js call stack depth separator
76 static std::string JS_SYMBOL_FILEPATH_SEP = "|";  // '|' is js symbol and filepath separator
77 static constexpr uint64_t BUF_SIZE = 128;
78 #endif
79 
80 using panda::JsiRuntimeCallInfo;
81 using panda::BooleanRef;
82 using panda::ObjectRef;
83 using panda::StringRef;
84 using panda::Global;
85 using panda::JSNApi;
86 using panda::FunctionRef;
87 using panda::PrimitiveRef;
88 using panda::ArrayBufferRef;
89 using panda::TypedArrayRef;
90 using panda::PromiseCapabilityRef;
91 using panda::PropertyAttribute;
92 using panda::NativePointerRef;
93 using panda::SymbolRef;
94 using panda::IntegerRef;
95 using panda::DateRef;
96 using panda::BigIntRef;
97 static constexpr auto PANDA_MAIN_FUNCTION = "_GLOBAL::func_main_0";
98 static constexpr auto PANDA_MODULE_NAME = "_GLOBAL_MODULE_NAME";
99 static constexpr auto PANDA_MODULE_NAME_LEN = 32;
100 static std::unordered_set<std::string> NATIVE_MODULE = {"system.app", "ohos.app", "system.router",
101     "system.curves", "ohos.curves", "system.matrix4", "ohos.matrix4"};
102 static constexpr auto NATIVE_MODULE_PREFIX = "@native:";
103 static constexpr auto OHOS_MODULE_PREFIX = "@ohos:";
104 #ifdef ENABLE_HITRACE
105 constexpr auto NAPI_PROFILER_PARAM_SIZE = 10;
106 std::atomic<uint64_t> g_chainId = 0;
107 constexpr int NAPI_CALL_STACK = 2; // just for napi call stack
108 #endif
109 
110 std::string ArkNativeEngine::tempModuleName_ {""};
111 bool ArkNativeEngine::napiProfilerEnabled {false};
112 bool ArkNativeEngine::napiProfilerParamReaded {false};
113 PermissionCheckCallback ArkNativeEngine::permissionCheckCallback_ {nullptr};
114 
115 // This interface is using by ace_engine
LocalValueToLocalNapiValue(panda::Local<panda::JSValueRef> local)116 napi_value LocalValueToLocalNapiValue(panda::Local<panda::JSValueRef> local)
117 {
118     return JsValueFromLocalValue(local);
119 }
120 
121 // This interface is using by ace_engine
NapiValueToLocalValue(napi_value v)122 panda::Local<panda::JSValueRef> NapiValueToLocalValue(napi_value v)
123 {
124     return LocalValueFromJsValue(v);
125 }
126 
127 #ifdef ENABLE_CONTAINER_SCOPE
FunctionSetContainerId(const EcmaVM *vm, panda::Local<panda::JSValueRef> &value)128 void FunctionSetContainerId(const EcmaVM *vm, panda::Local<panda::JSValueRef> &value)
129 {
130     if (!value->IsFunction(vm)) {
131         return;
132     }
133     panda::Local<panda::FunctionRef> funcValue(value);
134     if (funcValue->IsNative(vm)) {
135         return;
136     }
137 
138     auto extraInfo = funcValue->GetData(vm);
139     if (extraInfo != nullptr) {
140         return;
141     }
142 
143     NapiFunctionInfo *funcInfo = NapiFunctionInfo::CreateNewInstance();
144     if (funcInfo == nullptr) {
145         HILOG_ERROR("funcInfo is nullptr");
146         return;
147     }
148     funcInfo->scopeId = OHOS::Ace::ContainerScope::CurrentId();
149     funcValue->SetData(vm, reinterpret_cast<void*>(funcInfo),
150         [](void* env, void *externalPointer, void *data) {
151             auto info = reinterpret_cast<NapiFunctionInfo*>(data);
152             if (info != nullptr) {
153                 delete info;
154                 info = nullptr;
155             }
156         }, true);
157 }
158 #endif
159 
NapiDefineClass(napi_env env, const char* name, NapiNativeCallback callback, void* data, const NapiPropertyDescriptor* properties, size_t length)160 panda::Local<panda::JSValueRef> NapiDefineClass(napi_env env, const char* name, NapiNativeCallback callback,
161     void* data, const NapiPropertyDescriptor* properties, size_t length)
162 {
163     auto vm = const_cast<EcmaVM*>(reinterpret_cast<NativeEngine*>(env)->GetEcmaVm());
164     std::string className(name);
165     if (ArkNativeEngine::napiProfilerEnabled) {
166         className = ArkNativeEngine::tempModuleName_ + "." + name;
167     }
168 
169     NapiFunctionInfo* funcInfo = NapiFunctionInfo::CreateNewInstance();
170     if (funcInfo == nullptr) {
171         HILOG_ERROR("funcInfo is nullptr");
172         return panda::JSValueRef::Undefined(vm);
173     }
174     funcInfo->callback = callback;
175     funcInfo->data = data;
176 #ifdef ENABLE_CONTAINER_SCOPE
177     funcInfo->scopeId = OHOS::Ace::ContainerScope::CurrentId();
178 #endif
179 
180     Local<panda::FunctionRef> fn = panda::FunctionRef::NewConcurrentClassFunction(vm, ArkNativeFunctionCallBack,
181         [](void* env, void* externalPointer, void* data) {
182             auto info = reinterpret_cast<NapiFunctionInfo*>(data);
183                 if (info != nullptr) {
184                     delete info;
185                 }
186             },
187         reinterpret_cast<void*>(funcInfo), true);
188 
189     Local<panda::StringRef> fnName = panda::StringRef::NewFromUtf8(vm, className.c_str());
190     fn->SetName(vm, fnName);
191 
192     if (length == 0) {
193         return fn;
194     }
195     Local<panda::ObjectRef> classPrototype = fn->GetFunctionPrototype(vm);
196     Local<panda::ObjectRef> fnObj = fn->ToObject(vm);
197     for (size_t i = 0; i < length; i++) {
198         if (properties[i].attributes & NATIVE_STATIC) {
199             NapiDefineProperty(env, fnObj, properties[i]);
200         } else {
201             if (classPrototype->IsUndefined()) {
202                 HILOG_ERROR("ArkNativeEngineImpl::Class's prototype is null");
203                 continue;
204             }
205             reinterpret_cast<ArkNativeEngine*>(env)->SetModuleName(classPrototype, className);
206             NapiDefineProperty(env, classPrototype, properties[i]);
207         }
208     }
209 
210     return fn;
211 }
212 
NapiNativeCreateSendableFunction(napi_env env, const char* name, NapiNativeCallback cb, void* value)213 Local<panda::JSValueRef> NapiNativeCreateSendableFunction(napi_env env,
214                                                           const char* name,
215                                                           NapiNativeCallback cb,
216                                                           void* value)
217 {
218     auto engine = reinterpret_cast<NativeEngine*>(env);
219     auto vm = const_cast<EcmaVM*>(engine->GetEcmaVm());
220     NapiFunctionInfo* funcInfo = NapiFunctionInfo::CreateNewInstance();
221     if (funcInfo == nullptr) {
222         HILOG_ERROR("funcInfo is nullptr");
223         return JSValueRef::Undefined(vm);
224     }
225     funcInfo->callback = cb;
226     funcInfo->data = value;
227 
228     Local<panda::FunctionRef> fn = panda::FunctionRef::NewSendable(
229         vm, ArkNativeFunctionCallBack,
230         [](void* env, void* externalPointer, void* data) {
231             auto info = reinterpret_cast<NapiFunctionInfo*>(data);
232             if (info != nullptr) {
233                 delete info;
234             }
235         },
236         reinterpret_cast<void*>(funcInfo), true);
237     return fn;
238 }
239 
NapiDefineSendableClass(napi_env env, const char* name, NapiNativeCallback callback, void* data, const NapiPropertyDescriptor* properties, size_t propertiesLength, napi_value parent)240 panda::Local<panda::JSValueRef> NapiDefineSendableClass(napi_env env,
241                                                         const char* name,
242                                                         NapiNativeCallback callback,
243                                                         void* data,
244                                                         const NapiPropertyDescriptor* properties,
245                                                         size_t propertiesLength,
246                                                         napi_value parent)
247 {
248     const EcmaVM* vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
249     NapiFunctionInfo* funcInfo = NapiFunctionInfo::CreateNewInstance();
250     if (funcInfo == nullptr) {
251         HILOG_FATAL("funcInfo is nullptr");
252         return JSValueRef::Undefined(vm);
253     }
254     funcInfo->callback = callback;
255     funcInfo->data = data;
256 
257     std::string className(name);
258     if (ArkNativeEngine::napiProfilerEnabled) {
259         className = ArkNativeEngine::tempModuleName_ + "." + name;
260     }
261 
262     Local<panda::StringRef> fnName = panda::StringRef::NewFromUtf8(vm, className.c_str());
263     Local<JSValueRef> localParent = JSValueRef::Null(vm);
264     if (parent != nullptr) {
265         localParent = LocalValueFromJsValue(parent);
266     }
267 
268     auto infos = NativeSendable::CreateSendablePropertiesInfos(env, properties, propertiesLength);
269     Local<panda::FunctionRef> fn = panda::FunctionRef::NewSendableClassFunction(
270         vm, ArkNativeFunctionCallBack,
271         [](void* env, void* externalPointer, void* data) {
272             auto info = reinterpret_cast<NapiFunctionInfo*>(data);
273             if (info != nullptr) {
274                 delete info;
275             }
276         },
277         reinterpret_cast<void*>(funcInfo), fnName, infos, localParent, true);
278 
279     return fn;
280 }
281 
282 struct MoudleNameLocker {
MoudleNameLockerMoudleNameLocker283     explicit MoudleNameLocker(std::string moduleName)
284     {
285         ArkNativeEngine::tempModuleName_ = moduleName;
286     }
~MoudleNameLockerMoudleNameLocker287     ~MoudleNameLocker()
288     {
289         ArkNativeEngine::tempModuleName_ = "";
290     }
291 };
292 
GetNativePtrCallBack(void* data)293 void* ArkNativeEngine::GetNativePtrCallBack(void* data)
294 {
295     if (data == nullptr) {
296         HILOG_ERROR("data is nullptr");
297         return nullptr;
298     }
299     auto info = reinterpret_cast<NapiFunctionInfo*>(data);
300     auto cb = reinterpret_cast<void*>(info->callback);
301     return cb;
302 }
303 
CheckArkApiAllowList( NativeModule* module, panda::ecmascript::ApiCheckContext context, panda::Local<panda::ObjectRef>& exportCopy)304 bool ArkNativeEngine::CheckArkApiAllowList(
305     NativeModule* module, panda::ecmascript::ApiCheckContext context, panda::Local<panda::ObjectRef>& exportCopy)
306 {
307     std::unique_ptr<ApiAllowListChecker>& apiAllowListChecker = module->apiAllowListChecker;
308     if (apiAllowListChecker != nullptr) {
309         const std::string apiPath = context.moduleName->ToString(context.ecmaVm);
310         if ((*apiAllowListChecker)(apiPath)) {
311             CopyPropertyApiFilter(apiAllowListChecker, context.ecmaVm, context.exportObj, exportCopy, apiPath);
312         }
313         return true;
314     }
315     return false;
316 }
317 
CopyPropertyApiFilter(const std::unique_ptr<ApiAllowListChecker>& apiAllowListChecker, const EcmaVM* ecmaVm, const panda::Local<panda::ObjectRef> exportObj, panda::Local<panda::ObjectRef>& exportCopy, const std::string& apiPath)318 void ArkNativeEngine::CopyPropertyApiFilter(const std::unique_ptr<ApiAllowListChecker>& apiAllowListChecker,
319     const EcmaVM* ecmaVm, const panda::Local<panda::ObjectRef> exportObj, panda::Local<panda::ObjectRef>& exportCopy,
320     const std::string& apiPath)
321 {
322     panda::Local<panda::ArrayRef> namesArrayRef = exportObj->GetAllPropertyNames(ecmaVm, NATIVE_DEFAULT);
323     for (uint32_t i = 0; i < namesArrayRef->Length(ecmaVm); ++i) {
324         const panda::Local<panda::JSValueRef> nameValue = panda::ArrayRef::GetValueAt(ecmaVm, namesArrayRef, i);
325         const panda::Local<panda::JSValueRef> value = exportObj->Get(ecmaVm, nameValue);
326         const std::string curPath = apiPath + "." + nameValue->ToString(ecmaVm)->ToString(ecmaVm);
327         if ((*apiAllowListChecker)(curPath)) {
328             const std::string valueType = value->Typeof(ecmaVm)->ToString(ecmaVm);
329             if (valueType == "object") {
330                 panda::Local<panda::ObjectRef> subObject = ObjectRef::New(ecmaVm);
331                 CopyPropertyApiFilter(apiAllowListChecker, ecmaVm, value, subObject, curPath);
332                 exportCopy->Set(ecmaVm, nameValue, subObject);
333                 HILOG_DEBUG("Set the package '%{public}s' to the allow list", curPath.c_str());
334             } else if (valueType == "function") {
335                 exportCopy->Set(ecmaVm, nameValue, value);
336                 HILOG_DEBUG("Set the function '%{public}s' to the allow list", curPath.c_str());
337             } else {
338                 exportCopy->Set(ecmaVm, nameValue, value);
339                 HILOG_DEBUG("Set the element type is '%{public}s::%{public}s' to the allow list", valueType.c_str(),
340                     curPath.c_str());
341             }
342         }
343     }
344 }
345 
ArkNativeEngine(EcmaVM* vm, void* jsEngine, bool isLimitedWorker)346 ArkNativeEngine::ArkNativeEngine(EcmaVM* vm, void* jsEngine, bool isLimitedWorker) : NativeEngine(jsEngine, vm),
347                                                                                      topScope_(vm),
348                                                                                      isLimitedWorker_(isLimitedWorker)
349 {
350     HILOG_DEBUG("ArkNativeEngine::ArkNativeEngine");
351     panda::JSNApi::SetEnv(vm, this);
352 #ifdef ENABLE_HITRACE
353     if (!ArkNativeEngine::napiProfilerParamReaded) {
354         char napiProfilerParam[NAPI_PROFILER_PARAM_SIZE] = {0};
355         int ret = GetParameter("persist.hiviewdfx.napiprofiler.enabled", "false",
356             napiProfilerParam, sizeof(napiProfilerParam));
357         if (ret > 0 && strcmp(napiProfilerParam, "true") == 0) {
358             ArkNativeEngine::napiProfilerEnabled = true;
359         }
360         ArkNativeEngine::napiProfilerParamReaded = true;
361     }
362 #endif
363     LocalScope scope(vm_);
364     Local<StringRef> requireInternalName = StringRef::NewFromUtf8(vm, "requireInternal");
365     void* requireData = static_cast<void*>(this);
366 
367     options_ = new NapiOptions();
368     crossThreadCheck_ = JSNApi::IsMultiThreadCheckEnabled(vm);
369 #if defined(OHOS_PLATFORM) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
370     int napiProperties = OHOS::system::GetIntParameter<int>("persist.ark.napi.properties", -1);
371     if (options_ != nullptr) {
372         options_->SetProperties(napiProperties);
373     }
374 #endif
375     Local<FunctionRef> requireNapi =
376         FunctionRef::New(
377             vm,
378             [](JsiRuntimeCallInfo *info) -> Local<JSValueRef> {
379                 EcmaVM *ecmaVm = info->GetVM();
380                 panda::EscapeLocalScope scope(ecmaVm);
381                 NativeModuleManager* moduleManager = NativeModuleManager::GetInstance();
382                 ArkNativeEngine* arkNativeEngine = static_cast<ArkNativeEngine*>(info->GetData());
383                 Local<StringRef> moduleName(info->GetCallArgRef(0));
384                 NativeModule* module = nullptr;
385                 bool isAppModule = false;
386                 std::string errInfo = "";
387                 Local<JSValueRef> exports(JSValueRef::Undefined(ecmaVm));
388 #ifdef IOS_PLATFORM
389                 if (arkNativeEngine->isLimitedWorker_) {
390                     if (!moduleManager->CheckModuleRestricted(moduleName->ToString(ecmaVm).c_str())) {
391                         HILOG_ERROR("module %{public}s does not found in whitelist",
392                             moduleName->ToString(ecmaVm).c_str());
393                         return scope.Escape(exports);
394                     }
395                 }
396                 module = moduleManager->LoadNativeModule(
397                     moduleName->ToString(ecmaVm).c_str(), nullptr, false, errInfo, false, "");
398 #else
399                 const uint32_t lengthMax = 2;
400                 if (info->GetArgsNumber() >= lengthMax) {
401                     Local<BooleanRef> ret(info->GetCallArgRef(1));
402                     isAppModule = ret->Value();
403                 }
404                 arkNativeEngine->isAppModule_ = isAppModule;
405                 if (arkNativeEngine->isLimitedWorker_ && !isAppModule) {
406                     if (!moduleManager->CheckModuleRestricted(moduleName->ToString(ecmaVm).c_str())) {
407                         HILOG_ERROR("module %{public}s does not found in whitelist",
408                             moduleName->ToString(ecmaVm).c_str());
409                         return scope.Escape(exports);
410                     }
411                 }
412 
413                 if (info->GetArgsNumber() == 3) { // 3:Determine if the number of parameters is equal to 3
414                     Local<StringRef> path(info->GetCallArgRef(2)); // 2:Take the second parameter
415                     module = moduleManager->LoadNativeModule(moduleName->ToString(ecmaVm).c_str(),
416                         path->ToString(ecmaVm).c_str(), isAppModule, errInfo, false, "");
417                 } else if (info->GetArgsNumber() == 4) { // 4:Determine if the number of parameters is equal to 4
418                     Local<StringRef> path(info->GetCallArgRef(2)); // 2:Take the second parameter
419                     Local<StringRef> relativePath(info->GetCallArgRef(3)); // 3:Take the second parameter
420                     module = moduleManager->LoadNativeModule(moduleName->ToString(ecmaVm).c_str(), nullptr, isAppModule,
421                         errInfo, false, relativePath->ToString(ecmaVm).c_str());
422                 } else {
423                     module =
424                         moduleManager->LoadNativeModule(moduleName->ToString(ecmaVm).c_str(),
425                         nullptr, isAppModule, errInfo, false, "");
426                 }
427 #endif
428                 if (module != nullptr) {
429                     auto it = arkNativeEngine->loadedModules_.find(module);
430                     if (it != arkNativeEngine->loadedModules_.end()) {
431                         return scope.Escape(it->second.ToLocal(ecmaVm));
432                     }
433                     std::string strModuleName = moduleName->ToString(ecmaVm);
434                     moduleManager->SetNativeEngine(strModuleName, arkNativeEngine);
435                     MoudleNameLocker nameLocker(strModuleName);
436 
437                     if (module->jsCode == nullptr && module->getABCCode != nullptr) {
438                         module->getABCCode(&module->jsCode, &module->jsCodeLen);
439                     }
440                     if (module->jsABCCode != nullptr || module->jsCode != nullptr) {
441                         char fileName[NAPI_PATH_MAX] = { 0 };
442                         const char* name = module->name;
443                         if (sprintf_s(fileName, sizeof(fileName), "lib%s.z.so/%s.js", name, name) == -1) {
444                             HILOG_ERROR("sprintf_s file name failed");
445                             return scope.Escape(exports);
446                         }
447                         HILOG_DEBUG("load js code from %{public}s", fileName);
448                         const void *buffer = nullptr;
449                         if (module->jsABCCode) {
450                             buffer = static_cast<const void *>(module->jsABCCode);
451                         } else {
452                             buffer = static_cast<const void *>(module->jsCode);
453                         }
454                         auto exportObject = arkNativeEngine->LoadArkModule(buffer, module->jsCodeLen, fileName);
455                         if (exportObject->IsUndefined()) {
456                             HILOG_ERROR("load module failed");
457                             return scope.Escape(exports);
458                         } else {
459                             exports = exportObject;
460                             arkNativeEngine->loadedModules_[module] = Global<JSValueRef>(ecmaVm, exports);
461                         }
462                     } else if (module->registerCallback != nullptr) {
463                         Local<ObjectRef> exportObj = ObjectRef::New(ecmaVm);
464 #ifdef ENABLE_HITRACE
465                         StartTrace(HITRACE_TAG_ACE, "NAPI module init, name = " + std::string(module->name));
466 #endif
467                         arkNativeEngine->SetModuleName(exportObj, module->name);
468                         module->registerCallback(reinterpret_cast<napi_env>(arkNativeEngine),
469                                                  JsValueFromLocalValue(exportObj));
470 #ifdef ENABLE_HITRACE
471                         FinishTrace(HITRACE_TAG_ACE);
472 #endif
473                         panda::Local<panda::ObjectRef> exportCopy = panda::ObjectRef::New(ecmaVm);
474                         panda::ecmascript::ApiCheckContext context{moduleManager, ecmaVm, moduleName, exportObj, scope};
475                         if (CheckArkApiAllowList(module, context, exportCopy)) {
476                             return scope.Escape(exportCopy);
477                         }
478                         exports = exportObj;
479                         arkNativeEngine->loadedModules_[module] = Global<JSValueRef>(ecmaVm, exports);
480                     } else {
481                         HILOG_ERROR("init module failed");
482                         return scope.Escape(exports);
483                     }
484                 }
485                 if (module == nullptr) {
486                     HILOG_INFO("%{public}s", errInfo.c_str());
487                     exports = panda::ObjectRef::CreateNativeModuleFailureInfo(ecmaVm, errInfo);
488                 }
489                 return scope.Escape(exports);
490             },
491             nullptr,
492             requireData);
493 
494     Local<FunctionRef> requireInternal =
495         FunctionRef::New(
496             vm,
497             [](JsiRuntimeCallInfo *info) -> Local<JSValueRef> {
498                 EcmaVM *ecmaVm = info->GetVM();
499                 panda::EscapeLocalScope scope(ecmaVm);
500                 NativeModuleManager* moduleManager = NativeModuleManager::GetInstance();
501                 ArkNativeEngine* arkNativeEngine = static_cast<ArkNativeEngine*>(info->GetData());
502                 Local<StringRef> moduleName(info->GetCallArgRef(0));
503                 std::string errInfo = "";
504                 Local<JSValueRef> exports(JSValueRef::Undefined(ecmaVm));
505                 if (arkNativeEngine->isLimitedWorker_) {
506                     if (!moduleManager->CheckModuleRestricted(moduleName->ToString(ecmaVm).c_str())) {
507                         HILOG_ERROR("module %{public}s does not found in whitelist",
508                             moduleName->ToString(ecmaVm).c_str());
509                         return scope.Escape(exports);
510                     }
511                 }
512                 NativeModule* module = moduleManager->LoadNativeModule(moduleName->ToString(ecmaVm).c_str(),
513                     nullptr, false, errInfo, false, "");
514                 MoudleNameLocker nameLocker(moduleName->ToString(ecmaVm));
515                 if (module != nullptr && arkNativeEngine) {
516                     auto it = arkNativeEngine->loadedModules_.find(module);
517                     if (it != arkNativeEngine->loadedModules_.end()) {
518                         return scope.Escape(it->second.ToLocal(ecmaVm));
519                     }
520                     std::string strModuleName = moduleName->ToString(ecmaVm);
521                     moduleManager->SetNativeEngine(strModuleName, arkNativeEngine);
522                     Local<ObjectRef> exportObj = ObjectRef::New(ecmaVm);
523                     if (exportObj->IsObject(ecmaVm)) {
524                         arkNativeEngine->SetModuleName(exportObj, module->name);
525                         module->registerCallback(reinterpret_cast<napi_env>(arkNativeEngine),
526                                                  JsValueFromLocalValue(exportObj));
527                         exports = exportObj;
528                         arkNativeEngine->loadedModules_[module] = Global<JSValueRef>(ecmaVm, exports);
529                     } else {
530                         HILOG_ERROR("exportObject is nullptr");
531                         return scope.Escape(exports);
532                     }
533                 }
534                 return scope.Escape(exports);
535             },
536             nullptr,
537             requireData);
538 
539     Local<ObjectRef> global = panda::JSNApi::GetGlobalObject(vm);
540 #if !defined(PREVIEW)
541     Local<StringRef> requireName = StringRef::NewFromUtf8(vm, "requireNapi");
542     global->Set(vm, requireName, requireNapi);
543 #else
544     Local<StringRef> requireNapiPreview = StringRef::NewFromUtf8(vm, "requireNapiPreview");
545     global->Set(vm, requireNapiPreview, requireNapi);
546 #endif
547     global->Set(vm, requireInternalName, requireInternal);
548     JSNApi::SetNativePtrGetter(vm, reinterpret_cast<void*>(ArkNativeEngine::GetNativePtrCallBack));
549     // need to call init of base class.
550     NativeModuleManager* moduleManager = NativeModuleManager::GetInstance();
551     std::function<bool(const std::string&)> func = [moduleManager](const std::string& moduleKey) -> bool {
552         return moduleManager->UnloadNativeModule(moduleKey);
553     };
554     JSNApi::SetUnloadNativeModuleCallback(vm, func);
555     Init();
556     panda::JSNApi::SetLoop(vm, loop_);
557     panda::JSNApi::SetWeakFinalizeTaskCallback(vm, [this] () -> void {
558         this->PostFinalizeTasks();
559     });
560     JSNApi::SetAsyncCleanTaskCallback(vm, [this] (AsyncNativeCallbacksPack *callbacksPack) {
561         this->PostAsyncTask(callbacksPack);
562     });
563 #if defined(ENABLE_EVENT_HANDLER)
564     if (JSNApi::IsJSMainThreadOfEcmaVM(vm)) {
565         arkIdleMonitor_ = new ArkIdleMonitor(vm);
566         JSNApi::SetTriggerGCTaskCallback(vm, [this](TriggerGCData& data) {
567             this->PostTriggerGCTask(data);
568         });
569         arkIdleMonitor_->SetStartTimerCallback();
570         PostLooperTriggerIdleGCTask();
571     }
572 #endif
573 }
574 
~ArkNativeEngine()575 ArkNativeEngine::~ArkNativeEngine()
576 {
577     HILOG_DEBUG("ArkNativeEngine::~ArkNativeEngine");
578     Deinit();
579     // Free cached objects
580     for (auto&& [module, exportObj] : loadedModules_) {
581         exportObj.FreeGlobalHandleAddr();
582     }
583     // Free callbackRef
584     if (promiseRejectCallbackRef_ != nullptr) {
585         delete promiseRejectCallbackRef_;
586     }
587     if (checkCallbackRef_ != nullptr) {
588         delete checkCallbackRef_;
589     }
590     if (options_ != nullptr) {
591         delete options_;
592         options_ = nullptr;
593     }
594 
595     if (arkIdleMonitor_ != nullptr) {
596         delete arkIdleMonitor_;
597         arkIdleMonitor_ = nullptr;
598     }
599 }
600 
601 #ifdef ENABLE_HITRACE
CheckHookConfig(const std::string &nameRef)602 static inline bool CheckHookConfig(const std::string &nameRef)
603 {
604     if (g_hookJsConfig == nullptr || g_hookJsConfig->jsStackReport <= 0 ||
605         g_hookJsConfig->maxJsStackDepth == 0 || !g_hookJsConfig->jsFpUnwind) {
606         return false;
607     } else if (g_hookJsConfig->filterNapiName[0] != '\0' &&
608         nameRef.find(g_hookJsConfig->filterNapiName) != std::string::npos) {
609         return false;
610     }
611     return true;
612 }
613 #endif
614 
StartNapiProfilerTrace(panda::JsiRuntimeCallInfo* runtimeInfo, void* cb)615 static inline uint64_t StartNapiProfilerTrace(panda::JsiRuntimeCallInfo* runtimeInfo, void* cb)
616 {
617 #ifdef ENABLE_HITRACE
618     if (ArkNativeEngine::napiProfilerEnabled) {
619         EcmaVM *vm = runtimeInfo->GetVM();
620         LocalScope scope(vm);
621         Local<panda::FunctionRef> fn = runtimeInfo->GetFunctionRef();
622         Local<panda::StringRef> nameRef = fn->GetName(vm);
623         char threadName[BUF_SIZE];
624         prctl(PR_GET_NAME, threadName);
625         StartTraceArgs(HITRACE_TAG_ACE, "Napi called:%s, tname:%s", nameRef->ToString(vm).c_str(), threadName);
626     }
627     bool hookFlag = __get_hook_flag() && __get_global_hook_flag();
628     if (!hookFlag) {
629         return 0;
630     }
631     EcmaVM* vm = runtimeInfo->GetVM();
632     LocalScope scope(vm);
633     Local<panda::FunctionRef> fn = runtimeInfo->GetFunctionRef();
634     Local<panda::StringRef> nameRef = fn->GetName(vm);
635     if (g_hookJsConfig == nullptr) {
636         std::call_once(g_hookOnceFlag, []() { g_hookJsConfig = (HookJsConfig*)__get_hook_config(); });
637     }
638     // add memtrace function
639     if (g_hookJsConfig != nullptr && g_hookJsConfig->jsStackReport == NAPI_CALL_STACK && !g_hookJsConfig->jsFpUnwind) {
640         OHOS::HiviewDFX::HiTraceChain::ClearId();
641         std::unique_ptr<OHOS::HiviewDFX::HiTraceId> arkCallBackTraceId = std::make_unique<OHOS::HiviewDFX::HiTraceId>(
642             OHOS::HiviewDFX::HiTraceChain::Begin("New ArkCallBackTrace", 0));
643         char buffer[256] = {0}; // 256 : buffer size of tag name
644         if (sprintf_s(buffer, sizeof(buffer), "napi:0x%x:%s", arkCallBackTraceId->GetChainId(),
645                       nameRef->ToString(vm).c_str()) == -1) {
646             return 0;
647         }
648         uint64_t addr = reinterpret_cast<uint64_t>(cb);
649         ++g_chainId;
650         (void)memtrace(reinterpret_cast<void*>(addr + g_chainId), 8, buffer, true); // 8: the size of addr
651         return 0;
652     }
653     if (!CheckHookConfig(nameRef->ToString(vm))) {
654         return 0;
655     }
656     BlockHookScope blockHook; // block hook
657     std::string rawStack;
658     std::vector<JsFrameInfo> jsFrames;
659     uint64_t nestChainId = 0;
660     jsFrames.reserve(g_hookJsConfig->maxJsStackDepth);
661     auto env = reinterpret_cast<napi_env>(JSNApi::GetEnv(vm));
662     auto engine = reinterpret_cast<NativeEngine*>(env);
663     engine->BuildJsStackInfoListWithCustomDepth(jsFrames);
664     std::stringstream ssRawStack;
665     for (size_t i = 0; i < jsFrames.size() && i < g_hookJsConfig->maxJsStackDepth; i++) {
666         ssRawStack << jsFrames[i].functionName << JS_SYMBOL_FILEPATH_SEP << jsFrames[i].fileName << ":" <<
667             jsFrames[i].pos;
668         if (i < jsFrames.size() - 1) {
669             ssRawStack << JS_CALL_STACK_DEPTH_SEP;
670         }
671     }
672     rawStack = ssRawStack.str();
673     OHOS::HiviewDFX::HiTraceChain::Begin("ArkNativeFunctionCallBack", 0);
674     OHOS::HiviewDFX::HiTraceId hitraceId = OHOS::HiviewDFX::HiTraceChain::GetId();
675     // resolve nested calls to napi and ts
676     if (hitraceId.IsValid()) {
677         nestChainId = hitraceId.GetChainId();
678     }
679     uint64_t chainId = ++g_chainId;
680     hitraceId.SetChainId(chainId);
681     OHOS::HiviewDFX::HiTraceChain::SetId(hitraceId);
682     __send_hook_misc_data(chainId, rawStack.c_str(), rawStack.size() + 1, 1);
683     return nestChainId;
684 
685 #endif
686     return 0;
687 }
688 
FinishNapiProfilerTrace(uint64_t value)689 static inline void FinishNapiProfilerTrace(uint64_t value)
690 {
691 #ifdef ENABLE_HITRACE
692     if (ArkNativeEngine::napiProfilerEnabled) {
693         FinishTrace(HITRACE_TAG_ACE);
694     }
695     bool hookFlag = __get_hook_flag() && __get_global_hook_flag();
696     if (!hookFlag) {
697         return;
698     }
699     BlockHookScope blockHook; // block hook
700     OHOS::HiviewDFX::HiTraceId hitraceId = OHOS::HiviewDFX::HiTraceChain::GetId();
701     if (hitraceId.IsValid()) {
702         OHOS::HiviewDFX::HiTraceChain::End(hitraceId);
703         OHOS::HiviewDFX::HiTraceChain::ClearId();
704     }
705     // resolve nested calls to napi and ts
706     if (value) {
707         hitraceId.SetChainId(value);
708         OHOS::HiviewDFX::HiTraceChain::SetId(hitraceId);
709     }
710 
711 #endif
712 }
713 
714 template <bool changeState>
ArkNativeFunctionCallBack(JsiRuntimeCallInfo *runtimeInfo)715 panda::JSValueRef ArkNativeFunctionCallBack(JsiRuntimeCallInfo *runtimeInfo)
716 {
717     EcmaVM *vm = runtimeInfo->GetVM();
718     panda::LocalScope scope(vm);
719     bool getStackBeforeCallNapiSuccess = false;
720     JSNApi::GetStackBeforeCallNapiSuccess(vm, getStackBeforeCallNapiSuccess);
721     auto info = reinterpret_cast<NapiFunctionInfo*>(runtimeInfo->GetData());
722     auto env = reinterpret_cast<napi_env>(JSNApi::GetEnv(vm));
723     auto engine = reinterpret_cast<NativeEngine*>(env);
724     auto cb = info->callback;
725     if (engine == nullptr) {
726         HILOG_ERROR("native engine is null");
727         return **JSValueRef::Undefined(vm);
728     }
729 
730     uint64_t nestChainId = StartNapiProfilerTrace(runtimeInfo, reinterpret_cast<void *>(cb));
731 
732     if (JSNApi::IsMixedDebugEnabled(vm)) {
733         JSNApi::NotifyNativeCalling(vm, reinterpret_cast<void *>(cb));
734     }
735 
736     napi_value result = nullptr;
737     if (cb != nullptr) {
738         if constexpr (changeState) {
739             panda::JsiNativeScope nativeScope(vm);
740             result = cb(env, runtimeInfo);
741         } else {
742             result = cb(env, runtimeInfo);
743         }
744     }
745 
746     if (JSNApi::IsMixedDebugEnabled(vm)) {
747         JSNApi::NotifyNativeReturn(vm, reinterpret_cast<void *>(cb));
748     }
749 
750     Local<panda::JSValueRef> localRet = panda::JSValueRef::Undefined(vm);
751     if (result != nullptr) {
752         localRet = LocalValueFromJsValue(result);
753     }
754 
755     FinishNapiProfilerTrace(nestChainId);
756     // Fixme: Rethrow error to engine while clear lastException_
757     if (!engine->lastException_.IsEmpty()) {
758         engine->lastException_.Empty();
759     }
760 
761     if (localRet.IsEmpty()) {
762         return **JSValueRef::Undefined(vm);
763     }
764     if (getStackBeforeCallNapiSuccess) {
765         JSNApi::GetStackAfterCallNapi(vm);
766     }
767     return **localRet;
768 }
769 
NapiNativeCreateFunction(napi_env env, const char* name, NapiNativeCallback cb, void* value)770 static Local<panda::JSValueRef> NapiNativeCreateFunction(napi_env env, const char* name,
771                                                          NapiNativeCallback cb, void* value)
772 {
773     auto engine = reinterpret_cast<NativeEngine*>(env);
774     auto vm = const_cast<EcmaVM*>(engine->GetEcmaVm());
775     NapiFunctionInfo* funcInfo = NapiFunctionInfo::CreateNewInstance();
776     if (funcInfo == nullptr) {
777         HILOG_ERROR("funcInfo is nullptr");
778         return JSValueRef::Undefined(vm);
779     }
780     funcInfo->callback = cb;
781     funcInfo->data = value;
782 #ifdef ENABLE_CONTAINER_SCOPE
783     funcInfo->scopeId = OHOS::Ace::ContainerScope::CurrentId();
784 #endif
785 
786     Local<panda::FunctionRef> fn = panda::FunctionRef::NewConcurrent(
787         vm, ArkNativeFunctionCallBack,
788         [](void* env, void* externalPointer, void* data) {
789             auto info = reinterpret_cast<NapiFunctionInfo*>(data);
790             if (info != nullptr) {
791                 delete info;
792             }
793         },
794         reinterpret_cast<void*>(funcInfo), true
795     );
796     Local<panda::StringRef> fnName = panda::StringRef::NewFromUtf8(vm, name);
797     fn->SetName(vm, fnName);
798     return fn;
799 }
800 
GetProperty(EcmaVM* vm, Local<panda::ObjectRef> &obj, const char* name)801 static Local<JSValueRef> GetProperty(EcmaVM* vm, Local<panda::ObjectRef> &obj, const char* name)
802 {
803     Local<StringRef> key = StringRef::NewFromUtf8(vm, name);
804     Local<JSValueRef> val = obj->Get(vm, key);
805     return val;
806 }
807 
GetCString(EcmaVM* vm, Local<StringRef> str, char* buffer, size_t size, size_t* length)808 void GetCString(EcmaVM* vm, Local<StringRef> str, char* buffer, size_t size, size_t* length)
809 {
810     if (length == nullptr) {
811         return;
812     }
813     if (buffer == nullptr) {
814         *length = str->Utf8Length(vm, true) - 1;
815     } else if (size != 0) {
816         uint32_t copied = str->WriteUtf8(vm, buffer, size - 1, true) - 1;
817         buffer[copied] = '\0';
818         *length = copied;
819     } else {
820         *length = 0;
821     }
822 }
823 
NapiGetModuleName(napi_env env, Local<panda::ObjectRef> &obj)824 std::string NapiGetModuleName(napi_env env, Local<panda::ObjectRef> &obj)
825 {
826     auto engine = reinterpret_cast<NativeEngine*>(env);
827     auto vm = const_cast<EcmaVM*>(engine->GetEcmaVm());
828     std::string moduleName("");
829     auto nativeModuleName = GetProperty(vm, obj, PANDA_MODULE_NAME);
830     if (nativeModuleName->IsString(vm)) {
831         char arrayName[PANDA_MODULE_NAME_LEN] = {0};
832         size_t len = 0;
833         GetCString(vm, nativeModuleName, arrayName, PANDA_MODULE_NAME_LEN, &len);
834         moduleName += arrayName;
835         moduleName += ".";
836     }
837     return moduleName;
838 }
839 
NapiDefinePropertyInner(napi_env env, Local<panda::ObjectRef> &obj, NapiPropertyDescriptor &propertyDescriptor, Local<panda::JSValueRef> &propertyName, bool &result)840 void NapiDefinePropertyInner(napi_env env,
841                              Local<panda::ObjectRef> &obj,
842                              NapiPropertyDescriptor &propertyDescriptor,
843                              Local<panda::JSValueRef> &propertyName,
844                              bool &result)
845 {
846     auto engine = reinterpret_cast<NativeEngine*>(env);
847     auto vm = engine->GetEcmaVm();
848     bool writable = (propertyDescriptor.attributes & NATIVE_WRITABLE) != 0;
849     bool enumable = (propertyDescriptor.attributes & NATIVE_ENUMERABLE) != 0;
850     bool configable = (propertyDescriptor.attributes & NATIVE_CONFIGURABLE) != 0;
851     std::string fullName("");
852     if (propertyDescriptor.getter != nullptr || propertyDescriptor.setter != nullptr) {
853 #ifdef ENABLE_HITRACE
854         fullName += NapiGetModuleName(env, obj);
855 #endif
856         Local<panda::JSValueRef> localGetter = panda::JSValueRef::Undefined(vm);
857         Local<panda::JSValueRef> localSetter = panda::JSValueRef::Undefined(vm);
858 
859         if (propertyDescriptor.getter != nullptr) {
860             fullName += "getter";
861             localGetter = NapiNativeCreateFunction(env, fullName.c_str(),
862                                                    propertyDescriptor.getter, propertyDescriptor.data);
863         }
864         if (propertyDescriptor.setter != nullptr) {
865             fullName += "setter";
866             localSetter = NapiNativeCreateFunction(env, fullName.c_str(),
867                                                    propertyDescriptor.setter, propertyDescriptor.data);
868         }
869 
870         PropertyAttribute attr(panda::JSValueRef::Undefined(vm), false, enumable, configable);
871         result = obj->SetAccessorProperty(vm, propertyName, localGetter, localSetter, attr);
872     } else if (propertyDescriptor.method != nullptr) {
873 #ifdef ENABLE_HITRACE
874         fullName += NapiGetModuleName(env, obj);
875 #endif
876         if (propertyDescriptor.utf8name != nullptr) {
877             fullName += propertyDescriptor.utf8name;
878         } else {
879             fullName += propertyName->IsString(vm)
880                         ? Local<panda::StringRef>(propertyName)->ToString(vm)
881                         : Local<panda::SymbolRef>(propertyName)->GetDescription(vm)->ToString(vm);
882         }
883         Local<panda::JSValueRef> cbObj = NapiNativeCreateFunction(env, fullName.c_str(),
884                                                                   propertyDescriptor.method, propertyDescriptor.data);
885         PropertyAttribute attr(cbObj, writable, enumable, configable);
886         result = obj->DefineProperty(vm, propertyName, attr);
887     } else {
888         Local<panda::JSValueRef> val = LocalValueFromJsValue(propertyDescriptor.value);
889 
890         PropertyAttribute attr(val, writable, enumable, configable);
891         result = obj->DefineProperty(vm, propertyName, attr);
892     }
893 }
894 
NapiDefineProperty(napi_env env, Local<panda::ObjectRef> &obj, NapiPropertyDescriptor propertyDescriptor)895 bool NapiDefineProperty(napi_env env, Local<panda::ObjectRef> &obj, NapiPropertyDescriptor propertyDescriptor)
896 {
897     auto engine = reinterpret_cast<NativeEngine*>(env);
898     auto vm = engine->GetEcmaVm();
899     bool result = false;
900     Local<panda::JSValueRef> propertyName;
901     if (propertyDescriptor.utf8name != nullptr) {
902         propertyName = panda::StringRef::NewFromUtf8(vm, propertyDescriptor.utf8name);
903     } else {
904         propertyName = LocalValueFromJsValue(propertyDescriptor.name);
905     }
906     if (obj->IsJSShared(vm)) {
907         NativeSendable::NapiDefineSendabledProperty(env, obj, propertyDescriptor, propertyName, result);
908     } else {
909         NapiDefinePropertyInner(env, obj, propertyDescriptor, propertyName, result);
910     }
911     Local<panda::ObjectRef> excep = panda::JSNApi::GetUncaughtException(vm);
912     if (!excep.IsNull()) {
913         HILOG_DEBUG("ArkNativeObject::DefineProperty occur Exception");
914         panda::JSNApi::GetAndClearUncaughtException(vm);
915     }
916     return result;
917 }
918 
NapiCreateObjectWithProperties(napi_env env, size_t propertyCount, const napi_property_descriptor *properties, Local<panda::JSValueRef> *keys, PropertyAttribute *attrs)919 panda::Local<panda::ObjectRef> NapiCreateObjectWithProperties(napi_env env, size_t propertyCount,
920                                                               const napi_property_descriptor *properties,
921                                                               Local<panda::JSValueRef> *keys,
922                                                               PropertyAttribute *attrs)
923 {
924     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
925     panda::EscapeLocalScope scope(vm);
926     for (size_t i = 0; i < propertyCount; ++i) {
927         const napi_property_descriptor &property = properties[i];
928 
929         const char* utf8name = property.utf8name;
930         uint32_t attributes = property.attributes;
931         bool writable = (attributes & NATIVE_WRITABLE) != 0;
932         bool enumable = (attributes & NATIVE_ENUMERABLE) != 0;
933         bool configable = (attributes & NATIVE_CONFIGURABLE) != 0;
934         NapiNativeCallback method = reinterpret_cast<NapiNativeCallback>(property.method);
935         NapiNativeCallback getter = reinterpret_cast<NapiNativeCallback>(property.getter);
936         NapiNativeCallback setter = reinterpret_cast<NapiNativeCallback>(property.setter);
937         napi_value value = property.value;
938         void *data = property.data;
939 
940         Local<panda::JSValueRef> val = panda::JSValueRef::Undefined(vm);
941 
942         std::string fullName("");
943         if (getter != nullptr || setter != nullptr) {
944             Local<panda::JSValueRef> localGetter = panda::JSValueRef::Undefined(vm);
945             Local<panda::JSValueRef> localSetter = panda::JSValueRef::Undefined(vm);
946 
947             if (getter != nullptr) {
948                 fullName += "getter";
949                 localGetter = NapiNativeCreateFunction(env, fullName.c_str(), getter, data);
950             }
951             if (setter != nullptr) {
952                 fullName += "setter";
953                 localSetter = NapiNativeCreateFunction(env, fullName.c_str(), setter, data);
954             }
955 
956             val = panda::ObjectRef::CreateAccessorData(vm, localGetter, localSetter);
957             writable = false;
958         } else if (method != nullptr) {
959             fullName += utf8name;
960             val = NapiNativeCreateFunction(env, fullName.c_str(), method, data);
961         } else {
962             val = LocalValueFromJsValue(value);
963         }
964         new (reinterpret_cast<void *>(&attrs[i])) PropertyAttribute(val, writable, enumable, configable);
965         keys[i] = panda::StringRef::NewFromUtf8(vm, utf8name);
966     }
967     Local<panda::ObjectRef> object = panda::ObjectRef::NewWithProperties(vm, propertyCount, keys, attrs);
968     return scope.Escape(object);
969 }
970 
NapiCreateSObjectWithProperties(napi_env env, size_t propertyCount, const NapiPropertyDescriptor* properties)971 panda::Local<panda::ObjectRef> NapiCreateSObjectWithProperties(napi_env env,
972                                                                size_t propertyCount,
973                                                                const NapiPropertyDescriptor* properties)
974 {
975     auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
976     panda::EscapeLocalScope scope(vm);
977     FunctionRef::SendablePropertiesInfo info;
978     for (size_t i = 0; i < propertyCount; ++i) {
979         NativeSendable::InitSendablePropertiesInfo(env, info, properties[i]);
980     }
981     Local<panda::ObjectRef> object = panda::ObjectRef::NewSWithProperties(vm, info);
982     return scope.Escape(object);
983 }
984 
GetModuleFromName( const std::string& moduleName, bool isAppModule, const std::string& id, const std::string& param, const std::string& instanceName, void** instance)985 panda::Local<panda::ObjectRef> ArkNativeEngine::GetModuleFromName(
986     const std::string& moduleName, bool isAppModule, const std::string& id, const std::string& param,
987     const std::string& instanceName, void** instance)
988 {
989     panda::EscapeLocalScope scope(vm_);
990     Local<ObjectRef> exports(JSValueRef::Undefined(vm_));
991     NativeModuleManager* moduleManager = NativeModuleManager::GetInstance();
992     std::string errInfo = "";
993     NativeModule* module = moduleManager->LoadNativeModule(moduleName.c_str(), nullptr, isAppModule, errInfo);
994     if (module != nullptr) {
995         Local<StringRef> idStr = StringRef::NewFromUtf8(vm_, id.c_str(), id.size());
996         napi_value idValue = JsValueFromLocalValue(idStr);
997         Local<StringRef> paramStr = StringRef::NewFromUtf8(vm_, param.c_str(), param.size());
998         napi_value paramValue = JsValueFromLocalValue(paramStr);
999         Local<ObjectRef> exportObj = ObjectRef::New(vm_);
1000         NapiPropertyDescriptor idProperty, paramProperty;
1001         idProperty.utf8name = "id";
1002         idProperty.value = idValue;
1003         paramProperty.utf8name = "param";
1004         paramProperty.value = paramValue;
1005         SetModuleName(exportObj, module->name);
1006         NapiDefineProperty(reinterpret_cast<napi_env>(this), exportObj, idProperty);
1007         NapiDefineProperty(reinterpret_cast<napi_env>(this), exportObj, paramProperty);
1008         MoudleNameLocker nameLocker(module->name);
1009         module->registerCallback(reinterpret_cast<napi_env>(this), JsValueFromLocalValue(exportObj));
1010         napi_value nExport = JsValueFromLocalValue(exportObj);
1011         napi_value exportInstance = nullptr;
1012         napi_status status = napi_get_named_property(
1013             reinterpret_cast<napi_env>(this), nExport, instanceName.c_str(), &exportInstance);
1014         if (status != napi_ok) {
1015             HILOG_ERROR("GetModuleFromName napi_get_named_property status != napi_ok");
1016         }
1017 
1018         status = napi_unwrap(reinterpret_cast<napi_env>(this), exportInstance, reinterpret_cast<void**>(instance));
1019         if (status != napi_ok) {
1020             HILOG_ERROR("GetModuleFromName napi_unwrap status != napi_ok");
1021         }
1022         exports = exportObj;
1023     }
1024     return scope.Escape(exports);
1025 }
1026 
CreatePromise(NativeDeferred** deferred)1027 napi_value ArkNativeEngine::CreatePromise(NativeDeferred** deferred)
1028 {
1029     panda::EscapeLocalScope scope(vm_);
1030     Local<PromiseCapabilityRef> capability = PromiseCapabilityRef::New(vm_);
1031     if (capability->IsUndefined()) {
1032         return JsValueFromLocalValue(scope.Escape(JSValueRef::Undefined(vm_)));
1033     }
1034     *deferred = new ArkNativeDeferred(this, capability);
1035     Local<JSValueRef> promiseValue = capability->GetPromise(vm_);
1036     return JsValueFromLocalValue(scope.Escape(promiseValue));
1037 }
1038 
LoadModuleByName(const std::string& moduleName, bool isAppModule, const std::string& param, const std::string& instanceName, void* instance, const std::string& path)1039 panda::Local<panda::ObjectRef> ArkNativeEngine::LoadModuleByName(const std::string& moduleName, bool isAppModule,
1040     const std::string& param, const std::string& instanceName, void* instance, const std::string& path)
1041 {
1042     panda::EscapeLocalScope scope(vm_);
1043     Local<ObjectRef> exports(JSValueRef::Undefined(vm_));
1044     NativeModuleManager* moduleManager = NativeModuleManager::GetInstance();
1045     std::string errInfo = "";
1046     NativeModule* module = moduleManager->LoadNativeModule(moduleName.c_str(),
1047         path.empty() ? nullptr : path.c_str(), isAppModule, errInfo);
1048     if (module != nullptr) {
1049         Local<ObjectRef> exportObj = ObjectRef::New(vm_);
1050         NapiPropertyDescriptor paramProperty, instanceProperty;
1051         Local<StringRef> paramStr = StringRef::NewFromUtf8(vm_, param.c_str(), param.size());
1052         napi_value paramValue = JsValueFromLocalValue(paramStr);
1053         paramProperty.utf8name = "param";
1054         paramProperty.value = paramValue;
1055         Local<ObjectRef> instanceValue = ObjectRef::New(vm_);
1056         Local<StringRef> key = StringRef::GetNapiWrapperString(vm_);
1057         if (instance == nullptr && instanceValue->Has(vm_, key)) {
1058             Local<ObjectRef> wrapper = instanceValue->Get(vm_, key);
1059             auto ref = reinterpret_cast<NativeReference*>(wrapper->GetNativePointerField(vm_, 0));
1060             wrapper->SetNativePointerField(vm_, 0, nullptr, nullptr, nullptr, 0);
1061             instanceValue->Delete(vm_, key);
1062             delete ref;
1063         } else {
1064             Local<ObjectRef> object = ObjectRef::New(vm_);
1065             NativeReference* ref = nullptr;
1066             Local<JSValueRef> value(instanceValue);
1067             ref = new ArkNativeReference(this, value, 0, true, nullptr, instance, nullptr);
1068 
1069             object->SetNativePointerFieldCount(vm_, 1);
1070             object->SetNativePointerField(vm_, 0, ref, nullptr, nullptr, 0);
1071             PropertyAttribute attr(object, true, false, true);
1072             instanceValue->DefineProperty(vm_, key, attr);
1073         }
1074         instanceProperty.utf8name = instanceName.c_str();
1075         instanceProperty.value = JsValueFromLocalValue(instanceValue);
1076         SetModuleName(exportObj, module->name);
1077         NapiDefineProperty(reinterpret_cast<napi_env>(this), exportObj, paramProperty);
1078         NapiDefineProperty(reinterpret_cast<napi_env>(this), exportObj, instanceProperty);
1079 
1080         MoudleNameLocker nameLocker(module->name);
1081         module->registerCallback(reinterpret_cast<napi_env>(this), JsValueFromLocalValue(exportObj));
1082         exports = exportObj;
1083     }
1084     return scope.Escape(exports);
1085 }
1086 
Loop(LoopMode mode, bool needSync)1087 void ArkNativeEngine::Loop(LoopMode mode, bool needSync)
1088 {
1089     LocalScope scope(vm_);
1090     NativeEngine::Loop(mode, needSync);
1091     panda::JSNApi::ExecutePendingJob(vm_);
1092 }
1093 
SetModuleName(Local<ObjectRef> &nativeObj, std::string moduleName)1094 void ArkNativeEngine::SetModuleName(Local<ObjectRef> &nativeObj, std::string moduleName)
1095 {
1096 #ifdef ENABLE_HITRACE
1097     if (ArkNativeEngine::napiProfilerEnabled) {
1098         Local<StringRef> moduleNameStr = StringRef::NewFromUtf8(vm_, moduleName.c_str(), moduleName.size());
1099         Local<StringRef> key = StringRef::NewFromUtf8(vm_, PANDA_MODULE_NAME);
1100         nativeObj->Set(vm_, key, moduleNameStr);
1101     }
1102 #endif
1103 }
1104 
ConcurrentCallbackFunc(Local<JSValueRef> result, bool success, void *taskInfo, void *data)1105 static void ConcurrentCallbackFunc(Local<JSValueRef> result, bool success, void *taskInfo, void *data)
1106 {
1107     if (data == nullptr) {
1108         return;
1109     }
1110     auto engine = static_cast<ArkNativeEngine *>(data);
1111     auto concurrentCallbackFunc = engine->GetConcurrentCallbackFunc();
1112     if (concurrentCallbackFunc == nullptr) {
1113         return;
1114     }
1115     napi_env env = reinterpret_cast<napi_env>(engine);
1116     concurrentCallbackFunc(env, ArkNativeEngine::ArkValueToNapiValue(env, result), success, taskInfo);
1117 }
1118 
InitTaskPoolThread(NativeEngine* engine, NapiConcurrentCallback callback)1119 bool ArkNativeEngine::InitTaskPoolThread(NativeEngine* engine, NapiConcurrentCallback callback)
1120 {
1121     concurrentCallbackFunc_ = callback;
1122     return JSNApi::InitForConcurrentThread(vm_, ConcurrentCallbackFunc, static_cast<void *>(this));
1123 }
1124 
InitTaskPoolThread(napi_env env, NapiConcurrentCallback callback)1125 bool ArkNativeEngine::InitTaskPoolThread(napi_env env, NapiConcurrentCallback callback)
1126 {
1127     concurrentCallbackFunc_ = callback;
1128     return JSNApi::InitForConcurrentThread(vm_, ConcurrentCallbackFunc, static_cast<void *>(this));
1129 }
1130 
InitTaskPoolFunc(napi_env env, napi_value func, void* taskInfo)1131 bool ArkNativeEngine::InitTaskPoolFunc(napi_env env, napi_value func, void* taskInfo)
1132 {
1133     LocalScope scope(vm_);
1134     Local<JSValueRef> function = LocalValueFromJsValue(func);
1135     return JSNApi::InitForConcurrentFunction(vm_, function, taskInfo);
1136 }
1137 
HasPendingJob() const1138 bool ArkNativeEngine::HasPendingJob() const
1139 {
1140     return JSNApi::HasPendingJob(vm_);
1141 }
1142 
IsProfiling() const1143 bool ArkNativeEngine::IsProfiling() const
1144 {
1145     return JSNApi::IsProfiling(vm_);
1146 }
1147 
IsExecutingPendingJob() const1148 bool ArkNativeEngine::IsExecutingPendingJob() const
1149 {
1150     return panda::JSNApi::IsExecutingPendingJob(vm_);
1151 }
1152 
GetCurrentTaskInfo() const1153 void* ArkNativeEngine::GetCurrentTaskInfo() const
1154 {
1155     return JSNApi::GetCurrentTaskInfo(vm_);
1156 }
1157 
ClearCurrentTaskInfo()1158 void ArkNativeEngine::ClearCurrentTaskInfo()
1159 {
1160     JSNApi::ClearCurrentTaskInfo(vm_);
1161 }
1162 
TerminateExecution() const1163 void ArkNativeEngine::TerminateExecution() const
1164 {
1165     DFXJSNApi::TerminateExecution(vm_);
1166 }
1167 
NotifyTaskBegin() const1168 void ArkNativeEngine::NotifyTaskBegin() const
1169 {
1170     JSNApi::NotifyTaskBegin(vm_);
1171 }
1172 
NotifyTaskFinished() const1173 void ArkNativeEngine::NotifyTaskFinished() const
1174 {
1175     JSNApi::NotifyTaskFinished(vm_);
1176 }
1177 
CallFunction( napi_value thisVar, napi_value function, napi_value const* argv, size_t argc)1178 napi_value ArkNativeEngine::CallFunction(
1179     napi_value thisVar, napi_value function, napi_value const* argv, size_t argc)
1180 {
1181     if (function == nullptr) {
1182         return nullptr;
1183     }
1184     panda::EscapeLocalScope scope(vm_);
1185     Local<JSValueRef> thisObj = JSValueRef::Undefined(vm_);
1186     if (thisVar != nullptr) {
1187         thisObj = LocalValueFromJsValue(thisVar);
1188     }
1189     Local<FunctionRef> funcObj = LocalValueFromJsValue(function);
1190     std::vector<Local<JSValueRef>> args;
1191     args.reserve(argc);
1192     for (size_t i = 0; i < argc; i++) {
1193         if (argv[i] != nullptr) {
1194             args.emplace_back(LocalValueFromJsValue(argv[i]));
1195         } else {
1196             args.emplace_back(JSValueRef::Undefined(vm_));
1197         }
1198     }
1199 
1200     Local<JSValueRef> value = funcObj->Call(vm_, thisObj, args.data(), argc);
1201     if (panda::JSNApi::HasPendingException(vm_)) {
1202         HILOG_ERROR("pending exception when js function called");
1203         HILOG_ERROR("print exception info: ");
1204         panda::JSNApi::PrintExceptionInfo(vm_);
1205         return nullptr;
1206     }
1207 
1208     return JsValueFromLocalValue(scope.Escape(value));
1209 }
1210 
NapiNewTypedArray(const EcmaVM* vm, NativeTypedArrayType typedArrayType, Local<panda::ArrayBufferRef> arrayBuf, size_t byte_offset, size_t length, napi_value* result)1211 bool ArkNativeEngine::NapiNewTypedArray(const EcmaVM* vm, NativeTypedArrayType typedArrayType,
1212                                         Local<panda::ArrayBufferRef> arrayBuf,
1213                                         size_t byte_offset, size_t length, napi_value* result)
1214 {
1215     Local<panda::TypedArrayRef> typedArray;
1216     switch (typedArrayType) {
1217         case NATIVE_INT8_ARRAY:
1218             typedArray = panda::Int8ArrayRef::New(vm, arrayBuf, byte_offset, length);
1219             break;
1220         case NATIVE_UINT8_ARRAY:
1221             typedArray = panda::Uint8ArrayRef::New(vm, arrayBuf, byte_offset, length);
1222             break;
1223         case NATIVE_UINT8_CLAMPED_ARRAY:
1224             typedArray = panda::Uint8ClampedArrayRef::New(vm, arrayBuf, byte_offset, length);
1225             break;
1226         case NATIVE_INT16_ARRAY:
1227             typedArray = panda::Int16ArrayRef::New(vm, arrayBuf, byte_offset, length);
1228             break;
1229         case NATIVE_UINT16_ARRAY:
1230             typedArray = panda::Uint16ArrayRef::New(vm, arrayBuf, byte_offset, length);
1231             break;
1232         case NATIVE_INT32_ARRAY:
1233             typedArray = panda::Int32ArrayRef::New(vm, arrayBuf, byte_offset, length);
1234             break;
1235         case NATIVE_UINT32_ARRAY:
1236             typedArray = panda::Uint32ArrayRef::New(vm, arrayBuf, byte_offset, length);
1237             break;
1238         case NATIVE_FLOAT32_ARRAY:
1239             typedArray = panda::Float32ArrayRef::New(vm, arrayBuf, byte_offset, length);
1240             break;
1241         case NATIVE_FLOAT64_ARRAY:
1242             typedArray = panda::Float64ArrayRef::New(vm, arrayBuf, byte_offset, length);
1243             break;
1244         case NATIVE_BIGINT64_ARRAY:
1245             typedArray = panda::BigInt64ArrayRef::New(vm, arrayBuf, byte_offset, length);
1246             break;
1247         case NATIVE_BIGUINT64_ARRAY:
1248             typedArray = panda::BigUint64ArrayRef::New(vm, arrayBuf, byte_offset, length);
1249             break;
1250         default:
1251             *result = nullptr;
1252             return false;
1253     }
1254     *result = JsValueFromLocalValue(typedArray);
1255     return true;
1256 }
1257 
NapiNewSendableTypedArray(const EcmaVM* vm, NativeTypedArrayType typedArrayType, Local<panda::SendableArrayBufferRef> arrayBuf, size_t byte_offset, size_t length, napi_value* result)1258 bool ArkNativeEngine::NapiNewSendableTypedArray(const EcmaVM* vm, NativeTypedArrayType typedArrayType,
1259                                                 Local<panda::SendableArrayBufferRef> arrayBuf,
1260                                                 size_t byte_offset, size_t length, napi_value* result)
1261 {
1262     Local<panda::SendableTypedArrayRef> typedArray;
1263     switch (typedArrayType) {
1264         case NATIVE_INT8_ARRAY:
1265             typedArray = panda::SharedInt8ArrayRef::New(vm, arrayBuf, byte_offset, length);
1266             break;
1267         case NATIVE_UINT8_ARRAY:
1268             typedArray = panda::SharedUint8ArrayRef::New(vm, arrayBuf, byte_offset, length);
1269             break;
1270         case NATIVE_INT16_ARRAY:
1271             typedArray = panda::SharedInt16ArrayRef::New(vm, arrayBuf, byte_offset, length);
1272             break;
1273         case NATIVE_UINT16_ARRAY:
1274             typedArray = panda::SharedUint16ArrayRef::New(vm, arrayBuf, byte_offset, length);
1275             break;
1276         case NATIVE_INT32_ARRAY:
1277             typedArray = panda::SharedInt32ArrayRef::New(vm, arrayBuf, byte_offset, length);
1278             break;
1279         case NATIVE_UINT32_ARRAY:
1280             typedArray = panda::SharedUint32ArrayRef::New(vm, arrayBuf, byte_offset, length);
1281             break;
1282         case NATIVE_FLOAT32_ARRAY:
1283             typedArray = panda::SharedFloat32ArrayRef::New(vm, arrayBuf, byte_offset, length);
1284             break;
1285         case NATIVE_UINT8_CLAMPED_ARRAY:
1286             typedArray = panda::SharedUint8ClampedArrayRef::New(vm, arrayBuf, byte_offset, length);
1287             break;
1288         default:
1289             *result = nullptr;
1290             return false;
1291     }
1292     *result = JsValueFromLocalValue(typedArray);
1293     return true;
1294 }
1295 
GetTypedArrayType(panda::Local<panda::TypedArrayRef> typedArray)1296 NativeTypedArrayType ArkNativeEngine::GetTypedArrayType(panda::Local<panda::TypedArrayRef> typedArray)
1297 {
1298     NativeTypedArrayType thisType = NATIVE_INT8_ARRAY;
1299     if (typedArray->IsInt32Array(vm_)) {
1300         thisType = NATIVE_INT32_ARRAY;
1301     } else if (typedArray->IsInt8Array(vm_)) {
1302         thisType = NATIVE_INT8_ARRAY;
1303     } else if (typedArray->IsUint8Array(vm_)) {
1304         thisType = NATIVE_UINT8_ARRAY;
1305     } else if (typedArray->IsUint8ClampedArray(vm_)) {
1306         thisType = NATIVE_UINT8_CLAMPED_ARRAY;
1307     } else if (typedArray->IsInt16Array(vm_)) {
1308         thisType = NATIVE_INT16_ARRAY;
1309     } else if (typedArray->IsUint16Array(vm_)) {
1310         thisType = NATIVE_UINT16_ARRAY;
1311     } else if (typedArray->IsUint32Array(vm_)) {
1312         thisType = NATIVE_UINT32_ARRAY;
1313     } else if (typedArray->IsFloat32Array(vm_)) {
1314         thisType = NATIVE_FLOAT32_ARRAY;
1315     } else if (typedArray->IsFloat64Array(vm_)) {
1316         thisType = NATIVE_FLOAT64_ARRAY;
1317     } else if (typedArray->IsBigInt64Array(vm_)) {
1318         thisType = NATIVE_BIGINT64_ARRAY;
1319     } else if (typedArray->IsBigUint64Array(vm_)) {
1320         thisType = NATIVE_BIGUINT64_ARRAY;
1321     }
1322 
1323     return thisType;
1324 }
1325 
GetSendableTypedArrayType(panda::Local<panda::SendableTypedArrayRef> typedArray)1326 NativeTypedArrayType ArkNativeEngine::GetSendableTypedArrayType(panda::Local<panda::SendableTypedArrayRef> typedArray)
1327 {
1328     NativeTypedArrayType thisType = NATIVE_INT8_ARRAY;
1329     if (typedArray->IsJSSharedInt8Array(vm_)) {
1330         thisType = NATIVE_INT8_ARRAY;
1331     } else if (typedArray->IsJSSharedUint8Array(vm_)) {
1332         thisType = NATIVE_UINT8_ARRAY;
1333     } else if (typedArray->IsJSSharedInt16Array(vm_)) {
1334         thisType = NATIVE_INT16_ARRAY;
1335     } else if (typedArray->IsJSSharedUint16Array(vm_)) {
1336         thisType = NATIVE_UINT16_ARRAY;
1337     } else if (typedArray->IsJSSharedInt32Array(vm_)) {
1338         thisType = NATIVE_INT32_ARRAY;
1339     } else if (typedArray->IsJSSharedUint32Array(vm_)) {
1340         thisType = NATIVE_UINT32_ARRAY;
1341     } else if (typedArray->IsJSSharedFloat32Array(vm_)) {
1342         thisType = NATIVE_FLOAT32_ARRAY;
1343     } else if (typedArray->IsJSSharedUint8ClampedArray(vm_)) {
1344         thisType = NATIVE_UINT8_CLAMPED_ARRAY;
1345     }
1346 
1347     return thisType;
1348 }
1349 
1350 /*
1351  * Before: input: 1. @ohos.hilog
1352                   2. @system.app (NATIVE_MODULE contains this name)
1353  * After: return: 1.@ohos:hilog
1354  *                2.@native:system.app
1355  */
GetOhmurl(std::string path)1356 std::string ArkNativeEngine::GetOhmurl(std::string path)
1357 {
1358     const std::regex reg("@(ohos|system)\\.(\\S+)");
1359     path.erase(0, path.find_first_not_of(" "));
1360     path.erase(path.find_last_not_of(" ") + 1);
1361     bool ret = std::regex_match(path, reg);
1362     if (!ret) {
1363         HILOG_ERROR("ArkNativeEngine:The module name doesn't comply with the naming rules");
1364         return "";
1365     }
1366     std::string systemModule = path.substr(1);
1367     if (NATIVE_MODULE.count(systemModule)) {
1368         return NATIVE_MODULE_PREFIX + systemModule;
1369     } else {
1370         int pos = static_cast<int>(path.find('.'));
1371         std::string systemKey = path.substr(pos + 1, systemModule.size());
1372         return OHOS_MODULE_PREFIX + systemKey;
1373     }
1374 }
1375 
NapiLoadNativeModule(std::string path)1376 Local<JSValueRef> ArkNativeEngine::NapiLoadNativeModule(std::string path)
1377 {
1378     std::string key = GetOhmurl(path);
1379     if (key.size() == 0) {
1380         return JSValueRef::Undefined(vm_);
1381     }
1382     return panda::JSNApi::ExecuteNativeModule(vm_, key);
1383 }
1384 
CheckLoadType(const std::string &path)1385 ModuleTypes ArkNativeEngine::CheckLoadType(const std::string &path)
1386 {
1387     if (path[0] == '@') {
1388         return ModuleTypes::NATIVE_MODULE;
1389     } else if (path.find("ets/") == 0) { // ets/xxx/xxx
1390         return ModuleTypes::MODULE_INNER_FILE;
1391     }
1392     return ModuleTypes::UNKNOWN;
1393 }
1394 
NapiLoadModule(const char* path, const char* module_info)1395 napi_value ArkNativeEngine::NapiLoadModule(const char* path, const char* module_info)
1396 {
1397     if (path == nullptr) {
1398         HILOG_ERROR("ArkNativeEngine:The module name is empty");
1399         return nullptr;
1400     }
1401     panda::EscapeLocalScope scope(vm_);
1402     Local<JSValueRef> undefObj = JSValueRef::Undefined(vm_);
1403     Local<ObjectRef> exportObj(undefObj);
1404     std::string inputPath(path);
1405     std::string modulePath;
1406     if (module_info != nullptr) {
1407         modulePath = module_info;
1408     }
1409     switch (CheckLoadType(inputPath)) {
1410         case ModuleTypes::NATIVE_MODULE: {
1411             exportObj = NapiLoadNativeModule(inputPath);
1412             break;
1413         }
1414         case ModuleTypes::MODULE_INNER_FILE: {
1415             exportObj = panda::JSNApi::GetModuleNameSpaceFromFile(vm_, inputPath, modulePath);
1416             break;
1417         }
1418         default: {
1419             std::string msg = "ArkNativeEngine:NapiLoadModule input path:" + inputPath + " is invalid.";
1420             ThrowException(msg.c_str());
1421         }
1422     }
1423     if (!exportObj->IsObject(vm_)) {
1424         ThrowException("ArkNativeEngine:NapiLoadModule failed.");
1425         return JsValueFromLocalValue(scope.Escape(undefObj));
1426     }
1427     return JsValueFromLocalValue(scope.Escape(exportObj));
1428 }
1429 
NapiLoadModuleWithInfo(const char* path, const char* module_info)1430 napi_value ArkNativeEngine::NapiLoadModuleWithInfo(const char* path, const char* module_info)
1431 {
1432     if (path == nullptr) {
1433         HILOG_ERROR("ArkNativeEngine:The module name is empty");
1434         return nullptr;
1435     }
1436     panda::EscapeLocalScope scope(vm_);
1437     Local<JSValueRef> undefObj = JSValueRef::Undefined(vm_);
1438     Local<ObjectRef> exportObj(undefObj);
1439     std::string inputPath(path);
1440     std::string modulePath;
1441     if (module_info != nullptr) {
1442         modulePath = module_info;
1443         exportObj = panda::JSNApi::GetModuleNameSpaceWithModuleInfo(vm_, inputPath, modulePath);
1444     } else {
1445         exportObj = NapiLoadNativeModule(inputPath);
1446     }
1447 
1448     if (!exportObj->IsObject(vm_)) {
1449         ThrowException("ArkNativeEngine:NapiLoadModuleWithInfo failed.");
1450         return JsValueFromLocalValue(scope.Escape(undefObj));
1451     }
1452     return JsValueFromLocalValue(scope.Escape(exportObj));
1453 }
1454 
SuspendVMById(uint32_t tid)1455 bool ArkNativeEngine::SuspendVMById(uint32_t tid)
1456 {
1457 #if !defined(PREVIEW) && !defined(IOS_PLATFORM)
1458     return DFXJSNApi::SuspendVMById(vm_, tid);
1459 #else
1460     HILOG_WARN("ARK does not support dfx on windows");
1461     return false;
1462 #endif
1463 }
1464 
ResumeVMById(uint32_t tid)1465 void ArkNativeEngine::ResumeVMById(uint32_t tid)
1466 {
1467 #if !defined(PREVIEW) && !defined(IOS_PLATFORM)
1468     DFXJSNApi::ResumeVMById(vm_, tid);
1469 #else
1470     HILOG_WARN("ARK does not support dfx on windows");
1471     return;
1472 #endif
1473 }
1474 
SetPackagePath(const std::string appLibPathKey, const std::vector<std::string>& packagePath)1475 void ArkNativeEngine::SetPackagePath(const std::string appLibPathKey, const std::vector<std::string>& packagePath)
1476 {
1477     auto moduleManager = NativeModuleManager::GetInstance();
1478     if (moduleManager && !packagePath.empty()) {
1479         moduleManager->SetAppLibPath(appLibPathKey, packagePath);
1480     }
1481 }
1482 
CreateInstance(napi_value constructor, napi_value const *argv, size_t argc)1483 napi_value ArkNativeEngine::CreateInstance(napi_value constructor, napi_value const *argv, size_t argc)
1484 {
1485     if (constructor == nullptr) {
1486         return nullptr;
1487     }
1488     panda::EscapeLocalScope scope(vm_);
1489     Local<FunctionRef> value = LocalValueFromJsValue(constructor);
1490     std::vector<Local<JSValueRef>> args;
1491     args.reserve(argc);
1492     for (size_t i = 0; i < argc; i++) {
1493         if (argv[i] != nullptr) {
1494             args.emplace_back(LocalValueFromJsValue(argv[i]));
1495         } else {
1496             args.emplace_back(JSValueRef::Undefined(vm_));
1497         }
1498     }
1499     Local<JSValueRef> instance = value->Constructor(vm_, args.data(), argc);
1500     Local<ObjectRef> excep = panda::JSNApi::GetUncaughtException(vm_);
1501     if (!excep.IsNull()) {
1502         HILOG_ERROR("ArkNativeEngineImpl::CreateInstance occur Exception");
1503         return nullptr;
1504     }
1505     return JsValueFromLocalValue(scope.Escape(instance));
1506 }
1507 
CreateReference(napi_value value, uint32_t initialRefcount, bool flag, NapiNativeFinalize callback, void* data, void* hint, size_t nativeBindingSize)1508 NativeReference* ArkNativeEngine::CreateReference(napi_value value, uint32_t initialRefcount,
1509     bool flag, NapiNativeFinalize callback, void* data, void* hint, size_t nativeBindingSize)
1510 {
1511     return new ArkNativeReference(this, value, initialRefcount, flag, callback, data, hint, false, nativeBindingSize);
1512 }
1513 
CreateAsyncReference(napi_value value, uint32_t initialRefcount, bool flag, NapiNativeFinalize callback, void* data, void* hint)1514 NativeReference* ArkNativeEngine::CreateAsyncReference(napi_value value, uint32_t initialRefcount,
1515     bool flag, NapiNativeFinalize callback, void* data, void* hint)
1516 {
1517     return new ArkNativeReference(this, value, initialRefcount, flag, callback, data, hint, true);
1518 }
1519 
RunCallbacks(TriggerGCData *triggerGCData)1520 __attribute__((optnone)) void ArkNativeEngine::RunCallbacks(TriggerGCData *triggerGCData)
1521 {
1522 #ifdef ENABLE_HITRACE
1523     StartTrace(HITRACE_TAG_ACE, "RunTriggerGCTaskCallback");
1524 #endif
1525     std::pair<void *, uint8_t> &param = *triggerGCData;
1526     JSNApi::TriggerIdleGC(reinterpret_cast<panda::ecmascript::EcmaVM *>(param.first),
1527         static_cast<panda::JSNApi::TRIGGER_IDLE_GC_TYPE>(param.second));
1528 #ifdef ENABLE_HITRACE
1529     FinishTrace(HITRACE_TAG_ACE);
1530 #endif
1531 }
1532 
RunCallbacks(ArkFinalizersPack *finalizersPack)1533 __attribute__((optnone)) void ArkNativeEngine::RunCallbacks(ArkFinalizersPack *finalizersPack)
1534 {
1535 #ifdef ENABLE_HITRACE
1536     StartTrace(HITRACE_TAG_ACE, "RunFinalizeCallbacks:" + std::to_string(finalizersPack->GetNumFinalizers()));
1537 #endif
1538     finalizersPack->ProcessAll();
1539 #ifdef ENABLE_HITRACE
1540     FinishTrace(HITRACE_TAG_ACE);
1541 #endif
1542 }
1543 
RunAsyncCallbacks(std::vector<RefFinalizer> *finalizers)1544 __attribute__((optnone)) void ArkNativeEngine::RunAsyncCallbacks(std::vector<RefFinalizer> *finalizers)
1545 {
1546 #ifdef ENABLE_HITRACE
1547     StartTrace(HITRACE_TAG_ACE, "RunFinalizeCallbacks:" + std::to_string(finalizers->size()));
1548 #endif
1549     for (auto iter : (*finalizers)) {
1550         NapiNativeFinalize callback = iter.first;
1551         std::tuple<NativeEngine*, void*, void*> &param = iter.second;
1552         callback(reinterpret_cast<napi_env>(std::get<0>(param)),
1553                  std::get<1>(param), std::get<2>(param)); // 2 is the param.
1554     }
1555 #ifdef ENABLE_HITRACE
1556     FinishTrace(HITRACE_TAG_ACE);
1557 #endif
1558 }
1559 
PostFinalizeTasks()1560 void ArkNativeEngine::PostFinalizeTasks()
1561 {
1562     if (IsInDestructor()) {
1563         return;
1564     }
1565     if (!pendingAsyncFinalizers_.empty()) {
1566         uv_work_t *asynWork = new uv_work_t;
1567         std::vector<RefFinalizer> *asyncFinalizers = new std::vector<RefFinalizer>();
1568         asyncFinalizers->swap(pendingAsyncFinalizers_);
1569         asynWork->data = reinterpret_cast<void *>(asyncFinalizers);
1570 
1571         int ret = uv_queue_work_with_qos(GetUVLoop(), asynWork, [](uv_work_t *asynWork) {
1572             std::vector<RefFinalizer> *finalizers = reinterpret_cast<std::vector<RefFinalizer> *>(asynWork->data);
1573             RunAsyncCallbacks(finalizers);
1574             HILOG_DEBUG("uv_queue_work async running ");
1575             delete finalizers;
1576         }, [](uv_work_t *asynWork, int32_t) {
1577             delete asynWork;
1578         }, uv_qos_t(napi_qos_background));
1579         if (ret != 0) {
1580             HILOG_ERROR("uv_queue_work fail ret '%{public}d'", ret);
1581             RunAsyncCallbacks(asyncFinalizers);
1582             delete asynWork;
1583             delete asyncFinalizers;
1584         }
1585     }
1586     if (arkFinalizersPack_.Empty()) {
1587         return;
1588     }
1589     ArkFinalizersPack *finalizersPack = new ArkFinalizersPack();
1590     std::swap(arkFinalizersPack_, *finalizersPack);
1591     if (!IsMainThread()) {
1592         panda::JsiNativeScope nativeScope(vm_);
1593         RunCallbacks(finalizersPack);
1594         delete finalizersPack;
1595         return;
1596     }
1597     size_t bindingSize = finalizersPack->GetTotalNativeBindingSize();
1598     if (pendingFinalizersPackNativeBindingSize_ > FINALIZERS_PACK_PENDING_NATIVE_BINDING_SIZE_THRESHOLD &&
1599         bindingSize > 0) {
1600         HILOG_DEBUG("Pending Finalizers NativeBindingSize '%{public}zu' large than '%{public}zu', process sync.",
1601             pendingFinalizersPackNativeBindingSize_, FINALIZERS_PACK_PENDING_NATIVE_BINDING_SIZE_THRESHOLD);
1602         panda::JsiNativeScope nativeScope(vm_);
1603         RunCallbacks(finalizersPack);
1604         delete finalizersPack;
1605         return;
1606     }
1607     uv_work_t *syncWork = new uv_work_t;
1608     finalizersPack->RegisterFinishNotify([this] (size_t totalNativeBindingSize) {
1609         this->DecreasePendingFinalizersPackNativeBindingSize(totalNativeBindingSize);
1610     });
1611     IncreasePendingFinalizersPackNativeBindingSize(bindingSize);
1612 
1613     syncWork->data = reinterpret_cast<void *>(finalizersPack);
1614     int ret = uv_queue_work_with_qos(GetUVLoop(), syncWork, [](uv_work_t *) {}, [](uv_work_t *syncWork, int32_t) {
1615         ArkFinalizersPack *finalizersPack = reinterpret_cast<ArkFinalizersPack*>(syncWork->data);
1616         RunCallbacks(finalizersPack);
1617         HILOG_DEBUG("uv_queue_work running");
1618         delete syncWork;
1619         delete finalizersPack;
1620     }, uv_qos_t(napi_qos_background));
1621     if (ret != 0) {
1622         HILOG_ERROR("uv_queue_work fail ret '%{public}d'", ret);
1623         panda::JsiNativeScope nativeScope(vm_);
1624         RunCallbacks(finalizersPack);
1625         delete syncWork;
1626         delete finalizersPack;
1627     }
1628 }
1629 
RunCallbacks(AsyncNativeCallbacksPack *callbacksPack)1630 __attribute__((optnone)) void ArkNativeEngine::RunCallbacks(AsyncNativeCallbacksPack *callbacksPack)
1631 {
1632 #ifdef ENABLE_HITRACE
1633     StartTrace(HITRACE_TAG_ACE, "RunNativeCallbacks:" + std::to_string(callbacksPack->GetNumCallBacks()));
1634 #endif
1635     callbacksPack->ProcessAll();
1636 #ifdef ENABLE_HITRACE
1637     FinishTrace(HITRACE_TAG_ACE);
1638 #endif
1639 }
1640 
PostAsyncTask(AsyncNativeCallbacksPack *callBacksPack)1641 void ArkNativeEngine::PostAsyncTask(AsyncNativeCallbacksPack *callBacksPack)
1642 {
1643     if (IsInDestructor()) {
1644         delete callBacksPack;
1645         return;
1646     }
1647     uv_work_t *syncWork = new uv_work_t;
1648     syncWork->data = reinterpret_cast<void *>(callBacksPack);
1649 
1650     int ret = uv_queue_work_with_qos(GetUVLoop(), syncWork, [](uv_work_t *) {}, [](uv_work_t *syncWork, int32_t) {
1651         AsyncNativeCallbacksPack *finalizers = reinterpret_cast<AsyncNativeCallbacksPack*>(syncWork->data);
1652         RunCallbacks(finalizers);
1653         HILOG_DEBUG("uv_queue_work running");
1654         delete syncWork;
1655         delete finalizers;
1656     }, uv_qos_t(napi_qos_background));
1657     if (ret != 0) {
1658         HILOG_ERROR("uv_queue_work fail ret '%{public}d'", ret);
1659         panda::JsiNativeScope nativeScope(vm_);
1660         RunCallbacks(callBacksPack);
1661         delete callBacksPack;
1662         delete syncWork;
1663     }
1664 }
1665 
PostTriggerGCTask(TriggerGCData& data)1666 void ArkNativeEngine::PostTriggerGCTask(TriggerGCData& data)
1667 {
1668     TriggerGCData *triggerGCData = new TriggerGCData(data);
1669     uv_work_t *syncWork = new uv_work_t;
1670     syncWork->data = reinterpret_cast<void *>(triggerGCData);
1671     int ret = uv_queue_work_with_qos(GetUVLoop(), syncWork, [](uv_work_t *) {}, [](uv_work_t *syncWork, int32_t) {
1672             auto triggerGCData = reinterpret_cast<TriggerGCData *>(syncWork->data);
1673             RunCallbacks(triggerGCData);
1674             delete syncWork;
1675             delete triggerGCData;
1676         }, uv_qos_t(napi_qos_user_initiated));
1677     if (ret != 0) {
1678         HILOG_ERROR("uv_queue_work fail ret '%{public}d'", ret);
1679         RunCallbacks(triggerGCData);
1680         delete syncWork;
1681         delete triggerGCData;
1682     }
1683 }
1684 
1685 #if defined(OHOS_PLATFORM) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
SetAttribute(bool isLimitedWorker, panda::RuntimeOption &option)1686 void ArkNativeEngine::SetAttribute(bool isLimitedWorker, panda::RuntimeOption &option)
1687 {
1688     int arkProperties = OHOS::system::GetIntParameter<int>("persist.ark.properties", -1);
1689     std::string bundleName = OHOS::system::GetParameter("persist.ark.arkbundlename", "");
1690     std::string memConfigProperty = OHOS::system::GetParameter("persist.ark.mem_config_property", "");
1691     size_t gcThreadNum = OHOS::system::GetUintParameter<size_t>("persist.ark.gcthreads", 7);
1692     size_t longPauseTime = OHOS::system::GetUintParameter<size_t>("persist.ark.longpausetime", 40);
1693     bool asmInterpreterEnabled = OHOS::system::GetBoolParameter("persist.ark.asminterpreter", true);
1694     std::string asmOpcodeDisableRange = OHOS::system::GetParameter("persist.ark.asmopcodedisablerange", "");
1695     bool builtinsLazyEnabled = OHOS::system::GetBoolParameter("persist.ark.enablebuiltinslazy", true);
1696     option.SetEnableBuiltinsLazy(builtinsLazyEnabled);
1697     option.SetArkProperties(arkProperties);
1698     option.SetArkBundleName(bundleName);
1699     option.SetMemConfigProperty(memConfigProperty);
1700     option.SetGcThreadNum(gcThreadNum);
1701     option.SetLongPauseTime(longPauseTime);
1702     option.SetEnableAsmInterpreter(asmInterpreterEnabled);
1703     option.SetAsmOpcodeDisableRange(asmOpcodeDisableRange);
1704     option.SetIsWorker();
1705     option.SetIsRestrictedWorker(isLimitedWorker);
1706     HILOG_DEBUG("ArkNativeEngineImpl::CreateRuntimeFunc ark properties = %{public}d, bundlename = %{public}s",
1707         arkProperties, bundleName.c_str());
1708 }
1709 #endif
1710 
CreateRuntimeFunc(NativeEngine* engine, void* jsEngine, bool isLimitedWorker)1711 NativeEngine* ArkNativeEngine::CreateRuntimeFunc(NativeEngine* engine, void* jsEngine, bool isLimitedWorker)
1712 {
1713     panda::RuntimeOption option;
1714 #if defined(OHOS_PLATFORM) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
1715     SetAttribute(isLimitedWorker, option);
1716 #endif
1717     option.SetGcType(panda::RuntimeOption::GC_TYPE::GEN_GC);
1718     const int64_t poolSize = 0x1000000;
1719     option.SetGcPoolSize(poolSize);
1720 #if !defined(PREVIEW) && !defined(IOS_PLATFORM)
1721     option.SetLogLevel(panda::RuntimeOption::LOG_LEVEL::INFO);
1722 #endif
1723     option.SetDebuggerLibraryPath("");
1724     EcmaVM* vm = panda::JSNApi::CreateJSVM(option);
1725     if (vm == nullptr) {
1726         return nullptr;
1727     }
1728     // worker adaptation mergeabc
1729     const panda::ecmascript::EcmaVM* hostVM = reinterpret_cast<ArkNativeEngine*>(engine)->GetEcmaVm();
1730     panda::JSNApi::SynchronizVMInfo(vm, hostVM);
1731     ArkNativeEngine* arkEngine = new ArkNativeEngine(vm, jsEngine, isLimitedWorker);
1732     // init callback
1733     arkEngine->RegisterWorkerFunction(engine);
1734     arkEngine->SetHostEngine(engine);
1735     // sync apiVersion
1736     arkEngine->SetApiVersion(engine->GetApiVersion());
1737 
1738     auto cleanEnv = [vm]() {
1739         if (vm != nullptr) {
1740             HILOG_DEBUG("cleanEnv is called");
1741             panda::JSNApi::DestroyJSVM(vm);
1742         }
1743     };
1744     arkEngine->SetCleanEnv(cleanEnv);
1745     if (hostVM != nullptr) {
1746         panda::JSNApi::AddWorker(const_cast<EcmaVM*>(hostVM), vm);
1747     }
1748     return arkEngine;
1749 }
1750 
CreateRuntime(bool isLimitedWorker)1751 void* ArkNativeEngine::CreateRuntime(bool isLimitedWorker)
1752 {
1753     return ArkNativeEngine::CreateRuntimeFunc(this, jsEngine_, isLimitedWorker);
1754 }
1755 
SetJsDumpThresholds(size_t thresholds)1756 void ArkNativeEngine::SetJsDumpThresholds(size_t thresholds)
1757 {
1758     DFXJSNApi::SetJsDumpThresholds(vm_, thresholds);
1759 }
1760 
SetAppFreezeFilterCallback(AppFreezeFilterCallback callback)1761 void ArkNativeEngine::SetAppFreezeFilterCallback(AppFreezeFilterCallback callback)
1762 {
1763     DFXJSNApi::SetAppFreezeFilterCallback(vm_, callback);
1764 }
1765 
StartCpuProfiler(const std::string& fileName)1766 void ArkNativeEngine::StartCpuProfiler(const std::string& fileName)
1767 {
1768     JSNApi::SetNativePtrGetter(vm_, reinterpret_cast<void*>(ArkNativeEngine::GetNativePtrCallBack));
1769     DFXJSNApi::StartCpuProfilerForFile(vm_, fileName);
1770 }
1771 
StopCpuProfiler()1772 void ArkNativeEngine::StopCpuProfiler()
1773 {
1774     DFXJSNApi::StopCpuProfilerForFile(vm_);
1775     JSNApi::SetNativePtrGetter(vm_, nullptr);
1776 }
1777 
ResumeVM()1778 void ArkNativeEngine::ResumeVM()
1779 {
1780     DFXJSNApi::ResumeVM(vm_);
1781 }
1782 
SuspendVM()1783 bool ArkNativeEngine::SuspendVM()
1784 {
1785     return DFXJSNApi::SuspendVM(vm_);
1786 }
1787 
IsSuspended()1788 bool ArkNativeEngine::IsSuspended()
1789 {
1790     return DFXJSNApi::IsSuspended(vm_);
1791 }
1792 
CheckSafepoint()1793 bool ArkNativeEngine::CheckSafepoint()
1794 {
1795     return DFXJSNApi::CheckSafepoint(vm_);
1796 }
1797 
GetCurrentModuleInfo(std::string& moduleName, std::string& fileName, bool needRecordName)1798 void ArkNativeEngine::GetCurrentModuleInfo(std::string& moduleName, std::string& fileName, bool needRecordName)
1799 {
1800     LocalScope scope(vm_);
1801     std::pair<std::string, std::string> moduleInfo = panda::JSNApi::GetCurrentModuleInfo(vm_, needRecordName);
1802     moduleName = moduleInfo.first; // if needRecordName is true, then moduleName is recordName.
1803     fileName = moduleInfo.second;
1804 }
1805 
GetIsBundle()1806 bool ArkNativeEngine::GetIsBundle()
1807 {
1808     LocalScope scope(vm_);
1809     return panda::JSNApi::IsBundle(vm_);
1810 }
1811 
GetIsNormalizedOhmUrlPack()1812 bool ArkNativeEngine::GetIsNormalizedOhmUrlPack()
1813 {
1814     LocalScope scope(vm_);
1815     return panda::JSNApi::IsNormalizedOhmUrlPack(vm_);
1816 }
1817 
GetIsDebugModeEnabled()1818 bool ArkNativeEngine::GetIsDebugModeEnabled()
1819 {
1820     LocalScope scope(vm_);
1821     return panda::JSNApi::IsDebugModeEnabled(vm_);
1822 }
1823 
GetBundleName()1824 std::string ArkNativeEngine::GetBundleName()
1825 {
1826     LocalScope scope(vm_);
1827     return panda::JSNApi::GetBundleName(vm_);
1828 }
1829 
GetPkgName(const std::string &moduleName)1830 std::string ArkNativeEngine::GetPkgName(const std::string &moduleName)
1831 {
1832     LocalScope scope(vm_);
1833     return panda::JSNApi::GetPkgName(vm_, moduleName);
1834 }
1835 
GetProcessStartRealTime()1836 int ArkNativeEngine::GetProcessStartRealTime()
1837 {
1838     LocalScope scope(vm_);
1839     return panda::JSNApi::GetStartRealTime(vm_);
1840 }
1841 
IsExecuteModuleInAbcFile(std::string bundleName, std::string moduleName, std::string ohmurl)1842 bool ArkNativeEngine::IsExecuteModuleInAbcFile(std::string bundleName, std::string moduleName, std::string ohmurl)
1843 {
1844     LocalScope scope(vm_);
1845     return panda::JSNApi::IsExecuteModuleInAbcFile(vm_, bundleName, moduleName, ohmurl);
1846 }
1847 
ValueToNapiValue(JSValueWrapper& value)1848 napi_value ArkNativeEngine::ValueToNapiValue(JSValueWrapper& value)
1849 {
1850     Global<JSValueRef> arkValue = value;
1851     return JsValueFromLocalValue(arkValue.ToLocal(vm_));
1852 }
1853 
ArkValueToNapiValue(napi_env env, Local<JSValueRef> value)1854 napi_value ArkNativeEngine::ArkValueToNapiValue(napi_env env, Local<JSValueRef> value)
1855 {
1856     return JsValueFromLocalValue(value);
1857 }
1858 
GetSourceCodeInfo(napi_value value, ErrorPos pos)1859 std::string ArkNativeEngine::GetSourceCodeInfo(napi_value value, ErrorPos pos)
1860 {
1861     if (value == nullptr || pos.first == 0) {
1862         return "";
1863     }
1864 
1865     LocalScope scope(vm_);
1866     Local<panda::FunctionRef> func = LocalValueFromJsValue(value);
1867     uint32_t line = pos.first;
1868     uint32_t column = pos.second;
1869     Local<panda::StringRef> sourceCode = func->GetSourceCode(vm_, line);
1870     std::string sourceCodeStr = sourceCode->ToString(vm_);
1871     if (sourceCodeStr.empty()) {
1872         return "";
1873     }
1874     std::string sourceCodeInfo = "SourceCode:\n";
1875     sourceCodeInfo.append(sourceCodeStr).append("\n");
1876     for (uint32_t k = 1; k < column; k++) {
1877         sourceCodeInfo.push_back(' ');
1878     }
1879     sourceCodeInfo.append("^\n");
1880     return sourceCodeInfo;
1881 }
1882 
TriggerFatalException(panda::Local<panda::JSValueRef> exceptionValue)1883 void ArkNativeEngine::TriggerFatalException(panda::Local<panda::JSValueRef> exceptionValue)
1884 {
1885     panda::JSNApi::ThrowException(GetEcmaVm(), exceptionValue);
1886     HandleUncaughtException();
1887 }
1888 
AdjustExternalMemory(int64_t ChangeInBytes, int64_t* AdjustedValue)1889 bool ArkNativeEngine::AdjustExternalMemory(int64_t ChangeInBytes, int64_t* AdjustedValue)
1890 {
1891     return true;
1892 }
1893 
SetPromiseRejectCallback(NativeReference* rejectCallbackRef, NativeReference* checkCallbackRef)1894 void ArkNativeEngine::SetPromiseRejectCallback(NativeReference* rejectCallbackRef, NativeReference* checkCallbackRef)
1895 {
1896     if (rejectCallbackRef == nullptr || checkCallbackRef == nullptr) {
1897         HILOG_ERROR("rejectCallbackRef or checkCallbackRef is nullptr");
1898         return;
1899     }
1900     promiseRejectCallbackRef_ = rejectCallbackRef;
1901     checkCallbackRef_ = checkCallbackRef;
1902     JSNApi::SetHostPromiseRejectionTracker(vm_, reinterpret_cast<void*>(PromiseRejectCallback),
1903                                            reinterpret_cast<void*>(this));
1904 }
1905 
PromiseRejectCallback(void* info)1906 void ArkNativeEngine::PromiseRejectCallback(void* info)
1907 {
1908     panda::PromiseRejectInfo* promiseRejectInfo = reinterpret_cast<panda::PromiseRejectInfo*>(info);
1909     ArkNativeEngine* env = reinterpret_cast<ArkNativeEngine*>(promiseRejectInfo->GetData());
1910 
1911     if (env == nullptr) {
1912         HILOG_ERROR("engine is nullptr");
1913         return;
1914     }
1915 
1916     if (env->promiseRejectCallbackRef_ == nullptr || env->checkCallbackRef_ == nullptr) {
1917         HILOG_ERROR("promiseRejectCallbackRef or checkCallbackRef is nullptr");
1918         return;
1919     }
1920     panda::ecmascript::EcmaVM* vm = const_cast<EcmaVM*>(env->GetEcmaVm());
1921     LocalScope scope(vm);
1922     Local<JSValueRef> promise = promiseRejectInfo->GetPromise();
1923     Local<JSValueRef> reason = promiseRejectInfo->GetReason();
1924     panda::PromiseRejectInfo::PROMISE_REJECTION_EVENT operation = promiseRejectInfo->GetOperation();
1925 
1926     Local<JSValueRef> type(IntegerRef::New(vm, static_cast<int32_t>(operation)));
1927 
1928     Local<JSValueRef> args[] = {type, promise, reason};
1929 
1930     napi_value promiseNapiRejectCallback = env->promiseRejectCallbackRef_->Get(env);
1931     Local<FunctionRef> promiseRejectCallback = LocalValueFromJsValue(promiseNapiRejectCallback);
1932     if (!promiseRejectCallback.IsEmpty()) {
1933         promiseRejectCallback->Call(vm, JSValueRef::Undefined(vm), args, 3); // 3 args size
1934     }
1935 
1936     if (operation == panda::PromiseRejectInfo::PROMISE_REJECTION_EVENT::REJECT) {
1937         Local<JSValueRef> checkCallback = LocalValueFromJsValue(env->checkCallbackRef_->Get(env));
1938         if (!checkCallback.IsEmpty()) {
1939             JSNApi::SetHostEnqueueJob(vm, checkCallback, panda::QueueType::QUEUE_SCRIPT);
1940         }
1941     }
1942 }
1943 
DumpHeapSnapshot(const std::string& path, bool isVmMode, DumpFormat dumpFormat, bool isPrivate, bool captureNumericValue)1944 void ArkNativeEngine::DumpHeapSnapshot(const std::string& path, bool isVmMode, DumpFormat dumpFormat,
1945                                        bool isPrivate, bool captureNumericValue)
1946 {
1947     panda::ecmascript::DumpSnapShotOption dumpOption;
1948     dumpOption.isVmMode = isVmMode;
1949     dumpOption.isSync = true;
1950     if (dumpFormat == DumpFormat::JSON) {
1951         dumpOption.dumpFormat = panda::ecmascript::DumpFormat::JSON;
1952         dumpOption.isPrivate = isPrivate;
1953         dumpOption.captureNumericValue = captureNumericValue;
1954         DFXJSNApi::DumpHeapSnapshot(vm_, path, dumpOption);
1955     }
1956     if (dumpFormat == DumpFormat::BINARY) {
1957         dumpOption.dumpFormat = panda::ecmascript::DumpFormat::BINARY;
1958         DFXJSNApi::DumpHeapSnapshot(vm_, path, dumpOption);
1959     }
1960     if (dumpFormat == DumpFormat::OTHER) {
1961         dumpOption.dumpFormat = panda::ecmascript::DumpFormat::OTHER;
1962         DFXJSNApi::DumpHeapSnapshot(vm_, path, dumpOption); // 2:enum is 2
1963     }
1964 }
1965 
DumpCpuProfile()1966 void ArkNativeEngine::DumpCpuProfile()
1967 {
1968     DFXJSNApi::DumpCpuProfile(vm_);
1969 }
1970 
DumpHeapSnapshot(bool isVmMode, DumpFormat dumpFormat, bool isPrivate, bool isFullGC)1971 void ArkNativeEngine::DumpHeapSnapshot(bool isVmMode, DumpFormat dumpFormat, bool isPrivate, bool isFullGC)
1972 {
1973     panda::ecmascript::DumpSnapShotOption dumpOption;
1974     dumpOption.isVmMode = isVmMode;
1975     dumpOption.isPrivate = isPrivate;
1976     dumpOption.isFullGC = isFullGC;
1977     dumpOption.isSync = false;
1978     if (dumpFormat == DumpFormat::JSON) {
1979         dumpOption.dumpFormat = panda::ecmascript::DumpFormat::JSON;
1980         DFXJSNApi::DumpHeapSnapshot(vm_, dumpOption);
1981     }
1982     if (dumpFormat == DumpFormat::BINARY) {
1983         dumpOption.dumpFormat = panda::ecmascript::DumpFormat::BINARY;
1984         DFXJSNApi::DumpHeapSnapshot(vm_, dumpOption);
1985     }
1986     if (dumpFormat == DumpFormat::OTHER) {
1987         dumpOption.dumpFormat = panda::ecmascript::DumpFormat::OTHER;
1988         DFXJSNApi::DumpHeapSnapshot(vm_, dumpOption);
1989     }
1990 }
1991 
BuildNativeAndJsStackTrace(std::string& stackTraceStr)1992 bool ArkNativeEngine::BuildNativeAndJsStackTrace(std::string& stackTraceStr)
1993 {
1994 #if !defined(PREVIEW) && !defined(IOS_PLATFORM)
1995     return DFXJSNApi::BuildNativeAndJsStackTrace(vm_, stackTraceStr);
1996 #else
1997     HILOG_WARN("ARK does not support dfx on windows");
1998     return false;
1999 #endif
2000 }
2001 
BuildJsStackTrace(std::string& stackTraceStr)2002 bool ArkNativeEngine::BuildJsStackTrace(std::string& stackTraceStr)
2003 {
2004 #if !defined(PREVIEW) && !defined(IOS_PLATFORM)
2005     return DFXJSNApi::BuildJsStackTrace(vm_, stackTraceStr);
2006 #else
2007     HILOG_WARN("ARK does not support dfx on windows");
2008     return false;
2009 #endif
2010 }
2011 
BuildJsStackInfoListWithCustomDepth(std::vector<JsFrameInfo>& jsFrames)2012 bool ArkNativeEngine::BuildJsStackInfoListWithCustomDepth(std::vector<JsFrameInfo>& jsFrames)
2013 {
2014 #if !defined(PREVIEW) && !defined(IOS_PLATFORM)
2015     bool sign = DFXJSNApi::BuildJsStackInfoList(vm_, gettid(), jsFrames);
2016     return sign;
2017 #else
2018     HILOG_WARN("ARK does not support dfx on windows");
2019     return false;
2020 #endif
2021 }
2022 
DeleteWorker(NativeEngine* workerEngine)2023 bool ArkNativeEngine::DeleteWorker(NativeEngine* workerEngine)
2024 {
2025     if (workerEngine != nullptr) {
2026 #if !defined(PREVIEW)
2027         const panda::ecmascript::EcmaVM* workerVM = reinterpret_cast<ArkNativeEngine*>(workerEngine)->GetEcmaVm();
2028         if (workerVM != nullptr) {
2029             return panda::JSNApi::DeleteWorker(vm_, const_cast<EcmaVM*>(workerVM));
2030         }
2031 #else
2032         HILOG_WARN("ARK does not support dfx on windows");
2033 #endif
2034         return false;
2035         }
2036     return false;
2037 }
2038 
StartHeapTracking(double timeInterval, bool isVmMode)2039 bool ArkNativeEngine::StartHeapTracking(double timeInterval, bool isVmMode)
2040 {
2041     return DFXJSNApi::StartHeapTracking(vm_, timeInterval, isVmMode);
2042 }
2043 
StopHeapTracking(const std::string &filePath)2044 bool ArkNativeEngine::StopHeapTracking(const std::string &filePath)
2045 {
2046     return DFXJSNApi::StopHeapTracking(vm_, filePath);
2047 }
2048 
2049 #if !defined(PREVIEW)
PrintStatisticResult()2050 void ArkNativeEngine::PrintStatisticResult()
2051 {
2052     DFXJSNApi::PrintStatisticResult(vm_);
2053 }
2054 
StartRuntimeStat()2055 void ArkNativeEngine::StartRuntimeStat()
2056 {
2057     DFXJSNApi::StartRuntimeStat(vm_);
2058 }
2059 
StopRuntimeStat()2060 void ArkNativeEngine::StopRuntimeStat()
2061 {
2062     DFXJSNApi::StopRuntimeStat(vm_);
2063 }
2064 
GetArrayBufferSize()2065 size_t ArkNativeEngine::GetArrayBufferSize()
2066 {
2067     return DFXJSNApi::GetArrayBufferSize(vm_);
2068 }
2069 
GetHeapTotalSize()2070 size_t ArkNativeEngine::GetHeapTotalSize()
2071 {
2072     return DFXJSNApi::GetHeapTotalSize(vm_);
2073 }
2074 
GetHeapUsedSize()2075 size_t ArkNativeEngine::GetHeapUsedSize()
2076 {
2077     return DFXJSNApi::GetHeapUsedSize(vm_);
2078 }
2079 
GetHeapObjectSize()2080 size_t ArkNativeEngine::GetHeapObjectSize()
2081 {
2082     return DFXJSNApi::GetHeapObjectSize(vm_);
2083 }
2084 
GetHeapLimitSize()2085 size_t ArkNativeEngine::GetHeapLimitSize()
2086 {
2087     return DFXJSNApi::GetHeapLimitSize(vm_);
2088 }
2089 
GetProcessHeapLimitSize()2090 size_t ArkNativeEngine::GetProcessHeapLimitSize()
2091 {
2092     return DFXJSNApi::GetProcessHeapLimitSize();
2093 }
2094 
GetGCCount()2095 size_t ArkNativeEngine::GetGCCount()
2096 {
2097     return DFXJSNApi::GetGCCount(vm_);
2098 }
2099 
GetGCDuration()2100 size_t ArkNativeEngine::GetGCDuration()
2101 {
2102     return DFXJSNApi::GetGCDuration(vm_);
2103 }
2104 
GetAccumulatedAllocateSize()2105 size_t ArkNativeEngine::GetAccumulatedAllocateSize()
2106 {
2107     return DFXJSNApi::GetAccumulatedAllocateSize(vm_);
2108 }
2109 
GetAccumulatedFreeSize()2110 size_t ArkNativeEngine::GetAccumulatedFreeSize()
2111 {
2112     return DFXJSNApi::GetAccumulatedFreeSize(vm_);
2113 }
2114 
GetFullGCLongTimeCount()2115 size_t ArkNativeEngine::GetFullGCLongTimeCount()
2116 {
2117     return DFXJSNApi::GetFullGCLongTimeCount(vm_);
2118 }
2119 
NotifyApplicationState(bool inBackground)2120 void ArkNativeEngine::NotifyApplicationState(bool inBackground)
2121 {
2122     DFXJSNApi::NotifyApplicationState(vm_, inBackground);
2123     arkIdleMonitor_->NotifyChangeBackgroundState(inBackground);
2124 }
2125 
NotifyIdleStatusControl(std::function<void(bool)> callback)2126 void ArkNativeEngine::NotifyIdleStatusControl(std::function<void(bool)> callback)
2127 {
2128     DFXJSNApi::NotifyIdleStatusControl(vm_, callback);
2129 }
2130 
NotifyIdleTime(int idleMicroSec)2131 void ArkNativeEngine::NotifyIdleTime(int idleMicroSec)
2132 {
2133     DFXJSNApi::NotifyIdleTime(vm_, idleMicroSec);
2134 }
2135 
NotifyMemoryPressure(bool inHighMemoryPressure)2136 void ArkNativeEngine::NotifyMemoryPressure(bool inHighMemoryPressure)
2137 {
2138     DFXJSNApi::NotifyMemoryPressure(vm_, inHighMemoryPressure);
2139 }
2140 
NotifyForceExpandState(int32_t value)2141 void ArkNativeEngine::NotifyForceExpandState(int32_t value)
2142 {
2143     switch (ForceExpandState(value)) {
2144         case ForceExpandState::FINISH_COLD_START:
2145             DFXJSNApi::NotifyFinishColdStart(vm_, true);
2146             break;
2147         case ForceExpandState::START_HIGH_SENSITIVE:
2148             DFXJSNApi::NotifyHighSensitive(vm_, true);
2149             break;
2150         case ForceExpandState::FINISH_HIGH_SENSITIVE:
2151             DFXJSNApi::NotifyHighSensitive(vm_, false);
2152             break;
2153         default:
2154             HILOG_ERROR("Invalid Force Expand State: %{public}d.", value);
2155             break;
2156     }
2157 }
2158 #else
PrintStatisticResult()2159 void ArkNativeEngine::PrintStatisticResult()
2160 {
2161     HILOG_WARN("ARK does not support dfx on windows");
2162 }
2163 
StartRuntimeStat()2164 void ArkNativeEngine::StartRuntimeStat()
2165 {
2166     HILOG_WARN("ARK does not support dfx on windows");
2167 }
2168 
StopRuntimeStat()2169 void ArkNativeEngine::StopRuntimeStat()
2170 {
2171     HILOG_WARN("ARK does not support dfx on windows");
2172 }
2173 
GetArrayBufferSize()2174 size_t ArkNativeEngine::GetArrayBufferSize()
2175 {
2176     HILOG_WARN("ARK does not support dfx on windows");
2177     return 0;
2178 }
2179 
GetHeapTotalSize()2180 size_t ArkNativeEngine::GetHeapTotalSize()
2181 {
2182     HILOG_WARN("ARK does not support dfx on windows");
2183     return 0;
2184 }
2185 
GetHeapUsedSize()2186 size_t ArkNativeEngine::GetHeapUsedSize()
2187 {
2188     HILOG_WARN("ARK does not support dfx on windows");
2189     return 0;
2190 }
2191 
GetHeapObjectSize()2192 size_t ArkNativeEngine::GetHeapObjectSize()
2193 {
2194     HILOG_WARN("ARK does not support dfx on windows");
2195     return 0;
2196 }
2197 
GetHeapLimitSize()2198 size_t ArkNativeEngine::GetHeapLimitSize()
2199 {
2200     HILOG_WARN("ARK does not support dfx on windows");
2201     return 0;
2202 }
2203 
GetProcessHeapLimitSize()2204 size_t ArkNativeEngine::GetProcessHeapLimitSize()
2205 {
2206     HILOG_WARN("ARK does not support dfx on windows");
2207     return 0;
2208 }
2209 
GetGCCount()2210 size_t ArkNativeEngine::GetGCCount()
2211 {
2212     HILOG_WARN("ARK does not support dfx on windows");
2213     return 0;
2214 }
2215 
GetGCDuration()2216 size_t ArkNativeEngine::GetGCDuration()
2217 {
2218     HILOG_WARN("ARK does not support dfx on windows");
2219     return 0;
2220 }
2221 
GetAccumulatedAllocateSize()2222 size_t ArkNativeEngine::GetAccumulatedAllocateSize()
2223 {
2224     HILOG_WARN("ARK does not support dfx on windows");
2225     return 0;
2226 }
2227 
GetAccumulatedFreeSize()2228 size_t ArkNativeEngine::GetAccumulatedFreeSize()
2229 {
2230     HILOG_WARN("ARK does not support dfx on windows");
2231     return 0;
2232 }
2233 
GetFullGCLongTimeCount()2234 size_t ArkNativeEngine::GetFullGCLongTimeCount()
2235 {
2236     HILOG_WARN("ARK does not support dfx on windows");
2237     return 0;
2238 }
2239 
NotifyApplicationState([[maybe_unused]] bool inBackground)2240 void ArkNativeEngine::NotifyApplicationState([[maybe_unused]] bool inBackground)
2241 {
2242     HILOG_WARN("ARK does not support dfx on windows");
2243 }
2244 
NotifyIdleStatusControl([[maybe_unused]] std::function<void(bool)> callback)2245 void ArkNativeEngine::NotifyIdleStatusControl([[maybe_unused]] std::function<void(bool)> callback)
2246 {
2247     HILOG_WARN("ARK does not support dfx on windows");
2248 }
2249 
NotifyIdleTime([[maybe_unused]] int idleMicroSec)2250 void ArkNativeEngine::NotifyIdleTime([[maybe_unused]] int idleMicroSec)
2251 {
2252     HILOG_WARN("ARK does not support dfx on windows");
2253 }
2254 
NotifyMemoryPressure([[maybe_unused]] bool inHighMemoryPressure)2255 void ArkNativeEngine::NotifyMemoryPressure([[maybe_unused]] bool inHighMemoryPressure)
2256 {
2257     HILOG_WARN("ARK does not support dfx on windows");
2258 }
2259 
NotifyForceExpandState([[maybe_unused]] int32_t value)2260 void ArkNativeEngine::NotifyForceExpandState([[maybe_unused]] int32_t value)
2261 {
2262     HILOG_WARN("ARK does not support dfx on windows");
2263 }
2264 #endif
2265 
SetMockModuleList(const std::map<std::string, std::string> &list)2266 void ArkNativeEngine::SetMockModuleList(const std::map<std::string, std::string> &list)
2267 {
2268     JSNApi::SetMockModuleList(vm_, list);
2269 }
2270 
RegisterNapiUncaughtExceptionHandler(NapiUncaughtExceptionCallback callback)2271 void ArkNativeEngine::RegisterNapiUncaughtExceptionHandler(NapiUncaughtExceptionCallback callback)
2272 {
2273     JSNApi::EnableUserUncaughtErrorHandler(vm_);
2274     napiUncaughtExceptionCallback_ = callback;
2275 }
2276 
HandleUncaughtException()2277 void ArkNativeEngine::HandleUncaughtException()
2278 {
2279     if (napiUncaughtExceptionCallback_ == nullptr) {
2280         return;
2281     }
2282     LocalScope scope(vm_);
2283     lastException_.Empty();
2284     Local<ObjectRef> exception = JSNApi::GetAndClearUncaughtException(vm_);
2285     if (!exception.IsEmpty() && !exception->IsHole()) {
2286         if (napiUncaughtExceptionCallback_ != nullptr) {
2287             napiUncaughtExceptionCallback_(ArkValueToNapiValue(reinterpret_cast<napi_env>(this), exception));
2288         }
2289     }
2290 }
2291 
HasPendingException()2292 bool ArkNativeEngine::HasPendingException()
2293 {
2294     return panda::JSNApi::HasPendingException(vm_);
2295 }
2296 
RegisterPermissionCheck(PermissionCheckCallback callback)2297 void ArkNativeEngine::RegisterPermissionCheck(PermissionCheckCallback callback)
2298 {
2299     if (permissionCheckCallback_ == nullptr) {
2300         permissionCheckCallback_ = callback;
2301     }
2302 }
2303 
ExecutePermissionCheck()2304 bool ArkNativeEngine::ExecutePermissionCheck()
2305 {
2306     if (permissionCheckCallback_ != nullptr) {
2307         return permissionCheckCallback_();
2308     } else {
2309         HILOG_INFO("permissionCheckCallback_ is still nullptr when executing permission check!");
2310         return true;
2311     }
2312 }
2313 
RegisterTranslateBySourceMap(SourceMapCallback callback)2314 void ArkNativeEngine::RegisterTranslateBySourceMap(SourceMapCallback callback)
2315 {
2316     if (SourceMapCallback_ == nullptr) {
2317         SourceMapCallback_ = callback;
2318     }
2319     // regedit SourceMapCallback to ark_js_runtime
2320     panda::JSNApi::SetSourceMapCallback(vm_, callback);
2321 }
2322 
RegisterSourceMapTranslateCallback(SourceMapTranslateCallback callback)2323 void ArkNativeEngine::RegisterSourceMapTranslateCallback(SourceMapTranslateCallback callback)
2324 {
2325     panda::JSNApi::SetSourceMapTranslateCallback(vm_, callback);
2326 }
2327 
ExecuteTranslateBySourceMap(const std::string& rawStack)2328 std::string ArkNativeEngine::ExecuteTranslateBySourceMap(const std::string& rawStack)
2329 {
2330     if (SourceMapCallback_ != nullptr) {
2331         return SourceMapCallback_(rawStack);
2332     } else {
2333         HILOG_WARN("SourceMapCallback_ is nullptr.");
2334         return rawStack;
2335     }
2336 }
2337 
IsMixedDebugEnabled()2338 bool ArkNativeEngine::IsMixedDebugEnabled()
2339 {
2340     return JSNApi::IsMixedDebugEnabled(vm_);
2341 }
2342 
NotifyNativeCalling(const void *nativeAddress)2343 void ArkNativeEngine::NotifyNativeCalling(const void *nativeAddress)
2344 {
2345     JSNApi::NotifyNativeCalling(vm_, nativeAddress);
2346 }
2347 
AllowCrossThreadExecution() const2348 void ArkNativeEngine::AllowCrossThreadExecution() const
2349 {
2350     JSNApi::AllowCrossThreadExecution(vm_);
2351 }
2352 
2353 #if !defined(is_arkui_x) && defined(OHOS_PLATFORM)
DumpHybridStack(const EcmaVM* vm)2354 std::string DumpHybridStack(const EcmaVM* vm)
2355 {
2356     constexpr size_t skipframes = 5;
2357     auto unwinder = std::make_shared<OHOS::HiviewDFX::Unwinder>();
2358     std::vector<OHOS::HiviewDFX::DfxFrame> frames;
2359     unwinder->EnableMethodIdLocal(true);
2360     if (unwinder->UnwindLocal(false, false, DEFAULT_MAX_FRAME_NUM, skipframes)) {
2361         frames = unwinder->GetFrames();
2362     } else {
2363         HILOG_ERROR("Failed to unwind local");
2364     }
2365 
2366     for (auto &frame : frames) {
2367         if (frame.isJsFrame) {
2368             DFXJSNApi::TranslateJSStackInfo(vm, frame.mapName, frame.line, frame.column);
2369         }
2370     }
2371 
2372     return OHOS::HiviewDFX::Unwinder::GetFramesStr(frames);
2373 }
2374 #endif
2375 
PostLooperTriggerIdleGCTask()2376 void ArkNativeEngine::PostLooperTriggerIdleGCTask()
2377 {
2378 #if defined(ENABLE_EVENT_HANDLER)
2379     std::shared_ptr<OHOS::AppExecFwk::EventRunner> mainThreadRunner =
2380         OHOS::AppExecFwk::EventRunner::GetMainEventRunner();
2381     if (mainThreadRunner.get() == nullptr) {
2382         HILOG_FATAL("ArkNativeEngine:: the mainEventRunner is nullptr");
2383         return;
2384     }
2385     auto callback = [this](OHOS::AppExecFwk::EventRunnerStage stage,
2386         const OHOS::AppExecFwk::StageInfo* info) -> int {
2387         switch (stage) {
2388             case OHOS::AppExecFwk::EventRunnerStage::STAGE_BEFORE_WAITING:
2389                 arkIdleMonitor_->NotifyLooperIdleStart(info->timestamp, info->sleepTime);
2390                 break;
2391             case OHOS::AppExecFwk::EventRunnerStage::STAGE_AFTER_WAITING:
2392                 arkIdleMonitor_->NotifyLooperIdleEnd(info->timestamp);
2393                 break;
2394             default:
2395                 HILOG_ERROR("this branch is unreachable");
2396         }
2397         return 0;
2398     };
2399     uint32_t stage = (static_cast<uint32_t>(OHOS::AppExecFwk::EventRunnerStage::STAGE_BEFORE_WAITING) |
2400         static_cast<uint32_t>(OHOS::AppExecFwk::EventRunnerStage::STAGE_AFTER_WAITING));
2401     mainThreadRunner->GetEventQueue()->AddObserver(OHOS::AppExecFwk::Observer::ARKTS_GC, stage, callback);
2402 #endif
2403 }
2404 
GetObjectHash(napi_env env, napi_value src)2405 int32_t ArkNativeEngine::GetObjectHash(napi_env env, napi_value src)
2406 {
2407     auto engine = reinterpret_cast<NativeEngine*>(env);
2408     auto vm = engine->GetEcmaVm();
2409     auto nativeValue = LocalValueFromJsValue(src);
2410     return DFXJSNApi::GetObjectHash(vm, nativeValue);
2411 }
2412 // LCOV_EXCL_STOP
2413 
RunScriptPath(const char* path, bool checkPath)2414 bool ArkNativeEngine::RunScriptPath(const char* path, bool checkPath)
2415 {
2416     if (checkPath && !IsValidPandaFile(path)) {
2417         HILOG_ERROR("file is not exist or format is invalid");
2418         return false;
2419     }
2420     // LCOV_EXCL_START
2421     panda::JSExecutionScope executionScope(vm_);
2422     LocalScope scope(vm_);
2423     [[maybe_unused]] bool ret = panda::JSNApi::Execute(vm_, path, PANDA_MAIN_FUNCTION);
2424     if (panda::JSNApi::HasPendingException(vm_)) {
2425         HandleUncaughtException();
2426         return false;
2427     }
2428     // LCOV_EXCL_STOP
2429     return true;
2430 }
2431 
IsValidPandaFile(const char* path)2432 bool ArkNativeEngine::IsValidPandaFile(const char* path)
2433 {
2434     if (path == nullptr) {
2435         HILOG_ERROR("file path is nullptr");
2436         return false;
2437     }
2438 
2439     char filePath[PATH_MAX + 1] = { 0 };
2440     if (!RealPath(path, filePath, PATH_MAX + 1)) {
2441         HILOG_ERROR("failed to format path");
2442         return false;
2443     }
2444     struct stat fileStat;
2445     int ret = stat(filePath, &fileStat);
2446     if (ret != 0) {
2447         HILOG_ERROR("script file \"%{public}s\" is not exist", filePath);
2448         return false;
2449     }
2450 
2451     if (!(fileStat.st_mode & S_IFREG)) {
2452         HILOG_ERROR("script path \"%{public}s\" is a directory", filePath);
2453         return false;
2454     }
2455     std::ifstream abcStream(filePath, std::ios::in | std::ios::binary);
2456 
2457     constexpr size_t fileHeaderLength = sizeof(uint64_t);
2458     uint8_t fileHeader[fileHeaderLength] = { 0 };
2459     if (abcStream.is_open()) {
2460         size_t fileSize = fileStat.st_size;
2461         if (fileSize < fileHeaderLength) {
2462             HILOG_ERROR("faild to read file header, invalid format \"%{public}s\"", filePath);
2463             abcStream.close();
2464             return false;
2465         }
2466         abcStream.read(reinterpret_cast<char*>(fileHeader), fileHeaderLength);
2467         abcStream.close();
2468         return IsValidScriptBuffer(fileHeader, fileHeaderLength);
2469     }
2470     return false;
2471 }
2472 
IsValidScriptBuffer(uint8_t* scriptBuffer, size_t bufferSize)2473 bool ArkNativeEngine::IsValidScriptBuffer(uint8_t* scriptBuffer, size_t bufferSize)
2474 {
2475     if (scriptBuffer == nullptr) {
2476         HILOG_ERROR("buffer is nullptr");
2477         return false;
2478     }
2479     constexpr size_t headerLen = sizeof(uint64_t);
2480     if (bufferSize < headerLen) {
2481         HILOG_ERROR("invalid buffer");
2482         return false;
2483     }
2484     constexpr char pandaFileHeader[headerLen] = "PANDA";
2485     const uint64_t bytePandaHeader = *reinterpret_cast<const uint64_t*>(pandaFileHeader);
2486     char fileHeader[headerLen] = { 0 };
2487     // Ensure destMax paramter is set correctly to avoid buffer overflows
2488     if (memcpy_s(fileHeader, sizeof(fileHeader), scriptBuffer, sizeof(fileHeader)) != 0) {
2489         HILOG_ERROR("faild to read file header of buffer");
2490         return false;
2491     }
2492 
2493     uint64_t byteFileHeader = *reinterpret_cast<uint64_t*>(fileHeader);
2494     if (byteFileHeader != bytePandaHeader) {
2495         HILOG_ERROR("invalid format of file buffer");
2496         return false;
2497     }
2498     return true;
2499 }
2500 
2501 // The security interface needs to be modified accordingly.
RunScriptBuffer(const char* path, std::vector<uint8_t>& buffer, bool isBundle)2502 napi_value ArkNativeEngine::RunScriptBuffer(const char* path, std::vector<uint8_t>& buffer, bool isBundle)
2503 {
2504     if (!IsValidScriptBuffer(buffer.data(), buffer.size())) {
2505         HILOG_ERROR("invalid script buffer");
2506         return nullptr;
2507     }
2508 
2509     // LCOV_EXCL_START
2510     panda::EscapeLocalScope scope(vm_);
2511     [[maybe_unused]] bool ret = false;
2512     if (isBundle) {
2513         ret = panda::JSNApi::Execute(vm_, buffer.data(), buffer.size(), PANDA_MAIN_FUNCTION, path);
2514     } else {
2515         ret = panda::JSNApi::ExecuteModuleBuffer(vm_, buffer.data(), buffer.size(), path);
2516     }
2517 
2518     if (panda::JSNApi::HasPendingException(vm_)) {
2519         HandleUncaughtException();
2520         return nullptr;
2521     }
2522     Local<JSValueRef> undefObj = JSValueRef::Undefined(vm_);
2523     // LCOV_EXCL_STOP
2524     return JsValueFromLocalValue(scope.Escape(undefObj));
2525 }
2526 
RunScriptBuffer(const std::string& path, uint8_t* buffer, size_t size, bool isBundle)2527 bool ArkNativeEngine::RunScriptBuffer(const std::string& path, uint8_t* buffer, size_t size, bool isBundle)
2528 {
2529     if (!IsValidScriptBuffer(buffer, size)) {
2530         HILOG_ERROR("invalid script buffer");
2531         return false;
2532     }
2533 
2534     // LCOV_EXCL_START
2535     panda::JSExecutionScope executionScope(vm_);
2536     LocalScope scope(vm_);
2537     bool ret = false;
2538     if (isBundle) {
2539         ret = panda::JSNApi::ExecuteSecure(vm_, buffer, size, PANDA_MAIN_FUNCTION, path);
2540     } else {
2541         ret = panda::JSNApi::ExecuteModuleBufferSecure(vm_, buffer, size, path);
2542     }
2543 
2544     if (panda::JSNApi::HasPendingException(vm_)) {
2545         HandleUncaughtException();
2546         return false;
2547     }
2548     return ret;
2549     // LCOV_EXCL_STOP
2550 }
2551 
RunBufferScript(std::vector<uint8_t>& buffer)2552 napi_value ArkNativeEngine::RunBufferScript(std::vector<uint8_t>& buffer)
2553 {
2554     if (!IsValidScriptBuffer(buffer.data(), buffer.size())) {
2555         HILOG_ERROR("invalid script buffer");
2556         return nullptr;
2557     }
2558 
2559     // LCOV_EXCL_START
2560     panda::EscapeLocalScope scope(vm_);
2561     [[maybe_unused]] bool ret = panda::JSNApi::Execute(vm_, buffer.data(), buffer.size(), PANDA_MAIN_FUNCTION);
2562 
2563     if (panda::JSNApi::HasPendingException(vm_)) {
2564         HandleUncaughtException();
2565         return nullptr;
2566     }
2567     Local<JSValueRef> undefObj = JSValueRef::Undefined(vm_);
2568     return JsValueFromLocalValue(scope.Escape(undefObj));
2569     // LCOV_EXCL_STOP
2570 }
2571 
2572 #define EXECUTE_BUFFER(functionName)                                                                 \
2573     if (panda::JSNApi::IsBundle(vm_)) {                                                              \
2574         /* FA doesn't enable securemem */                                                            \
2575         ret = panda::JSNApi::Execute(vm_, buffer, bufferSize, PANDA_MAIN_FUNCTION, desc);            \
2576     } else if (bufferSize != 0) {                                                                    \
2577         if (entryPoint == nullptr) {                                                                 \
2578             HILOG_DEBUG("Input entryPoint is nullptr, please input entryPoint for merged ESModule"); \
2579             /* this path for bundle and abc compiled by single module js */                          \
2580             ret = panda::JSNApi::functionName(vm_, buffer, bufferSize, PANDA_MAIN_FUNCTION, desc);   \
2581         } else {                                                                                     \
2582             /* this path for mergeabc with specific entryPoint */                                    \
2583             ret = panda::JSNApi::functionName(vm_, buffer, bufferSize, entryPoint, desc);            \
2584         }                                                                                            \
2585     } else {                                                                                         \
2586         /* this path for worker */                                                                   \
2587         ret = panda::JSNApi::Execute(vm_, desc, PANDA_MAIN_FUNCTION);                                \
2588     }
2589 
RunActor(uint8_t* buffer, size_t bufferSize, const char* descriptor, char* entryPoint, bool checkPath)2590 napi_value ArkNativeEngine::RunActor(uint8_t* buffer, size_t bufferSize,
2591     const char* descriptor, char* entryPoint, bool checkPath)
2592 {
2593     if (buffer == nullptr && descriptor == nullptr) {
2594         HILOG_ERROR("invalid param, both buffer and descriptor are nullptr");
2595         return nullptr;
2596     }
2597 
2598     if ((buffer != nullptr && !IsValidScriptBuffer(buffer, bufferSize)) &&
2599         (checkPath && descriptor != nullptr && !IsValidPandaFile(descriptor))) {
2600         HILOG_ERROR("invalid param");
2601         return nullptr;
2602     }
2603 
2604     // LCOV_EXCL_START
2605     panda::EscapeLocalScope scope(vm_);
2606     std::string desc(descriptor);
2607     [[maybe_unused]] bool ret = false;
2608     // if apiVersion > API11, use secure path.
2609     if (IsApplicationApiVersionAPI11Plus()) {
2610         EXECUTE_BUFFER(ExecuteSecure);
2611     } else {
2612         EXECUTE_BUFFER(Execute);
2613     }
2614     if (panda::JSNApi::HasPendingException(vm_)) {
2615         HandleUncaughtException();
2616         return nullptr;
2617     }
2618     Local<JSValueRef> undefObj = JSValueRef::Undefined(vm_);
2619     return JsValueFromLocalValue(scope.Escape(undefObj));
2620     // LCOV_EXCL_STOP
2621 }
2622 
LoadArkModule(const void* buffer, int32_t len, const std::string& fileName)2623 panda::Local<panda::ObjectRef> ArkNativeEngine::LoadArkModule(const void* buffer,
2624     int32_t len, const std::string& fileName)
2625 {
2626     panda::EscapeLocalScope scope(vm_);
2627     Local<ObjectRef> undefObj(JSValueRef::Undefined(vm_));
2628     if (buffer == nullptr || len <= 0 || fileName.empty()) {
2629         HILOG_ERROR("fileName is nullptr or source code is nullptr");
2630         return scope.Escape(undefObj);
2631     }
2632     if (!IsValidScriptBuffer(reinterpret_cast<uint8_t*>(const_cast<void*>(buffer)), len)) {
2633         HILOG_ERROR("invalid script buffer");
2634         return scope.Escape(undefObj);
2635     }
2636 
2637     // LCOV_EXCL_START
2638     bool res = JSNApi::ExecuteModuleFromBuffer(vm_, buffer, len, fileName);
2639     if (!res) {
2640         HILOG_ERROR("Execute module failed");
2641         return scope.Escape(undefObj);
2642     }
2643 
2644     Local<ObjectRef> exportObj = JSNApi::GetExportObjectFromBuffer(vm_, fileName, "default");
2645     if (exportObj->IsNull()) {
2646         HILOG_ERROR("Get export object failed");
2647         return scope.Escape(undefObj);
2648     }
2649 
2650     HILOG_DEBUG("ArkNativeEngineImpl::LoadModule end");
2651     return scope.Escape(exportObj);
2652     // LCOV_EXCL_STOP
2653 }
2654 
ExecuteJsBin(const std::string& fileName, bool checkPath)2655 bool ArkNativeEngine::ExecuteJsBin(const std::string& fileName, bool checkPath)
2656 {
2657     if (checkPath && !IsValidPandaFile(fileName.c_str())) {
2658         HILOG_ERROR("faild to execute js bin, file is not exist or format is invalid");
2659         return false;
2660     }
2661     // LCOV_EXCL_START
2662     panda::JSExecutionScope executionScope(vm_);
2663     LocalScope scope(vm_);
2664     bool ret = JSNApi::Execute(vm_, fileName, PANDA_MAIN_FUNCTION);
2665     return ret;
2666     // LCOV_EXCL_STOP
2667 }
2668