!429 arkdb supports source code display and watch functionality

Merge pull request !429 from yp9522/client_source_watch_session
This commit is contained in:
openharmony_ci 2023-11-01 07:19:23 +00:00 committed by Gitee
commit 4bfe10501e
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
37 changed files with 1958 additions and 479 deletions

View File

@ -36,8 +36,11 @@ ohos_source_set("libark_client_set") {
"domain/test_client.cpp",
"manager/breakpoint_manager.cpp",
"manager/domain_manager.cpp",
"manager/source_manager.cpp",
"manager/stack_manager.cpp",
"manager/variable_manager.cpp",
"manager/watch_manager.cpp",
"session/session.cpp",
"utils/cli_command.cpp",
"utils/utils.cpp",
"websocket/websocket_client.cpp",

View File

@ -22,28 +22,14 @@
#include <securec.h>
#include "tooling/client/utils/cli_command.h"
#include "tooling/client/session/session.h"
#include "manager/message_manager.h"
namespace OHOS::ArkCompiler::Toolchain {
uint32_t g_messageId = 0;
uv_async_t* g_socketSignal;
uv_async_t* g_inputSignal;
uv_async_t* g_releaseHandle;
uv_loop_t* g_loop;
DomainManager g_domainManager;
WebsocketClient g_cliSocket;
bool StrToUInt(const char *content, uint32_t *result)
{
const int dec = 10;
char *endPtr = nullptr;
*result = std::strtoul(content, &endPtr, dec);
if (endPtr == content || *endPtr != '\0') {
return false;
}
return true;
}
void ReleaseHandle([[maybe_unused]] uv_async_t *releaseHandle)
{
uv_close(reinterpret_cast<uv_handle_t*>(g_inputSignal), [](uv_handle_t* handle) {
@ -72,21 +58,36 @@ void ReleaseHandle([[maybe_unused]] uv_async_t *releaseHandle)
}
}
void InputMessageInSession(uint32_t sessionId, std::vector<std::string>& cliCmdStr)
{
CliCommand cmd(cliCmdStr, sessionId);
cmd.ExecCommand();
return;
}
void InputOnMessage(uv_async_t *handle)
{
char* msg = static_cast<char*>(handle->data);
std::string inputStr = std::string(msg);
std::vector<std::string> cliCmdStr = Utils::SplitString(inputStr, " ");
g_messageId += 1;
CliCommand cmd(cliCmdStr, g_messageId, g_domainManager, g_cliSocket);
if (cmd.ExecCommand() == ErrCode::ERR_FAIL) {
g_messageId -= 1;
}
std::cout << ">>> ";
fflush(stdout);
if (msg != nullptr) {
free(msg);
}
std::vector<std::string> cliCmdStr = Utils::SplitString(inputStr, " ");
if (cliCmdStr[0] == "forall") {
if (strstr(cliCmdStr[1].c_str(), "session") != nullptr) {
std::cout << "command " << cliCmdStr[1] << " not support forall" << std::endl;
} else {
cliCmdStr.erase(cliCmdStr.begin());
SessionManager::getInstance().CmdForAllSessions(std::bind(InputMessageInSession, std::placeholders::_1,
cliCmdStr));
}
} else {
uint32_t sessionId = SessionManager::getInstance().GetCurrentSessionId();
InputMessageInSession(sessionId, cliCmdStr);
}
std::cout << ">>> ";
fflush(stdout);
}
void GetInputCommand([[maybe_unused]] void *arg)
@ -100,7 +101,6 @@ void GetInputCommand([[maybe_unused]] void *arg)
}
if ((!strcmp(inputStr.c_str(), "quit")) || (!strcmp(inputStr.c_str(), "q"))) {
LOGE("arkdb: quit");
g_cliSocket.Close();
if (uv_is_active(reinterpret_cast<uv_handle_t*>(g_releaseHandle))) {
uv_async_send(g_releaseHandle);
}
@ -111,7 +111,6 @@ void GetInputCommand([[maybe_unused]] void *arg)
char* msg = (char*)malloc(len + 1);
if ((msg != nullptr) && uv_is_active(reinterpret_cast<uv_handle_t*>(g_inputSignal))) {
if (strncpy_s(msg, len + 1, inputStr.c_str(), len) != 0) {
g_cliSocket.Close();
if (uv_is_active(reinterpret_cast<uv_handle_t*>(g_releaseHandle))) {
uv_async_send(g_releaseHandle);
}
@ -124,69 +123,31 @@ void GetInputCommand([[maybe_unused]] void *arg)
}
}
void SocketOnMessage(uv_async_t *handle)
void SocketOnMessage([[maybe_unused]] uv_async_t *handle)
{
char* msg = static_cast<char*>(handle->data);
g_domainManager.DispatcherReply(msg);
if (msg != nullptr) {
free(msg);
}
}
void GetSocketMessage([[maybe_unused]] void *arg)
{
while (g_cliSocket.IsConnected()) {
std::string decMessage = g_cliSocket.Decode();
uint32_t len = decMessage.length();
if (len == 0) {
uint32_t sessionId = 0;
std::string message;
while (MessageManager::getInstance().MessagePop(sessionId, message)) {
Session *session = SessionManager::getInstance().GetSessionById(sessionId);
if (session == nullptr) {
LOGE("arkdb get session by id %{public}u failed", sessionId);
continue;
}
char* msg = (char*)malloc(len + 1);
if ((msg != nullptr) && uv_is_active(reinterpret_cast<uv_handle_t*>(g_socketSignal))) {
if (strncpy_s(msg, len + 1, decMessage.c_str(), len) != 0) {
g_cliSocket.Close();
if (uv_is_active(reinterpret_cast<uv_handle_t*>(g_releaseHandle))) {
uv_async_send(g_releaseHandle);
}
break;
}
g_socketSignal->data = std::move(msg);
uv_async_send(g_socketSignal);
}
session->ProcSocketMsg(const_cast<char *>(message.c_str()));
}
}
int Main(const int argc, const char** argv)
{
uint32_t port = 0;
if (argc < 2) { // 2: two parameters
LOGE("arkdb is missing a parameter");
return -1;
}
if (strstr(argv[0], "arkdb") != nullptr) {
if (StrToUInt(argv[1], &port)) {
if ((port <= 0) || (port >= 65535)) { // 65535: max port
LOGE("arkdb:InitToolchainWebSocketForPort the port = %{public}d is wrong.", port);
return -1;
}
if (!g_cliSocket.InitToolchainWebSocketForPort(port, 5)) { // 5: five times
LOGE("arkdb:InitToolchainWebSocketForPort failed");
return -1;
}
} else {
if (!g_cliSocket.InitToolchainWebSocketForSockName(argv[1])) {
LOGE("arkdb:InitToolchainWebSocketForSockName failed");
return -1;
}
}
if (!g_cliSocket.ClientSendWSUpgradeReq()) {
LOGE("arkdb:ClientSendWSUpgradeReq failed");
return -1;
}
if (!g_cliSocket.ClientRecvWSUpgradeRsp()) {
LOGE("arkdb:ClientRecvWSUpgradeRsp failed");
std::string sockInfo(argv[1]);
if (SessionManager::getInstance().CreateDefaultSession(sockInfo)) {
LOGE("arkdb create default session failed");
return -1;
}
@ -204,9 +165,6 @@ int Main(const int argc, const char** argv)
uv_thread_t inputTid;
uv_thread_create(&inputTid, GetInputCommand, nullptr);
uv_thread_t socketTid;
uv_thread_create(&socketTid, GetSocketMessage, nullptr);
uv_run(g_loop, UV_RUN_DEFAULT);
}
return 0;

View File

@ -19,55 +19,59 @@
#include "common/log_wrapper.h"
#include "tooling/client/manager/breakpoint_manager.h"
#include "tooling/client/manager/source_manager.h"
#include "tooling/client/manager/stack_manager.h"
#include "tooling/base/pt_json.h"
#include "tooling/client/session/session.h"
using PtJson = panda::ecmascript::tooling::PtJson;
namespace OHOS::ArkCompiler::Toolchain {
bool DebuggerClient::DispatcherCmd(int id, const std::string &cmd, std::string* reqStr)
bool DebuggerClient::DispatcherCmd(const std::string &cmd)
{
std::map<std::string, std::function<std::string()>> dispatcherTable {
{ "break", std::bind(&DebuggerClient::BreakCommand, this, id)},
{ "backtrack", std::bind(&DebuggerClient::BacktrackCommand, this, id)},
{ "continue", std::bind(&DebuggerClient::ResumeCommand, this, id)},
{ "delete", std::bind(&DebuggerClient::DeleteCommand, this, id)},
{ "jump", std::bind(&DebuggerClient::JumpCommand, this, id)},
{ "disable", std::bind(&DebuggerClient::DisableCommand, this, id)},
{ "display", std::bind(&DebuggerClient::DisplayCommand, this, id)},
{ "enable", std::bind(&DebuggerClient::EnableCommand, this, id)},
{ "finish", std::bind(&DebuggerClient::FinishCommand, this, id)},
{ "frame", std::bind(&DebuggerClient::FrameCommand, this, id)},
{ "ignore", std::bind(&DebuggerClient::IgnoreCommand, this, id)},
{ "infobreakpoints", std::bind(&DebuggerClient::InfobreakpointsCommand, this, id)},
{ "infosource", std::bind(&DebuggerClient::InfosourceCommand, this, id)},
{ "list", std::bind(&DebuggerClient::ListCommand, this, id)},
{ "next", std::bind(&DebuggerClient::NextCommand, this, id)},
{ "ptype", std::bind(&DebuggerClient::PtypeCommand, this, id)},
{ "run", std::bind(&DebuggerClient::RunCommand, this, id)},
{ "setvar", std::bind(&DebuggerClient::SetvarCommand, this, id)},
{ "step", std::bind(&DebuggerClient::StepCommand, this, id)},
{ "undisplay", std::bind(&DebuggerClient::UndisplayCommand, this, id)},
{ "watch", std::bind(&DebuggerClient::WatchCommand, this, id)},
{ "resume", std::bind(&DebuggerClient::ResumeCommand, this, id)},
{ "step-into", std::bind(&DebuggerClient::StepIntoCommand, this, id)},
{ "step-out", std::bind(&DebuggerClient::StepOutCommand, this, id)},
{ "step-over", std::bind(&DebuggerClient::StepOverCommand, this, id)},
std::map<std::string, std::function<int()>> dispatcherTable {
{ "break", std::bind(&DebuggerClient::BreakCommand, this)},
{ "backtrack", std::bind(&DebuggerClient::BacktrackCommand, this)},
{ "continue", std::bind(&DebuggerClient::ResumeCommand, this)},
{ "delete", std::bind(&DebuggerClient::DeleteCommand, this)},
{ "jump", std::bind(&DebuggerClient::JumpCommand, this)},
{ "disable", std::bind(&DebuggerClient::DisableCommand, this)},
{ "display", std::bind(&DebuggerClient::DisplayCommand, this)},
{ "enable", std::bind(&DebuggerClient::EnableCommand, this)},
{ "finish", std::bind(&DebuggerClient::FinishCommand, this)},
{ "frame", std::bind(&DebuggerClient::FrameCommand, this)},
{ "ignore", std::bind(&DebuggerClient::IgnoreCommand, this)},
{ "infobreakpoints", std::bind(&DebuggerClient::InfobreakpointsCommand, this)},
{ "infosource", std::bind(&DebuggerClient::InfosourceCommand, this)},
{ "list", std::bind(&DebuggerClient::ListCommand, this)},
{ "next", std::bind(&DebuggerClient::NextCommand, this)},
{ "ptype", std::bind(&DebuggerClient::PtypeCommand, this)},
{ "run", std::bind(&DebuggerClient::RunCommand, this)},
{ "setvar", std::bind(&DebuggerClient::SetvarCommand, this)},
{ "step", std::bind(&DebuggerClient::StepCommand, this)},
{ "undisplay", std::bind(&DebuggerClient::UndisplayCommand, this)},
{ "watch", std::bind(&DebuggerClient::WatchCommand, this)},
{ "resume", std::bind(&DebuggerClient::ResumeCommand, this)},
{ "step-into", std::bind(&DebuggerClient::StepIntoCommand, this)},
{ "step-out", std::bind(&DebuggerClient::StepOutCommand, this)},
{ "step-over", std::bind(&DebuggerClient::StepOverCommand, this)},
};
auto entry = dispatcherTable.find(cmd);
if (entry != dispatcherTable.end()) {
*reqStr = entry->second();
LOGI("DebuggerClient DispatcherCmd reqStr1: %{public}s", reqStr->c_str());
entry->second();
LOGI("DebuggerClient DispatcherCmd cmd: %{public}s", cmd.c_str());
return true;
}
*reqStr = "Unknown commond: " + cmd;
LOGI("DebuggerClient DispatcherCmd reqStr2: %{public}s", reqStr->c_str());
LOGI("unknown command: %{public}s", cmd.c_str());
return false;
}
std::string DebuggerClient::BreakCommand(int id)
int DebuggerClient::BreakCommand()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
request->Add("method", "Debugger.setBreakpointByUrl");
@ -77,16 +81,24 @@ std::string DebuggerClient::BreakCommand(int id)
params->Add("lineNumber", breakPointInfoList_.back().lineNumber);
params->Add("url", breakPointInfoList_.back().url.c_str());
request->Add("params", params);
return request->Stringify();
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "Debugger");
}
return 0;
}
std::string DebuggerClient::BacktrackCommand([[maybe_unused]] int id)
int DebuggerClient::BacktrackCommand()
{
return "backtrack";
return 0;
}
std::string DebuggerClient::DeleteCommand(int id)
int DebuggerClient::DeleteCommand()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
request->Add("method", "Debugger.removeBreakpoint");
@ -95,155 +107,208 @@ std::string DebuggerClient::DeleteCommand(int id)
std::string breakpointId = breakPointInfoList_.back().url;
params->Add("breakpointId", breakpointId.c_str());
request->Add("params", params);
return request->Stringify();
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "Debugger");
}
return 0;
}
std::string DebuggerClient::DisableCommand(int id)
int DebuggerClient::DisableCommand()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
request->Add("method", "Debugger.disable");
std::unique_ptr<PtJson> params = PtJson::CreateObject();
request->Add("params", params);
return request->Stringify();
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "Debugger");
}
return 0;
}
std::string DebuggerClient::DisplayCommand([[maybe_unused]] int id)
int DebuggerClient::DisplayCommand()
{
return "display";
return 0;
}
std::string DebuggerClient::EnableCommand(int id)
int DebuggerClient::EnableCommand()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
request->Add("method", "Debugger.enable");
std::unique_ptr<PtJson> params = PtJson::CreateObject();
request->Add("params", params);
return request->Stringify();
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "Debugger");
}
return 0;
}
std::string DebuggerClient::FinishCommand([[maybe_unused]] int id)
int DebuggerClient::FinishCommand()
{
return "finish";
return 0;
}
std::string DebuggerClient::FrameCommand([[maybe_unused]] int id)
int DebuggerClient::FrameCommand()
{
return "frame";
return 0;
}
std::string DebuggerClient::IgnoreCommand([[maybe_unused]] int id)
int DebuggerClient::IgnoreCommand()
{
return "ignore";
return 0;
}
std::string DebuggerClient::InfobreakpointsCommand([[maybe_unused]] int id)
int DebuggerClient::InfobreakpointsCommand()
{
return "infobreakpoint";
return 0;
}
std::string DebuggerClient::InfosourceCommand([[maybe_unused]] int id)
int DebuggerClient::InfosourceCommand()
{
return "infosource";
return 0;
}
std::string DebuggerClient::JumpCommand([[maybe_unused]] int id)
int DebuggerClient::JumpCommand()
{
return "jump";
return 0;
}
std::string DebuggerClient::NextCommand([[maybe_unused]] int id)
int DebuggerClient::NextCommand()
{
return "next";
return 0;
}
std::string DebuggerClient::ListCommand([[maybe_unused]] int id)
int DebuggerClient::ListCommand()
{
return "list";
return 0;
}
std::string DebuggerClient::PtypeCommand([[maybe_unused]] int id)
int DebuggerClient::PtypeCommand()
{
return "ptype";
return 0;
}
std::string DebuggerClient::RunCommand([[maybe_unused]] int id)
int DebuggerClient::RunCommand()
{
return "run";
return 0;
}
std::string DebuggerClient::SetvarCommand([[maybe_unused]] int id)
int DebuggerClient::SetvarCommand()
{
return "Debugger.setVariableValue";
return 0;
}
std::string DebuggerClient::StepCommand([[maybe_unused]] int id)
int DebuggerClient::StepCommand()
{
return "step";
return 0;
}
std::string DebuggerClient::UndisplayCommand([[maybe_unused]] int id)
int DebuggerClient::UndisplayCommand()
{
return "undisplay";
return 0;
}
std::string DebuggerClient::WatchCommand([[maybe_unused]] int id)
int DebuggerClient::WatchCommand()
{
return "Debugger.evaluateOnCallFrame";
return 0;
}
std::string DebuggerClient::ResumeCommand(int id)
int DebuggerClient::ResumeCommand()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
request->Add("method", "Debugger.resume");
std::unique_ptr<PtJson> params = PtJson::CreateObject();
request->Add("params", params);
return request->Stringify();
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "Debugger");
}
return 0;
}
std::string DebuggerClient::StepIntoCommand(int id)
int DebuggerClient::StepIntoCommand()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
request->Add("method", "Debugger.stepInto");
std::unique_ptr<PtJson> params = PtJson::CreateObject();
request->Add("params", params);
return request->Stringify();
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "Debugger");
}
return 0;
}
std::string DebuggerClient::StepOutCommand(int id)
int DebuggerClient::StepOutCommand()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
request->Add("method", "Debugger.stepOut");
std::unique_ptr<PtJson> params = PtJson::CreateObject();
request->Add("params", params);
return request->Stringify();
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "Debugger");
}
return 0;
}
std::string DebuggerClient::StepOverCommand(int id)
int DebuggerClient::StepOverCommand()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
request->Add("method", "Debugger.stepOver");
std::unique_ptr<PtJson> params = PtJson::CreateObject();
request->Add("params", params);
return request->Stringify();
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "Debugger");
}
return 0;
}
void DebuggerClient::AddBreakPointInfo(const std::string& url, const int& lineNumber, const int& columnNumber)
{
BreakPointInfo breakPointInfo;
breakPointInfo.url = url;
breakPointInfo.lineNumber = lineNumber;
breakPointInfo.lineNumber = lineNumber - 1;
breakPointInfo.columnNumber = columnNumber;
breakPointInfoList_.emplace_back(breakPointInfo);
}
@ -261,14 +326,16 @@ void DebuggerClient::RecvReply(std::unique_ptr<PtJson> json)
return;
}
Result ret;
std::string wholeMethod;
std::string method;
ret = json->GetString("method", &wholeMethod);
Result ret = json->GetString("method", &wholeMethod);
if (ret != Result::SUCCESS) {
LOGE("arkdb: find method error");
}
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
SourceManager &sourceManager = session->GetSourceManager();
std::string::size_type length = wholeMethod.length();
std::string::size_type indexPoint = 0;
indexPoint = wholeMethod.find_first_of('.', 0);
@ -276,23 +343,13 @@ void DebuggerClient::RecvReply(std::unique_ptr<PtJson> json)
if (method == "paused") {
PausedReply(std::move(json));
return;
} else if (method == "scriptParsed") {
sourceManager.EnableReply(std::move(json));
return;
} else {
LOGI("arkdb: Debugger reply is: %{public}s", json->Stringify().c_str());
}
std::unique_ptr<PtJson> result;
ret = json->GetObject("result", &result);
if (ret != Result::SUCCESS) {
LOGE("arkdb: find result error");
return;
}
std::string breakpointId;
ret = result->GetString("breakpointId", &breakpointId);
if (ret == Result::SUCCESS) {
BreakPointManager &breakpoint = BreakPointManager::GetInstance();
breakpoint.Createbreaklocation(std::move(json));
}
handleResponse(std::move(json));
}
void DebuggerClient::PausedReply(const std::unique_ptr<PtJson> json)
@ -328,8 +385,49 @@ void DebuggerClient::PausedReply(const std::unique_ptr<PtJson> json)
data.emplace(i + 1, std::move(callFrameInfo));
}
StackManager &stackManager = StackManager::GetInstance();
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
StackManager& stackManager = session->GetStackManager();
SourceManager &sourceManager = session->GetSourceManager();
WatchManager &watchManager = session->GetWatchManager();
stackManager.ClearCallFrame();
stackManager.SetCallFrames(std::move(data));
sourceManager.GetDebugSources(callFrames->Get(0));
watchManager.RequestWatchInfo(callFrames->Get(0));
watchManager.DebugTrueState();
}
void DebuggerClient::handleResponse(std::unique_ptr<PtJson> json)
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
SourceManager &sourceManager = session->GetSourceManager();
WatchManager &watchManager = session->GetWatchManager();
BreakPointManager& breakpoint = session->GetBreakPointManager();
std::unique_ptr<PtJson> result;
Result ret = json->GetObject("result", &result);
if (ret != Result::SUCCESS) {
LOGE("arkdb: find result error");
return;
}
int32_t id;
ret = json->GetInt("id", &id);
if (ret == Result::SUCCESS) {
std::string scriptSource;
ret = result->GetString("scriptSource", &scriptSource);
if (ret == Result::SUCCESS) {
sourceManager.SetFileSource(id, scriptSource);
return;
}
}
std::string breakpointId;
ret = result->GetString("breakpointId", &breakpointId);
if (ret == Result::SUCCESS) {
breakpoint.Createbreaklocation(std::move(json));
sourceManager.GetDebugInfo(std::move(result));
return;
}
if (watchManager.HandleWatchResult(std::move(json), id)) {
return;
}
return;
}
} // OHOS::ArkCompiler::Toolchain

