• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #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