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 pos;
44     uintptr_t* nativePointer = nullptr;
45 };
46 struct ApiCheckContext {
47     NativeModuleManager* moduleManager;
48     EcmaVM* ecmaVm;
49     panda::Local<panda::StringRef>& moduleName;
50     panda::Local<panda::ObjectRef>& exportObj;
51     panda::EscapeLocalScope& scope;
52 };
53 }
54 using JsFrameInfo = panda::ecmascript::JsFrameInfo;
55 using DFXJSNApi = panda::DFXJSNApi;
56 using LocalScope = panda::LocalScope;
57 using JSNApi = panda::JSNApi;
58 using JSValueRef = panda::JSValueRef;
59 using JsiRuntimeCallInfo = panda::JsiRuntimeCallInfo;
60 using PropertyAttribute = panda::PropertyAttribute;
61 using NativePointerCallbackData = panda::NativePointerCallbackData;
62 using AsyncNativeCallbacksPack = panda::AsyncNativeCallbacksPack;
63 using TriggerGCTaskCallback = panda::TriggerGCTaskCallback;
64 using TriggerGCData = panda::TriggerGCData;
65 using ArkIdleMonitor = panda::ecmascript::ArkIdleMonitor;
66 
67 // indirect used by ace_engine and(or) ability_runtime
68 using panda::Local;
69 
70 template <bool changeState = true>
71 panda::JSValueRef ArkNativeFunctionCallBack(JsiRuntimeCallInfo *runtimeInfo);
72 void NapiDefinePropertyInner(napi_env env,
73                              Local<panda::ObjectRef> &obj,
74                              NapiPropertyDescriptor &propertyDescriptor,
75                              Local<panda::JSValueRef> &propertyName,
76                              bool &result);
77 bool NapiDefineProperty(napi_env env, panda::Local<panda::ObjectRef> &obj, NapiPropertyDescriptor propertyDescriptor);
78 NAPI_EXPORT panda::Local<panda::JSValueRef> NapiValueToLocalValue(napi_value v);
79 NAPI_EXPORT napi_value LocalValueToLocalNapiValue(panda::Local<panda::JSValueRef> local);
80 #ifdef ENABLE_CONTAINER_SCOPE
81 void FunctionSetContainerId(const EcmaVM *vm, panda::Local<panda::JSValueRef> &local);
82 #endif
83 #if !defined(is_arkui_x) && defined(OHOS_PLATFORM)
84 std::string DumpHybridStack(const EcmaVM* vm);
85 #endif
86 panda::Local<panda::JSValueRef> NapiDefineClass(napi_env env, const char* name, NapiNativeCallback callback,
87                                                 void* data, const NapiPropertyDescriptor* properties, size_t length);
88 Local<JSValueRef> NapiDefineSendableClass(napi_env env,
89                                           const char* name,
90                                           NapiNativeCallback callback,
91                                           void* data,
92                                           const NapiPropertyDescriptor* properties,
93                                           size_t propertiesLength,
94                                           napi_value parent);
95 panda::Local<panda::ObjectRef> NapiCreateSObjectWithProperties(napi_env env,
96                                                                size_t propertyCount,
97                                                                const NapiPropertyDescriptor* properties);
98 panda::Local<panda::ObjectRef> NapiCreateObjectWithProperties(napi_env env, size_t propertyCount,
99                                                               const napi_property_descriptor *properties,
100                                                               Local<panda::JSValueRef> *keys,
101                                                               panda::PropertyAttribute *attrs);
102 
103 enum class ForceExpandState : int32_t {
104     FINISH_COLD_START = 0,
105     START_HIGH_SENSITIVE,
106     FINISH_HIGH_SENSITIVE,
107 };
108 
109 enum class ModuleTypes : uint8_t {
110     NATIVE_MODULE = 0x01,
111     MODULE_INNER_FILE,
112     UNKNOWN
113 };
114 
115 class SerializationData {
116 public:
SerializationData()117     SerializationData() : data_(nullptr), size_(0) {}
118     ~SerializationData() = default;
119 
GetData()120     uint8_t* GetData() const
121     {
122         return data_.get();
123     }
GetSize()124     size_t GetSize() const
125     {
126         return size_;
127     }
128 
129 private:
130     struct DataDeleter {
operatorDataDeleter131         void operator()(uint8_t* p) const
132         {
133             free(p);
134         }
135     };
136 
137     std::unique_ptr<uint8_t, DataDeleter> data_;
138     size_t size_;
139 };
140 
141 class NAPI_EXPORT ArkNativeEngine : public NativeEngine {
142 friend struct MoudleNameLocker;
143 public:
144     // ArkNativeEngine constructor
145     ArkNativeEngine(EcmaVM* vm, void* jsEngine, bool isLimitedWorker = false);
146     // ArkNativeEngine destructor
147     ~ArkNativeEngine() override;
148 
GetEcmaVm()149     NAPI_EXPORT const EcmaVM* GetEcmaVm() const override
150     {
151         return vm_;
152     }
153 
154     void Loop(LoopMode mode, bool needSync = false) override;
155     void SetPromiseRejectCallback(NativeReference* rejectCallbackRef, NativeReference* checkCallbackRef) override;
156     // For concurrent
157     bool InitTaskPoolThread(NativeEngine* engine, NapiConcurrentCallback callback) override;
158     bool InitTaskPoolThread(napi_env env, NapiConcurrentCallback callback) override;
159     bool InitTaskPoolFunc(napi_env env, napi_value func, void* taskInfo) override;
160     void ClearCurrentTaskInfo() override;
161     bool HasPendingJob() const override;
162     bool IsProfiling() const override;
163     bool IsExecutingPendingJob() const override;
164     void* GetCurrentTaskInfo() const override;
165     void TerminateExecution() const override;
166     void NotifyTaskBegin() const override;
167     void NotifyTaskFinished() const override;
168 
169     // judge_typedarray
170     bool NapiNewTypedArray(const EcmaVM* vm, NativeTypedArrayType typedArrayType,
171                            Local<panda::ArrayBufferRef> arrayBuf,
172                            size_t byte_offset, size_t length, napi_value* result) override;
173     bool NapiNewSendableTypedArray(const EcmaVM* vm, NativeTypedArrayType typedArrayType,
174                                    Local<panda::SendableArrayBufferRef> arrayBuf,
175                                    size_t byte_offset, size_t length, napi_value* result) override;
176     NativeTypedArrayType GetTypedArrayType(panda::Local<panda::TypedArrayRef> typedArray) override;
177     NativeTypedArrayType GetSendableTypedArrayType(panda::Local<panda::SendableTypedArrayRef> typedArray) override;
178     // Call function
179     napi_value CallFunction(napi_value thisVar,
180                             napi_value function,
181                             napi_value const* argv,
182                             size_t argc) override;
183     bool RunScriptPath(const char* path, bool checkPath = false) override;
184 
185     napi_value RunScriptBuffer(const char* path, std::vector<uint8_t>& buffer, bool isBundle) override;
186     bool RunScriptBuffer(const std::string& path, uint8_t* buffer, size_t size, bool isBundle) override;
187 
188     // Run buffer script
189     napi_value RunBufferScript(std::vector<uint8_t>& buffer) override;
190     napi_value RunActor(uint8_t* buffer, size_t size, const char* descriptor,
191         char* entryPoint = nullptr, bool checkPath = false) override;
192     // Set lib path
193     NAPI_EXPORT void SetPackagePath(const std::string appLinPathKey, const std::vector<std::string>& packagePath);
194     napi_value CreateInstance(napi_value constructor, napi_value const* argv, size_t argc) override;
195 
196     // Create native reference
197     NativeReference* CreateReference(napi_value value, uint32_t initialRefcount, bool flag = false,
198         NapiNativeFinalize callback = nullptr, void* data = nullptr, void* hint = nullptr,
199         size_t nativeBindingSize = 0) override;
200     NativeReference* CreateAsyncReference(napi_value value, uint32_t initialRefcount, bool flag = false,
201         NapiNativeFinalize callback = nullptr, void* data = nullptr, void* hint = nullptr) override;
202     napi_value CreatePromise(NativeDeferred** deferred) override;
203     void* CreateRuntime(bool isLimitedWorker = false) override;
204     panda::Local<panda::ObjectRef> LoadArkModule(const void* buffer, int32_t len, const std::string& fileName);
205     napi_value ValueToNapiValue(JSValueWrapper& value) override;
206     NAPI_EXPORT static napi_value ArkValueToNapiValue(napi_env env, Local<JSValueRef> value);
207 
208     std::string GetSourceCodeInfo(napi_value value, ErrorPos pos) override;
209 
210     NAPI_EXPORT bool ExecuteJsBin(const std::string& fileName, bool checkPath = false);
211     static bool IsValidPandaFile(const char* path);
212     static bool IsValidScriptBuffer(uint8_t* scriptBuffer, size_t bufferSize);
213     NAPI_EXPORT panda::Local<panda::ObjectRef> LoadModuleByName(const std::string& moduleName, bool isAppModule,
214         const std::string& param, const std::string& instanceName, void* instance, const std::string& path = "");
215 
216     void TriggerFatalException(panda::Local<panda::JSValueRef> exceptionValue) override;
217     bool AdjustExternalMemory(int64_t ChangeInBytes, int64_t* AdjustedValue) override;
218 
219     // Set jsdump thresholds
220     void SetJsDumpThresholds(size_t thresholds) override;
221 
222     // Set Appfreeze Filter
223     void SetAppFreezeFilterCallback(AppFreezeFilterCallback callback) override;
224 
225     // Detect performance to obtain cpuprofiler file
226     void StartCpuProfiler(const std::string& fileName = "") override;
227     void StopCpuProfiler() override;
228 
229     void ResumeVM() override;
230     bool SuspendVM() override;
231     bool IsSuspended() override;
232     bool CheckSafepoint() override;
233     bool SuspendVMById(uint32_t tid) override;
234     void ResumeVMById(uint32_t tid) override;
235 
236     // isVmMode means the internal class in vm is visible.
237     // isPrivate means the number and string is not visible.
238     void DumpHeapSnapshot(const std::string& path, bool isVmMode = true,
239         DumpFormat dumpFormat = DumpFormat::JSON, bool isPrivate = false, bool captureNumericValue = false) 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<RefFinalizer> &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, const char* module_info) 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);
316     ModuleTypes CheckLoadType(const std::string &path);
GetPromiseRejectCallBackRef()317     NativeReference* GetPromiseRejectCallBackRef()
318     {
319         return promiseRejectCallbackRef_;
320     }
321 
SetPromiseRejectCallBackRef(NativeReference * rejectCallbackRef)322     void SetPromiseRejectCallBackRef(NativeReference* rejectCallbackRef) override
323     {
324         promiseRejectCallbackRef_ = rejectCallbackRef;
325     }
326 
GetConcurrentCallbackFunc()327     NapiConcurrentCallback GetConcurrentCallbackFunc()
328     {
329         return concurrentCallbackFunc_;
330     }
331 
GetCheckCallbackRef()332     NativeReference* GetCheckCallbackRef()
333     {
334         return checkCallbackRef_;
335     }
336 
SetCheckCallbackRef(NativeReference * checkCallbackRef)337     void SetCheckCallbackRef(NativeReference* checkCallbackRef) override
338     {
339         checkCallbackRef_ = checkCallbackRef;
340     }
341 
GetNapiUncaughtExceptionCallback()342     NapiUncaughtExceptionCallback GetNapiUncaughtExceptionCallback() override
343     {
344         return napiUncaughtExceptionCallback_;
345     }
346 
GetPromiseRejectCallback()347     void* GetPromiseRejectCallback() override
348     {
349         return reinterpret_cast<void*>(PromiseRejectCallback);
350     }
351 
352     void SetModuleName(panda::Local<panda::ObjectRef> &nativeObj, std::string moduleName);
353     void GetCurrentModuleInfo(std::string& moduleName, std::string& fileName, bool needRecordName) override;
354     bool GetIsBundle() override;
355     bool GetIsNormalizedOhmUrlPack() override;
356     bool GetIsDebugModeEnabled() override;
357     std::string GetBundleName() override;
358     std::string GetPkgName(const std::string &moduleName) override;
359     bool IsExecuteModuleInAbcFile(std::string bundleName, std::string moduleName, std::string ohmurl) override;
360     int GetProcessStartRealTime() override;
361     void PostLooperTriggerIdleGCTask();
362 
363     static bool napiProfilerEnabled;
364     static std::string tempModuleName_;
365 
366     static void* GetNativePtrCallBack(void* data);
367     static void CopyPropertyApiFilter(const std::unique_ptr<ApiAllowListChecker>& apiAllowListChecker,
368         const EcmaVM* ecmaVm, const panda::Local<panda::ObjectRef> exportObj,
369         panda::Local<panda::ObjectRef>& exportCopy, const std::string& apiPath);
370 
IsCrossThreadCheckEnabled()371     inline bool IsCrossThreadCheckEnabled() const override
372     {
373         return crossThreadCheck_;
374     }
375     static constexpr size_t FINALIZERS_PACK_PENDING_NATIVE_BINDING_SIZE_THRESHOLD = 500 * 1024 * 1024;  // 500 MB
376 
377 private:
GetNapiOptions()378     inline NapiOptions *GetNapiOptions() const override
379     {
380         return options_;
381     }
382 
383     static void RunCallbacks(ArkFinalizersPack *finalizersPack);
384     static void RunAsyncCallbacks(std::vector<RefFinalizer> *finalizers);
385     static void RunCallbacks(AsyncNativeCallbacksPack *callbacks);
386     static void RunCallbacks(TriggerGCData *triggerGCData);
387     static void SetAttribute(bool isLimitedWorker, panda::RuntimeOption &option);
388     static NativeEngine* CreateRuntimeFunc(NativeEngine* engine, void* jsEngine, bool isLimitedWorker = false);
389     static bool CheckArkApiAllowList(
390         NativeModule* module, panda::ecmascript::ApiCheckContext context, panda::Local<panda::ObjectRef>& exportCopy);
IncreasePendingFinalizersPackNativeBindingSize(size_t nativeBindingSize)391     void IncreasePendingFinalizersPackNativeBindingSize(size_t nativeBindingSize)
392     {
393         pendingFinalizersPackNativeBindingSize_ += nativeBindingSize;
394     }
DecreasePendingFinalizersPackNativeBindingSize(size_t nativeBindingSize)395     void DecreasePendingFinalizersPackNativeBindingSize(size_t nativeBindingSize)
396     {
397         pendingFinalizersPackNativeBindingSize_ -= nativeBindingSize;
398     }
399 
400     EcmaVM* vm_ = nullptr;
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     std::shared_ptr<ArkIdleMonitor> arkIdleMonitor_;
419 };
420 #endif /* FOUNDATION_ACE_NAPI_NATIVE_ENGINE_IMPL_ARK_ARK_NATIVE_ENGINE_H */
421