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