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 "module_manager/native_module_manager.h" 31 #include "native_engine/native_async_work.h" 32 #include "native_engine/native_deferred.h" 33 #include "native_engine/native_reference.h" 34 #include "native_engine/native_safe_async_work.h" 35 #include "native_engine/native_value.h" 36 #include "native_property.h" 37 #include "reference_manager/native_reference_manager.h" 38 #include "scope_manager/native_scope_manager.h" 39 #include "utils/macros.h" 40 41 typedef int32_t (*GetContainerScopeIdCallback)(void); 42 typedef void (*ContainerScopeCallback)(int32_t); 43 44 typedef struct uv_loop_s uv_loop_t; 45 46 struct NativeErrorExtendedInfo { 47 const char* message = nullptr; 48 void* reserved = nullptr; 49 uint32_t engineErrorCode = 0; 50 int errorCode = 0; 51 }; 52 53 struct ExceptionInfo { 54 const char* message_ = nullptr; 55 int32_t lineno_ = 0; 56 int32_t colno_ = 0; 57 ~ExceptionInfoExceptionInfo58 ~ExceptionInfo() 59 { 60 if (message_ != nullptr) { 61 delete[] message_; 62 } 63 } 64 }; 65 66 enum LoopMode { 67 LOOP_DEFAULT, LOOP_ONCE, LOOP_NOWAIT 68 }; 69 70 enum class DumpFormat { 71 JSON, BINARY, OTHER 72 }; 73 74 class CleanupHookCallback { 75 public: 76 using Callback = void (*)(void*); 77 CleanupHookCallback(Callback fn,void * arg,uint64_t insertion_order_counter)78 CleanupHookCallback(Callback fn, void* arg, uint64_t insertion_order_counter) 79 : fn_(fn), arg_(arg), insertion_order_counter_(insertion_order_counter) 80 {} 81 82 struct Hash { operatorHash83 inline size_t operator()(const CleanupHookCallback& cb) const 84 { 85 return std::hash<void*>()(cb.arg_); 86 } 87 }; 88 struct Equal { operatorEqual89 inline bool operator()(const CleanupHookCallback& a, const CleanupHookCallback& b) const 90 { 91 return a.fn_ == b.fn_ && a.arg_ == b.arg_; 92 }; 93 }; 94 95 private: 96 friend class NativeEngine; 97 Callback fn_; 98 void* arg_; 99 uint64_t insertion_order_counter_; 100 }; 101 102 using PostTask = std::function<void(bool needSync)>; 103 using CleanEnv = std::function<void()>; 104 using InitWorkerFunc = std::function<void(NativeEngine* engine)>; 105 using GetAssetFunc = std::function<void(const std::string& uri, std::vector<uint8_t>& content, std::string& ami)>; 106 using OffWorkerFunc = std::function<void(NativeEngine* engine)>; 107 using DebuggerPostTask = std::function<void(std::function<void()>&&)>; 108 using UncaughtExceptionCallback = std::function<void(NativeValue* value)>; 109 using PermissionCheckCallback = std::function<bool()>; 110 using NapiConcurrentCallback = void (*)(NativeEngine* engine, NativeValue* result, bool success, void* data); 111 using SourceMapCallback = std::function<std::string(const std::string& rawStack)>; 112 113 class NAPI_EXPORT NativeEngine { 114 public: 115 explicit NativeEngine(void* jsEngine); 116 virtual ~NativeEngine(); 117 118 virtual NativeScopeManager* GetScopeManager(); 119 virtual NativeModuleManager* GetModuleManager(); 120 virtual NativeReferenceManager* GetReferenceManager(); 121 virtual NativeCallbackScopeManager* GetCallbackScopeManager(); 122 virtual uv_loop_t* GetUVLoop() const; 123 virtual pthread_t GetTid() const; 124 125 virtual bool ReinitUVLoop(); 126 127 virtual void Loop(LoopMode mode, bool needSync = false); 128 virtual void SetPostTask(PostTask postTask); 129 virtual void TriggerPostTask(); 130 #if !defined(PREVIEW) 131 virtual void CheckUVLoop(); 132 virtual void CancelCheckUVLoop(); 133 #endif 134 virtual void* GetJsEngine(); 135 136 virtual NativeValue* GetGlobal() = 0; 137 138 virtual NativeValue* CreateNull() = 0; 139 virtual NativeValue* CreateUndefined() = 0; 140 virtual NativeValue* CreateBoolean(bool value) = 0; 141 virtual NativeValue* CreateNumber(int32_t value) = 0; 142 virtual NativeValue* CreateNumber(uint32_t value) = 0; 143 virtual NativeValue* CreateNumber(int64_t value) = 0; 144 virtual NativeValue* CreateNumber(double value) = 0; 145 virtual NativeValue* CreateBigInt(int64_t value) = 0; 146 virtual NativeValue* CreateBigInt(uint64_t value) = 0; 147 virtual NativeValue* CreateString(const char* value, size_t length) = 0; 148 virtual NativeValue* CreateString16(const char16_t* value, size_t length) = 0; 149 150 virtual NativeValue* CreateSymbol(NativeValue* value) = 0; 151 virtual NativeValue* CreateExternal(void* value, NativeFinalize callback, void* hint, 152 size_t nativeBindingSize = 0) = 0; 153 154 virtual NativeValue* CreateObject() = 0; 155 virtual NativeValue* CreateFunction(const char* name, size_t length, NativeCallback cb, void* value) = 0; 156 virtual NativeValue* CreateArray(size_t length) = 0; 157 virtual NativeValue* CreateBuffer(void** value, size_t length) = 0; 158 virtual NativeValue* CreateBufferCopy(void** value, size_t length, const void* data) = 0; 159 virtual NativeValue* CreateBufferExternal(void* value, size_t length, NativeFinalize cb, void* hint) = 0; 160 virtual NativeValue* CreateArrayBuffer(void** value, size_t length) = 0; 161 virtual NativeValue* CreateArrayBufferExternal(void* value, size_t length, NativeFinalize cb, void* hint) = 0; 162 163 virtual NativeValue* CreateTypedArray(NativeTypedArrayType type, 164 NativeValue* value, 165 size_t length, 166 size_t offset) = 0; 167 virtual NativeValue* CreateDataView(NativeValue* value, size_t length, size_t offset) = 0; 168 virtual NativeValue* CreatePromise(NativeDeferred** deferred) = 0; 169 virtual void SetPromiseRejectCallback(NativeReference* rejectCallbackRef, NativeReference* checkCallbackRef) = 0; 170 virtual NativeValue* CreateError(NativeValue* code, NativeValue* message) = 0; 171 172 virtual bool InitTaskPoolThread(NativeEngine* engine, NapiConcurrentCallback callback) = 0; 173 virtual bool InitTaskPoolFunc(NativeEngine* engine, NativeValue* func, void* taskInfo) = 0; 174 virtual void* GetCurrentTaskInfo() const = 0; 175 176 virtual NativeValue* CallFunction(NativeValue* thisVar, 177 NativeValue* function, 178 NativeValue* const *argv, 179 size_t argc) = 0; 180 virtual NativeValue* RunScript(NativeValue* script) = 0; 181 virtual NativeValue* RunScriptPath(const char* path) = 0; 182 virtual NativeValue* RunScriptBuffer(const char* path, std::vector<uint8_t>& buffer, bool isBundle) = 0; 183 virtual bool RunScriptBuffer(const std::string &path, uint8_t* buffer, size_t size, bool isBundle) = 0; 184 virtual NativeValue* RunBufferScript(std::vector<uint8_t>& buffer) = 0; 185 virtual NativeValue* RunActor(std::vector<uint8_t>& buffer, const char* descriptor) = 0; 186 virtual NativeValue* DefineClass(const char* name, 187 NativeCallback callback, 188 void* data, 189 const NativePropertyDescriptor* properties, 190 size_t length) = 0; 191 192 virtual NativeValue* CreateInstance(NativeValue* constructor, NativeValue* const *argv, size_t argc) = 0; 193 194 virtual NativeReference* CreateReference(NativeValue* value, uint32_t initialRefcount, 195 NativeFinalize callback = nullptr, void* data = nullptr, void* hint = nullptr) = 0; 196 197 virtual NativeAsyncWork* CreateAsyncWork(NativeValue* asyncResource, 198 NativeValue* asyncResourceName, 199 NativeAsyncExecuteCallback execute, 200 NativeAsyncCompleteCallback complete, 201 void* data); 202 203 virtual NativeAsyncWork* CreateAsyncWork(const std::string &asyncResourceName, 204 NativeAsyncExecuteCallback execute, 205 NativeAsyncCompleteCallback complete, 206 void* data); 207 virtual NativeSafeAsyncWork* CreateSafeAsyncWork(NativeValue* func, NativeValue* asyncResource, 208 NativeValue* asyncResourceName, size_t maxQueueSize, size_t threadCount, void* finalizeData, 209 NativeFinalize finalizeCallback, void* context, NativeThreadSafeFunctionCallJs callJsCallback); 210 211 virtual bool Throw(NativeValue* error) = 0; 212 virtual bool Throw(NativeErrorType type, const char* code, const char* message) = 0; 213 214 virtual void* CreateRuntime() = 0; 215 virtual NativeValue* Serialize(NativeEngine* context, NativeValue* value, NativeValue* transfer) = 0; 216 virtual NativeValue* Deserialize(NativeEngine* context, NativeValue* recorder) = 0; 217 virtual void DeleteSerializationData(NativeValue* value) const = 0; 218 virtual NativeValue* LoadModule(NativeValue* str, const std::string& fileName) = 0; 219 220 virtual void StartCpuProfiler(const std::string& fileName = "") = 0; 221 virtual void StopCpuProfiler() = 0; 222 223 virtual void ResumeVM() = 0; 224 virtual bool SuspendVM() = 0; 225 virtual bool IsSuspended() = 0; 226 virtual bool CheckSafepoint() = 0; 227 virtual bool SuspendVMById(uint32_t tid) = 0; 228 virtual void ResumeVMById(uint32_t tid) = 0; 229 230 virtual void DumpHeapSnapshot(const std::string &path, bool isVmMode = true, 231 DumpFormat dumpFormat = DumpFormat::JSON) = 0; 232 virtual void DumpHeapSnapshot(bool isVmMode = true, DumpFormat dumpFormat = DumpFormat::JSON, 233 bool isPrivate = false) = 0; 234 virtual bool BuildNativeAndJsStackTrace(std::string &stackTraceStr) = 0; 235 virtual bool BuildJsStackTrace(std::string &stackTraceStr) = 0; 236 virtual bool BuildJsStackInfoList(uint32_t tid, std::vector<JsFrameInfo>& jsFrames) = 0; 237 virtual bool DeleteWorker(NativeEngine* workerEngine) = 0; 238 virtual bool StartHeapTracking(double timeInterval, bool isVmMode = true) = 0; 239 virtual bool StopHeapTracking(const std::string &filePath) = 0; 240 241 virtual void AllowCrossThreadExecution() const = 0; 242 243 NativeErrorExtendedInfo* GetLastError(); 244 void SetLastError(int errorCode, uint32_t engineErrorCode = 0, void* engineReserved = nullptr); 245 void ClearLastError(); 246 virtual bool IsExceptionPending() const = 0; 247 virtual NativeValue* GetAndClearLastException() = 0; 248 void EncodeToUtf8(NativeValue* nativeValue, char* buffer, int32_t* written, size_t bufferSize, int32_t* nchars); 249 void EncodeToChinese(NativeValue* nativeValue, std::string& buffer, const std::string& encoding); 250 NativeEngine(NativeEngine&) = delete; 251 virtual NativeEngine& operator=(NativeEngine&) = delete; 252 253 virtual NativeValue* ValueToNativeValue(JSValueWrapper& value) = 0; 254 virtual bool TriggerFatalException(NativeValue* error) = 0; 255 virtual bool AdjustExternalMemory(int64_t ChangeInBytes, int64_t* AdjustedValue) = 0; 256 MarkWorkerThread()257 void MarkWorkerThread() 258 { 259 jsThreadType_ = JSThreadType::WORKER_THREAD; 260 } MarkTaskPoolThread()261 void MarkTaskPoolThread() 262 { 263 jsThreadType_ = JSThreadType::TASKPOOL_THREAD; 264 } IsWorkerThread()265 bool IsWorkerThread() const 266 { 267 return jsThreadType_ == JSThreadType::WORKER_THREAD; 268 } IsTaskPoolThread()269 bool IsTaskPoolThread() const 270 { 271 return jsThreadType_ == JSThreadType::TASKPOOL_THREAD; 272 } IsMainThread()273 bool IsMainThread() const 274 { 275 return jsThreadType_ == JSThreadType::MAIN_THREAD; 276 } 277 SetCleanEnv(CleanEnv cleanEnv)278 void SetCleanEnv(CleanEnv cleanEnv) 279 { 280 cleanEnv_ = cleanEnv; 281 } 282 283 // register init worker func 284 virtual void SetInitWorkerFunc(InitWorkerFunc func); 285 InitWorkerFunc GetInitWorkerFunc() const; 286 virtual void SetGetAssetFunc(GetAssetFunc func); 287 GetAssetFunc GetGetAssetFunc() const; 288 virtual void SetOffWorkerFunc(OffWorkerFunc func); 289 OffWorkerFunc GetOffWorkerFunc() const; 290 291 // call init worker func 292 virtual bool CallInitWorkerFunc(NativeEngine* engine); 293 virtual bool CallGetAssetFunc(const std::string& uri, std::vector<uint8_t>& content, std::string& ami); 294 virtual bool CallOffWorkerFunc(NativeEngine* engine); 295 296 // adapt worker to ace container 297 virtual void SetGetContainerScopeIdFunc(GetContainerScopeIdCallback func); 298 virtual void SetInitContainerScopeFunc(ContainerScopeCallback func); 299 virtual void SetFinishContainerScopeFunc(ContainerScopeCallback func); 300 virtual int32_t GetContainerScopeIdFunc(); 301 virtual bool InitContainerScopeFunc(int32_t id); 302 virtual bool FinishContainerScopeFunc(int32_t id); 303 304 #if !defined(PREVIEW) 305 virtual void SetDebuggerPostTaskFunc(DebuggerPostTask func); 306 virtual void CallDebuggerPostTaskFunc(std::function<void()>&& task); 307 #endif 308 309 virtual void SetHostEngine(NativeEngine* engine); 310 virtual NativeEngine* GetHostEngine() const; 311 312 virtual NativeValue* CreateDate(double value) = 0; 313 virtual NativeValue* CreateBigWords(int sign_bit, size_t word_count, const uint64_t* words) = 0; 314 using CleanupCallback = CleanupHookCallback::Callback; 315 virtual void AddCleanupHook(CleanupCallback fun, void* arg); 316 virtual void RemoveCleanupHook(CleanupCallback fun, void* arg); 317 318 void CleanupHandles(); 319 void IncreaseWaitingRequestCounter(); 320 void DecreaseWaitingRequestCounter(); 321 322 virtual void RunCleanup(); 323 IsStopping()324 bool IsStopping() const 325 { 326 return isStopping_.load(); 327 } 328 SetStopping(bool value)329 void SetStopping(bool value) 330 { 331 isStopping_.store(value); 332 } 333 334 virtual void PrintStatisticResult() = 0; 335 virtual void StartRuntimeStat() = 0; 336 virtual void StopRuntimeStat() = 0; 337 virtual size_t GetArrayBufferSize() = 0; 338 virtual size_t GetHeapTotalSize() = 0; 339 virtual size_t GetHeapUsedSize() = 0; 340 virtual void NotifyApplicationState(bool inBackground) = 0; 341 virtual void NotifyIdleStatusControl(std::function<void(bool)> callback) = 0; 342 virtual void NotifyIdleTime(int idleMicroSec) = 0; 343 virtual void NotifyMemoryPressure(bool inHighMemoryPressure = false) = 0; 344 345 void RegisterWorkerFunction(const NativeEngine* engine); 346 347 virtual void RegisterUncaughtExceptionHandler(UncaughtExceptionCallback callback) = 0; 348 virtual void HandleUncaughtException() = 0; HasPendingException()349 virtual bool HasPendingException() 350 { 351 return false; 352 } 353 virtual void RegisterPermissionCheck(PermissionCheckCallback callback) = 0; 354 virtual bool ExecutePermissionCheck() = 0; 355 virtual void RegisterTranslateBySourceMap(SourceMapCallback callback) = 0; 356 virtual std::string ExecuteTranslateBySourceMap(const std::string& rawStack) = 0; 357 // run script by path 358 NativeValue* RunScript(const char* path); 359 360 const char* GetModuleFileName(); 361 362 void SetModuleFileName(std::string &moduleName); 363 364 void SetInstanceData(void* data, NativeFinalize finalize_cb, void* hint); 365 void GetInstanceData(void** data); 366 367 /** 368 * @brief Set the Extension Infos 369 * 370 * @param extensionInfos extension infos to set 371 */ 372 void SetExtensionInfos(std::unordered_map<std::string, int32_t>&& extensionInfos); 373 374 /** 375 * @brief Get the Extension Infos 376 * 377 * @return extension infos 378 */ 379 const std::unordered_map<std::string, int32_t>& GetExtensionInfos(); 380 381 /** 382 * @brief Set the Module Blocklist 383 * 384 * @param blocklist the blocklist set to native engine 385 */ 386 void SetModuleBlocklist(std::unordered_map<int32_t, std::unordered_set<std::string>>&& blocklist); 387 388 /** 389 * @brief Set the Module Load Checker 390 * 391 * @param moduleCheckerDelegate the module checker delegate will intercept the module loading 392 */ 393 void SetModuleLoadChecker(const std::shared_ptr<ModuleCheckerDelegate>& moduleCheckerDelegate); 394 395 private: 396 void StartCleanupTimer(); 397 protected: 398 void *jsEngine_; 399 void* jsEngineInterface_; 400 401 void Init(); 402 void Deinit(); 403 404 NativeModuleManager* moduleManager_ = nullptr; 405 NativeScopeManager* scopeManager_ = nullptr; 406 NativeReferenceManager* referenceManager_ = nullptr; 407 NativeCallbackScopeManager* callbackScopeManager_ = nullptr; 408 409 uv_loop_t* loop_ = nullptr; 410 411 NativeErrorExtendedInfo lastError_; 412 413 // register for worker 414 InitWorkerFunc initWorkerFunc_ {nullptr}; 415 GetAssetFunc getAssetFunc_ {nullptr}; 416 OffWorkerFunc offWorkerFunc_ {nullptr}; 417 #if !defined(PREVIEW) 418 DebuggerPostTask debuggerPostTaskFunc_ {nullptr}; 419 #endif 420 NativeEngine* hostEngine_ {nullptr}; 421 422 private: 423 std::string moduleName_; 424 std::mutex instanceDataLock_; 425 NativeObjectInfo instanceDataInfo_; 426 void FinalizerInstanceData(void); 427 pthread_t tid_ = 0; 428 std::unordered_map<std::string, int32_t> extensionInfos_; 429 uv_sem_t uvSem_; 430 431 enum JSThreadType { MAIN_THREAD, WORKER_THREAD, TASKPOOL_THREAD }; 432 JSThreadType jsThreadType_ = JSThreadType::MAIN_THREAD; 433 434 #if !defined(PREVIEW) 435 static void UVThreadRunner(void* nativeEngine); 436 void PostLoopTask(); 437 438 bool checkUVLoop_ = false; 439 uv_thread_t uvThread_; 440 #endif 441 442 PostTask postTask_ = nullptr; 443 CleanEnv cleanEnv_ = nullptr; 444 uv_async_t uvAsync_; 445 std::unordered_set<CleanupHookCallback, CleanupHookCallback::Hash, CleanupHookCallback::Equal> cleanup_hooks_; 446 uint64_t cleanup_hook_counter_ = 0; 447 std::atomic_int request_waiting_ { 0 }; 448 std::atomic_bool isStopping_ { false }; 449 bool cleanupTimeout_ = false; 450 uv_timer_t timer_; 451 }; 452 453 #endif /* FOUNDATION_ACE_NAPI_NATIVE_ENGINE_NATIVE_ENGINE_H */ 454