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
42namespace panda::ecmascript {
43    class EcmaVM;
44}
45
46typedef int32_t (*GetContainerScopeIdCallback)(void);
47typedef void (*ContainerScopeCallback)(int32_t);
48typedef struct uv_loop_s uv_loop_t;
49
50struct NativeErrorExtendedInfo {
51    const char* message = nullptr;
52    void* reserved = nullptr;
53    uint32_t engineErrorCode = 0;
54    int errorCode = 0;
55};
56
57enum LoopMode {
58    LOOP_DEFAULT, LOOP_ONCE, LOOP_NOWAIT
59};
60
61enum class DumpFormat {
62    JSON, BINARY, OTHER
63};
64
65enum class WorkerVersion {
66    NONE, OLD, NEW
67};
68
69using CleanupCallback = void (*)(void*);
70using ThreadId = uint32_t;
71
72class NapiOptions;
73using PostTask = std::function<void(bool needSync)>;
74using CleanEnv = std::function<void()>;
75using InitWorkerFunc = std::function<void(NativeEngine* engine)>;
76using 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)>;
78using OffWorkerFunc = std::function<void(NativeEngine* engine)>;
79using DebuggerPostTask = std::function<void(std::function<void()>&&)>;
80using NapiUncaughtExceptionCallback = std::function<void(napi_value value)>;
81using PermissionCheckCallback = std::function<bool()>;
82using NapiConcurrentCallback = void (*)(napi_env env, napi_value result, bool success, void* data);
83using SourceMapCallback = std::function<std::string(const std::string& rawStack)>;
84using SourceMapTranslateCallback = std::function<bool(std::string& url, int& line, int& column)>;
85using AppFreezeFilterCallback = std::function<bool(const int32_t pid)>;
86using EcmaVM = panda::ecmascript::EcmaVM;
87using JsFrameInfo = panda::ecmascript::JsFrameInfo;
88
89class NAPI_EXPORT NativeEngine {
90public:
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;
100    inline ThreadId GetSysTid() const
101    {
102        return sysTid_;
103    };
104    static ThreadId GetCurSysTid();
105    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
121    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);
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
232    void MarkWorkerThread()
233    {
234        jsThreadType_.Update(static_cast<uintptr_t>(JSThreadType::WORKER_THREAD));
235    }
236    void MarkRestrictedWorkerThread()
237    {
238        jsThreadType_.Update(static_cast<uintptr_t>(JSThreadType::RESTRICTEDWORKER_THREAD));
239    }
240    void MarkTaskPoolThread()
241    {
242        jsThreadType_.Update(static_cast<uintptr_t>(JSThreadType::TASKPOOL_THREAD));
243    }
244    void MarkNativeThread()
245    {
246        jsThreadType_.Update(static_cast<uintptr_t>(JSThreadType::NATIVE_THREAD));
247    }
248    bool IsWorkerThread() const
249    {
250        return static_cast<JSThreadType>(jsThreadType_.GetOriginPointer()) == JSThreadType::WORKER_THREAD;
251    }
252    bool IsRestrictedWorkerThread() const
253    {
254        return static_cast<JSThreadType>(jsThreadType_.GetOriginPointer()) == JSThreadType::RESTRICTEDWORKER_THREAD;
255    }
256    bool IsTaskPoolThread() const
257    {
258        return static_cast<JSThreadType>(jsThreadType_.GetOriginPointer()) == JSThreadType::TASKPOOL_THREAD;
259    }
260    bool IsMainThread() const
261    {
262        return static_cast<JSThreadType>(jsThreadType_.GetOriginPointer()) == JSThreadType::MAIN_THREAD;
263    }
264    bool IsNativeThread() const
265    {
266        return static_cast<JSThreadType>(jsThreadType_.GetOriginPointer()) == JSThreadType::NATIVE_THREAD;
267    }
268
269    bool CheckAndSetWorkerVersion(WorkerVersion expected, WorkerVersion desired)
270    {
271        return workerVersion_.compare_exchange_strong(expected, desired);
272    }
273    bool IsTargetWorkerVersion(WorkerVersion target) const
274    {
275        return workerVersion_.load() == target;
276    }
277
278    void IncreaseSubEnvCounter()
279    {
280        subEnvCounter_++;
281    }
282    void DecreaseSubEnvCounter()
283    {
284        subEnvCounter_--;
285    }
286    bool HasSubEnv()
287    {
288        return subEnvCounter_.load() != 0;
289    }
290
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
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
349    bool IsStopping() const
350    {
351        return isStopping_.load();
352    }
353
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;
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
452    double NewAsyncId()
453    {
454        return 0;
455    }
456
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
478    bool IsInDestructor() const
479    {
480        return isInDestructor_;
481    }
482
483    static NativeEngine* GetMainThreadEngine()
484    {
485        std::lock_guard<std::mutex> lock(g_mainThreadEngineMutex_);
486        return g_mainThreadEngine_;
487    }
488
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
499private:
500    void InitUvField();
501    void CreateDefaultFunction(void);
502    void DestoryDefaultFunction(bool release);
503
504    virtual NapiOptions *GetNapiOptions() const = 0;
505
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
516protected:
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
541public:
542    uint64_t openHandleScopes_ = 0;
543    panda::Local<panda::ObjectRef> lastException_;
544
545private:
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
596class TryCatch : public panda::TryCatch {
597public:
598    explicit TryCatch(napi_env env)
599        : panda::TryCatch(reinterpret_cast<NativeEngine*>(env)->GetEcmaVm()),
600          engine_(reinterpret_cast<NativeEngine*>(env)) {}
601
602    ~TryCatch()
603    {
604        if (HasCaught()) {
605            engine_->lastException_ = GetException();
606        }
607    }
608private:
609   NativeEngine* engine_ = nullptr;
610};
611#endif /* FOUNDATION_ACE_NAPI_NATIVE_ENGINE_NATIVE_ENGINE_H */
612