1/*
2 * Copyright (c) 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#include "commonlibrary/ets_utils/tools/log.h"
17#include "napi/native_api.h"
18#include "native_engine.h"
19#include "napi/native_node_api.h"
20#include "securec.h"
21
22namespace OHOS::JsSysModule::Dfx {
23    constexpr int NUMBER_OF_PARAMETER_TWO = 2;
24    static napi_value DumpHeapSnapshot(napi_env env, napi_callback_info info)
25    {
26        size_t argc = NUMBER_OF_PARAMETER_TWO;
27        size_t requireArgc = NUMBER_OF_PARAMETER_TWO;
28        napi_get_cb_info(env, info, &argc, nullptr, nullptr, nullptr);
29        NAPI_ASSERT(env, argc <= requireArgc, "Wrong number of arguments");
30        napi_value argv[NUMBER_OF_PARAMETER_TWO] = { 0 };
31        napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
32        std::string tempStr = "";
33        size_t tempStrsize = 0;
34        if (napi_get_value_string_utf8(env, argv[0], nullptr, 0, &tempStrsize) != napi_ok) {
35            HILOG_ERROR("can not get argv[0] size");
36            return nullptr;
37        }
38        tempStr.reserve(tempStrsize + 1);
39        tempStr.resize(tempStrsize);
40        if (napi_get_value_string_utf8(env, argv[0], tempStr.data(), tempStrsize + 1, &tempStrsize) != napi_ok) {
41            HILOG_ERROR("can not get argv[0] value");
42            return nullptr;
43        }
44        std::string pathStr = tempStr;
45        bool isVmMode = true;
46        napi_get_value_bool(env, argv[1], &isVmMode);
47        NativeEngine *engine = reinterpret_cast<NativeEngine*>(env);
48        engine->DumpHeapSnapshot(pathStr, isVmMode);
49        napi_value result = nullptr;
50        NAPI_CALL(env, napi_get_undefined(env, &result));
51        return result;
52    }
53
54    static napi_value BuildNativeAndJsStackTrace(napi_env env, napi_callback_info info)
55    {
56        napi_value result = nullptr;
57        NativeEngine *engine = reinterpret_cast<NativeEngine*>(env);
58        std::string stackTraceResult = "";
59        bool temp = engine->BuildNativeAndJsStackTrace(stackTraceResult);
60        NAPI_CALL(env, napi_create_string_utf8(env, stackTraceResult.c_str(), stackTraceResult.size(), &result));
61        if (temp) {
62            return result;
63        } else {
64            return nullptr;
65        }
66    }
67
68    static napi_value StartHeapTracking(napi_env env, napi_callback_info info)
69    {
70        size_t argc = NUMBER_OF_PARAMETER_TWO;
71        size_t requireArgc = NUMBER_OF_PARAMETER_TWO;
72        napi_get_cb_info(env, info, &argc, nullptr, nullptr, nullptr);
73        NAPI_ASSERT(env, argc <= requireArgc, "Wrong number of arguments");
74        napi_value argv[NUMBER_OF_PARAMETER_TWO] = { 0 };
75        napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
76        double timeInterval = 0;
77        if (napi_get_value_double(env, argv[0], &timeInterval) != napi_ok) {
78            HILOG_ERROR("can not get argv[0] value");
79            return nullptr;
80        }
81        bool isVmMode = true;
82        if (napi_get_value_bool(env, argv[1], &isVmMode) != napi_ok) {
83            HILOG_ERROR("can not get argv[1] value");
84            return nullptr;
85        }
86        NativeEngine *engine = reinterpret_cast<NativeEngine*>(env);
87        auto startResult = engine->StartHeapTracking(timeInterval, isVmMode);
88        napi_value result = nullptr;
89        NAPI_CALL(env, napi_get_boolean(env, startResult, &result));
90        return result;
91    }
92
93    static napi_value StopHeapTracking(napi_env env, napi_callback_info info)
94    {
95        size_t argc = 1;
96        size_t requireArgc = 1;
97        napi_get_cb_info(env, info, &argc, nullptr, nullptr, nullptr);
98        NAPI_ASSERT(env, argc <= requireArgc, "Wrong number of arguments");
99        napi_value argv = nullptr;
100        napi_get_cb_info(env, info, &argc, &argv, nullptr, nullptr);
101        std::string tempStr = "";
102        size_t tempStrsize = 0;
103        if (napi_get_value_string_utf8(env, argv, nullptr, 0, &tempStrsize) != napi_ok) {
104            HILOG_ERROR("can not get argv size");
105            return nullptr;
106        }
107        tempStr.reserve(tempStrsize);
108        tempStr.resize(tempStrsize);
109        if (napi_get_value_string_utf8(env, argv, tempStr.data(), tempStrsize + 1, &tempStrsize) != napi_ok) {
110            HILOG_ERROR("can not get argv value");
111            return nullptr;
112        }
113        std::string filePath = tempStr;
114        NativeEngine *engine = reinterpret_cast<NativeEngine*>(env);
115        auto stopResult = engine->StopHeapTracking(filePath);
116        napi_value result = nullptr;
117        NAPI_CALL(env, napi_get_boolean(env, stopResult, &result));
118        return result;
119    }
120
121    static napi_value PrintStatisticResult(napi_env env, napi_callback_info info)
122    {
123        NativeEngine *engine = reinterpret_cast<NativeEngine*>(env);
124        engine->PrintStatisticResult();
125        napi_value result = nullptr;
126        NAPI_CALL(env, napi_get_undefined(env, &result));
127        return result;
128    }
129
130    static napi_value StartRuntimeStat(napi_env env, napi_callback_info info)
131    {
132        NativeEngine *engine = reinterpret_cast<NativeEngine*>(env);
133        engine->StartRuntimeStat();
134        napi_value result = nullptr;
135        NAPI_CALL(env, napi_get_undefined(env, &result));
136        return result;
137    }
138
139    static napi_value StopRuntimeStat(napi_env env, napi_callback_info info)
140    {
141        NativeEngine *engine = reinterpret_cast<NativeEngine*>(env);
142        engine->StopRuntimeStat();
143        napi_value result = nullptr;
144        NAPI_CALL(env, napi_get_undefined(env, &result));
145        return result;
146    }
147
148    static napi_value GetArrayBufferSize(napi_env env, napi_callback_info info)
149    {
150        NativeEngine *engine = reinterpret_cast<NativeEngine*>(env);
151        auto value = static_cast<uint32_t>(engine->GetArrayBufferSize());
152        napi_value result = nullptr;
153        NAPI_CALL(env, napi_create_uint32(env, value, &result));
154        return result;
155    }
156
157    static napi_value GetHeapTotalSize(napi_env env, napi_callback_info info)
158    {
159        NativeEngine *engine = reinterpret_cast<NativeEngine*>(env);
160        auto value = static_cast<uint32_t>(engine->GetHeapTotalSize());
161        napi_value result = nullptr;
162        NAPI_CALL(env, napi_create_uint32(env, value, &result));
163        return result;
164    }
165
166    static napi_value GetHeapUsedSize(napi_env env, napi_callback_info info)
167    {
168        NativeEngine *engine = reinterpret_cast<NativeEngine*>(env);
169        auto value = static_cast<uint32_t>(engine->GetHeapUsedSize());
170        napi_value result = nullptr;
171        NAPI_CALL(env, napi_create_uint32(env, value, &result));
172        return result;
173    }
174
175    static napi_value DfxInit(napi_env env, napi_value exports)
176    {
177        static napi_property_descriptor desc[] = {
178            DECLARE_NAPI_FUNCTION("dumpHeapSnapshot", DumpHeapSnapshot),
179            DECLARE_NAPI_FUNCTION("buildNativeAndJsStackTrace", BuildNativeAndJsStackTrace),
180            DECLARE_NAPI_FUNCTION("startHeapTracking", StartHeapTracking),
181            DECLARE_NAPI_FUNCTION("stopHeapTracking", StopHeapTracking),
182            DECLARE_NAPI_FUNCTION("printStatisticResult", PrintStatisticResult),
183            DECLARE_NAPI_FUNCTION("startRuntimeStat", StartRuntimeStat),
184            DECLARE_NAPI_FUNCTION("stopRuntimeStat", StopRuntimeStat),
185            DECLARE_NAPI_FUNCTION("getArrayBufferSize", GetArrayBufferSize),
186            DECLARE_NAPI_FUNCTION("getHeapTotalSize", GetHeapTotalSize),
187            DECLARE_NAPI_FUNCTION("getHeapUsedSize", GetHeapUsedSize),
188        };
189        NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
190        return exports;
191    }
192
193    // dfx module define
194    static napi_module dfxModule = {
195        .nm_version = 1,
196        .nm_flags = 0,
197        .nm_filename = nullptr,
198        .nm_register_func = DfxInit,
199        .nm_modname = "dfx",
200        .nm_priv = reinterpret_cast<void*>(0),
201        .reserved = {0},
202    };
203
204    // dfx module register
205    extern "C"
206    __attribute__((constructor)) void RegisterModule()
207    {
208        napi_module_register(&dfxModule);
209    }
210} // namespace OHOS::JsSysModule::Dfx
211