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