View File

@ -31,41 +31,43 @@ struct BreakPointInfo {
};
class DebuggerClient final {
public:
DebuggerClient() = default;
DebuggerClient(int32_t sessionId) : sessionId_(sessionId) {}
~DebuggerClient() = default;
bool DispatcherCmd(int id, const std::string &cmd, std::string* reqStr);
std::string BreakCommand(int id);
std::string BacktrackCommand(int id);
std::string DeleteCommand(int id);
std::string DisableCommand(int id);
std::string DisplayCommand(int id);
std::string EnableCommand(int id);
std::string FinishCommand(int id);
std::string FrameCommand(int id);
std::string IgnoreCommand(int id);
std::string InfobreakpointsCommand(int id);
std::string InfosourceCommand(int id);
std::string JumpCommand(int id);
std::string NextCommand(int id);
std::string ListCommand(int id);
std::string PtypeCommand(int id);
std::string RunCommand(int id);
std::string SetvarCommand(int id);
std::string StepCommand(int id);
std::string UndisplayCommand(int id);
std::string WatchCommand(int id);
std::string ResumeCommand(int id);
std::string StepIntoCommand(int id);
std::string StepOutCommand(int id);
std::string StepOverCommand(int id);
bool DispatcherCmd(const std::string &cmd);
int BreakCommand();
int BacktrackCommand();
int DeleteCommand();
int DisableCommand();
int DisplayCommand();
int EnableCommand();
int FinishCommand();
int FrameCommand();
int IgnoreCommand();
int InfobreakpointsCommand();
int InfosourceCommand();
int JumpCommand();
int NextCommand();
int ListCommand();
int PtypeCommand();
int RunCommand();
int SetvarCommand();
int StepCommand();
int UndisplayCommand();
int WatchCommand();
int ResumeCommand();
int StepIntoCommand();
int StepOutCommand();
int StepOverCommand();
void AddBreakPointInfo(const std::string& url, const int& lineNumber, const int& columnNumber = 0);
void RecvReply(std::unique_ptr<PtJson> json);
void PausedReply(const std::unique_ptr<PtJson> json);
void handleResponse(std::unique_ptr<PtJson> json);
private:
std::vector<BreakPointInfo> breakPointInfoList_ {};
int32_t sessionId_;
};
} // OHOS::ArkCompiler::Toolchain
#endif

View File

