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