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