@ -16,6 +16,7 @@
#include "tooling/client/domain/heapprofiler_client.h"
#include "common/log_wrapper.h"
#include "tooling/client/utils/utils.h"
#include "tooling/client/session/session.h"
#include <map>
#include <functional>
@ -24,38 +25,37 @@
using Result = panda::ecmascript::tooling::Result;
namespace OHOS::ArkCompiler::Toolchain {
static constexpr int32_t SAMPLING_INTERVAL = 16384;
bool HeapProfilerClient::DispatcherCmd(int id, const std::string &cmd, const std::string &arg, std::string* reqStr)
bool HeapProfilerClient::DispatcherCmd(const std::string &cmd, const std::string &arg)
{
if (reqStr == nullptr) {
return false;
}
path_ = arg;
std::map<std::string, std::function<std::string()>> dispatcherTable {
{ "allocationtrack", std::bind(&HeapProfilerClient::AllocationTrackCommand, this, id)},
{ "allocationtrack-stop", std::bind(&HeapProfilerClient::AllocationTrackStopCommand, this, id)},
{ "heapdump", std::bind(&HeapProfilerClient::HeapDumpCommand, this, id)},
{ "heapprofiler-enable", std::bind(&HeapProfilerClient::Enable, this, id)},
{ "heapprofiler-disable", std::bind(&HeapProfilerClient::Disable, this, id)},
{ "sampling", std::bind(&HeapProfilerClient::Samping, this, id)},
{ "sampling-stop", std::bind(&HeapProfilerClient::SampingStop, this, id)},
{ "collectgarbage", std::bind(&HeapProfilerClient::CollectGarbage, this, id)}
std::map<std::string, std::function<int()>> dispatcherTable {
{ "allocationtrack", std::bind(&HeapProfilerClient::AllocationTrackCommand, this)},
{ "allocationtrack-stop", std::bind(&HeapProfilerClient::AllocationTrackStopCommand, this)},
{ "heapdump", std::bind(&HeapProfilerClient::HeapDumpCommand, this)},
{ "heapprofiler-enable", std::bind(&HeapProfilerClient::Enable, this)},
{ "heapprofiler-disable", std::bind(&HeapProfilerClient::Disable, this)},
{ "sampling", std::bind(&HeapProfilerClient::Samping, this)},
{ "sampling-stop", std::bind(&HeapProfilerClient::SampingStop, this)},
{ "collectgarbage", std::bind(&HeapProfilerClient::CollectGarbage, this)}
};
auto entry = dispatcherTable.find(cmd);
if (entry != dispatcherTable.end() && entry->second != nullptr) {
*reqStr = entry->second();
LOGI("DispatcherCmd reqStr1: %{public}s", reqStr->c_str());
entry->second();
LOGI("DispatcherCmd reqStr1: %{public}s", cmd.c_str());
return true;
}
*reqStr = "Unknown commond: " + cmd;
LOGI("DispatcherCmd reqStr2: %{public}s", reqStr->c_str());
LOGI("unknown command: %{public}s", cmd.c_str());
return false;
}
std::string HeapProfilerClient::HeapDumpCommand(int id)
int HeapProfilerClient::HeapDumpCommand()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
idEventMap_.emplace(id, HEAPDUMP);
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
@ -66,11 +66,19 @@ std::string HeapProfilerClient::HeapDumpCommand(int id)
params->Add("captureNumericValue", true);
params->Add("exposeInternals", false);
request->Add("params", params);
return request->Stringify();
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "HeapProfiler");
}
return 0;
}
std::string HeapProfilerClient::AllocationTrackCommand(int id)
int HeapProfilerClient::AllocationTrackCommand()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
idEventMap_.emplace(id, ALLOCATION);
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
@ -79,11 +87,19 @@ std::string HeapProfilerClient::AllocationTrackCommand(int id)
std::unique_ptr<PtJson> params = PtJson::CreateObject();
params->Add("trackAllocations", true);
request->Add("params", params);
return request->Stringify();
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "HeapProfiler");
}
return 0;
}
std::string HeapProfilerClient::AllocationTrackStopCommand(int id)
int HeapProfilerClient::AllocationTrackStopCommand()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
idEventMap_.emplace(id, ALLOCATION_STOP);
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
@ -92,11 +108,19 @@ std::string HeapProfilerClient::AllocationTrackStopCommand(int id)
std::unique_ptr<PtJson> params = PtJson::CreateObject();
params->Add("reportProgress", true);
request->Add("params", params);
return request->Stringify();
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "HeapProfiler");
}
return 0;
}
std::string HeapProfilerClient::Enable(int id)
int HeapProfilerClient::Enable()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
idEventMap_.emplace(id, ENABLE);
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
@ -104,11 +128,19 @@ std::string HeapProfilerClient::Enable(int id)
std::unique_ptr<PtJson> params = PtJson::CreateObject();
request->Add("params", params);
return request->Stringify();
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "HeapProfiler");
}
return 0;
}
std::string HeapProfilerClient::Disable(int id)
int HeapProfilerClient::Disable()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
idEventMap_.emplace(id, DISABLE);
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
@ -116,11 +148,19 @@ std::string HeapProfilerClient::Disable(int id)
std::unique_ptr<PtJson> params = PtJson::CreateObject();
request->Add("params", params);
return request->Stringify();
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "HeapProfiler");
}
return 0;
}
std::string HeapProfilerClient::Samping(int id)
int HeapProfilerClient::Samping()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
idEventMap_.emplace(id, SAMPLING);
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
@ -129,11 +169,19 @@ std::string HeapProfilerClient::Samping(int id)
std::unique_ptr<PtJson> params = PtJson::CreateObject();
params->Add("samplingInterval", SAMPLING_INTERVAL);
request->Add("params", params);
return request->Stringify();
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "HeapProfiler");
}
return 0;
}
std::string HeapProfilerClient::SampingStop(int id)
int HeapProfilerClient::SampingStop()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
idEventMap_.emplace(id, SAMPLING_STOP);
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
@ -141,11 +189,19 @@ std::string HeapProfilerClient::SampingStop(int id)
std::unique_ptr<PtJson> params = PtJson::CreateObject();
request->Add("params", params);
return request->Stringify();
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "HeapProfiler");
}
return 0;
}
std::string HeapProfilerClient::CollectGarbage(int id)
int HeapProfilerClient::CollectGarbage()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
idEventMap_.emplace(id, COLLECT_GARBAGE);
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
@ -153,7 +209,12 @@ std::string HeapProfilerClient::CollectGarbage(int id)
std::unique_ptr<PtJson> params = PtJson::CreateObject();
request->Add("params", params);
return request->Stringify();
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "HeapProfiler");
}
return 0;
}
void HeapProfilerClient::RecvReply(std::unique_ptr<PtJson> json)
@ -213,10 +274,12 @@ void HeapProfilerClient::RecvReply(std::unique_ptr<PtJson> json)
return;
}
if (isAllocationMsg_) {
fileName_ = "/data/Heap-" + std::string(date) + "T" + std::string(time) + ".heaptimeline";
fileName_ = "/data/Heap-" + std::to_string(sessionId_) + "-" + std::string(date) + "T" + std::string(time) +
".heaptimeline";
std::cout << "heaptimeline file name is " << fileName_ << std::endl;
} else {
fileName_ = "/data/Heap-" + std::string(date) + "T" + std::string(time) + ".heapsnapshot";
fileName_ = "/data/Heap-"+ std::to_string(sessionId_) + "-" + std::string(date) + "T" + std::string(time) +
".heapsnapshot";
std::cout << "heapsnapshot file name is " << fileName_ << std::endl;
}
std::cout << ">>> ";

View File

@ -38,18 +38,18 @@ enum HeapProfilerEvent {
};
class HeapProfilerClient final {
public:
HeapProfilerClient() = default;
HeapProfilerClient(uint32_t sessionId) : sessionId_(sessionId) {}
~HeapProfilerClient() = default;
bool DispatcherCmd(int id, const std::string &cmd, const std::string &arg, std::string* reqStr);
std::string HeapDumpCommand(int id);
std::string AllocationTrackCommand(int id);
std::string AllocationTrackStopCommand(int id);
std::string Enable(int id);
std::string Disable(int id);
std::string Samping(int id);
std::string SampingStop(int id);
std::string CollectGarbage(int id);
bool DispatcherCmd(const std::string &cmd, const std::string &arg);
int HeapDumpCommand();
int AllocationTrackCommand();
int AllocationTrackStopCommand();
int Enable();
int Disable();
int Samping();
int SampingStop();
int CollectGarbage();
void RecvReply(std::unique_ptr<PtJson> json);
bool WriteHeapProfilerForFile(const std::string &fileName, const std::string &data);
@ -58,6 +58,7 @@ private:
std::map<uint32_t, HeapProfilerEvent> idEventMap_;
std::string path_;
bool isAllocationMsg_ {false};
uint32_t sessionId_;
};
} // OHOS::ArkCompiler::Toolchain
#endif

View File

@ -17,6 +17,7 @@
#include "tooling/base/pt_types.h"
#include "common/log_wrapper.h"
#include "tooling/client/utils/utils.h"
#include "tooling/client/session/session.h"
#include <map>
#include <functional>
@ -26,30 +27,31 @@
using Result = panda::ecmascript::tooling::Result;
using Profile = panda::ecmascript::tooling::Profile;
namespace OHOS::ArkCompiler::Toolchain {
ProfilerSingleton ProfilerSingleton::instance_;
bool ProfilerClient::DispatcherCmd(int id, const std::string &cmd, std::string* reqStr)
bool ProfilerClient::DispatcherCmd(const std::string &cmd)
{
std::map<std::string, std::function<std::string()>> dispatcherTable {
{ "cpuprofile", std::bind(&ProfilerClient::CpuprofileCommand, this, id)},
{ "cpuprofile-stop", std::bind(&ProfilerClient::CpuprofileStopCommand, this, id)},
{ "cpuprofile-setSamplingInterval", std::bind(&ProfilerClient::SetSamplingIntervalCommand, this, id)},
{ "cpuprofile-enable", std::bind(&ProfilerClient::CpuprofileEnableCommand, this, id)},
{ "cpuprofile-disable", std::bind(&ProfilerClient::CpuprofileDisableCommand, this, id)},
std::map<std::string, std::function<int()>> dispatcherTable {
{ "cpuprofile", std::bind(&ProfilerClient::CpuprofileCommand, this)},
{ "cpuprofile-stop", std::bind(&ProfilerClient::CpuprofileStopCommand, this)},
{ "cpuprofile-setSamplingInterval", std::bind(&ProfilerClient::SetSamplingIntervalCommand, this)},
{ "cpuprofile-enable", std::bind(&ProfilerClient::CpuprofileEnableCommand, this)},
{ "cpuprofile-disable", std::bind(&ProfilerClient::CpuprofileDisableCommand, this)},
};
auto entry = dispatcherTable.find(cmd);
if (entry == dispatcherTable.end()) {
*reqStr = "Unknown commond: " + cmd;
LOGI("DispatcherCmd reqStr2: %{public}s", reqStr->c_str());
LOGI("Unknown commond: %{public}s", cmd.c_str());
return false;
}
*reqStr = entry->second();
LOGI("DispatcherCmd reqStr1: %{public}s", reqStr->c_str());
entry->second();
LOGI("DispatcherCmd cmd: %{public}s", cmd.c_str());
return true;
}
std::string ProfilerClient::CpuprofileEnableCommand(int id)
int ProfilerClient::CpuprofileEnableCommand()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
idEventMap_.emplace(id, "cpuprofileenable");
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
@ -57,11 +59,19 @@ std::string ProfilerClient::CpuprofileEnableCommand(int id)
std::unique_ptr<PtJson> params = PtJson::CreateObject();
request->Add("params", params);
return request->Stringify();
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "Profiler");
}
return 0;
}
std::string ProfilerClient::CpuprofileDisableCommand(int id)
int ProfilerClient::CpuprofileDisableCommand()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
idEventMap_.emplace(id, "cpuprofiledisable");
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
@ -69,11 +79,19 @@ std::string ProfilerClient::CpuprofileDisableCommand(int id)
std::unique_ptr<PtJson> params = PtJson::CreateObject();
request->Add("params", params);
return request->Stringify();
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "Profiler");
}
return 0;
}
std::string ProfilerClient::CpuprofileCommand(int id)
int ProfilerClient::CpuprofileCommand()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
idEventMap_.emplace(id, "cpuprofile");
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
@ -81,11 +99,19 @@ std::string ProfilerClient::CpuprofileCommand(int id)
std::unique_ptr<PtJson> params = PtJson::CreateObject();
request->Add("params", params);
return request->Stringify();
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "Profiler");
}
return 0;
}
std::string ProfilerClient::CpuprofileStopCommand(int id)
int ProfilerClient::CpuprofileStopCommand()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
idEventMap_.emplace(id, "cpuprofilestop");
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
@ -93,11 +119,19 @@ std::string ProfilerClient::CpuprofileStopCommand(int id)
std::unique_ptr<PtJson> params = PtJson::CreateObject();
request->Add("params", params);
return request->Stringify();
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "Profiler");
}
return 0;
}
std::string ProfilerClient::SetSamplingIntervalCommand(int id)
int ProfilerClient::SetSamplingIntervalCommand()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
idEventMap_.emplace(id, "setsamplinginterval");
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
@ -106,12 +140,12 @@ std::string ProfilerClient::SetSamplingIntervalCommand(int id)
std::unique_ptr<PtJson> params = PtJson::CreateObject();
params->Add("interval", interval_);
request->Add("params", params);
return request->Stringify();
}
ProfilerSingleton& ProfilerSingleton::GetInstance()
{
return instance_;
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "Profiler");
}
return 0;
}
void ProfilerClient::RecvProfilerResult(std::unique_ptr<PtJson> json)
@ -149,10 +183,12 @@ void ProfilerClient::RecvProfilerResult(std::unique_ptr<PtJson> json)
return;
}
ProfilerSingleton& pro = ProfilerSingleton::GetInstance();
std::string fileName = "/data/CPU-" + std::string(date) + "T" + std::string(time) + ".cpuprofile";
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
ProfilerSingleton &pro = session->GetProfilerSingleton();
std::string fileName = "/data/CPU-" + std::to_string(sessionId_) + "-" + std::string(date) + "T" +
std::string(time) + ".cpuprofile";
std::string cpufile = pro.GetAddress() + fileName;
std::cout << "cpuprofile file name is " << cpufile << std::endl;
std::cout << "session " << sessionId_ << " cpuprofile file name is " << cpufile << std::endl;
std::cout << ">>> ";
fflush(stdout);
WriteCpuProfileForFile(cpufile, profile->Stringify());
@ -177,7 +213,8 @@ bool ProfilerClient::WriteCpuProfileForFile(const std::string &fileName, const s
ofs.write(data.c_str(), strSize);
ofs.close();
ofs.clear();
ProfilerSingleton& pro = ProfilerSingleton::GetInstance();
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
ProfilerSingleton &pro = session->GetProfilerSingleton();
pro.SetAddress("");
return true;
}

View File

