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_value.h"
37 #include "native_property.h"
38 #include "reference_manager/native_reference_manager.h"
39 #include "utils/macros.h"
40 #include "libpandafile/data_protect.h"
41 
42 namespace panda::ecmascript {
43     class EcmaVM;
44 }
45 
46 typedef int32_t (*GetContainerScopeIdCallback)(void);
47 typedef void (*ContainerScopeCallback)(int32_t);
48 typedef struct uv_loop_s uv_loop_t;
49 
50 struct NativeErrorExtendedInfo {
51     const char* message = nullptr;
52     void* reserved = nullptr;
53     uint32_t engineErrorCode = 0;
54     int errorCode = 0;
55 };
56 
57 enum LoopMode {
58     LOOP_DEFAULT, LOOP_ONCE, LOOP_NOWAIT
59 };
60 
61 enum class DumpFormat {
62     JSON, BINARY, OTHER
63 };
64 
65 enum class WorkerVersion {
66     NONE, OLD, NEW
67 };
68 
69 using CleanupCallback = void (*)(void*);
70 using ThreadId = uint32_t;
71 
72 class NapiOptions;
73 using PostTask = std::function<void(bool needSync)>;
74 using CleanEnv = std::function<void()>;
75 using InitWorkerFunc = std::function<void(NativeEngine* engine)>;
76 using GetAssetFunc = std::function<void(const std::string& uri, uint8_t **buff, size_t *buffSize,
77     std::vector<uint8_t>& content, std::string& ami, bool &useSecureMem, bool isRestricted)>;
78 using OffWorkerFunc = std::function<void(NativeEngine* engine)>;
79 using DebuggerPostTask = std::function<void(std::function<void()>&&)>;
80 using NapiUncaughtExceptionCallback = std::function<void(napi_value value)>;
81 using PermissionCheckCallback = std::function<bool()>;
82 using NapiConcurrentCallback = void (*)(napi_env env, napi_value result, bool success, void* data);
83 using SourceMapCallback = std::function<std::string(const std::string& rawStack)>;
84 using SourceMapTranslateCallback = std::function<bool(std::string& url, int& line, int& column)>;
85 using AppFreezeFilterCallback = std::function<bool(const int32_t pid)>;
86 using EcmaVM = panda::ecmascript::EcmaVM;
87 using JsFrameInfo = panda::ecmascript::JsFrameInfo;
88 
89 class NAPI_EXPORT NativeEngine {
90 public:
91     explicit NativeEngine(void* jsEngine);
92     NativeEngine(void* jsEngine, EcmaVM* vm);
93     virtual ~NativeEngine();
94 
95     virtual NativeModuleManager* GetModuleManager();
96     virtual NativeReferenceManager* GetReferenceManager();
97     virtual NativeCallbackScopeManager* GetCallbackScopeManager();
98     virtual uv_loop_t* GetUVLoop() const;
99     virtual pthread_t GetTid() const;
GetSysTid() const100     inline ThreadId GetSysTid() const
101     {
102         return sysTid_;
103     };
104     static ThreadId GetCurSysTid();
GetId() const105     inline uint64_t GetId() const
106     {
107         return id_;
108     };
109 
110     virtual bool ReinitUVLoop();
111 
112     virtual void Loop(LoopMode mode, bool needSync = false);
113     virtual void SetPostTask(PostTask postTask);
114     virtual void TriggerPostTask();
115 #if !defined(PREVIEW)
116     virtual void CheckUVLoop();
117     virtual void CancelCheckUVLoop();
118 #endif
119     virtual void* GetJsEngine();
120 
GetEcmaVm() const121     inline NAPI_EXPORT const EcmaVM* GetEcmaVm() const
122     {
123         return vm_;
124     }
125     virtual bool NapiNewTypedArray(const EcmaVM* vm, NativeTypedArrayType typedArrayType,
126                                    panda::Local<panda::ArrayBufferRef> arrayBuf, size_t byte_offset,
127                                    size_t length, napi_value* result) = 0;
128     virtual bool NapiNewSendableTypedArray(const EcmaVM* vm, NativeTypedArrayType typedArrayType,
129                                            panda::Local<panda::SendableArrayBufferRef> arrayBuf, size_t byte_offset,
130                                            size_t length, napi_value* result) = 0;
131     virtual NativeTypedArrayType GetTypedArrayType(panda::Local<panda::TypedArrayRef> typedArray) = 0;
132     virtual NativeTypedArrayType GetSendableTypedArrayType(panda::Local<panda::SendableTypedArrayRef> typedArray) = 0;
133     virtual void SetPromiseRejectCallback(NativeReference* rejectCallbackRef, NativeReference* checkCallbackRef) = 0;
134 
135     virtual bool InitTaskPoolThread(NativeEngine* engine, NapiConcurrentCallback callback) = 0;
136     virtual bool InitTaskPoolThread(napi_env env, NapiConcurrentCallback callback) = 0;
137     virtual bool InitTaskPoolFunc(napi_env env, napi_value func, void* taskInfo) = 0;
138     virtual void ClearCurrentTaskInfo() = 0;
139     virtual bool HasPendingJob() const = 0;
140     virtual bool IsProfiling() const = 0;
141     virtual bool IsExecutingPendingJob() const = 0;
142     virtual void* GetCurrentTaskInfo() const = 0;
143     virtual void TerminateExecution() const = 0;
144     virtual void NotifyTaskBegin() const = 0;
145     virtual void NotifyTaskFinished() const = 0;
146 
147     virtual napi_value CallFunction(napi_value thisVar,
148                                     napi_value function,
149                                     napi_value const *argv,
150                                     size_t argc) = 0;
151     virtual bool RunScriptPath(const char* path, bool checkPath = false) = 0;
152     virtual napi_value RunScriptBuffer(const char* path, std::vector<uint8_t>& buffer, bool isBundle) = 0;
153     virtual bool RunScriptBuffer(const std::string &path, uint8_t* buffer, size_t size, bool isBundle) = 0;
154     virtual napi_value RunBufferScript(std::vector<uint8_t>& buffer) = 0;
155     virtual napi_value RunActor(uint8_t* buffer, size_t bufferSize,
156         const char* descriptor, char* entryPoint = nullptr, bool checkPath = false) = 0;
157 
158     virtual napi_value CreateInstance(napi_value constructor, napi_value const *argv, size_t argc) = 0;
159 
160     virtual NativeReference* CreateReference(napi_value value, uint32_t initialRefcount,
161         bool flag = false, NapiNativeFinalize callback = nullptr, void* data = nullptr, void* hint = nullptr,
162         size_t nativeBindingSize = 0) = 0;
163 
164     virtual NativeReference* CreateAsyncReference(napi_value value, uint32_t initialRefcount,
165         bool flag = false, NapiNativeFinalize callback = nullptr, void* data = nullptr, void* hint = nullptr) = 0;
166 
167     virtual NativeAsyncWork* CreateAsyncWork(napi_value asyncResource,
168                                              napi_value asyncResourceName,
169                                              NativeAsyncExecuteCallback execute,
170                                              NativeAsyncCompleteCallback complete,
171                                              void* data);
172 
173     virtual NativeAsyncWork* CreateAsyncWork(const std::string &asyncResourceName,
174                                              NativeAsyncExecuteCallback execute,
175                                              NativeAsyncCompleteCallback complete,
176                                              void* data);
177     virtual NativeSafeAsyncWork* CreateSafeAsyncWork(napi_value func, napi_value asyncResource,
178         napi_value asyncResourceName, size_t maxQueueSize, size_t threadCount, void* finalizeData,
179         NativeFinalize finalizeCallback, void* context, NativeThreadSafeFunctionCallJs callJsCallback);
180 
181     virtual void* CreateRuntime(bool isLimitedWorker = false) = 0;
182     virtual napi_value CreatePromise(NativeDeferred** deferred) = 0;
183 
184     virtual void SetJsDumpThresholds(size_t thresholds) = 0;
185     virtual void SetAppFreezeFilterCallback(AppFreezeFilterCallback callback) = 0;
186 
187     virtual void StartCpuProfiler(const std::string& fileName = "") = 0;
188     virtual void StopCpuProfiler() = 0;
189 
190     virtual void ResumeVM() = 0;
191     virtual bool SuspendVM() = 0;
192     virtual bool IsSuspended() = 0;
193     virtual bool CheckSafepoint() = 0;
194     virtual bool SuspendVMById(uint32_t tid) = 0;
195     virtual void ResumeVMById(uint32_t tid) = 0;
196 
197     virtual void DumpHeapSnapshot(const std::string &path, bool isVmMode = true,
198         DumpFormat dumpFormat = DumpFormat::JSON, bool isPrivate = false, bool captureNumericValue = false) = 0;
199     virtual void DumpCpuProfile() = 0;
200     virtual void DumpHeapSnapshot(bool isVmMode = true, DumpFormat dumpFormat = DumpFormat::JSON,
201         bool isPrivate = false, bool isFullGC = true) = 0;
202     virtual bool BuildNativeAndJsStackTrace(std::string &stackTraceStr) = 0;
203     virtual bool BuildJsStackTrace(std::string &stackTraceStr) = 0;
204     virtual bool BuildJsStackInfoListWithCustomDepth(std::vector<JsFrameInfo>& jsFrames)
205         = 0;
206     virtual bool DeleteWorker(NativeEngine* workerEngine) = 0;
207     virtual bool StartHeapTracking(double timeInterval, bool isVmMode = true) = 0;
208     virtual bool StopHeapTracking(const std::string &filePath) = 0;
209 
210     virtual void AllowCrossThreadExecution() const = 0;
211 
212     NativeErrorExtendedInfo* GetLastError();
213     void SetLastError(int errorCode, uint32_t engineErrorCode = 0, void* engineReserved = nullptr);
ClearLastError()214     inline void ClearLastError()
215     {
216         lastError_.errorCode = 0;
217         lastError_.engineErrorCode = 0;
218         lastError_.message = nullptr;
219         lastError_.reserved = nullptr;
220     }
221     void EncodeToUtf8(napi_value value, char* buffer, uint32_t* written, size_t bufferSize, int32_t* nchars);
222     void EncodeToChinese(napi_value value, std::string& buffer, const std::string& encoding);
223     NativeEngine(NativeEngine&) = delete;
224     virtual NativeEngine& operator=(NativeEngine&) = delete;
225 
226     virtual napi_value ValueToNapiValue(JSValueWrapper& value) = 0;
227     virtual std::string GetSourceCodeInfo(napi_value value, ErrorPos pos) = 0;
228 
229     virtual void TriggerFatalException(panda::Local<panda::JSValueRef> exceptionValue) = 0;
230     virtual bool AdjustExternalMemory(int64_t ChangeInBytes, int64_t* AdjustedValue) = 0;
231 
MarkWorkerThread()232     void MarkWorkerThread()
233     {
234         jsThreadType_.Update(static_cast<uintptr_t>(JSThreadType::WORKER_THREAD));
235     }
MarkRestrictedWorkerThread()236     void MarkRestrictedWorkerThread()
237     {
238         jsThreadType_.Update(static_cast<uintptr_t>(JSThreadType::RESTRICTEDWORKER_THREAD));
239     }
MarkTaskPoolThread()240     void MarkTaskPoolThread()
241     {
242         jsThreadType_.Update(static_cast<uintptr_t>(JSThreadType::TASKPOOL_THREAD));
243     }
MarkNativeThread()244     void MarkNativeThread()
245     {
246         jsThreadType_.Update(static_cast<uintptr_t>(JSThreadType::NATIVE_THREAD));
247     }
IsWorkerThread() const248     bool IsWorkerThread() const
249     {
250         return static_cast<JSThreadType>(jsThreadType_.GetOriginPointer()) == JSThreadType::WORKER_THREAD;
251     }
IsRestrictedWorkerThread() const252     bool IsRestrictedWorkerThread() const
253     {
254         return static_cast<JSThreadType>(jsThreadType_.GetOriginPointer()) == JSThreadType::RESTRICTEDWORKER_THREAD;
255     }
IsTaskPoolThread() const256     bool IsTaskPoolThread() const
257     {
258         return static_cast<JSThreadType>(jsThreadType_.GetOriginPointer()) == JSThreadType::TASKPOOL_THREAD;
259     }
IsMainThread() const260     bool IsMainThread() const
261     {
262         return static_cast<JSThreadType>(jsThreadType_.GetOriginPointer()) == JSThreadType::MAIN_THREAD;
263     }
IsNativeThread() const264     bool IsNativeThread() const
265     {
266         return static_cast<JSThreadType>(jsThreadType_.GetOriginPointer()) == JSThreadType::NATIVE_THREAD;
267     }
268 
CheckAndSetWorkerVersion(WorkerVersion expected, WorkerVersion desired)269     bool CheckAndSetWorkerVersion(WorkerVersion expected, WorkerVersion desired)
270     {
271         return workerVersion_.compare_exchange_strong(expected, desired);
272     }
IsTargetWorkerVersion(WorkerVersion target) const273     bool IsTargetWorkerVersion(WorkerVersion target) const
274     {
275         return workerVersion_.load() == target;
276     }
277 
IncreaseSubEnvCounter()278     void IncreaseSubEnvCounter()
279     {
280         subEnvCounter_++;
281     }
DecreaseSubEnvCounter()282     void DecreaseSubEnvCounter()
283     {
284         subEnvCounter_--;
285     }
HasSubEnv()286     bool HasSubEnv()
287     {
288         return subEnvCounter_.load() != 0;
289     }
290 
SetCleanEnv(CleanEnv cleanEnv)291     void SetCleanEnv(CleanEnv cleanEnv)
292     {
293         cleanEnv_ = cleanEnv;
294     }
295 
296     // register init worker func
297     virtual void SetInitWorkerFunc(InitWorkerFunc func);
298     InitWorkerFunc GetInitWorkerFunc() const;
299     virtual void SetGetAssetFunc(GetAssetFunc func);
300     GetAssetFunc GetGetAssetFunc() const;
301     virtual void SetOffWorkerFunc(OffWorkerFunc func);
302     OffWorkerFunc GetOffWorkerFunc() const;
303 
304     // call init worker func
305     virtual bool CallInitWorkerFunc(NativeEngine* engine);
306     virtual bool CallGetAssetFunc(const std::string& uri, uint8_t **buff, size_t *buffSize,
307         std::vector<uint8_t>& content, std::string& ami, bool &useSecureMem, bool isRestricted);
308     virtual bool CallOffWorkerFunc(NativeEngine* engine);
309 
310     // adapt worker to ace container
311     virtual void SetGetContainerScopeIdFunc(GetContainerScopeIdCallback func);
312     virtual void SetInitContainerScopeFunc(ContainerScopeCallback func);
313     virtual void SetFinishContainerScopeFunc(ContainerScopeCallback func);
314     virtual int32_t GetContainerScopeIdFunc();
315     virtual bool InitContainerScopeFunc(int32_t id);
316     virtual bool FinishContainerScopeFunc(int32_t id);
317 
318 #if !defined(PREVIEW)
319     virtual void SetDebuggerPostTaskFunc(DebuggerPostTask func);
320     virtual void CallDebuggerPostTaskFunc(std::function<void()>&& task);
321 #endif
322 
323     virtual void SetHostEngine(NativeEngine* engine);
324     virtual NativeEngine* GetHostEngine() const;
325     virtual void SetApiVersion(int32_t apiVersion);
326     virtual int32_t GetApiVersion();
327     virtual bool IsApplicationApiVersionAPI11Plus();
328 
329     virtual napi_status AddCleanupHook(CleanupCallback fun, void* arg);
330     virtual napi_status RemoveCleanupHook(CleanupCallback fun, void* arg);
331 
332     void CleanupHandles();
333     void IncreaseWaitingRequestCounter();
334     void DecreaseWaitingRequestCounter();
335     bool HasWaitingRequest();
336 
337     void IncreaseListeningCounter();
338     void DecreaseListeningCounter();
339     bool HasListeningCounter();
340 
IsAlive(NativeEngine* env)341     inline static bool IsAlive(NativeEngine* env)
342     {
343         std::lock_guard<std::mutex> alivedEngLock(g_alivedEngineMutex_);
344         return g_alivedEngine_.find(env) != g_alivedEngine_.end();
345     }
346 
347     virtual void RunCleanup();
348 
IsStopping() const349     bool IsStopping() const
350     {
351         return isStopping_.load();
352     }
353 
SetStopping(bool value)354     void SetStopping(bool value)
355     {
356         isStopping_.store(value);
357     }
358 
359     virtual void PrintStatisticResult() = 0;
360     virtual void StartRuntimeStat() = 0;
361     virtual void StopRuntimeStat() = 0;
362     virtual size_t GetArrayBufferSize() = 0;
363     virtual size_t GetHeapTotalSize() = 0;
364     virtual size_t GetHeapUsedSize() = 0;
365     virtual size_t GetHeapObjectSize() = 0;
366     virtual size_t GetHeapLimitSize() = 0;
367     virtual size_t GetProcessHeapLimitSize() = 0;
368     virtual size_t GetGCCount() = 0;
369     virtual size_t GetGCDuration() = 0;
370     virtual size_t GetAccumulatedAllocateSize() = 0;
371     virtual size_t GetAccumulatedFreeSize() = 0;
372     virtual size_t GetFullGCLongTimeCount() = 0;
373     virtual void NotifyApplicationState(bool inBackground) = 0;
374     virtual void NotifyIdleStatusControl(std::function<void(bool)> callback) = 0;
375     virtual void NotifyIdleTime(int idleMicroSec) = 0;
376     virtual void NotifyMemoryPressure(bool inHighMemoryPressure = false) = 0;
377     virtual void NotifyForceExpandState(int32_t value) = 0;
378     virtual void SetMockModuleList(const std::map<std::string, std::string> &list) = 0;
379     virtual int32_t GetObjectHash(napi_env env, napi_value src) = 0;
380 
381     void RegisterWorkerFunction(const NativeEngine* engine);
382     virtual void RegisterNapiUncaughtExceptionHandler(NapiUncaughtExceptionCallback callback) = 0;
383     virtual void HandleUncaughtException() = 0;
HasPendingException()384     virtual bool HasPendingException()
385     {
386         return false;
387     }
388     virtual void ThrowException(const char* msg);
389     virtual void RegisterPermissionCheck(PermissionCheckCallback callback) = 0;
390     virtual bool ExecutePermissionCheck() = 0;
391     virtual void RegisterTranslateBySourceMap(SourceMapCallback callback) = 0;
392     virtual std::string ExecuteTranslateBySourceMap(const std::string& rawStack) = 0;
393     virtual void RegisterSourceMapTranslateCallback(SourceMapTranslateCallback callback) = 0;
394     virtual void SetPromiseRejectCallBackRef(NativeReference*) = 0;
395     virtual void SetCheckCallbackRef(NativeReference*) = 0;
396     virtual NapiUncaughtExceptionCallback GetNapiUncaughtExceptionCallback() = 0;
397     virtual void* GetPromiseRejectCallback() = 0;
398     virtual void GetCurrentModuleInfo(std::string& moduleName, std::string& fileName, bool needRecordName) = 0;
399     virtual bool GetIsBundle() = 0;
400     virtual bool GetIsNormalizedOhmUrlPack() = 0;
401     virtual bool GetIsDebugModeEnabled() = 0;
402     virtual std::string GetBundleName() = 0;
403     virtual bool IsExecuteModuleInAbcFile(std::string bundleName, std::string moduleName, std::string ohmurl) = 0;
404     virtual int GetProcessStartRealTime() = 0;
405     // run script by path
406     napi_value RunScriptForAbc(const char* path, char* entryPoint = nullptr);
407     napi_value RunScript(const char* path, char* entryPoint = nullptr);
408     napi_value RunScriptInRestrictedThread(const char* path);
409     bool GetAbcBuffer(const char* path, uint8_t **buffer, size_t* bufferSize, std::vector<uint8_t>& content,
410         std::string& ami, bool isRestrictedWorker = false);
411 
412     const char* GetModuleFileName();
413 
414     void SetModuleName(std::string &moduleName);
415     void SetModuleFileName(std::string &moduleFileName);
416 
417     void SetInstanceData(void* data, NativeFinalize finalize_cb, void* hint);
418     void GetInstanceData(void** data);
419 
420     /**
421      * @brief Set the Extension Infos
422      *
423      * @param extensionInfos extension infos to set
424      */
425     void SetExtensionInfos(std::unordered_map<std::string, int32_t>&& extensionInfos);
426 
427     /**
428      * @brief Get the Extension Infos
429      *
430      * @return extension infos
431      */
432     const std::unordered_map<std::string, int32_t>& GetExtensionInfos();
433 
434     /**
435      * @brief Set the Module Blocklist
436      *
437      * @param blocklist the blocklist set to native engine
438      */
439     void SetModuleBlocklist(std::unordered_map<int32_t, std::unordered_set<std::string>>&& blocklist);
440 
441     /**
442      * @brief Set the Module Load Checker
443      *
444      * @param moduleCheckerDelegate the module checker delegate will intercept the module loading
445      */
446     void SetModuleLoadChecker(const std::shared_ptr<ModuleCheckerDelegate>& moduleCheckerDelegate);
447 
448     virtual napi_value NapiLoadModule(const char* path, const char* module_info) = 0;
449     virtual napi_value NapiLoadModuleWithInfo(const char* path, const char* module_info) = 0;
450     virtual std::string GetPkgName(const std::string &moduleName) = 0;
451 
NewAsyncId()452     double NewAsyncId()
453     {
454         return 0;
455     }
456 
GetDefaultTriggerAsyncId()457     double GetDefaultTriggerAsyncId()
458     {
459         return 0;
460     }
461 
462     /**
463      * @brief run the uv loop in the engine by the designated uv run mode
464      *
465      * @param mode the specified uv mode that utilized to tell uv which mode will be used to run the uv loop
466      */
467     napi_status RunEventLoop(napi_event_mode mode);
468 
469     /**
470      * @brief stop the uv loop in the engine
471      */
472     napi_status StopEventLoop();
473 
474     napi_status SendEvent(const std::function<void()> &cb, napi_event_priority priority = napi_eprio_high);
475 
476     virtual bool IsCrossThreadCheckEnabled() const = 0;
477 
IsInDestructor() const478     bool IsInDestructor() const
479     {
480         return isInDestructor_;
481     }
482 
GetMainThreadEngine()483     static NativeEngine* GetMainThreadEngine()
484     {
485         std::lock_guard<std::mutex> lock(g_mainThreadEngineMutex_);
486         return g_mainThreadEngine_;
487     }
488 
SetMainThreadEngine(NativeEngine* engine)489     static void SetMainThreadEngine(NativeEngine* engine)
490     {
491         if (g_mainThreadEngine_ == nullptr) {
492             std::lock_guard<std::mutex> lock(g_mainThreadEngineMutex_);
493             if (g_mainThreadEngine_ == nullptr) {
494                 g_mainThreadEngine_ = engine;
495             }
496         }
497     }
498 
499 private:
500     void InitUvField();
501     void CreateDefaultFunction(void);
502     void DestoryDefaultFunction(bool release);
503 
504     virtual NapiOptions *GetNapiOptions() const = 0;
505 
SetUnalived()506     inline void SetUnalived()
507     {
508         std::lock_guard<std::mutex> alivedEngLock(g_alivedEngineMutex_);
509         g_alivedEngine_.erase(this);
510         return;
511     }
512 
513     // should only call once in life cycle of ArkNativeEngine(NativeEngine)
514     inline void SetAlived();
515 
516 protected:
517     void *jsEngine_ = nullptr;
518 
519     void Init();
520     void Deinit();
521 
522     NativeModuleManager* moduleManager_ = nullptr;
523     NativeReferenceManager* referenceManager_ = nullptr;
524     NativeCallbackScopeManager* callbackScopeManager_ = nullptr;
525 
526     uv_loop_t* loop_ = nullptr;
527 
528     NativeErrorExtendedInfo lastError_;
529 
530     // register for worker
531     InitWorkerFunc initWorkerFunc_ {nullptr};
532     GetAssetFunc getAssetFunc_ {nullptr};
533     OffWorkerFunc offWorkerFunc_ {nullptr};
534 #if !defined(PREVIEW)
535     DebuggerPostTask debuggerPostTaskFunc_ {nullptr};
536 #endif
537     NativeEngine* hostEngine_ {nullptr};
538     bool isAppModule_ = false;
539     EcmaVM* vm_ {nullptr};
540 
541 public:
542     uint64_t openHandleScopes_ = 0;
543     panda::Local<panda::ObjectRef> lastException_;
544 
545 private:
546     std::string moduleName_;
547     std::string moduleFileName_;
548     std::mutex instanceDataLock_;
549     NativeObjectInfo instanceDataInfo_;
550     void FinalizerInstanceData(void);
551     pthread_t tid_ { 0 };
552     ThreadId sysTid_ { 0 };
553     uint64_t id_ { 0 };
554     std::unordered_map<std::string, int32_t> extensionInfos_;
555     uv_sem_t uvSem_;
556     // Application's sdk version
557     int32_t apiVersion_ = 8;
558 
559     // the old worker api use before api9, the new worker api start with api9
560     enum JSThreadType { MAIN_THREAD, WORKER_THREAD, TASKPOOL_THREAD, RESTRICTEDWORKER_THREAD, NATIVE_THREAD };
561     panda::panda_file::DataProtect jsThreadType_ {panda::panda_file::DataProtect(uintptr_t(JSThreadType::MAIN_THREAD))};
562     // current is hostengine, can create old worker, new worker, or no workers on hostengine
563     std::atomic<WorkerVersion> workerVersion_ { WorkerVersion::NONE };
564 
565 #if !defined(PREVIEW)
566     static void UVThreadRunner(void* nativeEngine);
567     void PostLoopTask();
568 
569     bool checkUVLoop_ = false;
570     uv_thread_t uvThread_;
571 #endif
572     mutable std::shared_mutex eventMutex_;
573     napi_threadsafe_function defaultFunc_ = nullptr;
574     PostTask postTask_ = nullptr;
575     CleanEnv cleanEnv_ = nullptr;
576     uv_async_t uvAsync_;
577     std::unordered_map<void*, std::pair<CleanupCallback, uint64_t>> cleanupHooks_;
578     uint64_t cleanupHookCounter_ = 0;
579     std::atomic_int requestWaiting_ { 0 };
580     std::atomic_int listeningCounter_ { 0 };
581     std::atomic_int subEnvCounter_ { 0 };
582     std::atomic_bool isStopping_ { false };
583 
584     std::mutex loopRunningMutex_;
585     bool isLoopRunning_ = false;
586     bool isInDestructor_ {false};
587 
588     // protect alived engine set and last engine id
589     static std::mutex g_alivedEngineMutex_;
590     static std::unordered_set<NativeEngine*> g_alivedEngine_;
591     static uint64_t g_lastEngineId_;
592     static std::mutex g_mainThreadEngineMutex_;
593     static NativeEngine* g_mainThreadEngine_;
594 };
595 
596 class TryCatch : public panda::TryCatch {
597 public:
TryCatch(napi_env env)598     explicit TryCatch(napi_env env)
599         : panda::TryCatch(reinterpret_cast<NativeEngine*>(env)->GetEcmaVm()),
600           engine_(reinterpret_cast<NativeEngine*>(env)) {}
601 
~TryCatch()602     ~TryCatch()
603     {
604         if (HasCaught()) {
605             engine_->lastException_ = GetException();
606         }
607     }
608 private:
609    NativeEngine* engine_ = nullptr;
610 };
611 #endif /* FOUNDATION_ACE_NAPI_NATIVE_ENGINE_NATIVE_ENGINE_H */
612