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_IMPL_ARK_ARK_NATIVE_ENGINE_H 17 #define FOUNDATION_ACE_NAPI_NATIVE_ENGINE_IMPL_ARK_ARK_NATIVE_ENGINE_H 18 19 #include <memory> 20 #if !defined(PREVIEW) && !defined(IOS_PLATFORM) 21 #include <sys/wait.h> 22 #include <sys/types.h> 23 #endif 24 #include <iostream> 25 #include <map> 26 #include <mutex> 27 #include <regex> 28 #include <thread> 29 #include <unistd.h> 30 31 #include "ark_idle_monitor.h" 32 #include "ark_native_options.h" 33 #include "ecmascript/napi/include/dfx_jsnapi.h" 34 #include "ecmascript/napi/include/jsnapi.h" 35 #include "native_engine/impl/ark/ark_finalizers_pack.h" 36 #include "native_engine/native_engine.h" 37 38 namespace panda::ecmascript { 39 struct JsHeapDumpWork; 40 struct JsFrameInfo { 41 std::string functionName; 42 std::string fileName; 43 std::string packageName; 44 std::string pos; 45 uintptr_t* nativePointer = nullptr; 46 }; 47 struct ApiCheckContext { 48 NativeModuleManager* moduleManager; 49 EcmaVM* ecmaVm; 50 panda::Local<panda::StringRef>& moduleName; 51 panda::Local<panda::ObjectRef>& exportObj; 52 panda::EscapeLocalScope& scope; 53 }; 54 } 55 using JsFrameInfo = panda::ecmascript::JsFrameInfo; 56 using DFXJSNApi = panda::DFXJSNApi; 57 using LocalScope = panda::LocalScope; 58 using JSNApi = panda::JSNApi; 59 using JSValueRef = panda::JSValueRef; 60 using JsiRuntimeCallInfo = panda::JsiRuntimeCallInfo; 61 using PropertyAttribute = panda::PropertyAttribute; 62 using NativePointerCallbackData = panda::NativePointerCallbackData; 63 using AsyncNativeCallbacksPack = panda::AsyncNativeCallbacksPack; 64 using TriggerGCTaskCallback = panda::TriggerGCTaskCallback; 65 using TriggerGCData = panda::TriggerGCData; 66 using ArkIdleMonitor = panda::ecmascript::ArkIdleMonitor; 67 68 // indirect used by ace_engine and(or) ability_runtime 69 using panda::Local; 70 class NativeTimerCallbackInfo; 71 template <bool changeState = true> 72 panda::JSValueRef ArkNativeFunctionCallBack(JsiRuntimeCallInfo *runtimeInfo); 73 void NapiDefinePropertyInner(napi_env env, 74 Local<panda::ObjectRef> &obj, 75 NapiPropertyDescriptor &propertyDescriptor, 76 Local<panda::JSValueRef> &propertyName, 77 bool &result); 78 bool NapiDefineProperty(napi_env env, panda::Local<panda::ObjectRef> &obj, NapiPropertyDescriptor propertyDescriptor); 79 NAPI_EXPORT panda::Local<panda::JSValueRef> NapiValueToLocalValue(napi_value v); 80 NAPI_EXPORT napi_value LocalValueToLocalNapiValue(panda::Local<panda::JSValueRef> local); 81 #ifdef ENABLE_CONTAINER_SCOPE 82 void FunctionSetContainerId(const EcmaVM *vm, panda::Local<panda::JSValueRef> &local); 83 #endif 84 panda::Local<panda::JSValueRef> NapiDefineClass(napi_env env, const char* name, NapiNativeCallback callback, 85 void* data, const NapiPropertyDescriptor* properties, size_t length); 86 Local<JSValueRef> NapiDefineSendableClass(napi_env env, 87 const char* name, 88 NapiNativeCallback callback, 89 void* data, 90 const NapiPropertyDescriptor* properties, 91 size_t propertiesLength, 92 napi_value parent); 93 panda::Local<panda::ObjectRef> NapiCreateSObjectWithProperties(napi_env env, 94 size_t propertyCount, 95 const NapiPropertyDescriptor* properties); 96 panda::Local<panda::ObjectRef> NapiCreateObjectWithProperties(napi_env env, size_t propertyCount, 97 const napi_property_descriptor *properties, 98 Local<panda::JSValueRef> *keys, 99 panda::PropertyAttribute *attrs); 100 101 enum class ForceExpandState : int32_t { 102 FINISH_COLD_START = 0, 103 START_HIGH_SENSITIVE, 104 FINISH_HIGH_SENSITIVE, 105 }; 106 107 enum class ModuleTypes : uint8_t { 108 NATIVE_MODULE = 0x01, 109 MODULE_INNER_FILE, 110 UNKNOWN 111 }; 112 113 class SerializationData { 114 public: SerializationData()115 SerializationData() : data_(nullptr), size_(0) {} 116 ~SerializationData() = default; 117 GetData()118 uint8_t* GetData() const 119 { 120 return data_.get(); 121 } GetSize()122 size_t GetSize() const 123 { 124 return size_; 125 } 126 127 private: 128 struct DataDeleter { operatorDataDeleter129 void operator()(uint8_t* p) const 130 { 131 free(p); 132 } 133 }; 134 135 std::unique_ptr<uint8_t, DataDeleter> data_; 136 size_t size_; 137 }; 138 139 class NAPI_EXPORT ArkNativeEngine : public NativeEngine { 140 friend struct MoudleNameLocker; 141 public: 142 // ArkNativeEngine constructor 143 ArkNativeEngine(EcmaVM* vm, void* jsEngine, bool isLimitedWorker = false); 144 // ArkNativeEngine destructor 145 ~ArkNativeEngine() override; 146 GetEcmaVm()147 NAPI_EXPORT const EcmaVM* GetEcmaVm() const override 148 { 149 return vm_; 150 } 151 152 void Loop(LoopMode mode, bool needSync = false) override; 153 void SetPromiseRejectCallback(NativeReference* rejectCallbackRef, NativeReference* checkCallbackRef) override; 154 // For concurrent 155 bool InitTaskPoolThread(NativeEngine* engine, NapiConcurrentCallback callback) override; 156 bool InitTaskPoolThread(napi_env env, NapiConcurrentCallback callback) override; 157 bool InitTaskPoolFunc(napi_env env, napi_value func, void* taskInfo) override; 158 void ClearCurrentTaskInfo() override; 159 bool HasPendingJob() const override; 160 bool IsProfiling() const override; 161 bool IsExecutingPendingJob() const override; 162 void* GetCurrentTaskInfo() const override; 163 void TerminateExecution() const override; 164 void NotifyTaskBegin() const override; 165 void NotifyTaskFinished() const override; 166 167 // judge_typedarray 168 bool NapiNewTypedArray(const EcmaVM* vm, NativeTypedArrayType typedArrayType, 169 Local<panda::ArrayBufferRef> arrayBuf, 170 size_t byte_offset, size_t length, napi_value* result) override; 171 bool NapiNewSendableTypedArray(const EcmaVM* vm, NativeTypedArrayType typedArrayType, 172 Local<panda::SendableArrayBufferRef> arrayBuf, 173 size_t byte_offset, size_t length, napi_value* result) override; 174 NativeTypedArrayType GetTypedArrayType(panda::Local<panda::TypedArrayRef> typedArray) override; 175 NativeTypedArrayType GetSendableTypedArrayType(panda::Local<panda::SendableTypedArrayRef> typedArray) override; 176 // Call function 177 napi_value CallFunction(napi_value thisVar, 178 napi_value function, 179 napi_value const* argv, 180 size_t argc) override; 181 bool RunScriptPath(const char* path, bool checkPath = false) override; 182 183 napi_value RunScriptBuffer(const char* path, std::vector<uint8_t>& buffer, bool isBundle, 184 bool needUpdate = false) override; 185 bool RunScriptBuffer(const std::string& path, uint8_t* buffer, size_t size, bool isBundle) override; 186 187 // Run buffer script 188 napi_value RunBufferScript(std::vector<uint8_t>& buffer) override; 189 napi_value RunActor(uint8_t* buffer, size_t size, const char* descriptor, 190 char* entryPoint = nullptr, bool checkPath = false) override; 191 // Set lib path 192 NAPI_EXPORT void SetPackagePath(const std::string appLinPathKey, const std::vector<std::string>& packagePath); 193 napi_value CreateInstance(napi_value constructor, napi_value const* argv, size_t argc) override; 194 195 // Create native reference 196 NativeReference* CreateReference(napi_value value, uint32_t initialRefcount, bool flag = false, 197 NapiNativeFinalize callback = nullptr, void* data = nullptr, void* hint = nullptr, 198 size_t nativeBindingSize = 0) override; 199 NativeReference* CreateAsyncReference(napi_value value, uint32_t initialRefcount, bool flag = false, 200 NapiNativeFinalize callback = nullptr, void* data = nullptr, void* hint = nullptr) override; 201 napi_value CreatePromise(NativeDeferred** deferred) override; 202 void* CreateRuntime(bool isLimitedWorker = false) override; 203 panda::Local<panda::ObjectRef> LoadArkModule(const void *buffer, int32_t len, const std::string& fileName); 204 napi_value ValueToNapiValue(JSValueWrapper& value) override; 205 NAPI_EXPORT static napi_value ArkValueToNapiValue(napi_env env, Local<JSValueRef> value); 206 207 std::string GetSourceCodeInfo(napi_value value, ErrorPos pos) override; 208 209 NAPI_EXPORT bool ExecuteJsBin(const std::string& fileName, bool checkPath = false); 210 static bool IsValidPandaFile(const char* path); 211 static bool IsValidScriptBuffer(uint8_t* scriptBuffer, size_t bufferSize); 212 NAPI_EXPORT panda::Local<panda::ObjectRef> LoadModuleByName(const std::string& moduleName, bool isAppModule, 213 const std::string& param, const std::string& instanceName, void* instance, const std::string& path = ""); 214 215 void TriggerFatalException(panda::Local<panda::JSValueRef> exceptionValue) override; 216 bool AdjustExternalMemory(int64_t ChangeInBytes, int64_t* AdjustedValue) override; 217 218 // Set jsdump thresholds 219 void SetJsDumpThresholds(size_t thresholds) override; 220 221 // Set Appfreeze Filter 222 void SetAppFreezeFilterCallback(AppFreezeFilterCallback callback) override; 223 224 // Detect performance to obtain cpuprofiler file 225 void StartCpuProfiler(const std::string& fileName = "") override; 226 void StopCpuProfiler() override; 227 228 void ResumeVM() override; 229 bool SuspendVM() override; 230 bool IsSuspended() override; 231 bool CheckSafepoint() override; 232 bool SuspendVMById(uint32_t tid) override; 233 void ResumeVMById(uint32_t tid) override; 234 235 // isVmMode means the internal class in vm is visible. 236 // isPrivate means the number and string is not visible. 237 void DumpHeapSnapshot(const std::string& path, bool isVmMode = true, 238 DumpFormat dumpFormat = DumpFormat::JSON, bool isPrivate = false, bool captureNumericValue = false) override; 239 void DumpHeapSnapshot(int& fd, bool isFullGC, const std::function<void(uint8_t)> &allback) override; 240 void DumpCpuProfile() override; 241 // Dump the file into faultlog for heap leak. 242 void DumpHeapSnapshot(bool isVmMode = true, DumpFormat dumpFormat = DumpFormat::JSON, 243 bool isPrivate = false, bool isFullGC = true) override; 244 bool BuildNativeAndJsStackTrace(std::string& stackTraceStr) override; 245 bool BuildJsStackTrace(std::string& stackTraceStr) override; 246 bool BuildJsStackInfoListWithCustomDepth(std::vector<JsFrameInfo>& jsFrames) 247 override; 248 249 bool DeleteWorker(NativeEngine* workerEngine) override; 250 bool StartHeapTracking(double timeInterval, bool isVmMode = true) override; 251 bool StopHeapTracking(const std::string& filePath) override; 252 253 void PrintStatisticResult() override; 254 void StartRuntimeStat() override; 255 void StopRuntimeStat() override; 256 size_t GetArrayBufferSize() override; 257 size_t GetHeapTotalSize() override; 258 size_t GetHeapUsedSize() override; 259 size_t GetHeapObjectSize() override; 260 size_t GetHeapLimitSize() override; 261 size_t GetProcessHeapLimitSize() override; 262 size_t GetGCCount() override; 263 size_t GetGCDuration() override; 264 size_t GetAccumulatedAllocateSize() override; 265 size_t GetAccumulatedFreeSize() override; 266 size_t GetFullGCLongTimeCount() override; 267 void NotifyApplicationState(bool inBackground) override; 268 void NotifyIdleStatusControl(std::function<void(bool)> callback) override; 269 void NotifyIdleTime(int idleMicroSec) override; 270 void NotifyMemoryPressure(bool inHighMemoryPressure = false) override; 271 void NotifyForceExpandState(int32_t value) override; 272 273 void AllowCrossThreadExecution() const override; 274 static void PromiseRejectCallback(void* values); 275 276 void SetMockModuleList(const std::map<std::string, std::string> &list) override; 277 int32_t GetObjectHash(napi_env env, napi_value src) override; 278 279 // debugger 280 bool IsMixedDebugEnabled(); 281 void JsHeapStart(); 282 uint64_t GetCurrentTickMillseconds(); 283 bool JudgmentDumpExecuteTask(int pid); 284 void JudgmentDump(size_t limitSize); 285 void NotifyNativeCalling(const void *nativeAddress); 286 287 void PostFinalizeTasks(); 288 void PostAsyncTask(AsyncNativeCallbacksPack *callbacksPack); 289 void PostTriggerGCTask(TriggerGCData& data); 290 GetArkFinalizersPack()291 ArkFinalizersPack &GetArkFinalizersPack() 292 { 293 return arkFinalizersPack_; 294 } 295 GetPendingAsyncFinalizers()296 std::vector<RefAsyncFinalizer> &GetPendingAsyncFinalizers() 297 { 298 return pendingAsyncFinalizers_; 299 } 300 301 void RegisterNapiUncaughtExceptionHandler(NapiUncaughtExceptionCallback callback) override; 302 void HandleUncaughtException() override; 303 bool HasPendingException() override; 304 void RegisterPermissionCheck(PermissionCheckCallback callback) override; 305 bool ExecutePermissionCheck() override; 306 void RegisterTranslateBySourceMap(SourceMapCallback callback) override; 307 std::string ExecuteTranslateBySourceMap(const std::string& rawStack) override; 308 void RegisterSourceMapTranslateCallback(SourceMapTranslateCallback callback) override; 309 panda::Local<panda::ObjectRef> GetModuleFromName( 310 const std::string& moduleName, bool isAppModule, const std::string& id, const std::string& param, 311 const std::string& instanceName, void** instance); 312 napi_value NapiLoadModule(const char* path) override; 313 napi_value NapiLoadModuleWithInfo(const char* path, const char* module_info) override; 314 std::string GetOhmurl(std::string str); 315 Local<JSValueRef> NapiLoadNativeModule(std::string path); GetPromiseRejectCallBackRef()316 NativeReference* GetPromiseRejectCallBackRef() 317 { 318 return promiseRejectCallbackRef_; 319 } 320 RegisterAllPromiseCallback(NapiAllPromiseRejectCallback callback)321 void RegisterAllPromiseCallback(NapiAllPromiseRejectCallback callback) override 322 { 323 allPromiseRejectCallback_ = callback; 324 } 325 SetPromiseRejectCallBackRef(NativeReference * rejectCallbackRef)326 void SetPromiseRejectCallBackRef(NativeReference* rejectCallbackRef) override 327 { 328 promiseRejectCallbackRef_ = rejectCallbackRef; 329 } 330 GetConcurrentCallbackFunc()331 NapiConcurrentCallback GetConcurrentCallbackFunc() 332 { 333 return concurrentCallbackFunc_; 334 } 335 GetCheckCallbackRef()336 NativeReference* GetCheckCallbackRef() 337 { 338 return checkCallbackRef_; 339 } 340 SetCheckCallbackRef(NativeReference * checkCallbackRef)341 void SetCheckCallbackRef(NativeReference* checkCallbackRef) override 342 { 343 checkCallbackRef_ = checkCallbackRef; 344 } 345 GetNapiUncaughtExceptionCallback()346 NapiUncaughtExceptionCallback GetNapiUncaughtExceptionCallback() override 347 { 348 return napiUncaughtExceptionCallback_; 349 } 350 GetPromiseRejectCallback()351 void* GetPromiseRejectCallback() override 352 { 353 return reinterpret_cast<void*>(PromiseRejectCallback); 354 } 355 356 void SetModuleName(panda::Local<panda::ObjectRef> &nativeObj, std::string moduleName); 357 void GetCurrentModuleInfo(std::string& moduleName, std::string& fileName, bool needRecordName) override; 358 bool GetIsBundle() override; 359 bool GetIsNormalizedOhmUrlPack() override; 360 bool GetIsDebugModeEnabled() override; 361 std::string GetBundleName() override; 362 std::string GetPkgName(const std::string &moduleName) override; 363 bool IsExecuteModuleInAbcFile(std::string bundleName, std::string moduleName, std::string ohmurl) override; 364 int GetProcessStartRealTime() override; 365 void PostLooperTriggerIdleGCTask(); 366 367 static bool napiProfilerEnabled; 368 static std::string tempModuleName_; 369 370 static void* GetNativePtrCallBack(void* data); 371 static void CopyPropertyApiFilter(const std::unique_ptr<ApiAllowListChecker>& apiAllowListChecker, 372 const EcmaVM* ecmaVm, const panda::Local<panda::ObjectRef> exportObj, 373 panda::Local<panda::ObjectRef>& exportCopy, const std::string& apiPath); 374 IsCrossThreadCheckEnabled()375 inline bool IsCrossThreadCheckEnabled() const override 376 { 377 return crossThreadCheck_; 378 } 379 static constexpr size_t FINALIZERS_PACK_PENDING_NATIVE_BINDING_SIZE_THRESHOLD = 500 * 1024 * 1024; // 500 MB 380 GetTimerListHead()381 NativeTimerCallbackInfo* GetTimerListHead() const 382 { 383 return TimerListHead_; 384 } SetTimerListHead(NativeTimerCallbackInfo * info)385 void SetTimerListHead(NativeTimerCallbackInfo* info) 386 { 387 TimerListHead_ = info; 388 } 389 390 private: GetNapiOptions()391 inline NapiOptions *GetNapiOptions() const override 392 { 393 return options_; 394 } 395 396 static void RunCallbacks(ArkFinalizersPack *finalizersPack); 397 static void RunAsyncCallbacks(std::vector<RefAsyncFinalizer> *finalizers); 398 static void RunCallbacks(AsyncNativeCallbacksPack *callbacks); 399 static void RunCallbacks(TriggerGCData *triggerGCData); 400 static void SetAttribute(bool isLimitedWorker, panda::RuntimeOption &option); 401 static NativeEngine* CreateRuntimeFunc(NativeEngine* engine, void* jsEngine, bool isLimitedWorker = false); 402 static bool CheckArkApiAllowList( 403 NativeModule* module, panda::ecmascript::ApiCheckContext context, panda::Local<panda::ObjectRef>& exportCopy); IncreasePendingFinalizersPackNativeBindingSize(size_t nativeBindingSize)404 void IncreasePendingFinalizersPackNativeBindingSize(size_t nativeBindingSize) 405 { 406 pendingFinalizersPackNativeBindingSize_ += nativeBindingSize; 407 } DecreasePendingFinalizersPackNativeBindingSize(size_t nativeBindingSize)408 void DecreasePendingFinalizersPackNativeBindingSize(size_t nativeBindingSize) 409 { 410 pendingFinalizersPackNativeBindingSize_ -= nativeBindingSize; 411 } 412 413 EcmaVM* vm_ = nullptr; 414 bool needStop_ = false; 415 panda::LocalScope topScope_; 416 NapiConcurrentCallback concurrentCallbackFunc_ { nullptr }; 417 NativeReference* promiseRejectCallbackRef_ { nullptr }; 418 NativeReference* checkCallbackRef_ { nullptr }; 419 std::map<NativeModule*, panda::Global<panda::JSValueRef>> loadedModules_ {}; 420 static PermissionCheckCallback permissionCheckCallback_; 421 NapiUncaughtExceptionCallback napiUncaughtExceptionCallback_ { nullptr }; 422 NapiAllPromiseRejectCallback allPromiseRejectCallback_ {nullptr}; 423 SourceMapCallback SourceMapCallback_ { nullptr }; 424 static bool napiProfilerParamReaded; 425 bool isLimitedWorker_ = false; 426 size_t pendingFinalizersPackNativeBindingSize_ {0}; 427 ArkFinalizersPack arkFinalizersPack_ {}; 428 std::vector<RefAsyncFinalizer> pendingAsyncFinalizers_ {}; 429 // napi options and its cache 430 NapiOptions* options_ { nullptr }; 431 bool crossThreadCheck_ { false }; 432 NativeTimerCallbackInfo* TimerListHead_ {nullptr}; 433 }; 434 #endif /* FOUNDATION_ACE_NAPI_NATIVE_ENGINE_IMPL_ARK_ARK_NATIVE_ENGINE_H */ 435