@ -27,7 +27,7 @@ namespace OHOS::ArkCompiler::Toolchain {
using PtJson = panda::ecmascript::tooling::PtJson;
class ProfilerSingleton {
public:
static ProfilerSingleton& GetInstance();
ProfilerSingleton() = default;
void AddCpuName(const std::string &data)
{
@ -55,29 +55,28 @@ public:
private:
std::vector<std::string> cpulist_;
std::string address_ = "";
static ProfilerSingleton instance_;
ProfilerSingleton() = default;
ProfilerSingleton(const ProfilerSingleton&) = delete;
ProfilerSingleton& operator=(const ProfilerSingleton&) = delete;
};
class ProfilerClient final {
public:
ProfilerClient() = default;
ProfilerClient(uint32_t sessionId) : sessionId_(sessionId) {}
~ProfilerClient() = default;
bool DispatcherCmd(int id, const std::string &cmd, std::string* reqStr);
std::string CpuprofileCommand(int id);
std::string CpuprofileStopCommand(int id);
std::string SetSamplingIntervalCommand(int id);
std::string CpuprofileEnableCommand(int id);
std::string CpuprofileDisableCommand(int id);
bool DispatcherCmd(const std::string &cmd);
int CpuprofileCommand();
int CpuprofileStopCommand();
int SetSamplingIntervalCommand();
int CpuprofileEnableCommand();
int CpuprofileDisableCommand();
bool WriteCpuProfileForFile(const std::string &fileName, const std::string &data);
void RecvProfilerResult(std::unique_ptr<PtJson> json);
void SetSamplingInterval(int interval);
private:
int32_t interval_ = 0;
int32_t sessionId_;
std::map<uint32_t, std::string> idEventMap_ {};
};
} // OHOS::ArkCompiler::Toolchain

View File

@ -18,34 +18,37 @@
#include "common/log_wrapper.h"
#include "tooling/client/manager/variable_manager.h"
#include "tooling/base/pt_json.h"
#include "tooling/client/session/session.h"
using PtJson = panda::ecmascript::tooling::PtJson;
namespace OHOS::ArkCompiler::Toolchain {
bool RuntimeClient::DispatcherCmd(int id, const std::string &cmd, std::string* reqStr)
bool RuntimeClient::DispatcherCmd(const std::string &cmd)
{
std::map<std::string, std::function<std::string()>> dispatcherTable {
{ "heapusage", std::bind(&RuntimeClient::HeapusageCommand, this, id)},
{ "runtime-enable", std::bind(&RuntimeClient::RuntimeEnableCommand, this, id)},
{ "runtime-disable", std::bind(&RuntimeClient::RuntimeDisableCommand, this, id)},
{ "print", std::bind(&RuntimeClient::GetPropertiesCommand, this, id)},
{ "print2", std::bind(&RuntimeClient::GetPropertiesCommand2, this, id)},
{ "run", std::bind(&RuntimeClient::RunIfWaitingForDebuggerCommand, this, id)},
std::map<std::string, std::function<int()>> dispatcherTable {
{ "heapusage", std::bind(&RuntimeClient::HeapusageCommand, this)},
{ "runtime-enable", std::bind(&RuntimeClient::RuntimeEnableCommand, this)},
{ "runtime-disable", std::bind(&RuntimeClient::RuntimeDisableCommand, this)},
{ "print", std::bind(&RuntimeClient::GetPropertiesCommand, this)},
{ "print2", std::bind(&RuntimeClient::GetPropertiesCommand2, this)},
{ "run", std::bind(&RuntimeClient::RunIfWaitingForDebuggerCommand, this)},
};
auto entry = dispatcherTable.find(cmd);
if (entry != dispatcherTable.end()) {
*reqStr = entry->second();
LOGI("RuntimeClient DispatcherCmd reqStr1: %{public}s", reqStr->c_str());
entry->second();
LOGI("RuntimeClient DispatcherCmd reqStr1: %{public}s", cmd.c_str());
return true;
} else {
*reqStr = "Unknown commond: " + cmd;
LOGI("RuntimeClient DispatcherCmd reqStr2: %{public}s", reqStr->c_str());
LOGI("Unknown commond: %{public}s", cmd.c_str());
return false;
}
}
std::string RuntimeClient::HeapusageCommand(int id)
int RuntimeClient::HeapusageCommand()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
idMethodMap_[id] = std::make_tuple("getHeapUsage", "");
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
@ -53,11 +56,19 @@ std::string RuntimeClient::HeapusageCommand(int id)
std::unique_ptr<PtJson> params = PtJson::CreateObject();
request->Add("params", params);
return request->Stringify();
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "Runtime");
}
return 0;
}
std::string RuntimeClient::RuntimeEnableCommand(int id)
int RuntimeClient::RuntimeEnableCommand()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
idMethodMap_[id] = std::make_tuple("enable", "");
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
@ -65,11 +76,19 @@ std::string RuntimeClient::RuntimeEnableCommand(int id)
std::unique_ptr<PtJson> params = PtJson::CreateObject();
request->Add("params", params);
return request->Stringify();
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "Runtime");
}
return 0;
}
std::string RuntimeClient::RuntimeDisableCommand(int id)
int RuntimeClient::RuntimeDisableCommand()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
idMethodMap_[id] = std::make_tuple("disable", "");
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
@ -77,11 +96,19 @@ std::string RuntimeClient::RuntimeDisableCommand(int id)
std::unique_ptr<PtJson> params = PtJson::CreateObject();
request->Add("params", params);
return request->Stringify();
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "Runtime");
}
return 0;
}
std::string RuntimeClient::RunIfWaitingForDebuggerCommand(int id)
int RuntimeClient::RunIfWaitingForDebuggerCommand()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
idMethodMap_[id] = std::make_tuple("runIfWaitingForDebugger", "");
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
@ -89,11 +116,19 @@ std::string RuntimeClient::RunIfWaitingForDebuggerCommand(int id)
std::unique_ptr<PtJson> params = PtJson::CreateObject();
request->Add("params", params);
return request->Stringify();
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "Runtime");
}
return 0;
}
std::string RuntimeClient::GetPropertiesCommand(int id)
int RuntimeClient::GetPropertiesCommand()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
idMethodMap_[id] = std::make_tuple("getProperties", objectId_);
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
@ -105,11 +140,19 @@ std::string RuntimeClient::GetPropertiesCommand(int id)
params->Add("objectId", objectId_.c_str());
params->Add("ownProperties", true);
request->Add("params", params);
return request->Stringify();
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "Runtime");
}
return 0;
}
std::string RuntimeClient::GetPropertiesCommand2(int id)
int RuntimeClient::GetPropertiesCommand2()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
idMethodMap_[id] = std::make_tuple("getProperties", objectId_);
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
@ -121,7 +164,12 @@ std::string RuntimeClient::GetPropertiesCommand2(int id)
params->Add("objectId", "0");
params->Add("ownProperties", false);
request->Add("params", params);
return request->Stringify();
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "Runtime");
}
return 0;
}
void RuntimeClient::RecvReply(std::unique_ptr<PtJson> json)
@ -198,8 +246,9 @@ void RuntimeClient::HandleGetProperties(std::unique_ptr<PtJson> json, const int
return;
}
StackManager &stackManager = StackManager::GetInstance();
VariableManager &variableManager = VariableManager::GetInstance();
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
StackManager &stackManager = session->GetStackManager();
VariableManager &variableManager = session->GetVariableManager();
std::map<int32_t, std::map<int32_t, std::string>> treeInfo = stackManager.GetScopeChainInfo();
if (isInitializeTree_) {
variableManager.ClearVariableInfo();
@ -242,7 +291,8 @@ void RuntimeClient::HandleHeapUsage(std::unique_ptr<PtJson> json)
return;
}
VariableManager &variableManager = VariableManager::GetInstance();
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
VariableManager &variableManager = session->GetVariableManager();
std::unique_ptr<GetHeapUsageReturns> heapUsageReturns = GetHeapUsageReturns::Create(*result);
variableManager.SetHeapUsageInfo(std::move(heapUsageReturns));
variableManager.ShowHeapUsageInfo();

View File

@ -26,16 +26,16 @@ using Result = panda::ecmascript::tooling::Result;
namespace OHOS::ArkCompiler::Toolchain {
class RuntimeClient final {
public:
RuntimeClient() = default;
RuntimeClient(int32_t sessionId) : sessionId_(sessionId) {}
~RuntimeClient() = default;
bool DispatcherCmd(int id, const std::string &cmd, std::string *reqStr);
std::string HeapusageCommand(int id);
std::string RuntimeEnableCommand(int id);
std::string RuntimeDisableCommand(int id);
std::string RunIfWaitingForDebuggerCommand(int id);
std::string GetPropertiesCommand(int id);
std::string GetPropertiesCommand2(int id);
bool DispatcherCmd(const std::string &cmd);
int HeapusageCommand();
int RuntimeEnableCommand();
int RuntimeDisableCommand();
int RunIfWaitingForDebuggerCommand();
int GetPropertiesCommand();
int GetPropertiesCommand2();
std::string GetMethodById(const int &id);
std::string GetRequestObjectIdById(const int &id);
void RecvReply(std::unique_ptr<PtJson> json);
@ -61,6 +61,7 @@ private:
std::map<int, std::tuple<std::string, std::string>> idMethodMap_ {};
std::string objectId_ {"0"};
bool isInitializeTree_ {true};
int32_t sessionId_;
};
} // OHOS::ArkCompiler::Toolchain
#endif

View File

@ -18,47 +18,63 @@
#include "common/log_wrapper.h"
#include "tooling/client/manager/variable_manager.h"
#include "tooling/base/pt_json.h"
#include "tooling/client/session/session.h"
using PtJson = panda::ecmascript::tooling::PtJson;
namespace OHOS::ArkCompiler::Toolchain {
bool TestClient::DispatcherCmd(int id, const std::string &cmd, std::string* reqStr)
bool TestClient::DispatcherCmd(const std::string &cmd)
{
std::map<std::string, std::function<std::string()>> dispatcherTable {
{ "success", std::bind(&TestClient::SuccessCommand, this, id)},
{ "fail", std::bind(&TestClient::FailCommand, this, id)},
std::map<std::string, std::function<int()>> dispatcherTable {
{ "success", std::bind(&TestClient::SuccessCommand, this)},
{ "fail", std::bind(&TestClient::FailCommand, this)},
};
auto entry = dispatcherTable.find(cmd);
if (entry != dispatcherTable.end()) {
*reqStr = entry->second();
LOGI("TestClient DispatcherCmd reqStr1: %{public}s", reqStr->c_str());
entry->second();
LOGI("TestClient DispatcherCmd cmd: %{public}s", cmd.c_str());
return true;
} else {
*reqStr = "Unknown commond: " + cmd;
LOGI("TestClient DispatcherCmd reqStr2: %{public}s", reqStr->c_str());
LOGI("Unknown commond: %{public}s", cmd.c_str());
return false;
}
}
std::string TestClient::SuccessCommand(int id)
int TestClient::SuccessCommand()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
request->Add("method", "Test.success");
std::unique_ptr<PtJson> params = PtJson::CreateObject();
request->Add("params", params);
return request->Stringify();
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "Test");
}
return 0;
}
std::string TestClient::FailCommand(int id)
int TestClient::FailCommand()
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
request->Add("method", "Test.fail");
std::unique_ptr<PtJson> params = PtJson::CreateObject();
request->Add("params", params);
return request->Stringify();
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "Test");
}
return 0;
}
} // OHOS::ArkCompiler::Toolchain

View File

@ -26,12 +26,15 @@ using Result = panda::ecmascript::tooling::Result;
namespace OHOS::ArkCompiler::Toolchain {
class TestClient final {
public:
TestClient() = default;
TestClient(uint32_t sessionId) : sessionId_(sessionId) {}
~TestClient() = default;
bool DispatcherCmd(int id, const std::string &cmd, std::string *reqStr);
std::string SuccessCommand(int id);
std::string FailCommand(int id);
bool DispatcherCmd(const std::string &cmd);
int SuccessCommand();
int FailCommand();
private:
uint32_t sessionId_;
};
} // OHOS::ArkCompiler::Toolchain
#endif // ECMASCRIPT_TOOLING_CLIENT_DOMAIN_TEST_CLIENT_H

View File

