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