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