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