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