@ -17,16 +17,11 @@
#include "common/log_wrapper.h"
#include "tooling/client/utils/utils.h"
#include "tooling/client/session/session.h"
using PtJson = panda::ecmascript::tooling::PtJson;
using Result = panda::ecmascript::tooling::Result;
namespace OHOS::ArkCompiler::Toolchain {
BreakPointManager BreakPointManager::instance_;
BreakPointManager& BreakPointManager::GetInstance()
{
return instance_;
}
void BreakPointManager::Createbreaklocation(const std::unique_ptr<PtJson> json)
{
if (json == nullptr) {
@ -68,7 +63,7 @@ void BreakPointManager::Show()
size_t size = breaklist_.size();
for (size_t i = 0; i < size; i++) {
std::cout << (i + 1) << ':' << " url:" << breaklist_[i].url;
std::cout << " lineNumber:" << breaklist_[i].lineNumber
std::cout << " lineNumber:" << (std::atoi(breaklist_[i].lineNumber.c_str()) + 1)
<< " columnNumber:" << breaklist_[i].columnNumber << std::endl;
}
}

View File

@ -36,7 +36,7 @@ struct Breaklocation {
};
class BreakPointManager {
public:
static BreakPointManager& GetInstance();
BreakPointManager(int32_t sessionId) : sessionId_(sessionId) {}
void Createbreaklocation(const std::unique_ptr<PtJson> json);
void Show();
@ -44,9 +44,8 @@ public:
std::vector<Breaklocation> Getbreaklist() const;
private:
static BreakPointManager instance_;
[[maybe_unused]] int32_t sessionId_;
std::vector<Breaklocation> breaklist_ {};
BreakPointManager() = default;
BreakPointManager(const BreakPointManager&) = delete;
BreakPointManager& operator=(const BreakPointManager&) = delete;
};

View File

@ -18,10 +18,17 @@
#include "common/log_wrapper.h"
#include "tooling/client/manager/breakpoint_manager.h"
#include "tooling/base/pt_json.h"
#include "tooling/client/session/session.h"
using PtJson = panda::ecmascript::tooling::PtJson;
using Result = panda::ecmascript::tooling::Result;
namespace OHOS::ArkCompiler::Toolchain {
DomainManager::DomainManager(uint32_t sessionId)
: sessionId_(sessionId), heapProfilerClient_(sessionId), profilerClient_(sessionId),
debuggerClient_(sessionId), runtimeClient_(sessionId), testClient_(sessionId)
{
}
void DomainManager::DispatcherReply(char* msg)
{
std::string decMessage = std::string(msg);
@ -45,6 +52,9 @@ void DomainManager::DispatcherReply(char* msg)
domain = GetDomainById(id);
RemoveDomainById(id);
}
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
WatchManager &watchManager = session->GetWatchManager();
watchManager.DebugFalseState();
std::string wholeMethod;
ret = json->GetString("method", &wholeMethod);

View File

@ -27,7 +27,7 @@
namespace OHOS::ArkCompiler::Toolchain {
class DomainManager {
public:
DomainManager() = default;
explicit DomainManager(uint32_t sessionId);
~DomainManager() = default;
void DispatcherReply(char* msg);
@ -80,11 +80,12 @@ public:
}
private:
HeapProfilerClient heapProfilerClient_ {};
ProfilerClient profilerClient_ {};
DebuggerClient debuggerClient_ {};
RuntimeClient runtimeClient_ {};
TestClient testClient_ {};
[[maybe_unused]] uint32_t sessionId_;
HeapProfilerClient heapProfilerClient_;
ProfilerClient profilerClient_;
DebuggerClient debuggerClient_;
RuntimeClient runtimeClient_;
TestClient testClient_;
std::map<uint32_t, std::string> idDomainMap_ {};
};
} // OHOS::ArkCompiler::Toolchain

View File

@ -0,0 +1,70 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ECMASCRIPT_TOOLING_CLIENT_MANAGER_MESSAGE_MANAGER_H
#define ECMASCRIPT_TOOLING_CLIENT_MANAGER_MESSAGE_MANAGER_H
#include <iostream>
namespace OHOS::ArkCompiler::Toolchain {
class MessageManager final {
public:
~MessageManager()
{
uv_mutex_destroy(&messageMutex_);
}
static MessageManager& getInstance()
{
static MessageManager instance;
return instance;
}
void MessagePush(uint32_t sessionId, std::string& message)
{
uv_mutex_lock(&messageMutex_);
messageQue_.push(std::make_pair(sessionId, message));
uv_mutex_unlock(&messageMutex_);
}
bool MessagePop(uint32_t& sessionId, std::string& message)
{
uv_mutex_lock(&messageMutex_);
if (messageQue_.empty()) {
uv_mutex_unlock(&messageMutex_);
return false;
}
sessionId = messageQue_.front().first;
message = messageQue_.front().second;
messageQue_.pop();
uv_mutex_unlock(&messageMutex_);
return true;
}
private:
MessageManager()
{
uv_mutex_init(&messageMutex_);
}
MessageManager(const MessageManager&) = delete;
MessageManager& operator=(const MessageManager&) = delete;
uv_mutex_t messageMutex_;
std::queue<std::pair<uint32_t, std::string>> messageQue_;
};
} // OHOS::ArkCompiler::Toolchain
#endif

View File

@ -0,0 +1,315 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "tooling/client/manager/source_manager.h"
#include "common/log_wrapper.h"
#include "tooling/client/session/session.h"
using PtJson = panda::ecmascript::tooling::PtJson;
using Result = panda::ecmascript::tooling::Result;
namespace OHOS::ArkCompiler::Toolchain {
void SourceManager::SendRequeSource(int scriptId)
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
scriptIdMap_.emplace(std::make_pair(id, scriptId));
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
request->Add("method", "Debugger.getScriptSource");
std::unique_ptr<PtJson> params = PtJson::CreateObject();
params->Add("scriptId", std::to_string(scriptId).c_str());
request->Add("params", params);
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "Debugger");
}
return;
}
void SourceManager::EnableReply(const std::unique_ptr<PtJson> json)
{
if (json == nullptr) {
LOGE("arkdb: json parse error");
return;
}
if (!json->IsObject()) {
LOGE("arkdb: json parse format error");
json->ReleaseRoot();
return;
}
std::unique_ptr<PtJson> params;
Result ret = json->GetObject("params", &params);
if (ret != Result::SUCCESS) {
LOGE("arkdb: find params error");
return;
}
std::string scriptIdStr;
ret = params->GetString("scriptId", &scriptIdStr);
if (ret != Result::SUCCESS) {
LOGE("arkdb: find scriptId error");
return;
}
std::string fileName;
ret = params->GetString("url", &fileName);
if (ret != Result::SUCCESS) {
LOGE("arkdb: find fileName error");
return;
}
int scriptId = std::atoi(scriptIdStr.c_str());
SetFileName(scriptId, fileName);
SendRequeSource(scriptId);
return;
}
void SourceManager::SetFileName(int scriptId, const std::string& fileName)
{
fileSource_.insert(std::make_pair(scriptId, std::make_pair(fileName, std::vector<std::string> {})));
return;
}
void SourceManager::GetFileName()
{
for (auto it = fileSource_.begin(); it != fileSource_.end(); it++) {
std::cout << "scriptID : " << it->first;
std::cout << " fileName : " << it->second.first <<std::endl;
}
return;
}
void SourceManager::SetFileSource(int scriptIdIndex, const std::string& fileSource)
{
const int IGNOR_NEWLINE_FLAG = 2;
auto scriptIdIt = scriptIdMap_.find(scriptIdIndex);
if (scriptIdIt == scriptIdMap_.end()) {
return;
}
int scriptId = scriptIdIt->second;
auto it = fileSource_.find(scriptId);
if (it != fileSource_.end() && it->second.second.empty()) {
int startPos = 0;
std::string::size_type endPos = fileSource.find("\r\n");
while (endPos != std::string::npos) {
std::string line = fileSource.substr(startPos, endPos - startPos);
it->second.second.push_back(line);
startPos = endPos + IGNOR_NEWLINE_FLAG; // ignore "\r\n"
endPos = fileSource.find("\r\n", startPos);
}
it->second.second.push_back(fileSource.substr(startPos));
}
return;
}
std::vector<std::string> SourceManager::GetFileSource(int scriptId)
{
int linNum = 0;
auto it = fileSource_.find(scriptId);
if (it != fileSource_.end()) {
std::cout << "fileSource : " <<std::endl;
for (const std::string& value : it->second.second) {
std::cout << ++linNum << " " << value << std::endl;
}
return it->second.second;
}
return std::vector<std::string> {};
}
void SourceManager::GetDebugSources(const std::unique_ptr<PtJson> json)
{
std::string funcName;
Result ret = json->GetString("functionName", &funcName);
if (ret != Result::SUCCESS) {
LOGE("arkdb: get functionName error");
return;
}
std::unique_ptr<PtJson> location;
ret = json->GetObject("location", &location);
if (ret != Result::SUCCESS) {
LOGE("arkdb: get location error");
return;
}
std::string scriptIdStr;
ret = location->GetString("scriptId", &scriptIdStr);
if (ret != Result::SUCCESS) {
LOGE("arkdb: get scriptId error");
return;
}
scriptId_ = std::atoi(scriptIdStr.c_str());
ret = location->GetInt("lineNumber", &debugLineNum_);
if (ret != Result::SUCCESS) {
LOGE("arkdb: get lineNumber error");
return;
}
LOGE("arkdb: callFrames : funcName %{public}s, scriptid %{public}s, lineNum %{public}d",
funcName.c_str(), scriptIdStr.c_str(), debugLineNum_);
auto it = fileSource_.find(scriptId_);
if (it != fileSource_.end()) {
std::cout << (debugLineNum_ + 1) << " " << it->second.second[debugLineNum_] << std::endl;
std::cout << ">>> ";
fflush(stdout);
}
return;
}
void SourceManager::ListSourceCodeWithParameters(int startLine, int endLine)
{
const int BLANK_LINE = std::numeric_limits<int>::max();
const int STATR_LINE_OFFSET = 6;
const int END_LINE_OFFSET = 4;
const int END_LINE = 10;
if (startLine != BLANK_LINE && endLine == BLANK_LINE) {
auto it = fileSource_.find(scriptId_);
if (it == fileSource_.end()) {
LOGE("arkdb: get file source error");
return;
}
if (startLine >= static_cast<int>(it->second.second.size()) + STATR_LINE_OFFSET ||
startLine < 0) {
std::cout << "Line number out of range, this file has " <<
static_cast<int>(it->second.second.size()) << " lines" << std::endl;
return;
}
int showLine = startLine - STATR_LINE_OFFSET;
if (showLine < 0) {
showLine = 0;
endLine = END_LINE;
} else {
endLine = startLine + END_LINE_OFFSET;
}
if (endLine > static_cast<int>(it->second.second.size())) {
endLine = static_cast<int>(it->second.second.size());
}
for (; showLine < endLine; showLine++) {
std::cout << (showLine + 1) << " " << it->second.second[showLine] << std::endl;
}
} else if (startLine != BLANK_LINE && endLine != BLANK_LINE) {
auto it = fileSource_.find(scriptId_);
if (it == fileSource_.end()) {
LOGE("arkdb: get file source error");
return;
}
if (startLine > static_cast<int>(it->second.second.size()) ||
endLine > static_cast<int>(it->second.second.size()) ||
startLine < 1) {
std::cout << "Line number out of range, this file has " <<
static_cast<int>(it->second.second.size()) << " lines" << std::endl;
return;
}
if (endLine > static_cast<int>(it->second.second.size())) {
endLine = static_cast<int>(it->second.second.size());
}
for (int showLine = startLine - 1; showLine < endLine; showLine++) {
std::cout << (showLine + 1) << " " << it->second.second[showLine] << std::endl;
}
}
}
void SourceManager::ListSource(int startLine, int endLine)
{
const int BLANK_LINE = std::numeric_limits<int>::max();
const int STATR_LINE_OFFSET = 6;
const int END_LINE_OFFSET = 4;
const int END_LINE = 10;
if (startLine == BLANK_LINE && endLine == BLANK_LINE) {
auto it = fileSource_.find(scriptId_);
if (it == fileSource_.end()) {
LOGE("arkdb: get file source error");
return;
}
int showLine = (debugLineNum_ + 1) - STATR_LINE_OFFSET;
if (showLine < 0) {
showLine = 0;
endLine = END_LINE;
} else {
endLine = debugLineNum_ + END_LINE_OFFSET;
}
if (endLine > static_cast<int>(it->second.second.size())) {
endLine = static_cast<int>(it->second.second.size());
}
for (; showLine <= endLine; showLine++) {
std::cout << (showLine + 1) << " " << it->second.second[showLine] << std::endl;
}
} else {
ListSourceCodeWithParameters(startLine, endLine);
}
}
bool SourceManager::IsNumer(const std::string& str)
{
for (char c : str) {
if (std::isdigit(c)) {
return true;
}
}
return false;
}
void SourceManager::GetListSource(std::string lineNum)
{
const int BLANK_LINE = std::numeric_limits<int>::max();
if (lineNum != "") {
size_t found = lineNum.find(",");
if (found != std::string::npos) {
std::string startLine = lineNum.substr(0, found);
std::string endLine = lineNum.substr(found + 1);
ListSource(std::atoi(startLine.c_str()), std::atoi(endLine.c_str()));
} else {
if (!IsNumer(lineNum)) {
return;
}
ListSource(std::atoi(lineNum.c_str()), BLANK_LINE);
}
} else {
ListSource(BLANK_LINE, BLANK_LINE);
}
return;
}
void SourceManager::GetDebugInfo(const std::unique_ptr<PtJson> json)
{
Result ret;
std::unique_ptr<PtJson> locations;
ret = json->GetArray("locations", &locations);
if (ret != Result::SUCCESS) {
LOGE("json parse locations error");
return;
}
std::string scriptId;
ret = locations->Get(0)->GetString("scriptId", &scriptId);
if (ret != Result::SUCCESS) {
LOGE("json parse scriptId error");
return;
}
scriptId_ = std::atoi(scriptId.c_str());
ret = locations->Get(0)->GetInt("lineNumber", &debugLineNum_);
if (ret != Result::SUCCESS) {
LOGE("json parse lineNumber error");
return;
}
return;
}
}

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ECMASCRIPT_TOOLING_CLIENT_MANAGER_SOURCE_MANAGER_H
#define ECMASCRIPT_TOOLING_CLIENT_MANAGER_SOURCE_MANAGER_H
#include <iostream>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "tooling/base/pt_json.h"
#include "tooling/base/pt_types.h"
namespace OHOS::ArkCompiler::Toolchain {
using PtJson = panda::ecmascript::tooling::PtJson;
using Result = panda::ecmascript::tooling::Result;
class SourceManager {
public:
SourceManager(int32_t sessionId) : sessionId_(sessionId) {}
void SendRequeSource(int scriptId);
void EnableReply(const std::unique_ptr<PtJson> json);
void GetFileName();
void SetFileName(int scriptId, const std::string& fileName);
void SetFileSource(int scriptIdIndex, const std::string& fileSource);
std::vector<std::string> GetFileSource(int scriptId);
void GetDebugSources(const std::unique_ptr<PtJson> json);
void ListSourceCodeWithParameters(int startLine, int endLine);
void ListSource(int startLine, int endLine);
void GetListSource(std::string lineNum);
void GetDebugInfo(const std::unique_ptr<PtJson> json);
bool IsNumer(const std::string& str);
private:
[[maybe_unused]] int32_t sessionId_;
int32_t scriptId_;
int32_t debugLineNum_;
std::unordered_map<int, int> scriptIdMap_ {};
std::unordered_map<int, std::pair<std::string, std::vector<std::string>>> fileSource_ {};
SourceManager(const SourceManager&) = delete;
SourceManager& operator=(const SourceManager&) = delete;
};
} // OHOS::ArkCompiler::Toolchain
#endif

View File

