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 #ifndef FOUNDATION_ACE_NAPI_NATIVE_ENGINE_NATIVE_ENGINE_H 17 #define FOUNDATION_ACE_NAPI_NATIVE_ENGINE_NATIVE_ENGINE_H 18 19 #include <functional> 20 #include <list> 21 #include <string> 22 #include <unordered_map> 23 #include <unordered_set> 24 #include <vector> 25 #ifdef LINUX_PLATFORM 26 #include<atomic> 27 #endif 28 29 #include "callback_scope_manager/native_callback_scope_manager.h" 30 #include "ecmascript/napi/include/jsnapi.h" 31 #include "module_manager/native_module_manager.h" 32 #include "native_engine/native_async_work.h" 33 #include "native_engine/native_deferred.h" 34 #include "native_engine/native_reference.h" 35 #include "native_engine/native_safe_async_work.h" 36 #include "native_engine/native_event.h" 37 #include "native_engine/native_value.h" 38 #include "native_property.h" 39 #include "reference_manager/native_reference_manager.h" 40 #include "utils/macros.h" 41 #include "utils/data_protector.h" 42 43 namespace panda::ecmascript { 44 class EcmaVM; 45 } 46 47 typedef int32_t (*GetContainerScopeIdCallback)(void); 48 typedef void (*ContainerScopeCallback)(int32_t); 49 typedef struct uv_loop_s uv_loop_t; 50 51 struct NativeErrorExtendedInfo { 52 const char* message = nullptr; 53 void* reserved = nullptr; 54 uint32_t engineErrorCode = 0; 55 int errorCode = 0; 56 }; 57 58 enum LoopMode { 59 LOOP_DEFAULT, LOOP_ONCE, LOOP_NOWAIT 60 }; 61 62 enum class DumpFormat { 63 JSON, BINARY, OTHER 64 }; 65 66 enum class WorkerVersion { 67 NONE, OLD, NEW 68 }; 69 70 class WorkerThreadState { 71 public: CheckIdleState()72 void CheckIdleState() 73 { 74 if (!isRunning_.load() && taskCount_ == lastTaskCount_) { 75 checkCount_++; 76 return; 77 } 78 checkCount_ = 0; 79 lastTaskCount_ = taskCount_; 80 } 81 GetCheckCount()82 uint32_t GetCheckCount() 83 { 84 return checkCount_; 85 } 86 NoityTaskStart()87 void NoityTaskStart() 88 { 89 taskCount_++; 90 isRunning_.store(true); 91 } 92 NotifyTaskEnd()93 void NotifyTaskEnd() 94 { 95 isRunning_.store(false); 96 } 97 private: 98 std::atomic<bool> isRunning_ {false}; 99 uint32_t taskCount_ {0}; 100 uint32_t lastTaskCount_ {0}; 101 uint32_t checkCount_ {0}; 102 }; 103 104 using CleanupCallback = void (*)(void*); 105 using ThreadId = uint32_t; 106 class NapiOptions; 107 using PostTask = std::function<void(bool needSync)>; 108 using CleanEnv = std::function<void()>; 109 using InitWorkerFunc = std::function<void(NativeEngine* engine)>; 110 using GetAssetFunc = std::function<void(const std::string& uri, uint8_t **buff, size_t *buffSize, 111 std::vector<uint8_t>& content, std::string& ami, bool &useSecureMem, bool isRestricted)>; 112 using OffWorkerFunc = std::function<void(NativeEngine* engine)>; 113 using DebuggerPostTask = std::function<void(std::function<void()>&&)>; 114 using NapiUncaughtExceptionCallback = std::function<void(napi_value value)>; 115 using PermissionCheckCallback = std::function<bool()>; 116 using NapiConcurrentCallback = void (*)(napi_env env, napi_value result, bool success, void* data); 117 using SourceMapCallback = std::function<std::string(const std::string& rawStack)>; 118 using SourceMapTranslateCallback = std::function<bool(std::string& url, int& line, int& column, 119 std::string& packageName)>; 120 using AppFreezeFilterCallback = std::function<bool(const int32_t pid)>; 121 using EcmaVM = panda::ecmascript::EcmaVM; 122 using JsFrameInfo = panda::ecmascript::JsFrameInfo; 123 using NapiOnWorkerErrorCallback = std::function<bool(napi_env env, 124 napi_value exception, std::string name, uint32_t type)>; 125 using NapiOnMainThreadErrorCallback = std::function<bool(napi_env env, 126 std::string summary, std::string name, std::string message, std::string stack)>; 127 using NapiAllUnhandledRejectionCallback = std::function<bool(napi_env env, 128 napi_value* args, std::string name, uint32_t type)>; 129 using NapiAllPromiseRejectCallback = std::function<void(napi_value* args)>; 130 using NapiHasOnErrorCallback = std::function<bool()>; 131 using NapiHasAllUnhandledRejectionCallback = std::function<bool()>; 132 class NAPI_EXPORT NativeEngine { 133 public: 134 explicit NativeEngine(void* jsEngine); 135 virtual ~NativeEngine(); 136 137 virtual NativeModuleManager* GetModuleManager(); 138 virtual NativeReferenceManager* GetReferenceManager(); 139 virtual NativeCallbackScopeManager* GetCallbackScopeManager(); 140 virtual uv_loop_t* GetUVLoop() const; 141 virtual pthread_t GetTid() const; GetSysTid()142 inline ThreadId GetSysTid() const 143 { 144 return sysTid_; 145 }; 146 static ThreadId GetCurSysTid(); GetId()147 inline uint64_t GetId() const 148 { 149 return id_; 150 }; 151 152 virtual bool ReinitUVLoop(); 153 154 virtual void Loop(LoopMode mode, bool needSync = false); 155 virtual void SetPostTask(PostTask postTask); 156 virtual void TriggerPostTask(); 157 #if !defined(PREVIEW) 158 virtual void CheckUVLoop(); 159 virtual void CancelCheckUVLoop(); 160 #endif 161 virtual void* GetJsEngine(); 162 163 virtual const EcmaVM* GetEcmaVm() const = 0; 164 virtual bool NapiNewTypedArray(const EcmaVM* vm, NativeTypedArrayType typedArrayType, 165 panda::Local<panda::ArrayBufferRef> arrayBuf, size_t byte_offset, 166 size_t length, napi_value* result) = 0; 167 virtual bool NapiNewSendableTypedArray(const EcmaVM* vm, NativeTypedArrayType typedArrayType, 168 panda::Local<panda::SendableArrayBufferRef> arrayBuf, size_t byte_offset, 169 size_t length, napi_value* result) = 0; 170 virtual NativeTypedArrayType GetTypedArrayType(panda::Local<panda::TypedArrayRef> typedArray) = 0; 171 virtual NativeTypedArrayType GetSendableTypedArrayType(panda::Local<panda::SendableTypedArrayRef> typedArray) = 0; 172 virtual void SetPromiseRejectCallback(NativeReference* rejectCallbackRef, NativeReference* checkCallbackRef) = 0; 173 174 virtual bool InitTaskPoolThread(NativeEngine* engine, NapiConcurrentCallback callback) = 0; 175 virtual bool InitTaskPoolThread(napi_env env, NapiConcurrentCallback callback) = 0; 176 virtual bool InitTaskPoolFunc(napi_env env, napi_value func, void* taskInfo) = 0; 177 virtual void ClearCurrentTaskInfo() = 0; 178 virtual bool HasPendingJob() const = 0; 179 virtual bool IsProfiling() const = 0; 180 virtual bool IsExecutingPendingJob() const = 0; 181 virtual void* GetCurrentTaskInfo() const = 0; 182 virtual void TerminateExecution() const = 0; 183 virtual void NotifyTaskBegin() const = 0; 184 virtual void NotifyTaskFinished() const = 0; 185 186 virtual napi_value CallFunction(napi_value thisVar, 187 napi_value function, 188 napi_value const *argv, 189 size_t argc) = 0; 190 virtual bool RunScriptPath(const char* path, bool checkPath = false) = 0; 191 virtual napi_value RunScriptBuffer(const char* path, std::vector<uint8_t>& buffer, bool isBundle, 192 bool needUpdate = false) = 0; 193 virtual bool RunScriptBuffer(const std::string &path, uint8_t* buffer, size_t size, bool isBundle) = 0; 194 virtual napi_value RunBufferScript(std::vector<uint8_t>& buffer) = 0; 195 virtual napi_value RunActor(uint8_t* buffer, size_t bufferSize, 196 const char* descriptor, char* entryPoint = nullptr, bool checkPath = false) = 0; 197 198 virtual napi_value CreateInstance(napi_value constructor, napi_value const *argv, size_t argc) = 0; 199 200 virtual NativeReference* CreateReference(napi_value value, uint32_t initialRefcount, 201 bool flag = false, NapiNativeFinalize callback = nullptr, void* data = nullptr, void* hint = nullptr, 202 size_t nativeBindingSize = 0) = 0; 203 204 virtual NativeReference* CreateAsyncReference(napi_value value, uint32_t initialRefcount, 205 bool flag = false, NapiNativeFinalize callback = nullptr, void* data = nullptr, void* hint = nullptr) = 0; 206 207 virtual NativeAsyncWork* CreateAsyncWork(napi_value asyncResource, 208 napi_value asyncResourceName, 209 NativeAsyncExecuteCallback execute, 210 NativeAsyncCompleteCallback complete, 211 void* data); 212 213 virtual NativeAsyncWork* CreateAsyncWork(const std::string &asyncResourceName, 214 NativeAsyncExecuteCallback execute, 215 NativeAsyncCompleteCallback complete, 216 void* data); 217 virtual NativeSafeAsyncWork* CreateSafeAsyncWork(napi_value func, napi_value asyncResource, 218 napi_value asyncResourceName, size_t maxQueueSize, size_t threadCount, void* finalizeData, 219 NativeFinalize finalizeCallback, void* context, NativeThreadSafeFunctionCallJs callJsCallback); 220 virtual void* CreateRuntime(bool isLimitedWorker = false) = 0; 221 virtual napi_value CreatePromise(NativeDeferred** deferred) = 0; 222 223 virtual void SetJsDumpThresholds(size_t thresholds) = 0; 224 virtual void SetAppFreezeFilterCallback(AppFreezeFilterCallback callback) = 0; 225 226 virtual void StartCpuProfiler(const std::string& fileName = "") = 0; 227 virtual void StopCpuProfiler() = 0; 228 229 virtual void ResumeVM() = 0; 230 virtual bool SuspendVM() = 0; 231 virtual bool IsSuspended() = 0; 232 virtual bool CheckSafepoint() = 0; 233 virtual bool SuspendVMById(uint32_t tid) = 0; 234 virtual void ResumeVMById(uint32_t tid) = 0; 235 236 virtual void DumpHeapSnapshot(const std::string &path, bool isVmMode = true, 237 DumpFormat dumpFormat = DumpFormat::JSON, bool isPrivate = false, bool captureNumericValue = false) = 0; 238 virtual void DumpHeapSnapshot(int& fd, bool isFullGC, const std::function<void(uint8_t)> &callback) = 0; 239 virtual void DumpCpuProfile() = 0; 240 virtual void DumpHeapSnapshot(bool isVmMode = true, DumpFormat dumpFormat = DumpFormat::JSON, 241 bool isPrivate = false, bool isFullGC = true) = 0; 242 virtual bool BuildNativeAndJsStackTrace(std::string &stackTraceStr) = 0; 243 virtual bool BuildJsStackTrace(std::string &stackTraceStr) = 0; 244 virtual bool BuildJsStackInfoListWithCustomDepth(std::vector<JsFrameInfo>& jsFrames) 245 = 0; 246 virtual bool DeleteWorker(NativeEngine* workerEngine) = 0; 247 virtual bool StartHeapTracking(double timeInterval, bool isVmMode = true) = 0; 248 virtual bool StopHeapTracking(const std::string &filePath) = 0; 249 250 virtual void AllowCrossThreadExecution() const = 0; 251 252 NativeErrorExtendedInfo* GetLastError(); 253 void SetLastError(int errorCode, uint32_t engineErrorCode = 0, void* engineReserved = nullptr); ClearLastError()254 void ClearLastError() 255 { 256 lastError_.errorCode = 0; 257 lastError_.engineErrorCode = 0; 258 lastError_.message = nullptr; 259 lastError_.reserved = nullptr; 260 } 261 void EncodeToUtf8(napi_value value, char* buffer, uint32_t* written, size_t bufferSize, int32_t* nchars); 262 void EncodeToChinese(napi_value value, std::string& buffer, const std::string& encoding); 263 NativeEngine(NativeEngine&) = delete; 264 virtual NativeEngine& operator=(NativeEngine&) = delete; 265 266 virtual napi_value ValueToNapiValue(JSValueWrapper& value) = 0; 267 virtual std::string GetSourceCodeInfo(napi_value value, ErrorPos pos) = 0; 268 269 virtual void TriggerFatalException(panda::Local<panda::JSValueRef> exceptionValue) = 0; 270 virtual bool AdjustExternalMemory(int64_t ChangeInBytes, int64_t* AdjustedValue) = 0; 271 MarkWorkerThread()272 void MarkWorkerThread() 273 { 274 jsThreadType_.Update(static_cast<uintptr_t>(JSThreadType::WORKER_THREAD)); 275 } MarkRestrictedWorkerThread()276 void MarkRestrictedWorkerThread() 277 { 278 jsThreadType_.Update(static_cast<uintptr_t>(JSThreadType::RESTRICTEDWORKER_THREAD)); 279 } MarkTaskPoolThread()280 void MarkTaskPoolThread() 281 { 282 jsThreadType_.Update(static_cast<uintptr_t>(JSThreadType::TASKPOOL_THREAD)); 283 } MarkNativeThread()284 void MarkNativeThread() 285 { 286 jsThreadType_.Update(static_cast<uintptr_t>(JSThreadType::NATIVE_THREAD)); 287 } IsWorkerThread()288 bool IsWorkerThread() const 289 { 290 return static_cast<JSThreadType>(jsThreadType_.GetData()) == JSThreadType::WORKER_THREAD; 291 } IsRestrictedWorkerThread()292 bool IsRestrictedWorkerThread() const 293 { 294 return static_cast<JSThreadType>(jsThreadType_.GetData()) == JSThreadType::RESTRICTEDWORKER_THREAD; 295 } IsTaskPoolThread()296 bool IsTaskPoolThread() const 297 { 298 return static_cast<JSThreadType>(jsThreadType_.GetData()) == JSThreadType::TASKPOOL_THREAD; 299 } IsMainThread()300 bool IsMainThread() const 301 { 302 return static_cast<JSThreadType>(jsThreadType_.GetData()) == JSThreadType::MAIN_THREAD; 303 } IsNativeThread()304 bool IsNativeThread() const 305 { 306 return static_cast<JSThreadType>(jsThreadType_.GetData()) == JSThreadType::NATIVE_THREAD; 307 } 308 CheckAndSetWorkerVersion(WorkerVersion expected,WorkerVersion desired)309 bool CheckAndSetWorkerVersion(WorkerVersion expected, WorkerVersion desired) 310 { 311 return workerVersion_.compare_exchange_strong(expected, desired); 312 } IsTargetWorkerVersion(WorkerVersion target)313 bool IsTargetWorkerVersion(WorkerVersion target) const 314 { 315 return workerVersion_.load() == target; 316 } 317 IncreaseSubEnvCounter()318 void IncreaseSubEnvCounter() 319 { 320 subEnvCounter_++; 321 } DecreaseSubEnvCounter()322 void DecreaseSubEnvCounter() 323 { 324 subEnvCounter_--; 325 } HasSubEnv()326 bool HasSubEnv() 327 { 328 return subEnvCounter_.load() != 0; 329 } 330 SetCleanEnv(CleanEnv cleanEnv)331 void SetCleanEnv(CleanEnv cleanEnv) 332 { 333 cleanEnv_ = cleanEnv; 334 } 335 336 // register init worker func 337 virtual void SetInitWorkerFunc(InitWorkerFunc func); 338 InitWorkerFunc GetInitWorkerFunc() const; 339 virtual void SetGetAssetFunc(GetAssetFunc func); 340 GetAssetFunc GetGetAssetFunc() const; 341 virtual void SetOffWorkerFunc(OffWorkerFunc func); 342 OffWorkerFunc GetOffWorkerFunc() const; 343 344 // call init worker func 345 virtual bool CallInitWorkerFunc(NativeEngine* engine); 346 virtual bool CallGetAssetFunc(const std::string& uri, uint8_t **buff, size_t *buffSize, 347 std::vector<uint8_t>& content, std::string& ami, bool &useSecureMem, bool isRestricted); 348 virtual bool CallOffWorkerFunc(NativeEngine* engine); 349 350 // adapt worker to ace container 351 virtual void SetGetContainerScopeIdFunc(GetContainerScopeIdCallback func); 352 virtual void SetInitContainerScopeFunc(ContainerScopeCallback func); 353 virtual void SetFinishContainerScopeFunc(ContainerScopeCallback func); 354 virtual int32_t GetContainerScopeIdFunc(); 355 virtual bool InitContainerScopeFunc(int32_t id); 356 virtual bool FinishContainerScopeFunc(int32_t id); 357 358 #if !defined(PREVIEW) 359 virtual void SetDebuggerPostTaskFunc(DebuggerPostTask func); 360 virtual void CallDebuggerPostTaskFunc(std::function<void()>&& task); 361 #endif 362 363 virtual void SetHostEngine(NativeEngine* engine); 364 virtual NativeEngine* GetHostEngine() const; 365 virtual void SetApiVersion(int32_t apiVersion); 366 virtual int32_t GetApiVersion(); 367 virtual int32_t GetRealApiVersion(); 368 virtual bool IsApplicationApiVersionAPI11Plus(); 369 370 virtual napi_status AddCleanupHook(CleanupCallback fun, void* arg); 371 virtual napi_status RemoveCleanupHook(CleanupCallback fun, void* arg); 372 373 void CleanupHandles(); 374 void IncreaseWaitingRequestCounter(); 375 void DecreaseWaitingRequestCounter(); 376 bool HasWaitingRequest(); 377 378 void IncreaseListeningCounter(); 379 void DecreaseListeningCounter(); 380 bool HasListeningCounter(); 381 IsAlive(NativeEngine * env)382 inline static bool IsAlive(NativeEngine* env) 383 { 384 std::lock_guard<std::mutex> alivedEngLock(g_alivedEngineMutex_); 385 return g_alivedEngine_.find(env) != g_alivedEngine_.end(); 386 } 387 388 virtual void RunCleanup(); 389 IsStopping()390 bool IsStopping() const 391 { 392 return isStopping_.load(); 393 } 394 SetStopping(bool value)395 void SetStopping(bool value) 396 { 397 isStopping_.store(value); 398 } 399 400 virtual void PrintStatisticResult() = 0; 401 virtual void StartRuntimeStat() = 0; 402 virtual void StopRuntimeStat() = 0; 403 virtual size_t GetArrayBufferSize() = 0; 404 virtual size_t GetHeapTotalSize() = 0; 405 virtual size_t GetHeapUsedSize() = 0; 406 virtual size_t GetHeapObjectSize() = 0; 407 virtual size_t GetHeapLimitSize() = 0; 408 virtual size_t GetProcessHeapLimitSize() = 0; 409 virtual size_t GetGCCount() = 0; 410 virtual size_t GetGCDuration() = 0; 411 virtual size_t GetAccumulatedAllocateSize() = 0; 412 virtual size_t GetAccumulatedFreeSize() = 0; 413 virtual size_t GetFullGCLongTimeCount() = 0; 414 virtual void NotifyApplicationState(bool inBackground) = 0; 415 virtual void NotifyIdleStatusControl(std::function<void(bool)> callback) = 0; 416 virtual void NotifyIdleTime(int idleMicroSec) = 0; 417 virtual void NotifyMemoryPressure(bool inHighMemoryPressure = false) = 0; 418 virtual void NotifyForceExpandState(int32_t value) = 0; 419 virtual void SetMockModuleList(const std::map<std::string, std::string> &list) = 0; 420 virtual int32_t GetObjectHash(napi_env env, napi_value src) = 0; 421 422 void RegisterWorkerFunction(const NativeEngine* engine); 423 virtual void RegisterNapiUncaughtExceptionHandler(NapiUncaughtExceptionCallback callback) = 0; 424 virtual void RegisterAllPromiseCallback(NapiAllPromiseRejectCallback callback) = 0; 425 virtual void HandleUncaughtException() = 0; HasPendingException()426 virtual bool HasPendingException() 427 { 428 return false; 429 } 430 virtual void ThrowException(const char* msg); 431 virtual void RegisterPermissionCheck(PermissionCheckCallback callback) = 0; 432 virtual bool ExecutePermissionCheck() = 0; 433 virtual void RegisterTranslateBySourceMap(SourceMapCallback callback) = 0; 434 virtual std::string ExecuteTranslateBySourceMap(const std::string& rawStack) = 0; 435 virtual void RegisterSourceMapTranslateCallback(SourceMapTranslateCallback callback) = 0; 436 virtual void SetPromiseRejectCallBackRef(NativeReference*) = 0; 437 virtual void SetCheckCallbackRef(NativeReference*) = 0; 438 virtual NapiUncaughtExceptionCallback GetNapiUncaughtExceptionCallback() = 0; 439 virtual void* GetPromiseRejectCallback() = 0; 440 virtual void GetCurrentModuleInfo(std::string& moduleName, std::string& fileName, bool needRecordName) = 0; 441 virtual bool GetIsBundle() = 0; 442 virtual bool GetIsNormalizedOhmUrlPack() = 0; 443 virtual bool GetIsDebugModeEnabled() = 0; 444 virtual std::string GetBundleName() = 0; 445 virtual bool IsExecuteModuleInAbcFile(std::string bundleName, std::string moduleName, std::string ohmurl) = 0; 446 virtual int GetProcessStartRealTime() = 0; 447 // run script by path 448 napi_value RunScriptForAbc(const char* path, char* entryPoint = nullptr); 449 napi_value RunScript(const char* path, char* entryPoint = nullptr); 450 napi_value RunScriptInRestrictedThread(const char* path); 451 bool GetAbcBuffer(const char* path, uint8_t **buffer, size_t* bufferSize, std::vector<uint8_t>& content, 452 std::string& ami, bool isRestrictedWorker = false); 453 454 const char* GetModuleFileName(); 455 456 void SetModuleName(std::string &moduleName); 457 void SetModuleFileName(std::string &moduleFileName); 458 459 void SetInstanceData(void* data, NativeFinalize finalize_cb, void* hint); 460 void GetInstanceData(void** data); 461 462 /** 463 * @brief Set the Extension Infos 464 * 465 * @param extensionInfos extension infos to set 466 */ 467 void SetExtensionInfos(std::unordered_map<std::string, int32_t>&& extensionInfos); 468 469 /** 470 * @brief Get the Extension Infos 471 * 472 * @return extension infos 473 */ 474 const std::unordered_map<std::string, int32_t>& GetExtensionInfos(); 475 476 /** 477 * @brief Set the Module Blocklist 478 * 479 * @param blocklist the blocklist set to native engine 480 */ 481 void SetModuleBlocklist(std::unordered_map<int32_t, std::unordered_set<std::string>>&& blocklist); 482 483 /** 484 * @brief Set the Module Load Checker 485 * 486 * @param moduleCheckerDelegate the module checker delegate will intercept the module loading 487 */ 488 void SetModuleLoadChecker(const std::shared_ptr<ModuleCheckerDelegate>& moduleCheckerDelegate); 489 490 virtual napi_value NapiLoadModule(const char* path) = 0; 491 virtual napi_value NapiLoadModuleWithInfo(const char* path, const char* module_info) = 0; 492 virtual std::string GetPkgName(const std::string &moduleName) = 0; 493 NewAsyncId()494 double NewAsyncId() 495 { 496 return 0; 497 } 498 GetDefaultTriggerAsyncId()499 double GetDefaultTriggerAsyncId() 500 { 501 return 0; 502 } 503 504 /** 505 * @brief run the uv loop in the engine by the designated uv run mode 506 * 507 * @param mode the specified uv mode that utilized to tell uv which mode will be used to run the uv loop 508 */ 509 napi_status RunEventLoop(napi_event_mode mode); 510 511 /** 512 * @brief stop the uv loop in the engine 513 */ 514 napi_status StopEventLoop(); 515 516 virtual bool IsCrossThreadCheckEnabled() const = 0; 517 IsInDestructor()518 bool IsInDestructor() const 519 { 520 return isInDestructor_; 521 } 522 GetMainThreadEngine()523 static NativeEngine* GetMainThreadEngine() 524 { 525 std::lock_guard<std::mutex> lock(g_mainThreadEngineMutex_); 526 return g_mainThreadEngine_; 527 } 528 SetMainThreadEngine(NativeEngine * engine)529 static void SetMainThreadEngine(NativeEngine* engine) 530 { 531 if (g_mainThreadEngine_ == nullptr) { 532 std::lock_guard<std::mutex> lock(g_mainThreadEngineMutex_); 533 if (g_mainThreadEngine_ == nullptr) { 534 g_mainThreadEngine_ = engine; 535 } 536 } 537 } 538 HandleTaskpoolException(napi_value exception)539 void HandleTaskpoolException(napi_value exception) 540 { 541 auto callback = this->GetNapiUncaughtExceptionCallback(); 542 if (callback) { 543 callback(exception); 544 } 545 } 546 GetWorkerThreadState()547 WorkerThreadState* GetWorkerThreadState() 548 { 549 return workerThreadState_; 550 } 551 552 private: 553 void InitUvField(); 554 555 virtual NapiOptions *GetNapiOptions() const = 0; 556 SetUnalived()557 inline void SetUnalived() 558 { 559 std::lock_guard<std::mutex> alivedEngLock(g_alivedEngineMutex_); 560 g_alivedEngine_.erase(this); 561 return; 562 } 563 564 // should only call once in life cycle of ArkNativeEngine(NativeEngine) 565 inline void SetAlived(); 566 567 protected: 568 void *jsEngine_ = nullptr; 569 570 void Init(); 571 void Deinit(); 572 573 NativeModuleManager* moduleManager_ = nullptr; 574 NativeReferenceManager* referenceManager_ = nullptr; 575 NativeCallbackScopeManager* callbackScopeManager_ = nullptr; 576 577 uv_loop_t* loop_ = nullptr; 578 579 NativeErrorExtendedInfo lastError_; 580 581 // register for worker 582 void* worker_ = nullptr; 583 InitWorkerFunc initWorkerFunc_ {nullptr}; 584 GetAssetFunc getAssetFunc_ {nullptr}; 585 OffWorkerFunc offWorkerFunc_ {nullptr}; 586 #if !defined(PREVIEW) 587 DebuggerPostTask debuggerPostTaskFunc_ {nullptr}; 588 #endif 589 NativeEngine* hostEngine_ {nullptr}; 590 bool isAppModule_ = false; 591 WorkerThreadState* workerThreadState_; 592 593 public: 594 uint64_t openHandleScopes_ = 0; 595 panda::Local<panda::ObjectRef> lastException_; 596 597 private: 598 std::string moduleName_; 599 std::string moduleFileName_; 600 std::mutex instanceDataLock_; 601 NativeObjectInfo instanceDataInfo_; 602 void FinalizerInstanceData(void); 603 pthread_t tid_ { 0 }; 604 ThreadId sysTid_ { 0 }; 605 uint64_t id_ { 0 }; 606 std::unordered_map<std::string, int32_t> extensionInfos_; 607 uv_sem_t uvSem_; 608 // Application's sdk version 609 int32_t apiVersion_ = 8; 610 int32_t realApiVersion_ = 8; 611 612 // the old worker api use before api9, the new worker api start with api9 613 enum JSThreadType { MAIN_THREAD, WORKER_THREAD, TASKPOOL_THREAD, RESTRICTEDWORKER_THREAD, NATIVE_THREAD }; 614 DataProtector jsThreadType_ {DataProtector(uintptr_t(JSThreadType::MAIN_THREAD))}; 615 // current is hostengine, can create old worker, new worker, or no workers on hostengine 616 std::atomic<WorkerVersion> workerVersion_ { WorkerVersion::NONE }; 617 #if !defined(PREVIEW) 618 static void UVThreadRunner(void* nativeEngine); 619 void PostLoopTask(); 620 621 bool checkUVLoop_ = false; 622 uv_thread_t uvThread_; 623 #endif 624 mutable std::shared_mutex eventMutex_; 625 napi_threadsafe_function defaultFunc_ = nullptr; 626 PostTask postTask_ = nullptr; 627 CleanEnv cleanEnv_ = nullptr; 628 uv_async_t uvAsync_; 629 std::unordered_map<void*, std::pair<CleanupCallback, uint64_t>> cleanupHooks_; 630 uint64_t cleanupHookCounter_ = 0; 631 std::atomic_int requestWaiting_ { 0 }; 632 std::atomic_int listeningCounter_ { 0 }; 633 std::atomic_int subEnvCounter_ { 0 }; 634 std::atomic_bool isStopping_ { false }; 635 636 std::mutex loopRunningMutex_; 637 bool isLoopRunning_ = false; 638 bool isInDestructor_ {false}; 639 std::string taskName_ = ""; 640 641 // protect alived engine set and last engine id 642 static std::mutex g_alivedEngineMutex_; 643 static std::unordered_set<NativeEngine*> g_alivedEngine_; 644 static uint64_t g_lastEngineId_; 645 static std::mutex g_mainThreadEngineMutex_; 646 static NativeEngine* g_mainThreadEngine_; 647 648 public: GetEventMutex()649 inline std::shared_mutex& GetEventMutex() const 650 { 651 return eventMutex_; 652 } 653 GetDefaultFunc()654 inline napi_threadsafe_function GetDefaultFunc() 655 { 656 return defaultFunc_; 657 } 658 IsAliveLocked(NativeEngine * env)659 inline static bool IsAliveLocked(NativeEngine* env) 660 { 661 return g_alivedEngine_.find(env) != g_alivedEngine_.end(); 662 } 663 GetAliveEngineMutex()664 inline static std::mutex& GetAliveEngineMutex() { 665 return g_alivedEngineMutex_; 666 } 667 }; 668 669 class NapiErrorManager { 670 public: 671 static NapiErrorManager* GetInstance(); 672 RegisterOnErrorCallback(NapiOnWorkerErrorCallback workerErrorCb,NapiOnMainThreadErrorCallback mainThreadErrorCb)673 void RegisterOnErrorCallback(NapiOnWorkerErrorCallback workerErrorCb, 674 NapiOnMainThreadErrorCallback mainThreadErrorCb) 675 { 676 if (!onWorkerErrorCb_) { 677 onWorkerErrorCb_ = workerErrorCb; 678 } 679 if (!onMainThreadErrorCb_) { 680 onMainThreadErrorCb_ = mainThreadErrorCb; 681 } 682 } 683 GetOnWorkerErrorCallback()684 NapiOnWorkerErrorCallback &GetOnWorkerErrorCallback() 685 { 686 return onWorkerErrorCb_; 687 } 688 GetOnMainThreadErrorCallback()689 NapiOnMainThreadErrorCallback &GetOnMainThreadErrorCallback() 690 { 691 return onMainThreadErrorCb_; 692 } 693 RegisterAllUnhandledRejectionCallback(NapiAllUnhandledRejectionCallback callback)694 void RegisterAllUnhandledRejectionCallback(NapiAllUnhandledRejectionCallback callback) 695 { 696 if (!allUnhandledRejectionCb_) { 697 allUnhandledRejectionCb_ = callback; 698 } 699 } 700 GetAllUnhandledRejectionCallback()701 NapiAllUnhandledRejectionCallback &GetAllUnhandledRejectionCallback() 702 { 703 return allUnhandledRejectionCb_; 704 } 705 RegisterHasOnErrorCallback(NapiHasOnErrorCallback callback)706 void RegisterHasOnErrorCallback(NapiHasOnErrorCallback callback) 707 { 708 if (!hasOnErrorCb_) { 709 hasOnErrorCb_ = callback; 710 } 711 } 712 GetHasErrorCallback()713 NapiHasOnErrorCallback &GetHasErrorCallback() 714 { 715 return hasOnErrorCb_; 716 } 717 RegisterHasAllUnhandledRejectionCallback(NapiHasAllUnhandledRejectionCallback callback)718 void RegisterHasAllUnhandledRejectionCallback(NapiHasAllUnhandledRejectionCallback callback) 719 { 720 if (!hasAllUnhandledRejectionCb_) { 721 hasAllUnhandledRejectionCb_ = callback; 722 } 723 } 724 GetHasAllUnhandledRejectionCallback()725 NapiHasAllUnhandledRejectionCallback &GetHasAllUnhandledRejectionCallback() 726 { 727 return hasAllUnhandledRejectionCb_; 728 } 729 730 void NotifyUncaughtException(napi_env env, napi_value exception, std::string name, uint32_t type); 731 bool NotifyUncaughtException(napi_env env, const std::string &summary, const std::string &name, 732 const std::string &message, const std::string &stack); 733 void NotifyUnhandledRejection(napi_env env, napi_value* exception, std::string name, uint32_t type); 734 735 private: 736 static NapiErrorManager *instance_; 737 NapiOnWorkerErrorCallback onWorkerErrorCb_ { nullptr }; 738 NapiOnMainThreadErrorCallback onMainThreadErrorCb_ { nullptr }; 739 NapiAllUnhandledRejectionCallback allUnhandledRejectionCb_ { nullptr }; 740 NapiHasOnErrorCallback hasOnErrorCb_ { nullptr }; 741 NapiHasAllUnhandledRejectionCallback hasAllUnhandledRejectionCb_ { nullptr }; 742 }; 743 744 bool DumpHybridStack(const EcmaVM* vm, std::string &stack, uint32_t ignored = 0, int32_t deepth = -1); 745 746 class TryCatch : public panda::TryCatch { 747 public: TryCatch(napi_env env)748 explicit TryCatch(napi_env env) 749 : panda::TryCatch(reinterpret_cast<NativeEngine*>(env)->GetEcmaVm()), 750 engine_(reinterpret_cast<NativeEngine*>(env)) {} 751 ~TryCatch()752 ~TryCatch() 753 { 754 if (HasCaught()) { 755 engine_->lastException_ = GetException(); 756 } 757 } 758 private: 759 NativeEngine* engine_ = nullptr; 760 }; 761 762 class WorkerRunningScope { 763 public: WorkerRunningScope(napi_env env)764 explicit WorkerRunningScope(napi_env env) : env_(env) 765 { 766 auto engine = reinterpret_cast<NativeEngine*>(env_); 767 engine->GetWorkerThreadState()->NoityTaskStart(); 768 } 769 ~WorkerRunningScope()770 ~WorkerRunningScope() 771 { 772 auto engine = reinterpret_cast<NativeEngine*>(env_); 773 engine->GetWorkerThreadState()->NotifyTaskEnd(); 774 } 775 private: 776 napi_env env_; 777 }; 778 #endif /* FOUNDATION_ACE_NAPI_NATIVE_ENGINE_NATIVE_ENGINE_H */ 779