1e509ee18Sopenharmony_ci/*
2e509ee18Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
3e509ee18Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4e509ee18Sopenharmony_ci * you may not use this file except in compliance with the License.
5e509ee18Sopenharmony_ci * You may obtain a copy of the License at
6e509ee18Sopenharmony_ci *
7e509ee18Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8e509ee18Sopenharmony_ci *
9e509ee18Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10e509ee18Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11e509ee18Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12e509ee18Sopenharmony_ci * See the License for the specific language governing permissions and
13e509ee18Sopenharmony_ci * limitations under the License.
14e509ee18Sopenharmony_ci */
15e509ee18Sopenharmony_ci
16e509ee18Sopenharmony_ci#include "tooling/client/domain/runtime_client.h"
17e509ee18Sopenharmony_ci
18e509ee18Sopenharmony_ci#include "common/log_wrapper.h"
19e509ee18Sopenharmony_ci#include "tooling/client/manager/variable_manager.h"
20e509ee18Sopenharmony_ci#include "tooling/client/manager/watch_manager.h"
21e509ee18Sopenharmony_ci#include "tooling/base/pt_json.h"
22e509ee18Sopenharmony_ci#include "tooling/client/session/session.h"
23e509ee18Sopenharmony_ci#include "tooling/utils/utils.h"
24e509ee18Sopenharmony_ci
25e509ee18Sopenharmony_ciusing PtJson = panda::ecmascript::tooling::PtJson;
26e509ee18Sopenharmony_cinamespace OHOS::ArkCompiler::Toolchain {
27e509ee18Sopenharmony_cibool RuntimeClient::DispatcherCmd(const std::string &cmd)
28e509ee18Sopenharmony_ci{
29e509ee18Sopenharmony_ci    std::map<std::string, std::function<int()>> dispatcherTable {
30e509ee18Sopenharmony_ci        { "heapusage", std::bind(&RuntimeClient::HeapusageCommand, this)},
31e509ee18Sopenharmony_ci        { "runtime-enable", std::bind(&RuntimeClient::RuntimeEnableCommand, this)},
32e509ee18Sopenharmony_ci        { "runtime-disable", std::bind(&RuntimeClient::RuntimeDisableCommand, this)},
33e509ee18Sopenharmony_ci        { "print", std::bind(&RuntimeClient::GetPropertiesCommand, this)},
34e509ee18Sopenharmony_ci        { "run", std::bind(&RuntimeClient::RunIfWaitingForDebuggerCommand, this)},
35e509ee18Sopenharmony_ci    };
36e509ee18Sopenharmony_ci
37e509ee18Sopenharmony_ci    auto entry = dispatcherTable.find(cmd);
38e509ee18Sopenharmony_ci    if (entry != dispatcherTable.end()) {
39e509ee18Sopenharmony_ci        entry->second();
40e509ee18Sopenharmony_ci        LOGI("RuntimeClient DispatcherCmd reqStr1: %{public}s", cmd.c_str());
41e509ee18Sopenharmony_ci        return true;
42e509ee18Sopenharmony_ci    } else {
43e509ee18Sopenharmony_ci        LOGI("Unknown commond: %{public}s", cmd.c_str());
44e509ee18Sopenharmony_ci        return false;
45e509ee18Sopenharmony_ci    }
46e509ee18Sopenharmony_ci}
47e509ee18Sopenharmony_ci
48e509ee18Sopenharmony_ciint RuntimeClient::HeapusageCommand()
49e509ee18Sopenharmony_ci{
50e509ee18Sopenharmony_ci    Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
51e509ee18Sopenharmony_ci    uint32_t id = session->GetMessageId();
52e509ee18Sopenharmony_ci
53e509ee18Sopenharmony_ci    idMethodMap_[id] = std::make_tuple("getHeapUsage", "");
54e509ee18Sopenharmony_ci    std::unique_ptr<PtJson> request = PtJson::CreateObject();
55e509ee18Sopenharmony_ci    request->Add("id", id);
56e509ee18Sopenharmony_ci    request->Add("method", "Runtime.getHeapUsage");
57e509ee18Sopenharmony_ci
58e509ee18Sopenharmony_ci    std::unique_ptr<PtJson> params = PtJson::CreateObject();
59e509ee18Sopenharmony_ci    request->Add("params", params);
60e509ee18Sopenharmony_ci
61e509ee18Sopenharmony_ci    std::string message = request->Stringify();
62e509ee18Sopenharmony_ci    if (session->ClientSendReq(message)) {
63e509ee18Sopenharmony_ci        session->GetDomainManager().SetDomainById(id, "Runtime");
64e509ee18Sopenharmony_ci    }
65e509ee18Sopenharmony_ci    return 0;
66e509ee18Sopenharmony_ci}
67e509ee18Sopenharmony_ci
68e509ee18Sopenharmony_ciint RuntimeClient::RuntimeEnableCommand()
69e509ee18Sopenharmony_ci{
70e509ee18Sopenharmony_ci    Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
71e509ee18Sopenharmony_ci    uint32_t id = session->GetMessageId();
72e509ee18Sopenharmony_ci
73e509ee18Sopenharmony_ci    idMethodMap_[id] = std::make_tuple("enable", "");
74e509ee18Sopenharmony_ci    std::unique_ptr<PtJson> request = PtJson::CreateObject();
75e509ee18Sopenharmony_ci    request->Add("id", id);
76e509ee18Sopenharmony_ci    request->Add("method", "Runtime.enable");
77e509ee18Sopenharmony_ci
78e509ee18Sopenharmony_ci    std::unique_ptr<PtJson> params = PtJson::CreateObject();
79e509ee18Sopenharmony_ci    request->Add("params", params);
80e509ee18Sopenharmony_ci
81e509ee18Sopenharmony_ci    std::string message = request->Stringify();
82e509ee18Sopenharmony_ci    if (session->ClientSendReq(message)) {
83e509ee18Sopenharmony_ci        session->GetDomainManager().SetDomainById(id, "Runtime");
84e509ee18Sopenharmony_ci    }
85e509ee18Sopenharmony_ci    return 0;
86e509ee18Sopenharmony_ci}
87e509ee18Sopenharmony_ci
88e509ee18Sopenharmony_ciint RuntimeClient::RuntimeDisableCommand()
89e509ee18Sopenharmony_ci{
90e509ee18Sopenharmony_ci    Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
91e509ee18Sopenharmony_ci    uint32_t id = session->GetMessageId();
92e509ee18Sopenharmony_ci
93e509ee18Sopenharmony_ci    idMethodMap_[id] = std::make_tuple("disable", "");
94e509ee18Sopenharmony_ci    std::unique_ptr<PtJson> request = PtJson::CreateObject();
95e509ee18Sopenharmony_ci    request->Add("id", id);
96e509ee18Sopenharmony_ci    request->Add("method", "Runtime.disable");
97e509ee18Sopenharmony_ci
98e509ee18Sopenharmony_ci    std::unique_ptr<PtJson> params = PtJson::CreateObject();
99e509ee18Sopenharmony_ci    request->Add("params", params);
100e509ee18Sopenharmony_ci
101e509ee18Sopenharmony_ci    std::string message = request->Stringify();
102e509ee18Sopenharmony_ci    if (session->ClientSendReq(message)) {
103e509ee18Sopenharmony_ci        session->GetDomainManager().SetDomainById(id, "Runtime");
104e509ee18Sopenharmony_ci    }
105e509ee18Sopenharmony_ci    return 0;
106e509ee18Sopenharmony_ci}
107e509ee18Sopenharmony_ci
108e509ee18Sopenharmony_ciint RuntimeClient::RunIfWaitingForDebuggerCommand()
109e509ee18Sopenharmony_ci{
110e509ee18Sopenharmony_ci    Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
111e509ee18Sopenharmony_ci    uint32_t id = session->GetMessageId();
112e509ee18Sopenharmony_ci
113e509ee18Sopenharmony_ci    idMethodMap_[id] = std::make_tuple("runIfWaitingForDebugger", "");
114e509ee18Sopenharmony_ci    std::unique_ptr<PtJson> request = PtJson::CreateObject();
115e509ee18Sopenharmony_ci    request->Add("id", id);
116e509ee18Sopenharmony_ci    request->Add("method", "Runtime.runIfWaitingForDebugger");
117e509ee18Sopenharmony_ci
118e509ee18Sopenharmony_ci    std::unique_ptr<PtJson> params = PtJson::CreateObject();
119e509ee18Sopenharmony_ci    request->Add("params", params);
120e509ee18Sopenharmony_ci
121e509ee18Sopenharmony_ci    std::string message = request->Stringify();
122e509ee18Sopenharmony_ci    if (session->ClientSendReq(message)) {
123e509ee18Sopenharmony_ci        session->GetDomainManager().SetDomainById(id, "Runtime");
124e509ee18Sopenharmony_ci    }
125e509ee18Sopenharmony_ci    WatchManager &watchManager = session->GetWatchManager();
126e509ee18Sopenharmony_ci    watchManager.DebugFalseState();
127e509ee18Sopenharmony_ci    return 0;
128e509ee18Sopenharmony_ci}
129e509ee18Sopenharmony_ci
130e509ee18Sopenharmony_ciint RuntimeClient::GetPropertiesCommand()
131e509ee18Sopenharmony_ci{
132e509ee18Sopenharmony_ci    Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
133e509ee18Sopenharmony_ci    uint32_t id = session->GetMessageId();
134e509ee18Sopenharmony_ci
135e509ee18Sopenharmony_ci    idMethodMap_[id] = std::make_tuple("getProperties", objectId_);
136e509ee18Sopenharmony_ci    std::unique_ptr<PtJson> request = PtJson::CreateObject();
137e509ee18Sopenharmony_ci    request->Add("id", id);
138e509ee18Sopenharmony_ci    request->Add("method", "Runtime.getProperties");
139e509ee18Sopenharmony_ci
140e509ee18Sopenharmony_ci    std::unique_ptr<PtJson> params = PtJson::CreateObject();
141e509ee18Sopenharmony_ci    params->Add("accessorPropertiesOnly", false);
142e509ee18Sopenharmony_ci    params->Add("generatePreview", true);
143e509ee18Sopenharmony_ci    params->Add("objectId", objectId_.c_str());
144e509ee18Sopenharmony_ci    params->Add("ownProperties", true);
145e509ee18Sopenharmony_ci    request->Add("params", params);
146e509ee18Sopenharmony_ci
147e509ee18Sopenharmony_ci    std::string message = request->Stringify();
148e509ee18Sopenharmony_ci    if (session->ClientSendReq(message)) {
149e509ee18Sopenharmony_ci        session->GetDomainManager().SetDomainById(id, "Runtime");
150e509ee18Sopenharmony_ci    }
151e509ee18Sopenharmony_ci    return 0;
152e509ee18Sopenharmony_ci}
153e509ee18Sopenharmony_ci
154e509ee18Sopenharmony_ciint RuntimeClient::GetPropertiesCommand2()
155e509ee18Sopenharmony_ci{
156e509ee18Sopenharmony_ci    Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
157e509ee18Sopenharmony_ci    uint32_t id = session->GetMessageId();
158e509ee18Sopenharmony_ci
159e509ee18Sopenharmony_ci    idMethodMap_[id] = std::make_tuple("getProperties", objectId_);
160e509ee18Sopenharmony_ci    std::unique_ptr<PtJson> request = PtJson::CreateObject();
161e509ee18Sopenharmony_ci    request->Add("id", id);
162e509ee18Sopenharmony_ci    request->Add("method", "Runtime.getProperties");
163e509ee18Sopenharmony_ci
164e509ee18Sopenharmony_ci    std::unique_ptr<PtJson> params = PtJson::CreateObject();
165e509ee18Sopenharmony_ci    params->Add("accessorPropertiesOnly", true);
166e509ee18Sopenharmony_ci    params->Add("generatePreview", true);
167e509ee18Sopenharmony_ci    params->Add("objectId", "0");
168e509ee18Sopenharmony_ci    params->Add("ownProperties", false);
169e509ee18Sopenharmony_ci    request->Add("params", params);
170e509ee18Sopenharmony_ci
171e509ee18Sopenharmony_ci    std::string message = request->Stringify();
172e509ee18Sopenharmony_ci    if (session->ClientSendReq(message)) {
173e509ee18Sopenharmony_ci        session->GetDomainManager().SetDomainById(id, "Runtime");
174e509ee18Sopenharmony_ci    }
175e509ee18Sopenharmony_ci    return 0;
176e509ee18Sopenharmony_ci}
177e509ee18Sopenharmony_ci
178e509ee18Sopenharmony_civoid RuntimeClient::RecvReply(std::unique_ptr<PtJson> json)
179e509ee18Sopenharmony_ci{
180e509ee18Sopenharmony_ci    if (json == nullptr) {
181e509ee18Sopenharmony_ci        LOGE("arkdb: json parse error");
182e509ee18Sopenharmony_ci        return;
183e509ee18Sopenharmony_ci    }
184e509ee18Sopenharmony_ci
185e509ee18Sopenharmony_ci    if (!json->IsObject()) {
186e509ee18Sopenharmony_ci        LOGE("arkdb: json parse format error");
187e509ee18Sopenharmony_ci        json->ReleaseRoot();
188e509ee18Sopenharmony_ci        return;
189e509ee18Sopenharmony_ci    }
190e509ee18Sopenharmony_ci
191e509ee18Sopenharmony_ci    int replyId;
192e509ee18Sopenharmony_ci    Result ret = json->GetInt("id", &replyId);
193e509ee18Sopenharmony_ci    if (ret != Result::SUCCESS) {
194e509ee18Sopenharmony_ci        LOGE("arkdb: find id error");
195e509ee18Sopenharmony_ci        return;
196e509ee18Sopenharmony_ci    }
197e509ee18Sopenharmony_ci
198e509ee18Sopenharmony_ci    if (GetMethodById(replyId) == "getHeapUsage") {
199e509ee18Sopenharmony_ci        HandleHeapUsage(std::move(json));
200e509ee18Sopenharmony_ci    } else if (GetMethodById(replyId) == "getProperties") {
201e509ee18Sopenharmony_ci        HandleGetProperties(std::move(json), replyId);
202e509ee18Sopenharmony_ci    } else {
203e509ee18Sopenharmony_ci        LOGI("arkdb: Runtime replay message is %{public}s", json->Stringify().c_str());
204e509ee18Sopenharmony_ci    }
205e509ee18Sopenharmony_ci}
206e509ee18Sopenharmony_ci
207e509ee18Sopenharmony_cistd::string RuntimeClient::GetMethodById(const int &id)
208e509ee18Sopenharmony_ci{
209e509ee18Sopenharmony_ci    auto it = idMethodMap_.find(id);
210e509ee18Sopenharmony_ci    if (it != idMethodMap_.end()) {
211e509ee18Sopenharmony_ci        return std::get<0>(it->second);
212e509ee18Sopenharmony_ci    }
213e509ee18Sopenharmony_ci    return "";
214e509ee18Sopenharmony_ci}
215e509ee18Sopenharmony_ci
216e509ee18Sopenharmony_cistd::string RuntimeClient::GetRequestObjectIdById(const int &id)
217e509ee18Sopenharmony_ci{
218e509ee18Sopenharmony_ci    auto it = idMethodMap_.find(id);
219e509ee18Sopenharmony_ci    if (it != idMethodMap_.end()) {
220e509ee18Sopenharmony_ci        return std::get<1>(it->second);
221e509ee18Sopenharmony_ci    }
222e509ee18Sopenharmony_ci    return "";
223e509ee18Sopenharmony_ci}
224e509ee18Sopenharmony_ci
225e509ee18Sopenharmony_civoid RuntimeClient::HandleGetProperties(std::unique_ptr<PtJson> json, const int &id)
226e509ee18Sopenharmony_ci{
227e509ee18Sopenharmony_ci    if (json == nullptr) {
228e509ee18Sopenharmony_ci        LOGE("arkdb: json parse error");
229e509ee18Sopenharmony_ci        return;
230e509ee18Sopenharmony_ci    }
231e509ee18Sopenharmony_ci
232e509ee18Sopenharmony_ci    if (!json->IsObject()) {
233e509ee18Sopenharmony_ci        LOGE("arkdb: json parse format error");
234e509ee18Sopenharmony_ci        json->ReleaseRoot();
235e509ee18Sopenharmony_ci        return;
236e509ee18Sopenharmony_ci    }
237e509ee18Sopenharmony_ci
238e509ee18Sopenharmony_ci    std::unique_ptr<PtJson> result;
239e509ee18Sopenharmony_ci    Result ret = json->GetObject("result", &result);
240e509ee18Sopenharmony_ci    if (ret != Result::SUCCESS) {
241e509ee18Sopenharmony_ci        LOGE("arkdb: find result error");
242e509ee18Sopenharmony_ci        return;
243e509ee18Sopenharmony_ci    }
244e509ee18Sopenharmony_ci
245e509ee18Sopenharmony_ci    std::unique_ptr<PtJson> innerResult;
246e509ee18Sopenharmony_ci    ret = result->GetArray("result", &innerResult);
247e509ee18Sopenharmony_ci    if (ret != Result::SUCCESS) {
248e509ee18Sopenharmony_ci        LOGE("arkdb: find innerResult error");
249e509ee18Sopenharmony_ci        return;
250e509ee18Sopenharmony_ci    }
251e509ee18Sopenharmony_ci
252e509ee18Sopenharmony_ci    Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
253e509ee18Sopenharmony_ci    StackManager &stackManager = session->GetStackManager();
254e509ee18Sopenharmony_ci    VariableManager &variableManager = session->GetVariableManager();
255e509ee18Sopenharmony_ci    std::map<int32_t, std::map<int32_t, std::string>> treeInfo = stackManager.GetScopeChainInfo();
256e509ee18Sopenharmony_ci    if (isInitializeTree_) {
257e509ee18Sopenharmony_ci        variableManager.ClearVariableInfo();
258e509ee18Sopenharmony_ci        variableManager.InitializeTree(treeInfo);
259e509ee18Sopenharmony_ci    }
260e509ee18Sopenharmony_ci    std::string requestObjectIdStr = GetRequestObjectIdById(id);
261e509ee18Sopenharmony_ci    TreeNode *node = nullptr;
262e509ee18Sopenharmony_ci    if (!isInitializeTree_) {
263e509ee18Sopenharmony_ci        int32_t requestObjectId;
264e509ee18Sopenharmony_ci        if (!Utils::StrToInt32(requestObjectIdStr, requestObjectId)) {
265e509ee18Sopenharmony_ci            LOGE("arkdb: convert 'requestObjectId' from string to int error");
266e509ee18Sopenharmony_ci            return;
267e509ee18Sopenharmony_ci        }
268e509ee18Sopenharmony_ci        node = variableManager.FindNodeWithObjectId(requestObjectId);
269e509ee18Sopenharmony_ci    } else {
270e509ee18Sopenharmony_ci        node = variableManager.FindNodeObjectZero();
271e509ee18Sopenharmony_ci    }
272e509ee18Sopenharmony_ci
273e509ee18Sopenharmony_ci    for (int32_t i = 0; i < innerResult->GetSize(); i++) {
274e509ee18Sopenharmony_ci        std::unique_ptr<PropertyDescriptor> variableInfo = PropertyDescriptor::Create(*(innerResult->Get(i)));
275e509ee18Sopenharmony_ci        variableManager.AddVariableInfo(node, std::move(variableInfo));
276e509ee18Sopenharmony_ci    }
277e509ee18Sopenharmony_ci
278e509ee18Sopenharmony_ci    std::cout << std::endl;
279e509ee18Sopenharmony_ci    variableManager.PrintVariableInfo();
280e509ee18Sopenharmony_ci}
281e509ee18Sopenharmony_ci
282e509ee18Sopenharmony_civoid RuntimeClient::HandleHeapUsage(std::unique_ptr<PtJson> json)
283e509ee18Sopenharmony_ci{
284e509ee18Sopenharmony_ci    if (json == nullptr) {
285e509ee18Sopenharmony_ci        LOGE("arkdb: json parse error");
286e509ee18Sopenharmony_ci        return;
287e509ee18Sopenharmony_ci    }
288e509ee18Sopenharmony_ci
289e509ee18Sopenharmony_ci    if (!json->IsObject()) {
290e509ee18Sopenharmony_ci        LOGE("arkdb: json parse format error");
291e509ee18Sopenharmony_ci        json->ReleaseRoot();
292e509ee18Sopenharmony_ci        return;
293e509ee18Sopenharmony_ci    }
294e509ee18Sopenharmony_ci
295e509ee18Sopenharmony_ci    std::unique_ptr<PtJson> result;
296e509ee18Sopenharmony_ci    Result ret = json->GetObject("result", &result);
297e509ee18Sopenharmony_ci    if (ret != Result::SUCCESS) {
298e509ee18Sopenharmony_ci        LOGE("arkdb: find result error");
299e509ee18Sopenharmony_ci        return;
300e509ee18Sopenharmony_ci    }
301e509ee18Sopenharmony_ci
302e509ee18Sopenharmony_ci    Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
303e509ee18Sopenharmony_ci    VariableManager &variableManager = session->GetVariableManager();
304e509ee18Sopenharmony_ci    std::unique_ptr<GetHeapUsageReturns> heapUsageReturns = GetHeapUsageReturns::Create(*result);
305e509ee18Sopenharmony_ci    variableManager.SetHeapUsageInfo(std::move(heapUsageReturns));
306e509ee18Sopenharmony_ci    variableManager.ShowHeapUsageInfo();
307e509ee18Sopenharmony_ci}
308e509ee18Sopenharmony_ci} // OHOS::ArkCompiler::Toolchain