@ -15,14 +15,9 @@
#include "tooling/client/manager/stack_manager.h"
#include "common/log_wrapper.h"
#include "tooling/client/session/session.h"
namespace OHOS::ArkCompiler::Toolchain {
StackManager StackManager::instance_;
StackManager& StackManager::GetInstance()
{
return instance_;
}
void StackManager::SetCallFrames(std::map<int32_t, std::unique_ptr<CallFrame>> callFrames)
{
for (auto &callFrame : callFrames) {

View File

@ -30,7 +30,7 @@ using Scope = panda::ecmascript::tooling::Scope;
namespace OHOS::ArkCompiler::Toolchain {
class StackManager final {
public:
static StackManager& GetInstance();
StackManager(int32_t sessionId) : sessionId_(sessionId) {}
std::map<int32_t, std::map<int32_t, std::string>> GetScopeChainInfo();
void SetCallFrames(std::map<int32_t, std::unique_ptr<CallFrame>> callFrames);
@ -39,9 +39,8 @@ public:
void PrintScopeChainInfo(const std::map<int32_t, std::map<int32_t, std::string>>& scopeInfos);
private:
static StackManager instance_;
[[maybe_unused]] int32_t sessionId_;
std::map<int32_t, std::unique_ptr<CallFrame>> callFrames_ {};
StackManager() = default;
StackManager(const StackManager&) = delete;
StackManager& operator=(const StackManager&) = delete;
};

View File

@ -21,7 +21,6 @@
using PtJson = panda::ecmascript::tooling::PtJson;
namespace OHOS::ArkCompiler::Toolchain {
VariableManager VariableManager::instance_;
void TreeNode::AddChild(std::unique_ptr<PropertyDescriptor> descriptor)
{
children.push_back(std::make_unique<TreeNode>(std::move(descriptor)));
@ -253,11 +252,6 @@ int32_t Tree::FindObjectByIndexRecursive(const TreeNode* node, int32_t index) co
return 0;
}
VariableManager& VariableManager::GetInstance()
{
return instance_;
}
void VariableManager::SetHeapUsageInfo(std::unique_ptr<GetHeapUsageReturns> heapUsageReturns)
{
heapUsageInfo_.SetUsedSize(heapUsageReturns->GetUsedSize());

View File

@ -74,7 +74,7 @@ private:
class VariableManager final {
public:
static VariableManager& GetInstance();
VariableManager(int32_t sessionId) : sessionId_(sessionId) {}
void SetHeapUsageInfo(std::unique_ptr<GetHeapUsageReturns> heapUsageReturns);
void ShowHeapUsageInfo() const;
void ShowVariableInfos() const;
@ -88,8 +88,7 @@ public:
void Printinfo() const;
private:
VariableManager() = default;
static VariableManager instance_;
[[maybe_unused]] int32_t sessionId_;
GetHeapUsageReturns heapUsageInfo_ {};
Tree variableInfo_ {0};
VariableManager(const VariableManager&) = delete;

View File

@ -0,0 +1,263 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "tooling/client/manager/watch_manager.h"
#include "common/log_wrapper.h"
#include "tooling/client/session/session.h"
using PtJson = panda::ecmascript::tooling::PtJson;
using Result = panda::ecmascript::tooling::Result;
namespace OHOS::ArkCompiler::Toolchain {
WatchManager::WatchManager(uint32_t sessionId)
: sessionId_(sessionId), runtimeClient_(sessionId)
{
}
void WatchManager::SendRequestWatch(const int32_t &watchInfoIndex, const std::string &callFrameId)
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
watchInfoMap_.emplace(id, watchInfoIndex);
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
request->Add("method", "Debugger.evaluateOnCallFrame");
std::unique_ptr<PtJson> params = PtJson::CreateObject();
params->Add("callFrameId", callFrameId.c_str());
params->Add("expression", watchInfoList_[watchInfoIndex].c_str());
params->Add("objectGroup", "watch-group");
params->Add("includeCommandLineAPI", false);
params->Add("silent", true);
params->Add("returnByValue", false);
params->Add("generatePreview", false);
params->Add("throwOnSideEffect", false);
request->Add("params", params);
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
inputRowFlag_++;
session->GetDomainManager().SetDomainById(id, "Debugger");
}
return;
}
void WatchManager::GetPropertiesCommand(const int32_t &watchInfoIndex, const std::string &objectId)
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
uint32_t id = session->GetMessageId();
watchInfoMap_.emplace(id, watchInfoIndex);
std::unique_ptr<PtJson> request = PtJson::CreateObject();
request->Add("id", id);
request->Add("method", "Runtime.getProperties");
std::unique_ptr<PtJson> params = PtJson::CreateObject();
params->Add("accessorPropertiesOnly", false);
params->Add("generatePreview", true);
params->Add("objectId", objectId.c_str());
params->Add("ownProperties", true);
request->Add("params", params);
std::string message = request->Stringify();
if (session->ClientSendReq(message)) {
session->GetDomainManager().SetDomainById(id, "Debugger");
}
return;
}
void WatchManager::RequestWatchInfo(const std::unique_ptr<PtJson> &json)
{
Result ret = json->GetString("callFrameId", &callFrameId_);
if (ret != Result::SUCCESS) {
LOGE("arkdb: find callFrameId error");
return;
}
for (uint i = 0; i < watchInfoList_.size(); i++) {
SendRequestWatch(i, callFrameId_);
}
}
std::string WatchManager::GetCallFrameId()
{
return callFrameId_;
}
int WatchManager::GetWatchInfoSize()
{
return watchInfoList_.size();
}
void WatchManager::AddWatchInfo(const std::string& watchInfo)
{
watchInfoList_.emplace_back(watchInfo);
}
bool WatchManager::GetDebugState()
{
return IsDebug_;
}
void WatchManager::DebugFalseState()
{
IsDebug_ = false;
}
void WatchManager::DebugTrueState()
{
IsDebug_ = true;
}
void WatchManager::SetWatchInfoMap(const int &id, const int &index)
{
watchInfoMap_.emplace(id, index);
}
bool WatchManager::HandleWatchResult(const std::unique_ptr<PtJson> &json, int32_t id)
{
Result ret;
std::unique_ptr<PtJson> result;
ret = json->GetObject("result", &result);
if (ret != Result::SUCCESS) {
LOGE("json parse result error");
return false;
}
std::unique_ptr<PtJson> watchResult;
ret = result->GetObject("result", &watchResult);
if (ret != Result::SUCCESS) {
ShowWatchResult2(id, std::move(json));
LOGE("json parse result error");
return false;
}
if (!ShowWatchResult(std::move(watchResult), id)) {
return false;
}
inputRowFlag_--;
if (inputRowFlag_ == 0) {
std::cout << ">>> ";
fflush(stdout);
isShowWatchInfo_ = true;
}
return true;
}
bool WatchManager::ShowWatchResult(const std::unique_ptr<PtJson> &result, int32_t id)
{
std::string type;
Result ret = result->GetString("type", &type);
if (ret != Result::SUCCESS) {
LOGE("json parse type error");
return false;
}
if (inputRowFlag_ == GetWatchInfoSize() && isShowWatchInfo_) {
std::cout << "watch info :" << std::endl;
isShowWatchInfo_ = false;
}
if (type == "undefined") {
auto it = watchInfoMap_.find(id);
if (it == watchInfoMap_.end()) {
return false;
}
std::cout << " " << watchInfoList_[it->second] << " = undefined" << std::endl;
} else if (type == "object") {
std::string objectId;
ret = result->GetString("objectId", &objectId);
if (ret != Result::SUCCESS) {
LOGE("json parse object error");
return false;
}
auto it = watchInfoMap_.find(id);
if (it == watchInfoMap_.end()) {
return false;
}
GetPropertiesCommand(it->second, objectId);
inputRowFlag_++;
} else {
auto it = watchInfoMap_.find(id);
if (it == watchInfoMap_.end()) {
return false;
}
std::string description;
ret = result->GetString("description", &description);
if (ret != Result::SUCCESS) {
LOGE("json parse description error");
return false;
}
std::cout << " " << watchInfoList_[it->second] << " = " << description << std::endl;
}
watchInfoMap_.erase(id);
DebugTrueState();
return true;
}
void WatchManager::OutputWatchResult(const std::unique_ptr<PtJson> &watchResult)
{
for (int32_t i = 0; i < watchResult->GetSize(); i++) {
std::string name;
Result ret = watchResult->Get(i)->GetString("name", &name);
if (ret != Result::SUCCESS) {
LOGE("json parse name error");
continue;
}
std::unique_ptr<PtJson> value;
ret = watchResult->Get(i)->GetObject("value", &value);
if (ret != Result::SUCCESS) {
LOGE("json parse value error");
continue;
}
std::string description;
ret = value->GetString("description", &description);
if (ret != Result::SUCCESS) {
LOGE("json parse description error");
continue;
}
std::cout << name << " = " << description;
if (i < watchResult->GetSize() - 1) {
std::cout << ", ";
}
}
return;
}
bool WatchManager::ShowWatchResult2(const int &id, const std::unique_ptr<PtJson> &result)
{
std::unique_ptr<PtJson> resultWatch;
Result ret = result->GetObject("result", &resultWatch);
if (ret != Result::SUCCESS) {
LOGE("json parse result error");
return false;
}
std::unique_ptr<PtJson> watchResult;
ret = resultWatch->GetArray("result", &watchResult);
if (ret != Result::SUCCESS) {
LOGE("json parse result error");
return false;
}
auto it = watchInfoMap_.find(id);
if (it == watchInfoMap_.end()) {
return false;
}
std::cout << " " << watchInfoList_[it->second] << " = { ";
OutputWatchResult(std::move(watchResult));
std::cout << " }" << std::endl;
inputRowFlag_--;
if (inputRowFlag_ == 0) {
std::cout << ">>> ";
fflush(stdout);
isShowWatchInfo_ = true;
}
DebugTrueState();
watchInfoMap_.erase(id);
return true;
}
}

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ECMASCRIPT_TOOLING_CLIENT_MANAGER_WATCH_MANAGER_H
#define ECMASCRIPT_TOOLING_CLIENT_MANAGER_WATCH_MANAGER_H
#include <iostream>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "tooling/base/pt_json.h"
#include "tooling/base/pt_types.h"
#include "tooling/client/domain/runtime_client.h"
namespace OHOS::ArkCompiler::Toolchain {
using PtJson = panda::ecmascript::tooling::PtJson;
using Result = panda::ecmascript::tooling::Result;
class WatchManager {
public:
explicit WatchManager(uint32_t sessionId);
~WatchManager() = default;
void SendRequestWatch(const int32_t &watchInfoIndex, const std::string &callFrameId);
void GetPropertiesCommand(const int32_t &watchInfoIndex, const std::string &objectId);
void RequestWatchInfo(const std::unique_ptr<PtJson> &json);
void AddWatchInfo(const std::string& watchInfo);
bool GetDebugState();
void DebugFalseState();
void DebugTrueState();
bool HandleWatchResult(const std::unique_ptr<PtJson> &json, int32_t id);
bool ShowWatchResult(const std::unique_ptr<PtJson> &result, int32_t id);
void OutputWatchResult(const std::unique_ptr<PtJson> &watchResult);
bool ShowWatchResult2(const int &id, const std::unique_ptr<PtJson> &result);
std::string GetCallFrameId();
int GetWatchInfoSize();
void SetWatchInfoMap(const int &id, const int &index);
private:
[[maybe_unused]] int32_t sessionId_;
std::vector<std::string> watchInfoList_;
std::unordered_map<int, int> watchInfoMap_;
bool IsDebug_;
std::string callFrameId_;
RuntimeClient runtimeClient_;
int inputRowFlag_;
bool isShowWatchInfo_ = true;
};
} // OHOS::ArkCompiler::Toolchain
#endif

View File

@ -0,0 +1,208 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "tooling/client/session/session.h"
#include "common/log_wrapper.h"
#include "tooling/client/manager/message_manager.h"
#include "tooling/base/pt_json.h"
#include "tooling/client/utils/utils.h"
#include <iomanip>
using PtJson = panda::ecmascript::tooling::PtJson;
using Result = panda::ecmascript::tooling::Result;
namespace OHOS::ArkCompiler::Toolchain {
uv_async_t* g_socketSignal;
void SocketMessageThread(void *arg)
{
int sessionId = *(uint32_t *)arg;
Session *session = SessionManager::getInstance().GetSessionById(sessionId);
session->SocketMessageLoop();
}
Session::Session(uint32_t sessionId, std::string& sockInfo)
: sessionId_(sessionId), sockInfo_(sockInfo), domainManager_(sessionId), breakpoint_(sessionId),
stackManager_(sessionId), variableManager_(sessionId), sourceManager_(sessionId), watchManager_(sessionId)
{
}
void Session::SocketMessageLoop()
{
while (cliSocket_.IsConnected()) {
std::string decMessage = cliSocket_.Decode();
uint32_t len = decMessage.length();
if (len == 0) {
continue;
}
LOGI("arkdb [%{public}u] message = %{public}s", sessionId_, decMessage.c_str());
MessageManager::getInstance().MessagePush(sessionId_, decMessage);
if (uv_is_active(reinterpret_cast<uv_handle_t*>(g_socketSignal))) {
uv_async_send(g_socketSignal);
}
}
}
int Session::CreateSocket()
{
uint32_t port = 0;
if (Utils::StrToUInt(sockInfo_.c_str(), &port)) {
if ((port <= 0) || (port >= 65535)) { // 65535: max port
LOGE("arkdb:InitToolchainWebSocketForPort the port = %{public}d is wrong.", port);
return -1;
}
if (!cliSocket_.InitToolchainWebSocketForPort(port, 5)) { // 5: five times
LOGE("arkdb:InitToolchainWebSocketForPort failed");
return -1;
}
} else {
if (!cliSocket_.InitToolchainWebSocketForSockName(sockInfo_)) {
LOGE("arkdb:InitToolchainWebSocketForSockName failed");
return -1;
}
}
if (!cliSocket_.ClientSendWSUpgradeReq()) {
LOGE("arkdb:ClientSendWSUpgradeReq failed");
return -1;
}
if (!cliSocket_.ClientRecvWSUpgradeRsp()) {
LOGE("arkdb:ClientRecvWSUpgradeRsp failed");
return -1;
}
return 0;
}
int Session::Start()
{
if (CreateSocket()) {
return -1;
}
uv_thread_create(&socketTid_, SocketMessageThread, &sessionId_);
return 0;
}
int Session::Stop()
{
cliSocket_.Close();
return 0;
}
int SessionManager::CreateSessionById(uint32_t sessionId, std::string& sockInfo)
{
sessions_[sessionId] = std::make_unique<Session>(sessionId, sockInfo);
if (sessions_[sessionId]->Start()) {
sessions_[sessionId] = nullptr;
return -1;
}
return 0;
}
int SessionManager::CreateNewSession(std::string& sockInfo)
{
uint32_t sessionId = MAX_SESSION_NUM;
for (uint32_t i = 0; i < MAX_SESSION_NUM; ++i) {
if (sessions_[i] == nullptr) {
if (sessionId == MAX_SESSION_NUM) {
sessionId = i;
}
continue;
}
if (sessions_[i]->GetSockInfo() == sockInfo) {
return -1;
}
}
if (sessionId < MAX_SESSION_NUM) {
return CreateSessionById(sessionId, sockInfo);
}
return -1;
}
int SessionManager::CreateDefaultSession(std::string& sockInfo)
{
return CreateSessionById(0, sockInfo);
}
int SessionManager::DelSessionById(uint32_t sessionId)
{
Session *session = GetSessionById(sessionId);
if (session == nullptr) {
return -1;
}
session->Stop();
sessions_[sessionId] = nullptr;
if (sessionId == currentSessionId_) {
currentSessionId_ = 0;
std::cout << "session switch to 0" << std::endl;
}
return 0;
}
int SessionManager::SessionList()
{
for (uint32_t i = 0; i < MAX_SESSION_NUM; ++i) {
if (sessions_[i] != nullptr) {
std::string flag = (i == currentSessionId_) ? "* " : " ";
std::string sockState = sessions_[i]->GetSocketStateString();
std::cout << flag << i << ": ";
std::cout << std::setw(32) << std::left << sessions_[i]->GetSockInfo(); // 32: max length of socket info
std::cout << sockState << std::endl;
}
}
return 0;
}
int SessionManager::SessionSwitch(uint32_t sessionId)
{
Session *session = GetSessionById(sessionId);
if (session == nullptr) {
return -1;
}
currentSessionId_ = sessionId;
return 0;
}
void SessionManager::CmdForAllSessions(CmdForAllCB callback)
{
for (uint32_t sessionId = 0; sessionId < MAX_SESSION_NUM; ++sessionId) {
if (sessions_[sessionId] != nullptr) {
std::cout << "Executing command in session " << sessionId << ":" << std::endl;
callback(sessionId);
}
}
}
int SessionManager::CreateTestSession(std::string& sockInfo)
{
uint32_t sessionId = 0;
sessions_[sessionId] = std::make_unique<Session>(sessionId, sockInfo);
if (sessions_[sessionId]->CreateSocket()) {
sessions_[sessionId] = nullptr;
return -1;
}
return 0;
}
}

180
tooling/client/session/session.h Executable file
View File

@ -0,0 +1,180 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ECMASCRIPT_TOOLING_CLIENT_SESSION_H
#define ECMASCRIPT_TOOLING_CLIENT_SESSION_H
#include <atomic>
#include <iostream>
#include <memory>
#include <map>
#include <pthread.h>
#include <thread>
#include <uv.h>
#include "tooling/client/manager/domain_manager.h"
#include "tooling/client/manager/breakpoint_manager.h"
#include "tooling/client/manager/source_manager.h"
#include "tooling/client/manager/stack_manager.h"
#include "tooling/client/manager/variable_manager.h"
#include "tooling/client/manager/watch_manager.h"
#include "tooling/client/websocket/websocket_client.h"
namespace OHOS::ArkCompiler::Toolchain {
using CmdForAllCB = std::function<void(uint32_t sessionId)>;
extern uv_async_t* g_socketSignal;
class Session {
public:
explicit Session(uint32_t sessionId, std::string& sockInfo);
~Session()
{
Stop();
}
void SocketMessageLoop();
int CreateSocket();
int Start();
int Stop();
void CmdForAllSession(CmdForAllCB callback);
uint32_t GetMessageId()
{
return messageId_.fetch_add(1);
}
std::string& GetSockInfo()
{
return sockInfo_;
}
bool ClientSendReq(const std::string &message)
{
return cliSocket_.ClientSendReq(message);
}
DomainManager& GetDomainManager()
{
return domainManager_;
}
BreakPointManager& GetBreakPointManager()
{
return breakpoint_;
}
StackManager& GetStackManager()
{
return stackManager_;
}
VariableManager& GetVariableManager()
{
return variableManager_;
}
WebsocketClient& GetWebsocketClient()
{
return cliSocket_;
}
ProfilerSingleton& GetProfilerSingleton()
{
return profiler_;
}
std::string GetSocketStateString()
{
return cliSocket_.GetSocketStateString();
}
void ProcSocketMsg(char* msg)
{
domainManager_.DispatcherReply(msg);
}
SourceManager& GetSourceManager()
{
return sourceManager_;
}
WatchManager& GetWatchManager()
{
return watchManager_;
}
private:
uint32_t sessionId_;
std::string sockInfo_;
DomainManager domainManager_;
WebsocketClient cliSocket_;
uv_thread_t socketTid_;
std::atomic<uint32_t> messageId_ {1};
BreakPointManager breakpoint_;
StackManager stackManager_;
VariableManager variableManager_;
ProfilerSingleton profiler_;
SourceManager sourceManager_;
WatchManager watchManager_;
};
constexpr uint32_t MAX_SESSION_NUM = 8;
class SessionManager {
public:
static SessionManager& getInstance()
{
static SessionManager instance;
return instance;
}
uint32_t GetCurrentSessionId()
{
return currentSessionId_;
}
Session *GetCurrentSession()
{
if (currentSessionId_ >= MAX_SESSION_NUM || sessions_[currentSessionId_] == nullptr) {
return nullptr;
}
return sessions_[currentSessionId_].get();
}
Session *GetSessionById(uint32_t sessionId)
{
if (sessionId >= MAX_SESSION_NUM || sessions_[sessionId] == nullptr) {
return nullptr;
}
return sessions_[sessionId].get();
}
int CreateSessionById(uint32_t sessionId, std::string& sockInfo);
int CreateNewSession(std::string& sockInfo);
int CreateDefaultSession(std::string& sockInfo);
int DelSessionById(uint32_t sessionId);
int SessionList();
int SessionSwitch(uint32_t sessionId);
void CmdForAllSessions(CmdForAllCB callback);
int CreateTestSession(std::string& sockInfo);
private:
SessionManager() = default;
SessionManager(const SessionManager&) = delete;
SessionManager& operator=(const SessionManager&) = delete;
std::unique_ptr<Session> sessions_[MAX_SESSION_NUM];
uint32_t currentSessionId_ = 0;
};
} // namespace OHOS::ArkCompiler::Toolchain
#endif

View File

@ -25,6 +25,7 @@
#include "tooling/client/manager/domain_manager.h"
#include "tooling/client/manager/stack_manager.h"
#include "tooling/client/manager/variable_manager.h"
#include "tooling/client/session/session.h"
namespace OHOS::ArkCompiler::Toolchain {
const std::string HELP_MSG = "usage: <command> <options>\n"
@ -75,6 +76,11 @@ const std::string HELP_MSG = "usage: <command> <options>\n"
" step-out(so) step-out\n"
" step-over(sov) step-over\n"
" runtime-disable rt-disable\n"
" session-new add new session\n"
" session-remove del a session\n"
" session-list list all sessions\n"
" session switch session\n"
" forall command for all sessions\n"
" success test success\n"
" fail test fail\n";
@ -123,6 +129,10 @@ const std::vector<std::string> cmdList = {
"step-out",
"step-over",
"runtime-disable",
"session-new",
"session-remove",
"session-list",
"session",
"success",
"fail"
};
@ -194,6 +204,14 @@ void CliCommand::CreateCommandMap()
{std::make_pair("step-over", "sov"), std::bind(&CliCommand::DebuggerCommand, this, "step-over")},
{std::make_pair("runtime-disable", "rt-disable"),
std::bind(&CliCommand::RuntimeCommand, this, "runtime-disable")},
{std::make_pair("session-new", "session-new"),
std::bind(&CliCommand::SessionAddCommand, this, "session-new")},
{std::make_pair("session-remove", "session-remove"),
std::bind(&CliCommand::SessionDelCommand, this, "session-remove")},
{std::make_pair("session-list", "session-list"),
std::bind(&CliCommand::SessionListCommand, this, "session-list")},
{std::make_pair("session", "session"),
std::bind(&CliCommand::SessionSwitchCommand, this, "session")},
{std::make_pair("success", "success"),
std::bind(&CliCommand::TestCommand, this, "success")},
{std::make_pair("fail", "fail"),
@ -204,32 +222,25 @@ void CliCommand::CreateCommandMap()
ErrCode CliCommand::HeapProfilerCommand(const std::string &cmd)
{
std::cout << "exe success, cmd is " << cmd << std::endl;
std::string request;
bool result = false;
HeapProfilerClient &heapProfilerClient = domainManager_.GetHeapProfilerClient();
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
DomainManager &domainManager = session->GetDomainManager();
HeapProfilerClient &heapProfilerClient = domainManager.GetHeapProfilerClient();
VecStr argList = GetArgList();
if (argList.empty()) {
argList.push_back("/data/");
}
result = heapProfilerClient.DispatcherCmd(id_, cmd, argList[0], &request);
if (result) {
cliSocket_.ClientSendReq(request);
if (domainManager_.GetDomainById(id_).empty()) {
domainManager_.SetDomainById(id_, "HeapProfiler");
}
} else {
return ErrCode::ERR_FAIL;
}
return ErrCode::ERR_OK;
bool result = heapProfilerClient.DispatcherCmd(cmd, argList[0]);
return result ? ErrCode::ERR_OK : ErrCode::ERR_FAIL;
}
ErrCode CliCommand::CpuProfileCommand(const std::string &cmd)
{
std::cout << "exe success, cmd is " << cmd << std::endl;
std::string request;
bool result = false;
ProfilerClient &profilerClient = domainManager_.GetProfilerClient();
ProfilerSingleton& pro = ProfilerSingleton::GetInstance();
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
DomainManager &domainManager = session->GetDomainManager();
ProfilerClient &profilerClient = domainManager.GetProfilerClient();
ProfilerSingleton &pro = session->GetProfilerSingleton();
if (cmd == "cpuprofile-show") {
pro.ShowCpuFile();
return ErrCode::ERR_OK;
@ -240,29 +251,56 @@ ErrCode CliCommand::CpuProfileCommand(const std::string &cmd)
if (cmd == "cpuprofile-stop" && GetArgList().size() == 1) {
pro.SetAddress(GetArgList()[0]);
}
result = profilerClient.DispatcherCmd(id_, cmd, &request);
if (result) {
cliSocket_.ClientSendReq(request);
if (domainManager_.GetDomainById(id_).empty()) {
domainManager_.SetDomainById(id_, "Profiler");
}
} else {
return ErrCode::ERR_FAIL;
bool result = profilerClient.DispatcherCmd(cmd);
return result ? ErrCode::ERR_OK : ErrCode::ERR_FAIL;
}
ErrCode CliCommand::HandleDebuggerCommand(const std::string &cmd)
{
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
BreakPointManager &breakpoint = session->GetBreakPointManager();
SourceManager &sourceManager = session->GetSourceManager();
WatchManager &watchManager = session->GetWatchManager();
if (cmd == "display") {
breakpoint.Show();
return ErrCode::ERR_OK;
}
return ErrCode::ERR_OK;
if (cmd == "infosource") {
if (GetArgList().size() == 1) {
sourceManager.GetFileSource(std::atoi(GetArgList()[0].c_str()));
} else {
sourceManager.GetFileName();
}
return ErrCode::ERR_OK;
}
if (cmd == "list" && watchManager.GetDebugState()) {
if (GetArgList().size() == 1) {
sourceManager.GetListSource(GetArgList()[0]);
} else {
sourceManager.GetListSource("");
}
return ErrCode::ERR_OK;
}
if (cmd == "watch" && GetArgList().size() == 1) {
watchManager.AddWatchInfo(GetArgList()[0]);
if (watchManager.GetDebugState()) {
watchManager.SendRequestWatch(watchManager.GetWatchInfoSize() - 1, watchManager.GetCallFrameId());
}
return ErrCode::ERR_OK;
}
return ErrCode::ERR_FAIL;
}
ErrCode CliCommand::DebuggerCommand(const std::string &cmd)
{
std::cout << "exe success, cmd is " << cmd << std::endl;
std::string request;
bool result = false;
DebuggerClient &debuggerCli = domainManager_.GetDebuggerClient();
BreakPointManager &breakpoint = BreakPointManager::GetInstance();
if (cmd == "display") {
breakpoint.Show();
return ErrCode::ERR_OK;
}
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
DebuggerClient &debuggerCli = session->GetDomainManager().GetDebuggerClient();
BreakPointManager &breakpoint = session->GetBreakPointManager();
if (cmd == "delete") {
std::string bnumber = GetArgList()[0];
@ -281,12 +319,12 @@ ErrCode CliCommand::DebuggerCommand(const std::string &cmd)
}
if (cmd == "step-into" || cmd == "step-out" || cmd == "step-over") {
RuntimeClient &runtimeClient = domainManager_.GetRuntimeClient();
RuntimeClient &runtimeClient = session->GetDomainManager().GetRuntimeClient();
runtimeClient.SetIsInitializeTree(true);
}
if (cmd == "showstack") {
StackManager &stackManager = StackManager::GetInstance();
StackManager &stackManager = session->GetStackManager();
stackManager.ShowCallFrames();
}
@ -294,58 +332,98 @@ ErrCode CliCommand::DebuggerCommand(const std::string &cmd)
debuggerCli.AddBreakPointInfo(GetArgList()[0], std::stoi(GetArgList()[1]));
}
result = debuggerCli.DispatcherCmd(id_, cmd, &request);
if (HandleDebuggerCommand(cmd) == ErrCode::ERR_OK) {
return ErrCode::ERR_OK;
}
result = debuggerCli.DispatcherCmd(cmd);
return result ? ErrCode::ERR_OK : ErrCode::ERR_FAIL;
}
ErrCode CliCommand::RuntimeCommand(const std::string &cmd)
{
std::cout << "exe success, cmd is " << cmd << std::endl;
bool result = false;
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
RuntimeClient &runtimeClient = session->GetDomainManager().GetRuntimeClient();
if (cmd == "print" && GetArgList().size() == 1) {
runtimeClient.SetIsInitializeTree(false);
VariableManager &variableManager = session->GetVariableManager();
int32_t objectId = variableManager.FindObjectIdWithIndex(std::stoi(GetArgList()[0]));
runtimeClient.SetObjectId(std::to_string(objectId));
}
result = runtimeClient.DispatcherCmd(cmd);
if (result) {
cliSocket_.ClientSendReq(request);
if (domainManager_.GetDomainById(id_).empty()) {
domainManager_.SetDomainById(id_, "Debugger");
}
runtimeClient.SetObjectId("0");
} else {
return ErrCode::ERR_FAIL;
}
return ErrCode::ERR_OK;
}
ErrCode CliCommand::RuntimeCommand(const std::string &cmd)
ErrCode CliCommand::SessionAddCommand([[maybe_unused]] const std::string &cmd)
{
std::cout << "exe success, cmd is " << cmd << std::endl;
std::string request;
bool result = false;
RuntimeClient &runtimeClient = domainManager_.GetRuntimeClient();
if (cmd == "print" && GetArgList().size() == 1) {
runtimeClient.SetIsInitializeTree(false);
VariableManager &variableManager = VariableManager::GetInstance();
int32_t objectId = variableManager.FindObjectIdWithIndex(std::stoi(GetArgList()[0]));
runtimeClient.SetObjectId(std::to_string(objectId));
VecStr argList = GetArgList();
if (argList.size() >= 1) {
if (!SessionManager::getInstance().CreateNewSession(argList[0])) {
std::cout << "session create success" << std::endl;
return ErrCode::ERR_OK;
}
}
result = runtimeClient.DispatcherCmd(id_, cmd, &request);
if (result) {
cliSocket_.ClientSendReq(request);
runtimeClient.SetObjectId("0");
if (domainManager_.GetDomainById(id_).empty()) {
domainManager_.SetDomainById(id_, "Runtime");
std::cout << "session add failed" << std::endl;
return ErrCode::ERR_FAIL;
}
ErrCode CliCommand::SessionDelCommand([[maybe_unused]] const std::string &cmd)
{
VecStr argList = GetArgList();
if (argList.size() >= 1) {
uint32_t sessionId = 0;
if (Utils::StrToUInt(argList[0].c_str(), &sessionId)) {
if (sessionId == 0) {
std::cout << "cannot remove default session 0" << std::endl;
return ErrCode::ERR_OK;
}
if (SessionManager::getInstance().DelSessionById(sessionId) == 0) {
std::cout << "session remove success" << std::endl;
return ErrCode::ERR_OK;
}
}
}
return ErrCode::ERR_FAIL;
}
ErrCode CliCommand::SessionListCommand([[maybe_unused]] const std::string &cmd)
{
SessionManager::getInstance().SessionList();
return ErrCode::ERR_OK;
}
ErrCode CliCommand::SessionSwitchCommand([[maybe_unused]] const std::string &cmd)
{
VecStr argList = GetArgList();
if (argList.size() >= 1) {
uint32_t sessionId = 0;
if (Utils::StrToUInt(argList[0].c_str(), &sessionId)) {
if (SessionManager::getInstance().SessionSwitch(sessionId) == 0) {
std::cout << "session switch success" << std::endl;
return ErrCode::ERR_OK;
}
}
} else {
return ErrCode::ERR_FAIL;
}
return ErrCode::ERR_OK;
}
ErrCode CliCommand::TestCommand(const std::string &cmd)
{
std::string request;
bool result = false;
if (cmd == "success" || cmd == "fail") {
TestClient &testClient = domainManager_.GetTestClient();
result = testClient.DispatcherCmd(id_, cmd, &request);
if (result) {
cliSocket_.ClientSendReq(request);
if (domainManager_.GetDomainById(id_).empty()) {
domainManager_.SetDomainById(id_, "Test");
}
}
Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
TestClient &testClient = session->GetDomainManager().GetTestClient();
testClient.DispatcherCmd(cmd);
} else {
return ErrCode::ERR_FAIL;
}

View File

@ -27,6 +27,7 @@
#include "tooling/client/manager/domain_manager.h"
#include "tooling/client/utils/utils.h"
#include "tooling/client/websocket/websocket_client.h"
#include "tooling/client/session/session.h"
namespace OHOS::ArkCompiler::Toolchain {
using StrPair = std::pair<std::string, std::string>;
@ -39,8 +40,8 @@ enum class ErrCode : uint8_t {
class CliCommand {
public:
CliCommand(std::vector<std::string> cliCmdStr, int cmdId, DomainManager &domainManager, WebsocketClient &cliSocket)
: cmd_(cliCmdStr[0]), id_(cmdId), domainManager_(domainManager), cliSocket_(cliSocket)
CliCommand(std::vector<std::string> cliCmdStr, uint32_t sessionId)
: cmd_(cliCmdStr[0]), sessionId_(sessionId)
{
for (size_t i = 1u; i < cliCmdStr.size(); i++) {
argList_.push_back(cliCmdStr[i]);
@ -53,17 +54,17 @@ public:
ErrCode ExecCommand();
void CreateCommandMap();
ErrCode HeapProfilerCommand(const std::string &cmd);
ErrCode HandleDebuggerCommand(const std::string &cmd);
ErrCode DebuggerCommand(const std::string &cmd);
ErrCode CpuProfileCommand(const std::string &cmd);
ErrCode RuntimeCommand(const std::string &cmd);
ErrCode SessionAddCommand(const std::string &cmd);
ErrCode SessionDelCommand(const std::string &cmd);
ErrCode SessionListCommand(const std::string &cmd);
ErrCode SessionSwitchCommand(const std::string &cmd);
ErrCode TestCommand(const std::string &cmd);
ErrCode ExecHelpCommand();
uint32_t GetId() const
{
return id_;
}
VecStr GetArgList()
{
return argList_;
@ -74,9 +75,7 @@ private:
VecStr argList_ {};
std::map<StrPair, std::function<ErrCode()>> commandMap_;
std::string resultReceiver_ = "";
uint32_t id_ = 0;
DomainManager &domainManager_;
WebsocketClient &cliSocket_;
uint32_t sessionId_;
};
} // namespace OHOS::ArkCompiler::Toolchain

View File

@ -55,6 +55,17 @@ bool Utils::GetCurrentTime(char *date, char *tim, size_t size)
return true;
}
bool Utils::StrToUInt(const char *content, uint32_t *result)
{
const int dec = 10;
char *endPtr = nullptr;
*result = std::strtoul(content, &endPtr, dec);
if (endPtr == content || *endPtr != '\0') {
return false;
}
return true;
}
std::vector<std::string> Utils::SplitString(const std::string &str, const std::string &delimiter)
{
std::size_t strIndex = 0;

View File

@ -24,6 +24,7 @@ class Utils {
public:
static bool RealPath(const std::string &path, std::string &realPath, bool readOnly = true);
static bool GetCurrentTime(char *date, char *tim, size_t size);
static bool StrToUInt(const char *content, uint32_t *result);
static std::vector<std::string> SplitString(const std::string &str, const std::string &delimiter);
};
} // OHOS::ArkCompiler::Toolchain

View File

@ -254,11 +254,14 @@ std::string WebsocketClient::Decode()
return "";
}
char recvbuf[SOCKET_HEADER_LEN + 1];
errno = 0;
if (!Recv(client_, recvbuf, SOCKET_HEADER_LEN, 0)) {
LOGE("WebsocketClient:Decode failed, client websocket disconnect");
socketState_ = ToolchainSocketState::INITED;
close(client_);
client_ = -1;
if (errno != EAGAIN) {
LOGE("WebsocketClient:Decode failed, client websocket disconnect");
socketState_ = ToolchainSocketState::INITED;
close(client_);
client_ = -1;
}
return "";
}
ToolchainWebSocketFrame wsFrame;
@ -425,4 +428,15 @@ bool WebsocketClient::IsConnected()
{
return socketState_ == ToolchainSocketState::CONNECTED;
}
std::string WebsocketClient::GetSocketStateString()
{
std::vector<std::string> stateStr = {
"uninited",
"inited",
"connected"
};
return stateStr[socketState_];
}
} // namespace OHOS::ArkCompiler::Toolchain

View File

@ -43,7 +43,7 @@ public:
WebsocketClient() = default;
~WebsocketClient() = default;
bool InitToolchainWebSocketForPort(int port, uint32_t timeoutLimit = 5);
bool InitToolchainWebSocketForSockName(const std::string &sockName, uint32_t timeoutLimit = 0);
bool InitToolchainWebSocketForSockName(const std::string &sockName, uint32_t timeoutLimit = 5);
bool ClientSendWSUpgradeReq();
bool ClientRecvWSUpgradeRsp();
bool ClientSendReq(const std::string &message);
@ -56,6 +56,7 @@ public:
void Close();
bool SetWebSocketTimeOut(int32_t fd, uint32_t timeoutLimit);
bool IsConnected();
std::string GetSocketStateString();
private:
int32_t client_ {-1};

View File

@ -28,6 +28,7 @@ config("debug_api_test") {
"//arkcompiler/ets_runtime",
"../..",
"//third_party/cJSON",
"//third_party/libuv/include",
]
}

View File

@ -18,6 +18,7 @@
#include "tooling/client/domain/debugger_client.h"
#include "tooling/client/domain/runtime_client.h"
#include "tooling/client/utils/cli_command.h"
#include "tooling/client/session/session.h"
namespace panda::ecmascript::tooling::test {
TestMap TestUtil::testMap_;
@ -67,19 +68,19 @@ std::ostream &operator<<(std::ostream &out, ActionRule value)
return out << s;
}
void TestUtil::NotifySuccess(int cmdId, DomainManager &domainManager, WebsocketClient &client)
void TestUtil::NotifySuccess()
{
std::vector<std::string> cliCmdStr = { "success" };
CliCommand cmd(cliCmdStr, cmdId, domainManager, client);
CliCommand cmd(cliCmdStr, 0);
if (cmd.ExecCommand() == ErrCode::ERR_FAIL) {
LOG_DEBUGGER(ERROR) << "ExecCommand Test.success fail";
}
}
void TestUtil::NotifyFail(int cmdId, DomainManager &domainManager, WebsocketClient &client)
void TestUtil::NotifyFail()
{
std::vector<std::string> cliCmdStr = { "fail" };
CliCommand cmd(cliCmdStr, cmdId, domainManager, client);
CliCommand cmd(cliCmdStr, 0);
if (cmd.ExecCommand() == ErrCode::ERR_FAIL) {
LOG_DEBUGGER(ERROR) << "ExecCommand Test.fail fail";
}
@ -87,7 +88,6 @@ void TestUtil::NotifyFail(int cmdId, DomainManager &domainManager, WebsocketClie
void TestUtil::ForkSocketClient([[maybe_unused]] int port, const std::string &name)
{
int cmdId = 0;
#ifdef OHOS_PLATFORM
auto correntPid = getpid();
#endif
@ -98,28 +98,23 @@ void TestUtil::ForkSocketClient([[maybe_unused]] int port, const std::string &na
} else if (pid == 0) {
LOG_DEBUGGER(INFO) << "fork son pid: " << getpid();
std::this_thread::sleep_for(std::chrono::microseconds(500000)); // 500000: 500ms for wait debugger
DomainManager domainManager;
WebsocketClient client;
#ifdef OHOS_PLATFORM
std::string pidStr = std::to_string(correntPid);
std::string sockName = pidStr + "PandaDebugger";
bool ret = client.InitToolchainWebSocketForSockName(sockName, 120);
std::string sockInfo = pidStr + "PandaDebugger";
#else
bool ret = client.InitToolchainWebSocketForPort(port, 120);
std::string sockInfo = std::to_string(port);
#endif
LOG_ECMA_IF(!ret, FATAL) << "InitToolchainWebSocketForPort fail";
ret = client.ClientSendWSUpgradeReq();
LOG_ECMA_IF(!ret, FATAL) << "ClientSendWSUpgradeReq fail";
ret = client.ClientRecvWSUpgradeRsp();
LOG_ECMA_IF(!ret, FATAL) << "ClientRecvWSUpgradeRsp fail";
int ret = SessionManager::getInstance().CreateTestSession(sockInfo);
LOG_ECMA_IF(ret, FATAL) << "CreateTestSession fail";
WebsocketClient &client = SessionManager::getInstance().GetCurrentSession()->GetWebsocketClient();
auto &testAction = TestUtil::GetTest(name)->testAction;
for (const auto &action: testAction) {
LOG_DEBUGGER(INFO) << "message: " << action.message;
bool success = true;
if (action.action == SocketAction::SEND) {
std::vector<std::string> cliCmdStr = Utils::SplitString(action.message, " ");
CliCommand cmd(cliCmdStr, cmdId++, domainManager, client);
CliCommand cmd(cliCmdStr, 0);
success = (cmd.ExecCommand() == ErrCode::ERR_OK);
} else {
ASSERT(action.action == SocketAction::RECV);
@ -143,14 +138,14 @@ void TestUtil::ForkSocketClient([[maybe_unused]] int port, const std::string &na
}
if (!success) {
LOG_DEBUGGER(ERROR) << "Notify fail";
NotifyFail(cmdId++, domainManager, client);
client.Close();
NotifyFail();
SessionManager::getInstance().DelSessionById(0);
exit(-1);
}
}
NotifySuccess(cmdId++, domainManager, client);
client.Close();
NotifySuccess();
SessionManager::getInstance().DelSessionById(0);
exit(0);
}
LOG_DEBUGGER(INFO) << "ForkSocketClient end";

View File

@ -63,8 +63,8 @@ public:
static void ForkSocketClient(int port, const std::string &name);
private:
static void NotifyFail(int cmdId, DomainManager &domainManager, WebsocketClient &client);
static void NotifySuccess(int cmdId, DomainManager &domainManager, WebsocketClient &client);
static void NotifyFail();
static void NotifySuccess();
static TestMap testMap_;
};

View File

@ -35,7 +35,7 @@ public:
// break on start
{SocketAction::RECV, "Debugger.paused", ActionRule::STRING_CONTAIN},
// set breakpoint
{SocketAction::SEND, "b " DEBUGGER_JS_DIR "sample.js 21"},
{SocketAction::SEND, "b " DEBUGGER_JS_DIR "sample.js 22"},
{SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
// hit breakpoint after resume first time
{SocketAction::SEND, "resume"},