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