From 2cd388de17e063e1e502f49bb337adcf6fde233b Mon Sep 17 00:00:00 2001 From: Petrov Igor Date: Mon, 11 Nov 2024 18:38:39 +0300 Subject: [PATCH 01/48] [MM] Support hybrid build for JS and STS Support arkplatform as common library for JS and STS VMs Issue: https://gitee.com/openharmony/arkcompiler_runtime_core/issues/IB80F7 Testing: `ark.py` Signed-off-by: Petrov Igor --- build/compile_script/ark.py | 10 ++++++++++ build/core/gn/BUILD.gn | 18 ++++++++++++++++++ build/third_party_gn/libuv/BUILD.gn | 21 ++++++++++----------- 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/build/compile_script/ark.py b/build/compile_script/ark.py index c3fba732..f97fd3c3 100755 --- a/build/compile_script/ark.py +++ b/build/compile_script/ark.py @@ -228,6 +228,11 @@ class ArkPy: "description": "Compile arkcompiler target and run regresstest with arkcompiler target.", "gn_targets_depend_on": ["default"], }, + "hybrid": { + "flags": ["hybrid"], + "description": "Compile ArkJS and STS parts in hybrid mode.", + "gn_targets_depend_on": ["hybrid"], + }, "gn_target": { "flags": [""], # any other flags "description": @@ -1015,6 +1020,11 @@ class ArkPy: self.build_for_runtime_core_unittest(out_path, gn_args, self.RUNTIME_CORE_UNITTEST_LOG_FILE_NAME) elif self.is_dict_flags_match_arg(self.ARG_DICT.get("target").get("regresstest"), arg_list[0]): self.build_for_regress_test(out_path, gn_args, arg_list) + elif self.is_dict_flags_match_arg(self.ARG_DICT.get("target").get("hybrid"), arg_list[0]): + self.build_for_gn_target(out_path, + gn_args + ["ark_ets_hybrid=true", "ark_js_hybrid=true"], + self.ARG_DICT.get("target").get("hybrid").get("gn_targets_depend_on"), + self.GN_TARGET_LOG_FILE_NAME) else: self.build_for_gn_target(out_path, gn_args, arg_list, self.GN_TARGET_LOG_FILE_NAME) return diff --git a/build/core/gn/BUILD.gn b/build/core/gn/BUILD.gn index 8281cdfa..96b180d5 100644 --- a/build/core/gn/BUILD.gn +++ b/build/core/gn/BUILD.gn @@ -91,6 +91,24 @@ group("static_core") { "$ark_root/static_core/libpandabase:libarktsbase", "$ark_root/static_core/libpandafile:libarktsfile", ] + if (target_os != "mingw") { + deps += [ "$ark_root/static_core/runtime:libarkruntime" ] + } +} + +group("hybrid") { + deps = [ + ":ets_frontend", + ":ets_runtime", + ":static_core", + "$ark_root/static_core/plugins/ets:etsstdlib(${host_toolchain})", + ] + if (target_os != "mingw") { + deps += [ + "$ark_root/static_core/plugins/ets/runtime/interop_js:ets_interop_js_napi", + "$ark_root/static_core/tools/ark_js_napi_cli:ark_js_napi_cli", + ] + } } group("toolchain") { diff --git a/build/third_party_gn/libuv/BUILD.gn b/build/third_party_gn/libuv/BUILD.gn index 5bb82bb0..183cd2b4 100644 --- a/build/third_party_gn/libuv/BUILD.gn +++ b/build/third_party_gn/libuv/BUILD.gn @@ -66,10 +66,9 @@ config("libuv_config") { "-D_POSIX_C_SOURCE=200112", ] - # Adding NDEBUG macro manually to avoid compilation - # error in debug version, FIX ME - # https://gitee.com/openharmony/build/pulls/1206/files - defines += [ "NDEBUG" ] + if (!is_debug) { + defines += [ "NDEBUG" ] + } } else if (is_mingw || is_win) { cflags += [ "-Wno-missing-braces", @@ -127,13 +126,13 @@ ohos_source_set("libuv_source") { if (is_mac || (defined(is_ios) && is_ios)) { sources += nonwin_srcs + [ "//third_party/libuv/src/unix/bsd-ifaddrs.c", - "//third_party/libuv/src/unix/kqueue.c", - "//third_party/libuv/src/unix/random-getentropy.c", "//third_party/libuv/src/unix/darwin-proctitle.c", "//third_party/libuv/src/unix/darwin.c", "//third_party/libuv/src/unix/fsevents.c", - "//third_party/libuv/src/unix/os390-proctitle.c", + "//third_party/libuv/src/unix/kqueue.c", "//third_party/libuv/src/unix/log_unix.c", + "//third_party/libuv/src/unix/os390-proctitle.c", + "//third_party/libuv/src/unix/random-getentropy.c", "//third_party/libuv/src/unix/trace_unix.c", ] } else if (is_mingw || is_win) { @@ -170,10 +169,10 @@ ohos_source_set("libuv_source") { sources += nonwin_srcs + [ "//third_party/libuv/src/unix/linux.c", "//third_party/libuv/src/unix/procfs-exepath.c", + "//third_party/libuv/src/unix/proctitle.c", "//third_party/libuv/src/unix/random-getentropy.c", "//third_party/libuv/src/unix/random-getrandom.c", "//third_party/libuv/src/unix/random-sysctl-linux.c", - "//third_party/libuv/src/unix/proctitle.c", ] sources += [ "src/log_ohos.c", @@ -182,20 +181,20 @@ ohos_source_set("libuv_source") { } else if (is_linux) { sources += nonwin_srcs + [ "//third_party/libuv/src/unix/linux.c", + "//third_party/libuv/src/unix/log_unix.c", "//third_party/libuv/src/unix/procfs-exepath.c", + "//third_party/libuv/src/unix/proctitle.c", "//third_party/libuv/src/unix/random-getrandom.c", "//third_party/libuv/src/unix/random-sysctl-linux.c", - "//third_party/libuv/src/unix/proctitle.c", - "//third_party/libuv/src/unix/log_unix.c", "//third_party/libuv/src/unix/trace_unix.c", ] } else { sources += nonwin_srcs + [ "//third_party/libuv/src/unix/linux.c", "//third_party/libuv/src/unix/procfs-exepath.c", + "//third_party/libuv/src/unix/proctitle.c", "//third_party/libuv/src/unix/random-getrandom.c", "//third_party/libuv/src/unix/random-sysctl-linux.c", - "//third_party/libuv/src/unix/proctitle.c", ] } subsystem_name = "thirdparty" -- Gitee From 1a40964d7b019f8d4ca1520e2b74e8569bcf3c60 Mon Sep 17 00:00:00 2001 From: Petrov Igor Date: Thu, 19 Dec 2024 13:03:10 +0300 Subject: [PATCH 02/48] [Build] Set hybrid build as default Issue: https://gitee.com/openharmony/arkcompiler_runtime_core/issues/IBCEZI Testing: CI Signed-off-by: Petrov Igor --- build/compile_script/ark.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build/compile_script/ark.py b/build/compile_script/ark.py index f97fd3c3..77ab229f 100755 --- a/build/compile_script/ark.py +++ b/build/compile_script/ark.py @@ -325,6 +325,7 @@ class ArkPy: def libs_dir(is_arm, is_aot, is_pgo, out_dir, x64_out_dir) -> str: if is_arm and is_aot and is_pgo: return (f"--libs-dir ../../{out_dir}/arkcompiler/ets_runtime:" + f"../../{out_dir}/arkcompiler/runtime_core:" f"../../{out_dir}/thirdparty/icu:" f"../../{out_dir}/third_party/icu:" f"../../thirdparty/zlib:" @@ -334,6 +335,7 @@ class ArkPy: f":../../{x64_out_dir}/thirdparty/icu/") if not is_arm and is_aot: return (f"--libs-dir ../../{out_dir}/arkcompiler/ets_runtime" + f":../../{out_dir}/arkcompiler/runtime_core" f":../../{out_dir}/thirdparty/icu:" f"../../{out_dir}/third_party/icu:" f"../../thirdparty/zlib:" @@ -407,6 +409,7 @@ class ArkPy: f" --timeout {timeout}" \ f" --libs-dir ../../{out_path}/arkcompiler/ets_runtime:../../{out_path}/thirdparty/icu:" \ f"../../{out_path}/thirdparty/zlib:../../prebuilts/clang/ohos/linux-x86_64/llvm/lib" \ + f":../../{out_path}/arkcompiler/runtime_core" \ " --ark-arch aarch64" \ f" --ark-arch-root=../../{out_path}/common/common/libc/" \ f" --ark-tool=../../{out_path}/arkcompiler/ets_runtime/ark_js_vm" \ @@ -433,6 +436,7 @@ class ArkPy: f" --timeout {timeout}" \ f" --libs-dir ../../{out_path}/arkcompiler/ets_runtime:../../{out_path}/thirdparty/icu" \ f":../../{out_path}/thirdparty/zlib:../../prebuilts/clang/ohos/linux-x86_64/llvm/lib" \ + f":../../{out_path}/arkcompiler/runtime_core" \ f" --ark-tool=../../{out_path}/arkcompiler/ets_runtime/ark_js_vm" \ f" --ark-aot-tool=../../{out_path}/arkcompiler/ets_runtime/ark_aot_compiler" \ f" --ark-frontend-binary=../../{out_path}/arkcompiler/ets_frontend/es2abc" \ @@ -453,6 +457,7 @@ class ArkPy: f" --libs-dir ../../prebuilts/clang/ohos/linux-x86_64/llvm/lib:../../{out_path}/thirdparty/icu/" \ f":../../{out_path}/thirdparty/bounds_checking_function" \ f":../../{out_path}/arkcompiler/ets_runtime:" \ + f"../../{out_path}/arkcompiler/runtime_core:" \ " --ark-arch aarch64" \ " --run-jit" \ f" --ark-arch-root=../../{out_path}/common/common/libc/" \ @@ -465,6 +470,7 @@ class ArkPy: cmd = f"cd arkcompiler/ets_frontend && python3 {test_script_name} {args_to_cmd} --timeout {timeout}" \ f" --libs-dir ../../{out_path}/arkcompiler/ets_runtime:../../{out_path}/thirdparty/icu" \ f":../../{out_path}/thirdparty/zlib:../../prebuilts/clang/ohos/linux-x86_64/llvm/lib" \ + f":../../{out_path}/arkcompiler/runtime_core" \ " --run-jit" \ f" --ark-tool=../../{out_path}/arkcompiler/ets_runtime/ark_js_vm" \ f" --ark-frontend-binary=../../{out_path}/arkcompiler/ets_frontend/es2abc" \ -- Gitee From 570f5cc9996dbbe03a4ef219341bf6dfec0e905e Mon Sep 17 00:00:00 2001 From: Tao Wu Date: Tue, 7 Jan 2025 21:43:40 +0800 Subject: [PATCH 03/48] Standalone build for static linker Support building static linker for Linux, Windows and OHOS by standalone build. Issue: https://gitee.com/openharmony/arkcompiler_runtime_core/issues/IBGBHL Signed-off-by: Tao Wu Change-Id: I94121910dca88382a319846962efed977bc427d2 --- build/core/gn/BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/build/core/gn/BUILD.gn b/build/core/gn/BUILD.gn index 96b180d5..de909824 100644 --- a/build/core/gn/BUILD.gn +++ b/build/core/gn/BUILD.gn @@ -90,6 +90,7 @@ group("static_core") { "$ark_root/static_core/compiler:libarktscompiler", "$ark_root/static_core/libpandabase:libarktsbase", "$ark_root/static_core/libpandafile:libarktsfile", + "$ark_root/static_core/static_linker:static_linker", ] if (target_os != "mingw") { deps += [ "$ark_root/static_core/runtime:libarkruntime" ] -- Gitee From ebc72fe854e632bea4536ac3e3ab2e28ed372696 Mon Sep 17 00:00:00 2001 From: kurnevichstanislav Date: Tue, 17 Dec 2024 18:19:20 +0300 Subject: [PATCH 04/48] Add interop gtests helper to hybrid build group Issue: https://gitee.com/openharmony/arkcompiler_toolchain/issues/IBBYSB?from=project-issue Signed-off-by: kurnevichstanislav Change-Id: I23fba18cb26a4d1989a8ed864ba6428a56989143 --- build/compile_script/ark.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/build/compile_script/ark.py b/build/compile_script/ark.py index 77ab229f..60035a4c 100755 --- a/build/compile_script/ark.py +++ b/build/compile_script/ark.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- # -# Copyright (c) 2022-2024 Huawei Device Co., Ltd. +# Copyright (c) 2022-2025 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 @@ -229,9 +229,9 @@ class ArkPy: "gn_targets_depend_on": ["default"], }, "hybrid": { - "flags": ["hybrid"], + "flags": ["hybrid", "hybrid_tests"], "description": "Compile ArkJS and STS parts in hybrid mode.", - "gn_targets_depend_on": ["hybrid"], + "gn_targets_depend_on": [], }, "gn_target": { "flags": [""], # any other flags @@ -1027,9 +1027,10 @@ class ArkPy: elif self.is_dict_flags_match_arg(self.ARG_DICT.get("target").get("regresstest"), arg_list[0]): self.build_for_regress_test(out_path, gn_args, arg_list) elif self.is_dict_flags_match_arg(self.ARG_DICT.get("target").get("hybrid"), arg_list[0]): + targets = arg_list self.build_for_gn_target(out_path, gn_args + ["ark_ets_hybrid=true", "ark_js_hybrid=true"], - self.ARG_DICT.get("target").get("hybrid").get("gn_targets_depend_on"), + targets, self.GN_TARGET_LOG_FILE_NAME) else: self.build_for_gn_target(out_path, gn_args, arg_list, self.GN_TARGET_LOG_FILE_NAME) -- Gitee From dcaae8c7ee0d775a47d4340e47e33b54d3d6f761 Mon Sep 17 00:00:00 2001 From: Artem Udovichenko Date: Fri, 24 Jan 2025 10:56:23 +0300 Subject: [PATCH 05/48] Fix stacktrace printing Issue: https://gitee.com/openharmony/arkcompiler_runtime_core/issues/IBJE1G Change-Id: Ia7b3dce273ab693a7bbe709b01b750c637838b18 Signed-off-by: Artem Udovichenko --- BUILD.gn | 3 +++ 1 file changed, 3 insertions(+) diff --git a/BUILD.gn b/BUILD.gn index 6e6df7b9..e49e8430 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -169,12 +169,14 @@ config("ark_toolchain_common_config") { cflags_cc += [ "-O3", "-ggdb3", + "-gdwarf-4", "-fno-omit-frame-pointer", "-D_GLIBCXX_ASSERTIONS", ] cflags_c += [ "-O3", "-ggdb3", + "-gdwarf-4", "-fno-omit-frame-pointer", "-D_GLIBCXX_ASSERTIONS", ] @@ -182,6 +184,7 @@ config("ark_toolchain_common_config") { cflags_cc += [ "-O0", "-ggdb3", + "-gdwarf-4", ] } else { defines += [ "NDEBUG" ] -- Gitee From 984b58424f9b1ef1129a36ef8bb51c96babd8cf2 Mon Sep 17 00:00:00 2001 From: lijunru Date: Wed, 19 Feb 2025 20:34:07 +0800 Subject: [PATCH 06/48] Add lsp build target Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/IBP1PP Signed-off-by: lijunru --- build/core/gn/BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/build/core/gn/BUILD.gn b/build/core/gn/BUILD.gn index de909824..6dc3d457 100644 --- a/build/core/gn/BUILD.gn +++ b/build/core/gn/BUILD.gn @@ -72,6 +72,7 @@ group("ets_frontend") { target_os == "mac") { deps = [ "$ets_frontend_root/es2panda:es2panda", + "$ets_frontend_root/ets2panda/lsp:lsp_packages", "$ets_frontend_root/merge_abc:merge_abc", ] } -- Gitee From 950bc17f0a9c62ddccb7174db1f44a6d81901281 Mon Sep 17 00:00:00 2001 From: wengchangcheng Date: Thu, 13 Mar 2025 15:52:19 +0800 Subject: [PATCH 07/48] add base_runtime Issue: https://gitee.com/openharmony/arkcompiler_toolchain/issues/IBT461 Signed-off-by: wengchangcheng Change-Id: Ie249c562b99b8a2cc1e775fed2b8688f0d22a7ab --- BUILD.gn | 5 ++++- build/core/gn/BUILD.gn | 7 ++++++- build/templates/cxx/external_deps_handler.py | 6 +++++- toolchain_config.gni | 3 ++- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/BUILD.gn b/BUILD.gn index e49e8430..18f559fb 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022 Huawei Device Co., Ltd. +# Copyright (c) 2021-2025 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 @@ -274,6 +274,9 @@ group("ark_js_host_unittest") { "//arkcompiler/ets_runtime:ark_runtime_host_unittest", "//arkcompiler/toolchain:ark_toolchain_host_unittest", ] + if (ark_standalone_build) { + deps += [ "$base_root:base_runtime_host_unittest" ] + } } group("runtime_core_host_ut") { diff --git a/build/core/gn/BUILD.gn b/build/core/gn/BUILD.gn index 6dc3d457..e97716b5 100644 --- a/build/core/gn/BUILD.gn +++ b/build/core/gn/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2022 Huawei Device Co., Ltd. +# Copyright (c) 2022-2025 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 @@ -28,6 +28,7 @@ print() group("default") { deps = [ + ":base_runtime", ":ets_frontend", ":ets_runtime", ":runtime_core", @@ -130,3 +131,7 @@ group("toolchain") { ] } } + +group("base_runtime") { + deps = [ "$base_root:libbase_runtime" ] +} diff --git a/build/templates/cxx/external_deps_handler.py b/build/templates/cxx/external_deps_handler.py index 82107af7..a449aeda 100755 --- a/build/templates/cxx/external_deps_handler.py +++ b/build/templates/cxx/external_deps_handler.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- # -# Copyright (c) 2022 Huawei Device Co., Ltd. +# Copyright (c) 2022-2025 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 @@ -92,6 +92,10 @@ def main(): config_info = read_json_file("{}arkcompiler/ets_runtime/bundle.json".format(args.root_src_dir)) target_name = dep.split(":")[1] deps.append(get_full_path_from_target_name(config_info, target_name)) + elif dep.startswith("base_runtime"): + config_info = read_json_file("{}arkcompiler/base_runtime/bundle.json".format(args.root_src_dir)) + target_name = dep.split(":")[1] + deps.append(get_full_path_from_target_name(config_info, target_name)) elif dep.startswith("runtime_core"): config_info = read_json_file("{}arkcompiler/runtime_core/bundle.json".format(args.root_src_dir)) target_name = dep.split(":")[1] diff --git a/toolchain_config.gni b/toolchain_config.gni index e02bd052..e5dde911 100644 --- a/toolchain_config.gni +++ b/toolchain_config.gni @@ -1,4 +1,4 @@ -# Copyright (c) 2022 Huawei Device Co., Ltd. +# Copyright (c) 2022-2025 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 @@ -31,6 +31,7 @@ if (!ark_standalone_build) { } ark_root = "//arkcompiler/runtime_core" js_root = "//arkcompiler/ets_runtime" +base_root = "//arkcompiler/base_runtime" global_root = "//base/global/i18n" hilog_root = "//base/hiviewdfx/hilog/interfaces/native/innerkits" qos_root = "//foundation/resourceschedule/qos_manager" -- Gitee From 5451f68f99eabf6e5d711ce0ef9dca21c67475a7 Mon Sep 17 00:00:00 2001 From: lukai Date: Wed, 19 Mar 2025 10:55:54 +0800 Subject: [PATCH 08/48] Merge remote-tracking branch 'openharmony/master' Merge remote-tracking branch 'openharmony/master' into fr1108 Squashed Issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IBUITJ Signed-off-by: lukai Change-Id: Iffc3a055448abca8aa84fb4d67a59d40c4ff7818 --- tooling/agent/debugger_impl.cpp | 232 ++++++++++++++---- tooling/agent/debugger_impl.h | 36 ++- tooling/backend/js_pt_hooks.cpp | 17 +- tooling/backend/js_pt_hooks.h | 1 + tooling/base/pt_events.cpp | 9 + tooling/base/pt_events.h | 7 + tooling/base/pt_json.cpp | 16 ++ tooling/base/pt_json.h | 3 + tooling/base/pt_params.cpp | 61 +++++ tooling/base/pt_params.h | 40 +++ tooling/base/pt_returns.h | 4 +- tooling/base/pt_script.h | 11 + tooling/base/pt_types.cpp | 12 + tooling/base/pt_types.h | 11 + tooling/client/domain/debugger_client.cpp | 55 +++++ tooling/client/domain/debugger_client.h | 2 + tooling/client/utils/cli_command.cpp | 9 + tooling/client/utils/cli_command.h | 1 + tooling/test/client_utils/test_list.cpp | 2 + tooling/test/debugger_impl_test.cpp | 37 +++ tooling/test/debugger_params_test.cpp | 39 +++ tooling/test/debugger_returns_test.cpp | 8 +- tooling/test/debugger_script_test.cpp | 12 + tooling/test/pt_json_test.cpp | 11 + .../testcases/js_accelerate_launch_test.h | 131 ++++++++++ tooling/test/utils/test_hooks.h | 2 + 26 files changed, 704 insertions(+), 65 deletions(-) create mode 100644 tooling/test/testcases/js_accelerate_launch_test.h diff --git a/tooling/agent/debugger_impl.cpp b/tooling/agent/debugger_impl.cpp index 4d111cb5..69e12052 100755 --- a/tooling/agent/debugger_impl.cpp +++ b/tooling/agent/debugger_impl.cpp @@ -88,51 +88,49 @@ bool DebuggerImpl::NotifyScriptParsed(const std::string &fileName, std::string_v return false; } + if (!vm_->GetJsDebuggerManager()->GetFaApp() && jsPandaFile->IsBundlePack()) { + LOG_DEBUGGER(DEBUG) << "NotifyScriptParsed: Unmerge file: " << fileName; + return false; + } + const char *recordName = entryPoint.data(); auto mainMethodIndex = panda_file::File::EntityId(jsPandaFile->GetMainMethodIndex(recordName)); const std::string &source = extractor->GetSourceCode(mainMethodIndex); const std::string &url = extractor->GetSourceFile(mainMethodIndex); - - recordNames_[url].insert(recordName); - // if load module, it needs to check whether clear singlestepper_ ClearSingleStepper(); if (MatchUrlAndFileName(url, fileName)) { + LOG_DEBUGGER(WARN) << "DebuggerImpl::NotifyScriptParsed: Script already been parsed: " + << "url: " << url << " fileName: " << fileName; return false; } - urlFileNameMap_[url].insert(fileName); - // Notify script parsed event - std::unique_ptr script = std::make_unique(g_scriptId++, fileName, url, source); - - frontend_.ScriptParsed(vm_, *script); - - // Store parsed script in map - scripts_[script->GetScriptId()] = std::move(script); + SaveParsedScriptsAndUrl(fileName, url, recordName, source); return true; } -bool DebuggerImpl::SendableScriptParsed(const std::string &fileName, const std::string &url, - const std::string &source, const std::string &recordName) +std::vector> DebuggerImpl::SetBreakpointsWhenParsingScript(const std::string &url) { - if (!CheckScriptParsed(fileName)) { - return false; + std::vector> outLocations {}; + for (const auto &breakpoint : breakpointPendingMap_[url]) { + if (!ProcessSingleBreakpoint(*breakpoint, outLocations)) { + std::string invalidBpId = "invalid"; + std::shared_ptr bpInfo = std::make_shared(); + bpInfo->SetId(invalidBpId) + .SetLineNumber(breakpoint->GetLineNumber()) + .SetColumnNumber(breakpoint->GetColumnNumber()); + outLocations.emplace_back(bpInfo); + } } + return outLocations; +} - recordNames_[url].insert(recordName); - - // if load module, it needs to check whether clear singlestepper_ - ClearSingleStepper(); - - urlFileNameMap_[url].insert(fileName); - // Notify script parsed event - std::unique_ptr script = std::make_unique(g_scriptId++, fileName, url, source); - - frontend_.ScriptParsed(vm_, *script); - - // Store parsed script in map - scripts_[script->GetScriptId()] = std::move(script); - return true; +bool DebuggerImpl::NeedToSetBreakpointsWhenParsingScript(const std::string &url) +{ + if (breakpointPendingMap_.find(url) != breakpointPendingMap_.end()) { + return !breakpointPendingMap_[url].empty(); + } + return false; } bool DebuggerImpl::CheckScriptParsed([[maybe_unused]] const std::string &fileName) @@ -146,7 +144,7 @@ bool DebuggerImpl::CheckScriptParsed([[maybe_unused]] const std::string &fileNam } #endif - // The release application does not require scriptParsed + // check if Debugable flag is true in module.json if (!vm_->GetJsDebuggerManager()->IsDebugApp()) { return false; } @@ -154,8 +152,27 @@ bool DebuggerImpl::CheckScriptParsed([[maybe_unused]] const std::string &fileNam return true; } -bool DebuggerImpl::SendableMethodEntry(JSHandle method) +void DebuggerImpl::SaveParsedScriptsAndUrl(const std::string &fileName, const std::string &url, + const std::string &recordName, const std::string &source) +{ + // Save recordName to its corresponding url + recordNames_[url].insert(recordName); + // Save parsed fileName to its corresponding url + urlFileNameMap_[url].insert(fileName); + // Create and save script + std::shared_ptr script = std::make_shared(g_scriptId++, fileName, url, source); + scripts_[script->GetScriptId()] = script; + // Check if is launch accelerate mode & has pending bps to set + if (IsLaunchAccelerateMode() && NeedToSetBreakpointsWhenParsingScript(url)) { + script->SetLocations(SetBreakpointsWhenParsingScript(url)); + } + // Notify frontend ScriptParsed event + frontend_.ScriptParsed(vm_, *script); +} + +bool DebuggerImpl::NotifyScriptParsedBySendable(JSHandle method) { + // Find extractor and retrieve infos const JSPandaFile *jsPandaFile = method->GetJSPandaFile(); if (jsPandaFile == nullptr) { LOG_DEBUGGER(ERROR) << "JSPandaFile is nullptr"; @@ -169,14 +186,23 @@ bool DebuggerImpl::SendableMethodEntry(JSHandle method) auto methodId = method->GetMethodId(); const std::string &url = extractor->GetSourceFile(methodId); const std::string &fileName = std::string(jsPandaFile->GetJSPandaFileDesc()); - if (!MatchUrlAndFileName(url, fileName)) { - // scriptParsed - const std::string &source = extractor->GetSourceCode(methodId); - const std::string &recordName = std::string(method->GetRecordNameStr()); - SendableScriptParsed(fileName, url, source, recordName); - return true; + // Check url path & is debugable in module.json + if (!CheckScriptParsed(fileName)) { + return false; } - return false; + // Clear SingleStepper before notify + ClearSingleStepper(); + // Check if this (url, fileName) pair has already been parsed + if (MatchUrlAndFileName(url, fileName)) { + LOG_DEBUGGER(WARN) << "DebuggerImpl::NotifyScriptParsedBySendable: Script already been parsed: " + << "url: " << url << " fileName: " << fileName; + return false; + } + // Parse and save this file + const std::string &source = extractor->GetSourceCode(methodId); + const std::string &recordName = std::string(method->GetRecordNameStr()); + SaveParsedScriptsAndUrl(fileName, url, recordName, source); + return true; } bool DebuggerImpl::MatchUrlAndFileName(const std::string &url, const std::string &fileName) @@ -184,7 +210,6 @@ bool DebuggerImpl::MatchUrlAndFileName(const std::string &url, const std::string auto urlFileNameIter = urlFileNameMap_.find(url); if (urlFileNameIter != urlFileNameMap_.end()) { if (urlFileNameIter->second.find(fileName) != urlFileNameIter->second.end()) { - LOG_DEBUGGER(WARN) << "MatchUrlAndFileName: already loaded: " << url; return true; } } @@ -449,7 +474,8 @@ void DebuggerImpl::InitializeExtendedProtocolsList() "setNativeRange", "resetSingleStepper", "callFunctionOn", - "smartStepInto" + "smartStepInto", + "saveAllPossibleBreakpoints" }; debuggerExtendedProtocols_ = std::move(debuggerProtocolList); } @@ -543,6 +569,9 @@ void DebuggerImpl::DispatcherImpl::Dispatch(const DispatchRequest &request) case Method::CALL_FUNCTION_ON: CallFunctionOn(request); break; + case Method::SAVE_ALL_POSSIBLE_BREAKPOINTS: + SaveAllPossibleBreakpoints(request); + break; default: SendResponse(request, DispatchResponse::Fail("Unknown method: " + request.GetMethod())); break; @@ -607,6 +636,8 @@ DebuggerImpl::DispatcherImpl::Method DebuggerImpl::DispatcherImpl::GetMethodEnum return Method::CLIENT_DISCONNECT; } else if (method == "callFunctionOn") { return Method::CALL_FUNCTION_ON; + } else if (method == "saveAllPossibleBreakpoints") { + return Method::SAVE_ALL_POSSIBLE_BREAKPOINTS; } else { return Method::UNKNOWN; } @@ -771,12 +802,24 @@ void DebuggerImpl::DispatcherImpl::GetPossibleAndSetBreakpointByUrl(const Dispat return; } - std::vector> outLocation; + std::vector> outLocation; DispatchResponse response = debugger_->GetPossibleAndSetBreakpointByUrl(*params, outLocation); GetPossibleAndSetBreakpointByUrlReturns result(std::move(outLocation)); SendResponse(request, response, result); } +void DebuggerImpl::DispatcherImpl::SaveAllPossibleBreakpoints(const DispatchRequest &request) +{ + std::unique_ptr params = + SaveAllPossibleBreakpointsParams::Create(request.GetParams()); + if (params == nullptr) { + SendResponse(request, DispatchResponse::Fail("wrong params")); + return; + } + DispatchResponse response = debugger_->SaveAllPossibleBreakpoints(*params); + SendResponse(request, response); +} + void DebuggerImpl::DispatcherImpl::SetPauseOnExceptions(const DispatchRequest &request) { std::unique_ptr params = SetPauseOnExceptionsParams::Create(request.GetParams()); @@ -1008,7 +1051,8 @@ void DebuggerImpl::Frontend::ScriptParsed(const EcmaVM *vm, const PtScript &scri .SetEndLine(script.GetEndLine()) .SetEndColumn(0) .SetExecutionContextId(0) - .SetHash(script.GetHash()); + .SetHash(script.GetHash()) + .SetLocations(script.GetLocations()); channel_->SendNotification(scriptParsed); } @@ -1045,6 +1089,8 @@ DispatchResponse DebuggerImpl::Enable([[maybe_unused]] const EnableParams ¶m ASSERT(id != nullptr); *id = 0; vm_->GetJsDebuggerManager()->SetDebugMode(true); + // Enable corresponding features requested by IDE + EnableDebuggerFeatures(params); for (auto &script : scripts_) { frontend_.ScriptParsed(vm_, *script.second); } @@ -1052,6 +1098,42 @@ DispatchResponse DebuggerImpl::Enable([[maybe_unused]] const EnableParams ¶m return DispatchResponse::Ok(); } +void DebuggerImpl::EnableDebuggerFeatures(const EnableParams ¶ms) +{ + if (!params.HasEnableOptionsList()) { + return; + } + auto enableOptionsList = params.GetEnableOptionsList(); + if (enableOptionsList.empty()) { + return; + } + for (auto &option : enableOptionsList) { + LOG_DEBUGGER(INFO) << "Debugger feature " << option << " is enabled"; + EnableFeature(GetDebuggerFeatureEnum(option)); + } +} + +DebuggerFeature DebuggerImpl::GetDebuggerFeatureEnum(std::string &option) +{ + if (option == "enableLaunchAccelerate") { + return DebuggerFeature::LAUNCH_ACCELERATE; + } + // Future features could be added here to parse as DebuggerFeatureEnum + return DebuggerFeature::UNKNOWN; +} + +void DebuggerImpl::EnableFeature(DebuggerFeature feature) +{ + switch (feature) { + case DebuggerFeature::LAUNCH_ACCELERATE: + EnableLaunchAccelerateMode(); + DebuggerApi::DisableFirstTimeFlag(jsDebugger_); + break; + default: + break; + } +} + DispatchResponse DebuggerImpl::Disable() { DebuggerApi::RemoveAllBreakpoints(jsDebugger_); @@ -1206,6 +1288,9 @@ DispatchResponse DebuggerImpl::RemoveBreakpointsByUrl(const RemoveBreakpointsByU } LOG_DEBUGGER(INFO) << "All breakpoints on " << url << " are removed"; + if (IsLaunchAccelerateMode()) { + breakpointPendingMap_.erase(url); + } return DispatchResponse::Ok(); } @@ -1300,7 +1385,7 @@ DispatchResponse DebuggerImpl::SetBreakpointsActive(const SetBreakpointsActivePa } DispatchResponse DebuggerImpl::GetPossibleAndSetBreakpointByUrl(const GetPossibleAndSetBreakpointParams ¶ms, - std::vector> &outLocations) + std::vector> &outLocations) { if (!vm_->GetJsDebuggerManager()->IsDebugMode()) { return DispatchResponse::Fail("GetPossibleAndSetBreakpointByUrl: debugger agent is not enabled"); @@ -1312,18 +1397,69 @@ DispatchResponse DebuggerImpl::GetPossibleAndSetBreakpointByUrl(const GetPossibl for (const auto &breakpoint : *breakpointList) { if (!ProcessSingleBreakpoint(*breakpoint, outLocations)) { std::string invalidBpId = "invalid"; - std::unique_ptr bpInfo = std::make_unique(); + std::shared_ptr bpInfo = std::make_shared(); bpInfo->SetId(invalidBpId) .SetLineNumber(breakpoint->GetLineNumber()) .SetColumnNumber(breakpoint->GetColumnNumber()); - outLocations.emplace_back(std::move(bpInfo)); + outLocations.emplace_back(bpInfo); + } + // Insert this bp into bp pending map + if (IsLaunchAccelerateMode()) { + InsertIntoPendingBreakpoints(*breakpoint); } } return DispatchResponse::Ok(); } +bool DebuggerImpl::InsertIntoPendingBreakpoints(const BreakpointInfo &breakpoint) +{ + auto condition = breakpoint.HasCondition() ? breakpoint.GetCondition() : std::optional {}; + auto bpShared = BreakpointInfo::CreateAsSharedPtr(breakpoint.GetLineNumber(), breakpoint.GetColumnNumber(), + breakpoint.GetUrl(), (condition.has_value() ? condition.value() : "")); + if (breakpointPendingMap_.empty() || + breakpointPendingMap_.find(breakpoint.GetUrl()) == breakpointPendingMap_.end()) { + CUnorderedSet, HashBreakpointInfo> set {}; + set.insert(bpShared); + breakpointPendingMap_[breakpoint.GetUrl()] = set; + return true; + } + return (breakpointPendingMap_[breakpoint.GetUrl()].insert(bpShared)).second; +} + +DispatchResponse DebuggerImpl::SaveAllPossibleBreakpoints(const SaveAllPossibleBreakpointsParams ¶ms) +{ + if (!vm_->GetJsDebuggerManager()->IsDebugMode()) { + return DispatchResponse::Fail("SaveAllPossibleBreakpoints: debugger agent is not enabled"); + } + if (!IsLaunchAccelerateMode()) { + return DispatchResponse::Fail("SaveAllPossibleBreakpoints: protocol is not enabled"); + } + if (!params.HasBreakpointsMap()) { + return DispatchResponse::Fail("SaveAllPossibleBreakpoints: no pending breakpoint exists"); + } + SavePendingBreakpoints(params); + return DispatchResponse::Ok(); +} + +void DebuggerImpl::SavePendingBreakpoints(const SaveAllPossibleBreakpointsParams ¶ms) +{ + for (const auto &entry : *(params.GetBreakpointsMap())) { + if (breakpointPendingMap_.find(entry.first) == breakpointPendingMap_.end()) { + CUnorderedSet, HashBreakpointInfo> set {}; + for (auto &info : entry.second) { + set.insert(info); + } + breakpointPendingMap_[entry.first] = set; + } else { + for (auto &info : entry.second) { + breakpointPendingMap_[entry.first].insert(info); + } + } + } +} + bool DebuggerImpl::ProcessSingleBreakpoint(const BreakpointInfo &breakpoint, - std::vector> &outLocations) + std::vector> &outLocations) { const std::string &url = breakpoint.GetUrl(); int32_t lineNumber = breakpoint.GetLineNumber(); @@ -1367,9 +1503,9 @@ bool DebuggerImpl::ProcessSingleBreakpoint(const BreakpointInfo &breakpoint, BreakpointDetails bpMetaData {lineNumber, 0, url}; std::string outId = BreakpointDetails::ToString(bpMetaData); - std::unique_ptr bpInfo = std::make_unique(); + std::shared_ptr bpInfo = std::make_unique(); bpInfo->SetScriptId(scriptId).SetLineNumber(lineNumber).SetColumnNumber(0).SetId(outId); - outLocations.emplace_back(std::move(bpInfo)); + outLocations.emplace_back(bpInfo); return true; } diff --git a/tooling/agent/debugger_impl.h b/tooling/agent/debugger_impl.h index c8b35633..9fd14336 100644 --- a/tooling/agent/debugger_impl.h +++ b/tooling/agent/debugger_impl.h @@ -32,6 +32,7 @@ class TestHooks; } // namespace test enum class DebuggerState { DISABLED, ENABLED, PAUSED }; +enum class DebuggerFeature { LAUNCH_ACCELERATE, UNKNOWN }; class DebuggerImpl final { public: DebuggerImpl(const EcmaVM *vm, ProtocolChannel *channel, RuntimeImpl *runtime); @@ -40,10 +41,8 @@ public: // event bool NotifyScriptParsed(const std::string &fileName, std::string_view entryPoint = "func_main_0"); - bool SendableScriptParsed(const std::string &fileName, const std::string &url, - const std::string &source, const std::string &recordName); bool CheckScriptParsed(const std::string &fileName); - bool SendableMethodEntry(JSHandle method); + bool NotifyScriptParsedBySendable(JSHandle method); bool MatchUrlAndFileName(const std::string &url, const std::string &fileName); bool NotifySingleStep(const JSPtLocation &location); void NotifyPaused(std::optional location, PauseReason reason); @@ -79,7 +78,7 @@ public: bool isSmartBreakpoint = false); DispatchResponse SetBreakpointsActive(const SetBreakpointsActiveParams ¶ms); DispatchResponse GetPossibleAndSetBreakpointByUrl(const GetPossibleAndSetBreakpointParams ¶ms, - std::vector> &outLocations); + std::vector> &outLocations); DispatchResponse SetPauseOnExceptions(const SetPauseOnExceptionsParams ¶ms); DispatchResponse SetSkipAllPauses(const SetSkipAllPausesParams ¶ms); DispatchResponse SetNativeRange(const SetNativeRangeParams ¶ms); @@ -97,7 +96,7 @@ public: const CallFunctionOnParams ¶ms, std::unique_ptr *outRemoteObject, std::optional> *outExceptionDetails); - + DispatchResponse SaveAllPossibleBreakpoints(const SaveAllPossibleBreakpointsParams ¶ms); /** * @brief: match first script and callback * @@ -179,6 +178,7 @@ public: void DropFrame(const DispatchRequest &request); void ClientDisconnect(const DispatchRequest &request); void CallFunctionOn(const DispatchRequest &request); + void SaveAllPossibleBreakpoints(const DispatchRequest &request); enum class Method { CONTINUE_TO_LOCATION, @@ -209,6 +209,7 @@ public: RESET_SINGLE_STEPPER, CLIENT_DISCONNECT, CALL_FUNCTION_ON, + SAVE_ALL_POSSIBLE_BREAKPOINTS, UNKNOWN }; Method GetMethodEnum(const std::string& method); @@ -252,10 +253,19 @@ private: bool CheckPauseOnException(); bool IsWithinVariableScope(const LocalVariableInfo &localVariableInfo, uint32_t bcOffset); bool ProcessSingleBreakpoint(const BreakpointInfo &breakpoint, - std::vector> &outLocations); + std::vector> &outLocations); bool IsVariableSkipped(const std::string &varName); Local CheckAndGenerateCondFunc(const std::optional &condition); void InitializeExtendedProtocolsList(); + bool NeedToSetBreakpointsWhenParsingScript(const std::string &url); + std::vector> SetBreakpointsWhenParsingScript(const std::string &url); + void SavePendingBreakpoints(const SaveAllPossibleBreakpointsParams ¶ms); + bool InsertIntoPendingBreakpoints(const BreakpointInfo &breakpoint); + void SaveParsedScriptsAndUrl(const std::string &fileName, const std::string &url, + const std::string &recordName, const std::string &source = ""); + void EnableDebuggerFeatures(const EnableParams ¶ms); + DebuggerFeature GetDebuggerFeatureEnum(std::string &option); + void EnableFeature(DebuggerFeature feature); const std::unordered_set &GetRecordName(const std::string &url) { @@ -266,6 +276,14 @@ private: } return recordName; } + void EnableLaunchAccelerateMode() + { + breakOnStartEnable_ = false; + } + bool IsLaunchAccelerateMode() const + { + return !breakOnStartEnable_; + } class Frontend { public: @@ -297,7 +315,7 @@ private: std::unordered_map> recordNames_ {}; std::unordered_map> urlFileNameMap_ {}; - std::unordered_map> scripts_ {}; + std::unordered_map> scripts_ {}; PauseOnExceptionsState pauseOnException_ {PauseOnExceptionsState::NONE}; DebuggerState debuggerState_ {DebuggerState::ENABLED}; bool pauseOnNextByteCode_ {false}; @@ -319,6 +337,10 @@ private: JsDebuggerManager::SingleStepperFunc stepperFunc_ {nullptr}; JsDebuggerManager::ReturnNativeFunc returnNative_ {nullptr}; std::vector debuggerExtendedProtocols_ {}; + // For launch accelerate mode + std::unordered_map, HashBreakpointInfo>> + breakpointPendingMap_ {}; + bool breakOnStartEnable_ {true}; friend class JSPtHooks; friend class test::TestHooks; diff --git a/tooling/backend/js_pt_hooks.cpp b/tooling/backend/js_pt_hooks.cpp index b704d8b6..4c484ed4 100644 --- a/tooling/backend/js_pt_hooks.cpp +++ b/tooling/backend/js_pt_hooks.cpp @@ -84,7 +84,9 @@ void JSPtHooks::LoadModule(std::string_view pandaFileName, std::string_view entr [[maybe_unused]] LocalScope scope(debugger_->vm_); if (debugger_->NotifyScriptParsed(pandaFileName.data(), entryPoint)) { - firstTime_ = true; + if (!debugger_->IsLaunchAccelerateMode()) { + firstTime_ = true; + } } } @@ -110,8 +112,15 @@ void JSPtHooks::SendableMethodEntry(JSHandle method) [[maybe_unused]] LocalScope scope(debugger_->vm_); - if (debugger_->SendableMethodEntry(method)) { - firstTime_ = true; - }; + if (debugger_->NotifyScriptParsedBySendable(method)) { + if (!debugger_->IsLaunchAccelerateMode()) { + firstTime_ = true; + } + } +} + +void JSPtHooks::DisableFirstTimeFlag() +{ + firstTime_ = false; } } // namespace panda::ecmascript::tooling diff --git a/tooling/backend/js_pt_hooks.h b/tooling/backend/js_pt_hooks.h index a8429053..58c76e4f 100644 --- a/tooling/backend/js_pt_hooks.h +++ b/tooling/backend/js_pt_hooks.h @@ -41,6 +41,7 @@ public: void VmStart() override {} void VmDeath() override {} void SendableMethodEntry(JSHandle method) override; + void DisableFirstTimeFlag() override; private: NO_COPY_SEMANTIC(JSPtHooks); diff --git a/tooling/base/pt_events.cpp b/tooling/base/pt_events.cpp index 88f7ef01..f3a4e608 100644 --- a/tooling/base/pt_events.cpp +++ b/tooling/base/pt_events.cpp @@ -191,6 +191,15 @@ std::unique_ptr ScriptParsed::ToJson() const result->Add("embedderName", embedderName_->c_str()); } + std::unique_ptr array = PtJson::CreateArray(); + size_t len = locations_.size(); + for (size_t i = 0; i < len; i++) { + ASSERT(locations_[i] != nullptr); + std::unique_ptr location = locations_[i]->ToJson(); + array->Push(location); + } + result->Add("locations", array); + std::unique_ptr object = PtJson::CreateObject(); object->Add("method", GetName().c_str()); object->Add("params", result); diff --git a/tooling/base/pt_events.h b/tooling/base/pt_events.h index 47aa85d5..9d1bea7e 100644 --- a/tooling/base/pt_events.h +++ b/tooling/base/pt_events.h @@ -808,6 +808,12 @@ public: return embedderName_.has_value(); } + ScriptParsed &SetLocations(std::vector> locations) + { + locations_ = locations; + return *this; + } + private: NO_COPY_SEMANTIC(ScriptParsed); NO_MOVE_SEMANTIC(ScriptParsed); @@ -829,6 +835,7 @@ private: std::optional codeOffset_ {}; std::optional scriptLanguage_ {}; std::optional embedderName_ {}; + std::vector> locations_ {}; }; class AddHeapSnapshotChunk final : public PtBaseEvents { diff --git a/tooling/base/pt_json.cpp b/tooling/base/pt_json.cpp index 94b592e7..d265606c 100644 --- a/tooling/base/pt_json.cpp +++ b/tooling/base/pt_json.cpp @@ -249,6 +249,22 @@ std::string PtJson::GetKey() const return std::string(object_->string); } +std::vector PtJson::GetKeysArray() const +{ + std::vector result; + if (object_ == nullptr) { + return result; + } + cJSON *node = object_->child; + while (node != nullptr) { + if (node->string != nullptr) { + result.emplace_back(std::string(node->string)); + } + node = node->next; + } + return result; +} + cJSON *PtJson::GetJson() const { return object_; diff --git a/tooling/base/pt_json.h b/tooling/base/pt_json.h index d66e0d7f..dcaa0b8b 100644 --- a/tooling/base/pt_json.h +++ b/tooling/base/pt_json.h @@ -18,6 +18,7 @@ #include #include +#include #include "cJSON.h" #include "common/macros.h" @@ -73,6 +74,8 @@ public: std::string GetKey() const; + std::vector GetKeysArray() const; + cJSON *GetJson() const; // Type check diff --git a/tooling/base/pt_params.cpp b/tooling/base/pt_params.cpp index 293db741..3f5934db 100644 --- a/tooling/base/pt_params.cpp +++ b/tooling/base/pt_params.cpp @@ -30,6 +30,22 @@ std::unique_ptr EnableParams::Create(const PtJson ¶ms) error += "Wrong type of 'maxScriptsCacheSize';"; } + std::unique_ptr options; + std::vector enableOptionsList; + ret = params.GetArray("options", &options); + if (ret == Result::SUCCESS) { + int32_t length = options->GetSize(); + for (int32_t i = 0; i < length; i++) { + auto option = options->Get(i); + if (option != nullptr && option->IsString()) { + enableOptionsList.emplace_back(option->GetString()); + } + } + paramsObject->enableOptionList_ = enableOptionsList; + } else if (ret == Result::TYPE_ERROR) { + error += "Wrong type of 'options';"; + } + if (!error.empty()) { LOG_DEBUGGER(ERROR) << "EnableParams::Create " << error; return nullptr; @@ -1301,4 +1317,49 @@ std::unique_ptr SeriliazationTimeoutCheck } return paramsObject; } + +std::unique_ptr SaveAllPossibleBreakpointsParams::Create(const PtJson ¶ms) +{ + auto paramsObject = std::make_unique(); + std::unordered_map>> breakpointMap {}; + std::string error; + Result ret; + + std::unique_ptr locationList; + ret = params.GetObject("locations", &locationList); + if (ret != Result::SUCCESS) { + LOG_DEBUGGER(ERROR) << "SaveAllPossibleBreakpointsParams::Get Breakpoints location: " << error; + return nullptr; + } + + auto keys = locationList->GetKeysArray(); + std::unique_ptr breakpoints; + for (const auto &key : keys) { + ret = locationList->GetArray(key.c_str(), &breakpoints); + if (ret == Result::SUCCESS) { + int32_t length = breakpoints->GetSize(); + std::vector> breakpointList; + for (int32_t i = 0; i < length; i++) { + auto json = *breakpoints->Get(i); + json.Add("url", key.c_str()); + std::shared_ptr info = BreakpointInfo::Create(json); + if (info == nullptr) { + error += "'breakpoints' items BreakpointInfo is invalid;"; + break; + } + breakpointList.emplace_back(std::move(info)); + } + breakpointMap[key] = breakpointList; + } else if (ret == Result::TYPE_ERROR) { + error += "Wrong type of 'breakpoints'"; + } + } + if (!error.empty()) { + LOG_DEBUGGER(ERROR) << "SaveAllPossibleBreakpointsParams::Create " << error; + return nullptr; + } + paramsObject->breakpointsMap_ = breakpointMap; + + return paramsObject; +} } // namespace panda::ecmascript::tooling diff --git a/tooling/base/pt_params.h b/tooling/base/pt_params.h index ea8a5110..404616ef 100644 --- a/tooling/base/pt_params.h +++ b/tooling/base/pt_params.h @@ -74,11 +74,23 @@ public: return maxScriptsCacheSize_.has_value(); } + bool HasEnableOptionsList() const + { + return enableOptionList_.has_value(); + } + + std::vector GetEnableOptionsList() const + { + ASSERT(HasEnableOptionsList()); + return enableOptionList_.value(); + } + private: NO_COPY_SEMANTIC(EnableParams); NO_MOVE_SEMANTIC(EnableParams); std::optional maxScriptsCacheSize_ {}; + std::optional> enableOptionList_ {}; }; class EvaluateOnCallFrameParams : public PtBaseParams { @@ -1370,5 +1382,33 @@ private: static constexpr int32_t DEFAULT_THRESHOLD = 8; int32_t threshold_ { DEFAULT_THRESHOLD }; }; + +class SaveAllPossibleBreakpointsParams : public PtBaseParams { +public: + SaveAllPossibleBreakpointsParams() = default; + ~SaveAllPossibleBreakpointsParams() = default; + + static std::unique_ptr Create(const PtJson ¶ms); + + const std::unordered_map>> *GetBreakpointsMap() const + { + if (!HasBreakpointsMap()) { + return nullptr; + } + return &(breakpointsMap_.value()); + } + + bool HasBreakpointsMap() const + { + return breakpointsMap_.has_value(); + } + +private: + NO_COPY_SEMANTIC(SaveAllPossibleBreakpointsParams); + NO_MOVE_SEMANTIC(SaveAllPossibleBreakpointsParams); + + std::optional>>> + breakpointsMap_ {}; +}; } // namespace panda::ecmascript::tooling #endif \ No newline at end of file diff --git a/tooling/base/pt_returns.h b/tooling/base/pt_returns.h index dea06ed9..d9dfa1ef 100644 --- a/tooling/base/pt_returns.h +++ b/tooling/base/pt_returns.h @@ -85,7 +85,7 @@ private: class GetPossibleAndSetBreakpointByUrlReturns : public PtBaseReturns { public: - explicit GetPossibleAndSetBreakpointByUrlReturns(std::vector> locations) + explicit GetPossibleAndSetBreakpointByUrlReturns(std::vector> locations) : locations_(std::move(locations)) {} ~GetPossibleAndSetBreakpointByUrlReturns() override = default; @@ -97,7 +97,7 @@ private: NO_COPY_SEMANTIC(GetPossibleAndSetBreakpointByUrlReturns); NO_MOVE_SEMANTIC(GetPossibleAndSetBreakpointByUrlReturns); - std::vector> locations_ {}; + std::vector> locations_ {}; }; class EvaluateOnCallFrameReturns : public PtBaseReturns { diff --git a/tooling/base/pt_script.h b/tooling/base/pt_script.h index d401881c..2d797e2b 100644 --- a/tooling/base/pt_script.h +++ b/tooling/base/pt_script.h @@ -102,6 +102,16 @@ public: endLine_ = endLine; } + std::vector> GetLocations() const + { + return locations_; + } + + void SetLocations(std::vector> locations) + { + locations_ = locations; + } + private: NO_COPY_SEMANTIC(PtScript); NO_MOVE_SEMANTIC(PtScript); @@ -113,6 +123,7 @@ private: std::string scriptSource_ {}; // js source code std::string sourceMapUrl_ {}; // source map url int32_t endLine_ {0}; // total line number of source file + std::vector> locations_ {}; }; } // namespace panda::ecmascript::tooling #endif diff --git a/tooling/base/pt_types.cpp b/tooling/base/pt_types.cpp index 73aab2f7..a161ce9a 100644 --- a/tooling/base/pt_types.cpp +++ b/tooling/base/pt_types.cpp @@ -3386,6 +3386,18 @@ std::unique_ptr BreakpointInfo::Create(const PtJson ¶ms) return paramsObject; } +std::shared_ptr BreakpointInfo::CreateAsSharedPtr(int32_t line, int32_t column, + std::string url, std::string condition) +{ + auto result = std::make_shared(); + result->lineNumber_ = line; + result->columnNumber_ = column; + result->url_ = url; + result->condition_ = condition; + + return result; +} + std::unique_ptr BreakpointInfo::ToJson() const { std::unique_ptr result = PtJson::CreateObject(); diff --git a/tooling/base/pt_types.h b/tooling/base/pt_types.h index 03a2b66b..39efb84e 100644 --- a/tooling/base/pt_types.h +++ b/tooling/base/pt_types.h @@ -100,6 +100,8 @@ public: ~BreakpointInfo() override = default; static std::unique_ptr Create(const PtJson ¶ms); + static std::shared_ptr CreateAsSharedPtr(int32_t line, int32_t column, + std::string url, std::string condition = ""); std::unique_ptr ToJson() const override; int32_t GetLineNumber() const @@ -173,6 +175,15 @@ private: std::optional restrictToFunction_ {}; }; +class HashBreakpointInfo { +public: + size_t operator()(const std::shared_ptr &bpoint) const + { + return (std::hash()(bpoint->GetUrl())) ^ + (std::hash()(bpoint->GetLineNumber())) ^ + (std::hash()(bpoint->GetColumnNumber())); + } +}; // Runtime.ScriptId using ScriptId = int32_t; diff --git a/tooling/client/domain/debugger_client.cpp b/tooling/client/domain/debugger_client.cpp index 1e21e836..7c5612e8 100644 --- a/tooling/client/domain/debugger_client.cpp +++ b/tooling/client/domain/debugger_client.cpp @@ -54,6 +54,8 @@ bool DebuggerClient::DispatcherCmd(const std::string &cmd) { "step-into", std::bind(&DebuggerClient::StepIntoCommand, this)}, { "step-out", std::bind(&DebuggerClient::StepOutCommand, this)}, { "step-over", std::bind(&DebuggerClient::StepOverCommand, this)}, + { "enable-launch-accelerate", std::bind(&DebuggerClient::EnableLaunchAccelerateCommand, this)}, + { "saveAllPossibleBreakpoints", std::bind(&DebuggerClient::SaveAllPossibleBreakpointsCommand, this)}, }; auto entry = dispatcherTable.find(cmd); @@ -433,4 +435,57 @@ void DebuggerClient::handleResponse(std::unique_ptr json) } return; } + +int DebuggerClient::SaveAllPossibleBreakpointsCommand() +{ + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + + std::unique_ptr request = PtJson::CreateObject(); + request->Add("id", id); + request->Add("method", "Debugger.saveAllPossibleBreakpoints"); + + std::unique_ptr params = PtJson::CreateObject(); + std::unique_ptr locations = PtJson::CreateObject(); + std::unique_ptr vector = PtJson::CreateArray(); + + std::unique_ptr bp = PtJson::CreateObject(); + bp->Add("lineNumber", breakPointInfoList_.back().lineNumber); + bp->Add("columnNumber", breakPointInfoList_.back().columnNumber); + vector->Push(bp); + locations->Add(breakPointInfoList_.back().url.c_str(), vector); + params->Add("locations", locations); + request->Add("params", params); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "Debugger"); + } + + return 0; +} + +int DebuggerClient::EnableLaunchAccelerateCommand() +{ + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + + std::unique_ptr request = PtJson::CreateObject(); + request->Add("id", id); + request->Add("method", "Debugger.enable"); + + std::unique_ptr params = PtJson::CreateObject(); + std::unique_ptr options = PtJson::CreateArray(); + + options->Push("enableLaunchAccelerate"); + params->Add("options", options); + request->Add("params", params); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "Debugger"); + } + + return 0; +} } // OHOS::ArkCompiler::Toolchain \ No newline at end of file diff --git a/tooling/client/domain/debugger_client.h b/tooling/client/domain/debugger_client.h index ddf03031..aaeffd40 100644 --- a/tooling/client/domain/debugger_client.h +++ b/tooling/client/domain/debugger_client.h @@ -59,6 +59,8 @@ public: int StepIntoCommand(); int StepOutCommand(); int StepOverCommand(); + int EnableLaunchAccelerateCommand(); + int SaveAllPossibleBreakpointsCommand(); void AddBreakPointInfo(const std::string& url, const int& lineNumber, const int& columnNumber = 0); void RecvReply(std::unique_ptr json); diff --git a/tooling/client/utils/cli_command.cpp b/tooling/client/utils/cli_command.cpp index 8fb86ac2..477a8287 100644 --- a/tooling/client/utils/cli_command.cpp +++ b/tooling/client/utils/cli_command.cpp @@ -182,6 +182,10 @@ void CliCommand::CreateCommandMap() {std::make_pair("enable", "enable"), std::bind(&CliCommand::DebuggerCommand, this, "enable")}, {std::make_pair("finish", "fin"), std::bind(&CliCommand::DebuggerCommand, this, "finish")}, {std::make_pair("frame", "f"), std::bind(&CliCommand::DebuggerCommand, this, "frame")}, + {std::make_pair("enable-launch-accelerate", "enable-acc"), + std::bind(&CliCommand::DebuggerCommand, this, "enable-launch-accelerate")}, + {std::make_pair("saveAllPossibleBreakpoints", "b-new"), + std::bind(&CliCommand::SaveAllPossibleBreakpointsCommand, this, "saveAllPossibleBreakpoints")}, }; CreateOtherCommandMap(); } @@ -622,6 +626,11 @@ ErrCode CliCommand::TestCommand(const std::string &cmd) return ErrCode::ERR_OK; } +ErrCode CliCommand::SaveAllPossibleBreakpointsCommand(const std::string &cmd) +{ + return BreakCommand(cmd); +} + ErrCode CliCommand::ExecHelpCommand() { std::cout << HELP_MSG; diff --git a/tooling/client/utils/cli_command.h b/tooling/client/utils/cli_command.h index 2720521d..88cafd29 100644 --- a/tooling/client/utils/cli_command.h +++ b/tooling/client/utils/cli_command.h @@ -72,6 +72,7 @@ public: ErrCode SessionSwitchCommand(const std::string &cmd); ErrCode TestCommand(const std::string &cmd); ErrCode ExecHelpCommand(); + ErrCode SaveAllPossibleBreakpointsCommand(const std::string &cmd); void OutputCommand(const std::string &cmd, bool flag); VecStr GetArgList() diff --git a/tooling/test/client_utils/test_list.cpp b/tooling/test/client_utils/test_list.cpp index cdd96ac0..233b6c48 100644 --- a/tooling/test/client_utils/test_list.cpp +++ b/tooling/test/client_utils/test_list.cpp @@ -70,6 +70,7 @@ #include "tooling/test/testcases/js_heapusage_loop_test.h" #include "tooling/test/testcases/js_heapusage_recursion_test.h" #include "tooling/test/testcases/js_smart_stepInto_test.h" +#include "tooling/test/testcases/js_accelerate_launch_test.h" namespace panda::ecmascript::tooling::test { static std::string g_currentTestName = ""; @@ -129,6 +130,7 @@ static void RegisterTests() TestUtil::RegisterTest("JsHeapusageLoopTest", GetJsHeapusageLoopTest()); TestUtil::RegisterTest("JsHeapusageRecursionTest", GetJsHeapusageRecursionTest()); TestUtil::RegisterTest("JsSmartStepoutTest", GetJsSmartStepoutTest()); + TestUtil::RegisterTest("JsAccelerateLaunchTest", GetJsAccelerateLaunchTest()); } std::vector GetTestList() diff --git a/tooling/test/debugger_impl_test.cpp b/tooling/test/debugger_impl_test.cpp index 0fbb8811..7d0e3654 100644 --- a/tooling/test/debugger_impl_test.cpp +++ b/tooling/test/debugger_impl_test.cpp @@ -194,6 +194,43 @@ HWTEST_F_L0(DebuggerImplTest, Dispatcher_Dispatch_Enable__002) } } +HWTEST_F_L0(DebuggerImplTest, Dispatcher_Dispatch_Enable_Accelerate_Launch_Mode) +{ + std::string outStrForCallbackCheck = ""; + std::function callback = + [&outStrForCallbackCheck]([[maybe_unused]] const void *ptr, const std::string &inStrOfReply) { + outStrForCallbackCheck = inStrOfReply;}; + ProtocolChannel *protocolChannel = new ProtocolHandler(callback, ecmaVm); + auto runtimeImpl = std::make_unique(ecmaVm, protocolChannel); + auto debuggerImpl = std::make_unique(ecmaVm, protocolChannel, runtimeImpl.get()); + auto dispatcherImpl = std::make_unique(protocolChannel, std::move(debuggerImpl)); + EXPECT_FALSE(ecmaVm->GetJsDebuggerManager()->IsDebugMode()); + + std::string msg = std::string() + + R"({ + "id":0, + "method":"Debugger.enable", + "params":{ + "maxScriptsCacheSize":1024, + "options":[ + "enableLaunchAccelerate" + ] + } + })"; + DispatchRequest request(msg); + dispatcherImpl->Dispatch(request); + + bool condition = outStrForCallbackCheck.find("protocols") != std::string::npos && + outStrForCallbackCheck.find("debuggerId") != std::string::npos && + outStrForCallbackCheck.find("saveAllPossibleBreakpoints") != std::string::npos; + EXPECT_TRUE(condition); + EXPECT_TRUE(ecmaVm->GetJsDebuggerManager()->IsDebugMode()); + if (protocolChannel) { + delete protocolChannel; + protocolChannel = nullptr; + } +} + HWTEST_F_L0(DebuggerImplTest, Dispatcher_Dispatch_Disable__001) { std::string outStrForCallbackCheck = ""; diff --git a/tooling/test/debugger_params_test.cpp b/tooling/test/debugger_params_test.cpp index 07877ed9..f01dcc53 100644 --- a/tooling/test/debugger_params_test.cpp +++ b/tooling/test/debugger_params_test.cpp @@ -224,6 +224,45 @@ HWTEST_F_L0(DebuggerParamsTest, EnableParamsCreateTest) EXPECT_EQ(enableParams->GetMaxScriptsCacheSize(), 100); } +HWTEST_F_L0(DebuggerParamsTest, EnableParamsAccelerateLaunchModeCreateTest) +{ + std::string msg; + std::unique_ptr enableParams; + + // abnormal + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + enableParams = EnableParams::Create(DispatchRequest(msg).GetParams()); + ASSERT_NE(enableParams, nullptr); + EXPECT_FALSE(enableParams->HasMaxScriptsCacheSize()); + + // normal + msg = std::string() + R"({"id":0,"method":"Debugger.Test", + "params":{"options":["enableLaunchAccelerate"], "maxScriptsCacheSize":100}})"; + enableParams = EnableParams::Create(DispatchRequest(msg).GetParams()); + ASSERT_NE(enableParams, nullptr); + EXPECT_EQ(enableParams->GetMaxScriptsCacheSize(), 100); + EXPECT_EQ(enableParams->GetEnableOptionsList().size(), 1); +} + +HWTEST_F_L0(DebuggerParamsTest, SaveAllPossibleBreakpointsParamsCreateTest) +{ + std::string msg; + std::unique_ptr params; + + // abnormal + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + params = SaveAllPossibleBreakpointsParams::Create(DispatchRequest(msg).GetParams()); + ASSERT_EQ(params, nullptr); + + // normal + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ + "locations":{"actualUrl/actualFileName.ts":[{"lineNumber": 7, "columnNumber": 8}]}}})"; + params = SaveAllPossibleBreakpointsParams::Create(DispatchRequest(msg).GetParams()); + ASSERT_NE(params, nullptr); + EXPECT_TRUE(params->HasBreakpointsMap()); + EXPECT_EQ(params->GetBreakpointsMap()->size(), 1); +} + HWTEST_F_L0(DebuggerParamsTest, StartSamplingParamsCreateTest) { std::string msg; diff --git a/tooling/test/debugger_returns_test.cpp b/tooling/test/debugger_returns_test.cpp index 28062b6b..abe1dfd4 100644 --- a/tooling/test/debugger_returns_test.cpp +++ b/tooling/test/debugger_returns_test.cpp @@ -417,12 +417,12 @@ HWTEST_F_L0(DebuggerReturnsTest, SearchInContentReturnsToJsonTest) HWTEST_F_L0(DebuggerReturnsTest, GetPossibleAndSetBreakpointByUrlReturnsToJsonTest) { - auto locations = std::vector>(); - std::unique_ptr breakpointReturnInfo = std::make_unique(); + auto locations = std::vector>(); + std::shared_ptr breakpointReturnInfo = std::make_shared(); breakpointReturnInfo->SetScriptId(11).SetLineNumber(1).SetColumnNumber(44); - locations.emplace_back(std::move(breakpointReturnInfo)); + locations.emplace_back(breakpointReturnInfo); std::unique_ptr getPossibleAndSetBreakpointByUrlReturns = std::make_unique - (std::move(locations)); + (locations); std::unique_ptr locationsJS; ASSERT_EQ(getPossibleAndSetBreakpointByUrlReturns->ToJson()->GetArray("locations", &locationsJS), Result::SUCCESS); ASSERT_NE(locationsJS, nullptr); diff --git a/tooling/test/debugger_script_test.cpp b/tooling/test/debugger_script_test.cpp index ce1492c3..38562947 100644 --- a/tooling/test/debugger_script_test.cpp +++ b/tooling/test/debugger_script_test.cpp @@ -106,4 +106,16 @@ HWTEST_F_L0(DebuggerScriptTest, EndLineTest) script->SetEndLine(200); ASSERT_EQ(script->GetEndLine(), 200); } + +HWTEST_F_L0(DebuggerScriptTest, LocationsTest) +{ + std::unique_ptr script = std::make_unique(1, "name_1", "url_1", "source_1"); + std::vector> locations {}; + std::shared_ptr bpInfo = std::make_shared(); + std::string invalidBpId = "invalid"; + bpInfo->SetId(invalidBpId).SetLineNumber(1).SetColumnNumber(0); + locations.emplace_back(bpInfo); + script->SetLocations(locations); + ASSERT_EQ(script->GetLocations().size(), 1); +} } // namespace panda::test \ No newline at end of file diff --git a/tooling/test/pt_json_test.cpp b/tooling/test/pt_json_test.cpp index 9f42e46a..c128aedb 100644 --- a/tooling/test/pt_json_test.cpp +++ b/tooling/test/pt_json_test.cpp @@ -313,4 +313,15 @@ HWTEST_F_L0(PtJsonTest, ResultUInt64Test) ASSERT_EQ(test->GetUInt64("b", &ui64), Result::SUCCESS); EXPECT_EQ(ui64, static_cast(100)); } + +HWTEST_F_L0(PtJsonTest, GetKeysArraytest) +{ + auto test = PtJson::CreateObject(); + test->Add("a", "ResultUInt64Test"); + test->Add("b", 100); + auto keys = test->GetKeysArray(); + EXPECT_EQ(keys.size(), 2); + EXPECT_TRUE(keys.at(0) == "a"); + EXPECT_TRUE(keys.at(1) == "b"); +} } \ No newline at end of file diff --git a/tooling/test/testcases/js_accelerate_launch_test.h b/tooling/test/testcases/js_accelerate_launch_test.h new file mode 100644 index 00000000..45366e4a --- /dev/null +++ b/tooling/test/testcases/js_accelerate_launch_test.h @@ -0,0 +1,131 @@ +/* + * 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_TEST_TESTCASES_JS_ACCELERATE_LAUNCH_TEST_H +#define ECMASCRIPT_TOOLING_TEST_TESTCASES_JS_ACCELERATE_LAUNCH_TEST_H + +#include "tooling/test/client_utils/test_util.h" + +namespace panda::ecmascript::tooling::test { +class JsAccelerateLaunchTest : public TestActions { +public: + JsAccelerateLaunchTest() + { + testAction = { + // Enable Accelerate Launch Mode + {SocketAction::SEND, "enable-acc"}, + {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, + {SocketAction::SEND, "runtime-enable"}, + {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, + // Debugger.saveAllPossibleBreakpoints + {SocketAction::SEND, "b-new " DEBUGGER_JS_DIR "sample.js 22"}, + {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, + {SocketAction::SEND, "run"}, + {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, + // load sample.js + {SocketAction::RECV, "Debugger.scriptParsed", ActionRule::STRING_CONTAIN}, + {SocketAction::RECV, "Debugger.paused", ActionRule::STRING_CONTAIN}, + {SocketAction::SEND, "resume"}, + {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN}, + {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, + {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE, [this] (auto recv, auto, auto) -> bool { + std::unique_ptr json = PtJson::Parse(recv); + Result ret; + std::string method; + ret = json->GetString("method", &method); + if (ret != Result::SUCCESS || method != "Debugger.paused") { + return false; + } + + std::unique_ptr params = nullptr; + ret = json->GetObject("params", ¶ms); + if (ret != Result::SUCCESS) { + return false; + } + + std::unique_ptr hitBreakpoints = nullptr; + ret = params->GetArray("hitBreakpoints", &hitBreakpoints); + if (ret != Result::SUCCESS) { + return false; + } + + std::string breakpoint; + breakpoint = hitBreakpoints->Get(0)->GetString(); + if (ret != Result::SUCCESS || breakpoint.find(sourceFile_) == std::string::npos || + breakpoint.find("21") == std::string::npos) { + return false; + } + return true; + }}, + {SocketAction::SEND, "b " DEBUGGER_JS_DIR "sample.js 23"}, + {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, + {SocketAction::SEND, "resume"}, + {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN}, + {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, + {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE, [this] (auto recv, auto, auto) -> bool { + std::unique_ptr json = PtJson::Parse(recv); + Result ret; + std::string method; + ret = json->GetString("method", &method); + if (ret != Result::SUCCESS || method != "Debugger.paused") { + return false; + } + + std::unique_ptr params = nullptr; + ret = json->GetObject("params", ¶ms); + if (ret != Result::SUCCESS) { + return false; + } + + std::unique_ptr hitBreakpoints = nullptr; + ret = params->GetArray("hitBreakpoints", &hitBreakpoints); + if (ret != Result::SUCCESS) { + return false; + } + + std::string breakpoint; + breakpoint = hitBreakpoints->Get(0)->GetString(); + if (ret != Result::SUCCESS || breakpoint.find(sourceFile_) == std::string::npos || + breakpoint.find("22") == std::string::npos) { + return false; + } + return true; + }}, + {SocketAction::SEND, "success"}, + {SocketAction::SEND, "resume"}, + {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN}, + {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, + }; + } + + std::pair GetEntryPoint() override + { + return {pandaFile_, entryPoint_}; + } + ~JsAccelerateLaunchTest() = default; + +private: + std::string pandaFile_ = DEBUGGER_ABC_DIR "sample.abc"; + std::string sourceFile_ = DEBUGGER_JS_DIR "sample.js"; + std::string entryPoint_ = "_GLOBAL::func_main_0"; +}; + +std::unique_ptr GetJsAccelerateLaunchTest() +{ + return std::make_unique(); +} +} // namespace panda::ecmascript::tooling::test + +#endif // ECMASCRIPT_TOOLING_TEST_TESTCASES_JS_ACCELERATE_LAUNCH_TEST_H diff --git a/tooling/test/utils/test_hooks.h b/tooling/test/utils/test_hooks.h index 88cda04a..1fd7e2bd 100644 --- a/tooling/test/utils/test_hooks.h +++ b/tooling/test/utils/test_hooks.h @@ -118,6 +118,8 @@ public: void SendableMethodEntry([[maybe_unused]] JSHandle method) override {} + void DisableFirstTimeFlag() override {} + void TerminateTest() { debugInterface_->UnregisterHooks(); -- Gitee From 6fd3ad823d1f7ffc243ebce7b81a899baf955e96 Mon Sep 17 00:00:00 2001 From: wengchangcheng Date: Thu, 27 Mar 2025 14:30:53 +0800 Subject: [PATCH 09/48] Revert "add base_runtime" This reverts commit 950bc17f0a9c62ddccb7174db1f44a6d81901281. Issue: https://gitee.com/openharmony/arkcompiler_toolchain/issues/IBWPWK Change-Id: I39219b79c4b1344c2c9d2f130bce1a39d794090f Signed-off-by: wengchangcheng Change-Id: I78fa15fba4477bcdf35e83c56ae5e496cd0e1dd6 --- BUILD.gn | 3 --- build/core/gn/BUILD.gn | 5 ----- build/templates/cxx/external_deps_handler.py | 4 ---- toolchain_config.gni | 1 - 4 files changed, 13 deletions(-) diff --git a/BUILD.gn b/BUILD.gn index 18f559fb..04aae54c 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -274,9 +274,6 @@ group("ark_js_host_unittest") { "//arkcompiler/ets_runtime:ark_runtime_host_unittest", "//arkcompiler/toolchain:ark_toolchain_host_unittest", ] - if (ark_standalone_build) { - deps += [ "$base_root:base_runtime_host_unittest" ] - } } group("runtime_core_host_ut") { diff --git a/build/core/gn/BUILD.gn b/build/core/gn/BUILD.gn index e97716b5..57349680 100644 --- a/build/core/gn/BUILD.gn +++ b/build/core/gn/BUILD.gn @@ -28,7 +28,6 @@ print() group("default") { deps = [ - ":base_runtime", ":ets_frontend", ":ets_runtime", ":runtime_core", @@ -131,7 +130,3 @@ group("toolchain") { ] } } - -group("base_runtime") { - deps = [ "$base_root:libbase_runtime" ] -} diff --git a/build/templates/cxx/external_deps_handler.py b/build/templates/cxx/external_deps_handler.py index a449aeda..506b91fc 100755 --- a/build/templates/cxx/external_deps_handler.py +++ b/build/templates/cxx/external_deps_handler.py @@ -92,10 +92,6 @@ def main(): config_info = read_json_file("{}arkcompiler/ets_runtime/bundle.json".format(args.root_src_dir)) target_name = dep.split(":")[1] deps.append(get_full_path_from_target_name(config_info, target_name)) - elif dep.startswith("base_runtime"): - config_info = read_json_file("{}arkcompiler/base_runtime/bundle.json".format(args.root_src_dir)) - target_name = dep.split(":")[1] - deps.append(get_full_path_from_target_name(config_info, target_name)) elif dep.startswith("runtime_core"): config_info = read_json_file("{}arkcompiler/runtime_core/bundle.json".format(args.root_src_dir)) target_name = dep.split(":")[1] diff --git a/toolchain_config.gni b/toolchain_config.gni index e5dde911..9442eb52 100644 --- a/toolchain_config.gni +++ b/toolchain_config.gni @@ -31,7 +31,6 @@ if (!ark_standalone_build) { } ark_root = "//arkcompiler/runtime_core" js_root = "//arkcompiler/ets_runtime" -base_root = "//arkcompiler/base_runtime" global_root = "//base/global/i18n" hilog_root = "//base/hiviewdfx/hilog/interfaces/native/innerkits" qos_root = "//foundation/resourceschedule/qos_manager" -- Gitee From d787736f5c1079bc950dc7f09ef48cbbf85b5349 Mon Sep 17 00:00:00 2001 From: zhuheng Date: Sun, 30 Mar 2025 10:03:59 +0800 Subject: [PATCH 10/48] Revert "Merge remote-tracking branch 'openharmony/master'" This reverts commit 5451f68f99eabf6e5d711ce0ef9dca21c67475a7. Issue: https://gitee.com/openharmony/arkcompiler_toolchain/issues/IBXBB1 Signed-off-by: zhuheng Change-Id: Ib1123fd911cb6476972a12aa258d7f53cba7c7ac --- tooling/agent/debugger_impl.cpp | 232 ++++-------------- tooling/agent/debugger_impl.h | 36 +-- tooling/backend/js_pt_hooks.cpp | 17 +- tooling/backend/js_pt_hooks.h | 1 - tooling/base/pt_events.cpp | 9 - tooling/base/pt_events.h | 7 - tooling/base/pt_json.cpp | 16 -- tooling/base/pt_json.h | 3 - tooling/base/pt_params.cpp | 61 ----- tooling/base/pt_params.h | 40 --- tooling/base/pt_returns.h | 4 +- tooling/base/pt_script.h | 11 - tooling/base/pt_types.cpp | 12 - tooling/base/pt_types.h | 11 - tooling/client/domain/debugger_client.cpp | 55 ----- tooling/client/domain/debugger_client.h | 2 - tooling/client/utils/cli_command.cpp | 9 - tooling/client/utils/cli_command.h | 1 - tooling/test/client_utils/test_list.cpp | 2 - tooling/test/debugger_impl_test.cpp | 37 --- tooling/test/debugger_params_test.cpp | 39 --- tooling/test/debugger_returns_test.cpp | 8 +- tooling/test/debugger_script_test.cpp | 12 - tooling/test/pt_json_test.cpp | 11 - .../testcases/js_accelerate_launch_test.h | 131 ---------- tooling/test/utils/test_hooks.h | 2 - 26 files changed, 65 insertions(+), 704 deletions(-) delete mode 100644 tooling/test/testcases/js_accelerate_launch_test.h diff --git a/tooling/agent/debugger_impl.cpp b/tooling/agent/debugger_impl.cpp index 69e12052..4d111cb5 100755 --- a/tooling/agent/debugger_impl.cpp +++ b/tooling/agent/debugger_impl.cpp @@ -88,49 +88,51 @@ bool DebuggerImpl::NotifyScriptParsed(const std::string &fileName, std::string_v return false; } - if (!vm_->GetJsDebuggerManager()->GetFaApp() && jsPandaFile->IsBundlePack()) { - LOG_DEBUGGER(DEBUG) << "NotifyScriptParsed: Unmerge file: " << fileName; - return false; - } - const char *recordName = entryPoint.data(); auto mainMethodIndex = panda_file::File::EntityId(jsPandaFile->GetMainMethodIndex(recordName)); const std::string &source = extractor->GetSourceCode(mainMethodIndex); const std::string &url = extractor->GetSourceFile(mainMethodIndex); + + recordNames_[url].insert(recordName); + // if load module, it needs to check whether clear singlestepper_ ClearSingleStepper(); if (MatchUrlAndFileName(url, fileName)) { - LOG_DEBUGGER(WARN) << "DebuggerImpl::NotifyScriptParsed: Script already been parsed: " - << "url: " << url << " fileName: " << fileName; return false; } + urlFileNameMap_[url].insert(fileName); - SaveParsedScriptsAndUrl(fileName, url, recordName, source); + // Notify script parsed event + std::unique_ptr script = std::make_unique(g_scriptId++, fileName, url, source); + + frontend_.ScriptParsed(vm_, *script); + + // Store parsed script in map + scripts_[script->GetScriptId()] = std::move(script); return true; } -std::vector> DebuggerImpl::SetBreakpointsWhenParsingScript(const std::string &url) +bool DebuggerImpl::SendableScriptParsed(const std::string &fileName, const std::string &url, + const std::string &source, const std::string &recordName) { - std::vector> outLocations {}; - for (const auto &breakpoint : breakpointPendingMap_[url]) { - if (!ProcessSingleBreakpoint(*breakpoint, outLocations)) { - std::string invalidBpId = "invalid"; - std::shared_ptr bpInfo = std::make_shared(); - bpInfo->SetId(invalidBpId) - .SetLineNumber(breakpoint->GetLineNumber()) - .SetColumnNumber(breakpoint->GetColumnNumber()); - outLocations.emplace_back(bpInfo); - } + if (!CheckScriptParsed(fileName)) { + return false; } - return outLocations; -} -bool DebuggerImpl::NeedToSetBreakpointsWhenParsingScript(const std::string &url) -{ - if (breakpointPendingMap_.find(url) != breakpointPendingMap_.end()) { - return !breakpointPendingMap_[url].empty(); - } - return false; + recordNames_[url].insert(recordName); + + // if load module, it needs to check whether clear singlestepper_ + ClearSingleStepper(); + + urlFileNameMap_[url].insert(fileName); + // Notify script parsed event + std::unique_ptr script = std::make_unique(g_scriptId++, fileName, url, source); + + frontend_.ScriptParsed(vm_, *script); + + // Store parsed script in map + scripts_[script->GetScriptId()] = std::move(script); + return true; } bool DebuggerImpl::CheckScriptParsed([[maybe_unused]] const std::string &fileName) @@ -144,7 +146,7 @@ bool DebuggerImpl::CheckScriptParsed([[maybe_unused]] const std::string &fileNam } #endif - // check if Debugable flag is true in module.json + // The release application does not require scriptParsed if (!vm_->GetJsDebuggerManager()->IsDebugApp()) { return false; } @@ -152,27 +154,8 @@ bool DebuggerImpl::CheckScriptParsed([[maybe_unused]] const std::string &fileNam return true; } -void DebuggerImpl::SaveParsedScriptsAndUrl(const std::string &fileName, const std::string &url, - const std::string &recordName, const std::string &source) -{ - // Save recordName to its corresponding url - recordNames_[url].insert(recordName); - // Save parsed fileName to its corresponding url - urlFileNameMap_[url].insert(fileName); - // Create and save script - std::shared_ptr script = std::make_shared(g_scriptId++, fileName, url, source); - scripts_[script->GetScriptId()] = script; - // Check if is launch accelerate mode & has pending bps to set - if (IsLaunchAccelerateMode() && NeedToSetBreakpointsWhenParsingScript(url)) { - script->SetLocations(SetBreakpointsWhenParsingScript(url)); - } - // Notify frontend ScriptParsed event - frontend_.ScriptParsed(vm_, *script); -} - -bool DebuggerImpl::NotifyScriptParsedBySendable(JSHandle method) +bool DebuggerImpl::SendableMethodEntry(JSHandle method) { - // Find extractor and retrieve infos const JSPandaFile *jsPandaFile = method->GetJSPandaFile(); if (jsPandaFile == nullptr) { LOG_DEBUGGER(ERROR) << "JSPandaFile is nullptr"; @@ -186,23 +169,14 @@ bool DebuggerImpl::NotifyScriptParsedBySendable(JSHandle method) auto methodId = method->GetMethodId(); const std::string &url = extractor->GetSourceFile(methodId); const std::string &fileName = std::string(jsPandaFile->GetJSPandaFileDesc()); - // Check url path & is debugable in module.json - if (!CheckScriptParsed(fileName)) { - return false; - } - // Clear SingleStepper before notify - ClearSingleStepper(); - // Check if this (url, fileName) pair has already been parsed - if (MatchUrlAndFileName(url, fileName)) { - LOG_DEBUGGER(WARN) << "DebuggerImpl::NotifyScriptParsedBySendable: Script already been parsed: " - << "url: " << url << " fileName: " << fileName; - return false; + if (!MatchUrlAndFileName(url, fileName)) { + // scriptParsed + const std::string &source = extractor->GetSourceCode(methodId); + const std::string &recordName = std::string(method->GetRecordNameStr()); + SendableScriptParsed(fileName, url, source, recordName); + return true; } - // Parse and save this file - const std::string &source = extractor->GetSourceCode(methodId); - const std::string &recordName = std::string(method->GetRecordNameStr()); - SaveParsedScriptsAndUrl(fileName, url, recordName, source); - return true; + return false; } bool DebuggerImpl::MatchUrlAndFileName(const std::string &url, const std::string &fileName) @@ -210,6 +184,7 @@ bool DebuggerImpl::MatchUrlAndFileName(const std::string &url, const std::string auto urlFileNameIter = urlFileNameMap_.find(url); if (urlFileNameIter != urlFileNameMap_.end()) { if (urlFileNameIter->second.find(fileName) != urlFileNameIter->second.end()) { + LOG_DEBUGGER(WARN) << "MatchUrlAndFileName: already loaded: " << url; return true; } } @@ -474,8 +449,7 @@ void DebuggerImpl::InitializeExtendedProtocolsList() "setNativeRange", "resetSingleStepper", "callFunctionOn", - "smartStepInto", - "saveAllPossibleBreakpoints" + "smartStepInto" }; debuggerExtendedProtocols_ = std::move(debuggerProtocolList); } @@ -569,9 +543,6 @@ void DebuggerImpl::DispatcherImpl::Dispatch(const DispatchRequest &request) case Method::CALL_FUNCTION_ON: CallFunctionOn(request); break; - case Method::SAVE_ALL_POSSIBLE_BREAKPOINTS: - SaveAllPossibleBreakpoints(request); - break; default: SendResponse(request, DispatchResponse::Fail("Unknown method: " + request.GetMethod())); break; @@ -636,8 +607,6 @@ DebuggerImpl::DispatcherImpl::Method DebuggerImpl::DispatcherImpl::GetMethodEnum return Method::CLIENT_DISCONNECT; } else if (method == "callFunctionOn") { return Method::CALL_FUNCTION_ON; - } else if (method == "saveAllPossibleBreakpoints") { - return Method::SAVE_ALL_POSSIBLE_BREAKPOINTS; } else { return Method::UNKNOWN; } @@ -802,24 +771,12 @@ void DebuggerImpl::DispatcherImpl::GetPossibleAndSetBreakpointByUrl(const Dispat return; } - std::vector> outLocation; + std::vector> outLocation; DispatchResponse response = debugger_->GetPossibleAndSetBreakpointByUrl(*params, outLocation); GetPossibleAndSetBreakpointByUrlReturns result(std::move(outLocation)); SendResponse(request, response, result); } -void DebuggerImpl::DispatcherImpl::SaveAllPossibleBreakpoints(const DispatchRequest &request) -{ - std::unique_ptr params = - SaveAllPossibleBreakpointsParams::Create(request.GetParams()); - if (params == nullptr) { - SendResponse(request, DispatchResponse::Fail("wrong params")); - return; - } - DispatchResponse response = debugger_->SaveAllPossibleBreakpoints(*params); - SendResponse(request, response); -} - void DebuggerImpl::DispatcherImpl::SetPauseOnExceptions(const DispatchRequest &request) { std::unique_ptr params = SetPauseOnExceptionsParams::Create(request.GetParams()); @@ -1051,8 +1008,7 @@ void DebuggerImpl::Frontend::ScriptParsed(const EcmaVM *vm, const PtScript &scri .SetEndLine(script.GetEndLine()) .SetEndColumn(0) .SetExecutionContextId(0) - .SetHash(script.GetHash()) - .SetLocations(script.GetLocations()); + .SetHash(script.GetHash()); channel_->SendNotification(scriptParsed); } @@ -1089,8 +1045,6 @@ DispatchResponse DebuggerImpl::Enable([[maybe_unused]] const EnableParams ¶m ASSERT(id != nullptr); *id = 0; vm_->GetJsDebuggerManager()->SetDebugMode(true); - // Enable corresponding features requested by IDE - EnableDebuggerFeatures(params); for (auto &script : scripts_) { frontend_.ScriptParsed(vm_, *script.second); } @@ -1098,42 +1052,6 @@ DispatchResponse DebuggerImpl::Enable([[maybe_unused]] const EnableParams ¶m return DispatchResponse::Ok(); } -void DebuggerImpl::EnableDebuggerFeatures(const EnableParams ¶ms) -{ - if (!params.HasEnableOptionsList()) { - return; - } - auto enableOptionsList = params.GetEnableOptionsList(); - if (enableOptionsList.empty()) { - return; - } - for (auto &option : enableOptionsList) { - LOG_DEBUGGER(INFO) << "Debugger feature " << option << " is enabled"; - EnableFeature(GetDebuggerFeatureEnum(option)); - } -} - -DebuggerFeature DebuggerImpl::GetDebuggerFeatureEnum(std::string &option) -{ - if (option == "enableLaunchAccelerate") { - return DebuggerFeature::LAUNCH_ACCELERATE; - } - // Future features could be added here to parse as DebuggerFeatureEnum - return DebuggerFeature::UNKNOWN; -} - -void DebuggerImpl::EnableFeature(DebuggerFeature feature) -{ - switch (feature) { - case DebuggerFeature::LAUNCH_ACCELERATE: - EnableLaunchAccelerateMode(); - DebuggerApi::DisableFirstTimeFlag(jsDebugger_); - break; - default: - break; - } -} - DispatchResponse DebuggerImpl::Disable() { DebuggerApi::RemoveAllBreakpoints(jsDebugger_); @@ -1288,9 +1206,6 @@ DispatchResponse DebuggerImpl::RemoveBreakpointsByUrl(const RemoveBreakpointsByU } LOG_DEBUGGER(INFO) << "All breakpoints on " << url << " are removed"; - if (IsLaunchAccelerateMode()) { - breakpointPendingMap_.erase(url); - } return DispatchResponse::Ok(); } @@ -1385,7 +1300,7 @@ DispatchResponse DebuggerImpl::SetBreakpointsActive(const SetBreakpointsActivePa } DispatchResponse DebuggerImpl::GetPossibleAndSetBreakpointByUrl(const GetPossibleAndSetBreakpointParams ¶ms, - std::vector> &outLocations) + std::vector> &outLocations) { if (!vm_->GetJsDebuggerManager()->IsDebugMode()) { return DispatchResponse::Fail("GetPossibleAndSetBreakpointByUrl: debugger agent is not enabled"); @@ -1397,69 +1312,18 @@ DispatchResponse DebuggerImpl::GetPossibleAndSetBreakpointByUrl(const GetPossibl for (const auto &breakpoint : *breakpointList) { if (!ProcessSingleBreakpoint(*breakpoint, outLocations)) { std::string invalidBpId = "invalid"; - std::shared_ptr bpInfo = std::make_shared(); + std::unique_ptr bpInfo = std::make_unique(); bpInfo->SetId(invalidBpId) .SetLineNumber(breakpoint->GetLineNumber()) .SetColumnNumber(breakpoint->GetColumnNumber()); - outLocations.emplace_back(bpInfo); - } - // Insert this bp into bp pending map - if (IsLaunchAccelerateMode()) { - InsertIntoPendingBreakpoints(*breakpoint); + outLocations.emplace_back(std::move(bpInfo)); } } return DispatchResponse::Ok(); } -bool DebuggerImpl::InsertIntoPendingBreakpoints(const BreakpointInfo &breakpoint) -{ - auto condition = breakpoint.HasCondition() ? breakpoint.GetCondition() : std::optional {}; - auto bpShared = BreakpointInfo::CreateAsSharedPtr(breakpoint.GetLineNumber(), breakpoint.GetColumnNumber(), - breakpoint.GetUrl(), (condition.has_value() ? condition.value() : "")); - if (breakpointPendingMap_.empty() || - breakpointPendingMap_.find(breakpoint.GetUrl()) == breakpointPendingMap_.end()) { - CUnorderedSet, HashBreakpointInfo> set {}; - set.insert(bpShared); - breakpointPendingMap_[breakpoint.GetUrl()] = set; - return true; - } - return (breakpointPendingMap_[breakpoint.GetUrl()].insert(bpShared)).second; -} - -DispatchResponse DebuggerImpl::SaveAllPossibleBreakpoints(const SaveAllPossibleBreakpointsParams ¶ms) -{ - if (!vm_->GetJsDebuggerManager()->IsDebugMode()) { - return DispatchResponse::Fail("SaveAllPossibleBreakpoints: debugger agent is not enabled"); - } - if (!IsLaunchAccelerateMode()) { - return DispatchResponse::Fail("SaveAllPossibleBreakpoints: protocol is not enabled"); - } - if (!params.HasBreakpointsMap()) { - return DispatchResponse::Fail("SaveAllPossibleBreakpoints: no pending breakpoint exists"); - } - SavePendingBreakpoints(params); - return DispatchResponse::Ok(); -} - -void DebuggerImpl::SavePendingBreakpoints(const SaveAllPossibleBreakpointsParams ¶ms) -{ - for (const auto &entry : *(params.GetBreakpointsMap())) { - if (breakpointPendingMap_.find(entry.first) == breakpointPendingMap_.end()) { - CUnorderedSet, HashBreakpointInfo> set {}; - for (auto &info : entry.second) { - set.insert(info); - } - breakpointPendingMap_[entry.first] = set; - } else { - for (auto &info : entry.second) { - breakpointPendingMap_[entry.first].insert(info); - } - } - } -} - bool DebuggerImpl::ProcessSingleBreakpoint(const BreakpointInfo &breakpoint, - std::vector> &outLocations) + std::vector> &outLocations) { const std::string &url = breakpoint.GetUrl(); int32_t lineNumber = breakpoint.GetLineNumber(); @@ -1503,9 +1367,9 @@ bool DebuggerImpl::ProcessSingleBreakpoint(const BreakpointInfo &breakpoint, BreakpointDetails bpMetaData {lineNumber, 0, url}; std::string outId = BreakpointDetails::ToString(bpMetaData); - std::shared_ptr bpInfo = std::make_unique(); + std::unique_ptr bpInfo = std::make_unique(); bpInfo->SetScriptId(scriptId).SetLineNumber(lineNumber).SetColumnNumber(0).SetId(outId); - outLocations.emplace_back(bpInfo); + outLocations.emplace_back(std::move(bpInfo)); return true; } diff --git a/tooling/agent/debugger_impl.h b/tooling/agent/debugger_impl.h index 9fd14336..c8b35633 100644 --- a/tooling/agent/debugger_impl.h +++ b/tooling/agent/debugger_impl.h @@ -32,7 +32,6 @@ class TestHooks; } // namespace test enum class DebuggerState { DISABLED, ENABLED, PAUSED }; -enum class DebuggerFeature { LAUNCH_ACCELERATE, UNKNOWN }; class DebuggerImpl final { public: DebuggerImpl(const EcmaVM *vm, ProtocolChannel *channel, RuntimeImpl *runtime); @@ -41,8 +40,10 @@ public: // event bool NotifyScriptParsed(const std::string &fileName, std::string_view entryPoint = "func_main_0"); + bool SendableScriptParsed(const std::string &fileName, const std::string &url, + const std::string &source, const std::string &recordName); bool CheckScriptParsed(const std::string &fileName); - bool NotifyScriptParsedBySendable(JSHandle method); + bool SendableMethodEntry(JSHandle method); bool MatchUrlAndFileName(const std::string &url, const std::string &fileName); bool NotifySingleStep(const JSPtLocation &location); void NotifyPaused(std::optional location, PauseReason reason); @@ -78,7 +79,7 @@ public: bool isSmartBreakpoint = false); DispatchResponse SetBreakpointsActive(const SetBreakpointsActiveParams ¶ms); DispatchResponse GetPossibleAndSetBreakpointByUrl(const GetPossibleAndSetBreakpointParams ¶ms, - std::vector> &outLocations); + std::vector> &outLocations); DispatchResponse SetPauseOnExceptions(const SetPauseOnExceptionsParams ¶ms); DispatchResponse SetSkipAllPauses(const SetSkipAllPausesParams ¶ms); DispatchResponse SetNativeRange(const SetNativeRangeParams ¶ms); @@ -96,7 +97,7 @@ public: const CallFunctionOnParams ¶ms, std::unique_ptr *outRemoteObject, std::optional> *outExceptionDetails); - DispatchResponse SaveAllPossibleBreakpoints(const SaveAllPossibleBreakpointsParams ¶ms); + /** * @brief: match first script and callback * @@ -178,7 +179,6 @@ public: void DropFrame(const DispatchRequest &request); void ClientDisconnect(const DispatchRequest &request); void CallFunctionOn(const DispatchRequest &request); - void SaveAllPossibleBreakpoints(const DispatchRequest &request); enum class Method { CONTINUE_TO_LOCATION, @@ -209,7 +209,6 @@ public: RESET_SINGLE_STEPPER, CLIENT_DISCONNECT, CALL_FUNCTION_ON, - SAVE_ALL_POSSIBLE_BREAKPOINTS, UNKNOWN }; Method GetMethodEnum(const std::string& method); @@ -253,19 +252,10 @@ private: bool CheckPauseOnException(); bool IsWithinVariableScope(const LocalVariableInfo &localVariableInfo, uint32_t bcOffset); bool ProcessSingleBreakpoint(const BreakpointInfo &breakpoint, - std::vector> &outLocations); + std::vector> &outLocations); bool IsVariableSkipped(const std::string &varName); Local CheckAndGenerateCondFunc(const std::optional &condition); void InitializeExtendedProtocolsList(); - bool NeedToSetBreakpointsWhenParsingScript(const std::string &url); - std::vector> SetBreakpointsWhenParsingScript(const std::string &url); - void SavePendingBreakpoints(const SaveAllPossibleBreakpointsParams ¶ms); - bool InsertIntoPendingBreakpoints(const BreakpointInfo &breakpoint); - void SaveParsedScriptsAndUrl(const std::string &fileName, const std::string &url, - const std::string &recordName, const std::string &source = ""); - void EnableDebuggerFeatures(const EnableParams ¶ms); - DebuggerFeature GetDebuggerFeatureEnum(std::string &option); - void EnableFeature(DebuggerFeature feature); const std::unordered_set &GetRecordName(const std::string &url) { @@ -276,14 +266,6 @@ private: } return recordName; } - void EnableLaunchAccelerateMode() - { - breakOnStartEnable_ = false; - } - bool IsLaunchAccelerateMode() const - { - return !breakOnStartEnable_; - } class Frontend { public: @@ -315,7 +297,7 @@ private: std::unordered_map> recordNames_ {}; std::unordered_map> urlFileNameMap_ {}; - std::unordered_map> scripts_ {}; + std::unordered_map> scripts_ {}; PauseOnExceptionsState pauseOnException_ {PauseOnExceptionsState::NONE}; DebuggerState debuggerState_ {DebuggerState::ENABLED}; bool pauseOnNextByteCode_ {false}; @@ -337,10 +319,6 @@ private: JsDebuggerManager::SingleStepperFunc stepperFunc_ {nullptr}; JsDebuggerManager::ReturnNativeFunc returnNative_ {nullptr}; std::vector debuggerExtendedProtocols_ {}; - // For launch accelerate mode - std::unordered_map, HashBreakpointInfo>> - breakpointPendingMap_ {}; - bool breakOnStartEnable_ {true}; friend class JSPtHooks; friend class test::TestHooks; diff --git a/tooling/backend/js_pt_hooks.cpp b/tooling/backend/js_pt_hooks.cpp index 4c484ed4..b704d8b6 100644 --- a/tooling/backend/js_pt_hooks.cpp +++ b/tooling/backend/js_pt_hooks.cpp @@ -84,9 +84,7 @@ void JSPtHooks::LoadModule(std::string_view pandaFileName, std::string_view entr [[maybe_unused]] LocalScope scope(debugger_->vm_); if (debugger_->NotifyScriptParsed(pandaFileName.data(), entryPoint)) { - if (!debugger_->IsLaunchAccelerateMode()) { - firstTime_ = true; - } + firstTime_ = true; } } @@ -112,15 +110,8 @@ void JSPtHooks::SendableMethodEntry(JSHandle method) [[maybe_unused]] LocalScope scope(debugger_->vm_); - if (debugger_->NotifyScriptParsedBySendable(method)) { - if (!debugger_->IsLaunchAccelerateMode()) { - firstTime_ = true; - } - } -} - -void JSPtHooks::DisableFirstTimeFlag() -{ - firstTime_ = false; + if (debugger_->SendableMethodEntry(method)) { + firstTime_ = true; + }; } } // namespace panda::ecmascript::tooling diff --git a/tooling/backend/js_pt_hooks.h b/tooling/backend/js_pt_hooks.h index 58c76e4f..a8429053 100644 --- a/tooling/backend/js_pt_hooks.h +++ b/tooling/backend/js_pt_hooks.h @@ -41,7 +41,6 @@ public: void VmStart() override {} void VmDeath() override {} void SendableMethodEntry(JSHandle method) override; - void DisableFirstTimeFlag() override; private: NO_COPY_SEMANTIC(JSPtHooks); diff --git a/tooling/base/pt_events.cpp b/tooling/base/pt_events.cpp index f3a4e608..88f7ef01 100644 --- a/tooling/base/pt_events.cpp +++ b/tooling/base/pt_events.cpp @@ -191,15 +191,6 @@ std::unique_ptr ScriptParsed::ToJson() const result->Add("embedderName", embedderName_->c_str()); } - std::unique_ptr array = PtJson::CreateArray(); - size_t len = locations_.size(); - for (size_t i = 0; i < len; i++) { - ASSERT(locations_[i] != nullptr); - std::unique_ptr location = locations_[i]->ToJson(); - array->Push(location); - } - result->Add("locations", array); - std::unique_ptr object = PtJson::CreateObject(); object->Add("method", GetName().c_str()); object->Add("params", result); diff --git a/tooling/base/pt_events.h b/tooling/base/pt_events.h index 9d1bea7e..47aa85d5 100644 --- a/tooling/base/pt_events.h +++ b/tooling/base/pt_events.h @@ -808,12 +808,6 @@ public: return embedderName_.has_value(); } - ScriptParsed &SetLocations(std::vector> locations) - { - locations_ = locations; - return *this; - } - private: NO_COPY_SEMANTIC(ScriptParsed); NO_MOVE_SEMANTIC(ScriptParsed); @@ -835,7 +829,6 @@ private: std::optional codeOffset_ {}; std::optional scriptLanguage_ {}; std::optional embedderName_ {}; - std::vector> locations_ {}; }; class AddHeapSnapshotChunk final : public PtBaseEvents { diff --git a/tooling/base/pt_json.cpp b/tooling/base/pt_json.cpp index d265606c..94b592e7 100644 --- a/tooling/base/pt_json.cpp +++ b/tooling/base/pt_json.cpp @@ -249,22 +249,6 @@ std::string PtJson::GetKey() const return std::string(object_->string); } -std::vector PtJson::GetKeysArray() const -{ - std::vector result; - if (object_ == nullptr) { - return result; - } - cJSON *node = object_->child; - while (node != nullptr) { - if (node->string != nullptr) { - result.emplace_back(std::string(node->string)); - } - node = node->next; - } - return result; -} - cJSON *PtJson::GetJson() const { return object_; diff --git a/tooling/base/pt_json.h b/tooling/base/pt_json.h index dcaa0b8b..d66e0d7f 100644 --- a/tooling/base/pt_json.h +++ b/tooling/base/pt_json.h @@ -18,7 +18,6 @@ #include #include -#include #include "cJSON.h" #include "common/macros.h" @@ -74,8 +73,6 @@ public: std::string GetKey() const; - std::vector GetKeysArray() const; - cJSON *GetJson() const; // Type check diff --git a/tooling/base/pt_params.cpp b/tooling/base/pt_params.cpp index 3f5934db..293db741 100644 --- a/tooling/base/pt_params.cpp +++ b/tooling/base/pt_params.cpp @@ -30,22 +30,6 @@ std::unique_ptr EnableParams::Create(const PtJson ¶ms) error += "Wrong type of 'maxScriptsCacheSize';"; } - std::unique_ptr options; - std::vector enableOptionsList; - ret = params.GetArray("options", &options); - if (ret == Result::SUCCESS) { - int32_t length = options->GetSize(); - for (int32_t i = 0; i < length; i++) { - auto option = options->Get(i); - if (option != nullptr && option->IsString()) { - enableOptionsList.emplace_back(option->GetString()); - } - } - paramsObject->enableOptionList_ = enableOptionsList; - } else if (ret == Result::TYPE_ERROR) { - error += "Wrong type of 'options';"; - } - if (!error.empty()) { LOG_DEBUGGER(ERROR) << "EnableParams::Create " << error; return nullptr; @@ -1317,49 +1301,4 @@ std::unique_ptr SeriliazationTimeoutCheck } return paramsObject; } - -std::unique_ptr SaveAllPossibleBreakpointsParams::Create(const PtJson ¶ms) -{ - auto paramsObject = std::make_unique(); - std::unordered_map>> breakpointMap {}; - std::string error; - Result ret; - - std::unique_ptr locationList; - ret = params.GetObject("locations", &locationList); - if (ret != Result::SUCCESS) { - LOG_DEBUGGER(ERROR) << "SaveAllPossibleBreakpointsParams::Get Breakpoints location: " << error; - return nullptr; - } - - auto keys = locationList->GetKeysArray(); - std::unique_ptr breakpoints; - for (const auto &key : keys) { - ret = locationList->GetArray(key.c_str(), &breakpoints); - if (ret == Result::SUCCESS) { - int32_t length = breakpoints->GetSize(); - std::vector> breakpointList; - for (int32_t i = 0; i < length; i++) { - auto json = *breakpoints->Get(i); - json.Add("url", key.c_str()); - std::shared_ptr info = BreakpointInfo::Create(json); - if (info == nullptr) { - error += "'breakpoints' items BreakpointInfo is invalid;"; - break; - } - breakpointList.emplace_back(std::move(info)); - } - breakpointMap[key] = breakpointList; - } else if (ret == Result::TYPE_ERROR) { - error += "Wrong type of 'breakpoints'"; - } - } - if (!error.empty()) { - LOG_DEBUGGER(ERROR) << "SaveAllPossibleBreakpointsParams::Create " << error; - return nullptr; - } - paramsObject->breakpointsMap_ = breakpointMap; - - return paramsObject; -} } // namespace panda::ecmascript::tooling diff --git a/tooling/base/pt_params.h b/tooling/base/pt_params.h index 404616ef..ea8a5110 100644 --- a/tooling/base/pt_params.h +++ b/tooling/base/pt_params.h @@ -74,23 +74,11 @@ public: return maxScriptsCacheSize_.has_value(); } - bool HasEnableOptionsList() const - { - return enableOptionList_.has_value(); - } - - std::vector GetEnableOptionsList() const - { - ASSERT(HasEnableOptionsList()); - return enableOptionList_.value(); - } - private: NO_COPY_SEMANTIC(EnableParams); NO_MOVE_SEMANTIC(EnableParams); std::optional maxScriptsCacheSize_ {}; - std::optional> enableOptionList_ {}; }; class EvaluateOnCallFrameParams : public PtBaseParams { @@ -1382,33 +1370,5 @@ private: static constexpr int32_t DEFAULT_THRESHOLD = 8; int32_t threshold_ { DEFAULT_THRESHOLD }; }; - -class SaveAllPossibleBreakpointsParams : public PtBaseParams { -public: - SaveAllPossibleBreakpointsParams() = default; - ~SaveAllPossibleBreakpointsParams() = default; - - static std::unique_ptr Create(const PtJson ¶ms); - - const std::unordered_map>> *GetBreakpointsMap() const - { - if (!HasBreakpointsMap()) { - return nullptr; - } - return &(breakpointsMap_.value()); - } - - bool HasBreakpointsMap() const - { - return breakpointsMap_.has_value(); - } - -private: - NO_COPY_SEMANTIC(SaveAllPossibleBreakpointsParams); - NO_MOVE_SEMANTIC(SaveAllPossibleBreakpointsParams); - - std::optional>>> - breakpointsMap_ {}; -}; } // namespace panda::ecmascript::tooling #endif \ No newline at end of file diff --git a/tooling/base/pt_returns.h b/tooling/base/pt_returns.h index d9dfa1ef..dea06ed9 100644 --- a/tooling/base/pt_returns.h +++ b/tooling/base/pt_returns.h @@ -85,7 +85,7 @@ private: class GetPossibleAndSetBreakpointByUrlReturns : public PtBaseReturns { public: - explicit GetPossibleAndSetBreakpointByUrlReturns(std::vector> locations) + explicit GetPossibleAndSetBreakpointByUrlReturns(std::vector> locations) : locations_(std::move(locations)) {} ~GetPossibleAndSetBreakpointByUrlReturns() override = default; @@ -97,7 +97,7 @@ private: NO_COPY_SEMANTIC(GetPossibleAndSetBreakpointByUrlReturns); NO_MOVE_SEMANTIC(GetPossibleAndSetBreakpointByUrlReturns); - std::vector> locations_ {}; + std::vector> locations_ {}; }; class EvaluateOnCallFrameReturns : public PtBaseReturns { diff --git a/tooling/base/pt_script.h b/tooling/base/pt_script.h index 2d797e2b..d401881c 100644 --- a/tooling/base/pt_script.h +++ b/tooling/base/pt_script.h @@ -102,16 +102,6 @@ public: endLine_ = endLine; } - std::vector> GetLocations() const - { - return locations_; - } - - void SetLocations(std::vector> locations) - { - locations_ = locations; - } - private: NO_COPY_SEMANTIC(PtScript); NO_MOVE_SEMANTIC(PtScript); @@ -123,7 +113,6 @@ private: std::string scriptSource_ {}; // js source code std::string sourceMapUrl_ {}; // source map url int32_t endLine_ {0}; // total line number of source file - std::vector> locations_ {}; }; } // namespace panda::ecmascript::tooling #endif diff --git a/tooling/base/pt_types.cpp b/tooling/base/pt_types.cpp index a161ce9a..73aab2f7 100644 --- a/tooling/base/pt_types.cpp +++ b/tooling/base/pt_types.cpp @@ -3386,18 +3386,6 @@ std::unique_ptr BreakpointInfo::Create(const PtJson ¶ms) return paramsObject; } -std::shared_ptr BreakpointInfo::CreateAsSharedPtr(int32_t line, int32_t column, - std::string url, std::string condition) -{ - auto result = std::make_shared(); - result->lineNumber_ = line; - result->columnNumber_ = column; - result->url_ = url; - result->condition_ = condition; - - return result; -} - std::unique_ptr BreakpointInfo::ToJson() const { std::unique_ptr result = PtJson::CreateObject(); diff --git a/tooling/base/pt_types.h b/tooling/base/pt_types.h index 39efb84e..03a2b66b 100644 --- a/tooling/base/pt_types.h +++ b/tooling/base/pt_types.h @@ -100,8 +100,6 @@ public: ~BreakpointInfo() override = default; static std::unique_ptr Create(const PtJson ¶ms); - static std::shared_ptr CreateAsSharedPtr(int32_t line, int32_t column, - std::string url, std::string condition = ""); std::unique_ptr ToJson() const override; int32_t GetLineNumber() const @@ -175,15 +173,6 @@ private: std::optional restrictToFunction_ {}; }; -class HashBreakpointInfo { -public: - size_t operator()(const std::shared_ptr &bpoint) const - { - return (std::hash()(bpoint->GetUrl())) ^ - (std::hash()(bpoint->GetLineNumber())) ^ - (std::hash()(bpoint->GetColumnNumber())); - } -}; // Runtime.ScriptId using ScriptId = int32_t; diff --git a/tooling/client/domain/debugger_client.cpp b/tooling/client/domain/debugger_client.cpp index 7c5612e8..1e21e836 100644 --- a/tooling/client/domain/debugger_client.cpp +++ b/tooling/client/domain/debugger_client.cpp @@ -54,8 +54,6 @@ bool DebuggerClient::DispatcherCmd(const std::string &cmd) { "step-into", std::bind(&DebuggerClient::StepIntoCommand, this)}, { "step-out", std::bind(&DebuggerClient::StepOutCommand, this)}, { "step-over", std::bind(&DebuggerClient::StepOverCommand, this)}, - { "enable-launch-accelerate", std::bind(&DebuggerClient::EnableLaunchAccelerateCommand, this)}, - { "saveAllPossibleBreakpoints", std::bind(&DebuggerClient::SaveAllPossibleBreakpointsCommand, this)}, }; auto entry = dispatcherTable.find(cmd); @@ -435,57 +433,4 @@ void DebuggerClient::handleResponse(std::unique_ptr json) } return; } - -int DebuggerClient::SaveAllPossibleBreakpointsCommand() -{ - Session *session = SessionManager::getInstance().GetSessionById(sessionId_); - uint32_t id = session->GetMessageId(); - - std::unique_ptr request = PtJson::CreateObject(); - request->Add("id", id); - request->Add("method", "Debugger.saveAllPossibleBreakpoints"); - - std::unique_ptr params = PtJson::CreateObject(); - std::unique_ptr locations = PtJson::CreateObject(); - std::unique_ptr vector = PtJson::CreateArray(); - - std::unique_ptr bp = PtJson::CreateObject(); - bp->Add("lineNumber", breakPointInfoList_.back().lineNumber); - bp->Add("columnNumber", breakPointInfoList_.back().columnNumber); - vector->Push(bp); - locations->Add(breakPointInfoList_.back().url.c_str(), vector); - params->Add("locations", locations); - request->Add("params", params); - - std::string message = request->Stringify(); - if (session->ClientSendReq(message)) { - session->GetDomainManager().SetDomainById(id, "Debugger"); - } - - return 0; -} - -int DebuggerClient::EnableLaunchAccelerateCommand() -{ - Session *session = SessionManager::getInstance().GetSessionById(sessionId_); - uint32_t id = session->GetMessageId(); - - std::unique_ptr request = PtJson::CreateObject(); - request->Add("id", id); - request->Add("method", "Debugger.enable"); - - std::unique_ptr params = PtJson::CreateObject(); - std::unique_ptr options = PtJson::CreateArray(); - - options->Push("enableLaunchAccelerate"); - params->Add("options", options); - request->Add("params", params); - - std::string message = request->Stringify(); - if (session->ClientSendReq(message)) { - session->GetDomainManager().SetDomainById(id, "Debugger"); - } - - return 0; -} } // OHOS::ArkCompiler::Toolchain \ No newline at end of file diff --git a/tooling/client/domain/debugger_client.h b/tooling/client/domain/debugger_client.h index aaeffd40..ddf03031 100644 --- a/tooling/client/domain/debugger_client.h +++ b/tooling/client/domain/debugger_client.h @@ -59,8 +59,6 @@ public: int StepIntoCommand(); int StepOutCommand(); int StepOverCommand(); - int EnableLaunchAccelerateCommand(); - int SaveAllPossibleBreakpointsCommand(); void AddBreakPointInfo(const std::string& url, const int& lineNumber, const int& columnNumber = 0); void RecvReply(std::unique_ptr json); diff --git a/tooling/client/utils/cli_command.cpp b/tooling/client/utils/cli_command.cpp index 477a8287..8fb86ac2 100644 --- a/tooling/client/utils/cli_command.cpp +++ b/tooling/client/utils/cli_command.cpp @@ -182,10 +182,6 @@ void CliCommand::CreateCommandMap() {std::make_pair("enable", "enable"), std::bind(&CliCommand::DebuggerCommand, this, "enable")}, {std::make_pair("finish", "fin"), std::bind(&CliCommand::DebuggerCommand, this, "finish")}, {std::make_pair("frame", "f"), std::bind(&CliCommand::DebuggerCommand, this, "frame")}, - {std::make_pair("enable-launch-accelerate", "enable-acc"), - std::bind(&CliCommand::DebuggerCommand, this, "enable-launch-accelerate")}, - {std::make_pair("saveAllPossibleBreakpoints", "b-new"), - std::bind(&CliCommand::SaveAllPossibleBreakpointsCommand, this, "saveAllPossibleBreakpoints")}, }; CreateOtherCommandMap(); } @@ -626,11 +622,6 @@ ErrCode CliCommand::TestCommand(const std::string &cmd) return ErrCode::ERR_OK; } -ErrCode CliCommand::SaveAllPossibleBreakpointsCommand(const std::string &cmd) -{ - return BreakCommand(cmd); -} - ErrCode CliCommand::ExecHelpCommand() { std::cout << HELP_MSG; diff --git a/tooling/client/utils/cli_command.h b/tooling/client/utils/cli_command.h index 88cafd29..2720521d 100644 --- a/tooling/client/utils/cli_command.h +++ b/tooling/client/utils/cli_command.h @@ -72,7 +72,6 @@ public: ErrCode SessionSwitchCommand(const std::string &cmd); ErrCode TestCommand(const std::string &cmd); ErrCode ExecHelpCommand(); - ErrCode SaveAllPossibleBreakpointsCommand(const std::string &cmd); void OutputCommand(const std::string &cmd, bool flag); VecStr GetArgList() diff --git a/tooling/test/client_utils/test_list.cpp b/tooling/test/client_utils/test_list.cpp index 233b6c48..cdd96ac0 100644 --- a/tooling/test/client_utils/test_list.cpp +++ b/tooling/test/client_utils/test_list.cpp @@ -70,7 +70,6 @@ #include "tooling/test/testcases/js_heapusage_loop_test.h" #include "tooling/test/testcases/js_heapusage_recursion_test.h" #include "tooling/test/testcases/js_smart_stepInto_test.h" -#include "tooling/test/testcases/js_accelerate_launch_test.h" namespace panda::ecmascript::tooling::test { static std::string g_currentTestName = ""; @@ -130,7 +129,6 @@ static void RegisterTests() TestUtil::RegisterTest("JsHeapusageLoopTest", GetJsHeapusageLoopTest()); TestUtil::RegisterTest("JsHeapusageRecursionTest", GetJsHeapusageRecursionTest()); TestUtil::RegisterTest("JsSmartStepoutTest", GetJsSmartStepoutTest()); - TestUtil::RegisterTest("JsAccelerateLaunchTest", GetJsAccelerateLaunchTest()); } std::vector GetTestList() diff --git a/tooling/test/debugger_impl_test.cpp b/tooling/test/debugger_impl_test.cpp index 7d0e3654..0fbb8811 100644 --- a/tooling/test/debugger_impl_test.cpp +++ b/tooling/test/debugger_impl_test.cpp @@ -194,43 +194,6 @@ HWTEST_F_L0(DebuggerImplTest, Dispatcher_Dispatch_Enable__002) } } -HWTEST_F_L0(DebuggerImplTest, Dispatcher_Dispatch_Enable_Accelerate_Launch_Mode) -{ - std::string outStrForCallbackCheck = ""; - std::function callback = - [&outStrForCallbackCheck]([[maybe_unused]] const void *ptr, const std::string &inStrOfReply) { - outStrForCallbackCheck = inStrOfReply;}; - ProtocolChannel *protocolChannel = new ProtocolHandler(callback, ecmaVm); - auto runtimeImpl = std::make_unique(ecmaVm, protocolChannel); - auto debuggerImpl = std::make_unique(ecmaVm, protocolChannel, runtimeImpl.get()); - auto dispatcherImpl = std::make_unique(protocolChannel, std::move(debuggerImpl)); - EXPECT_FALSE(ecmaVm->GetJsDebuggerManager()->IsDebugMode()); - - std::string msg = std::string() + - R"({ - "id":0, - "method":"Debugger.enable", - "params":{ - "maxScriptsCacheSize":1024, - "options":[ - "enableLaunchAccelerate" - ] - } - })"; - DispatchRequest request(msg); - dispatcherImpl->Dispatch(request); - - bool condition = outStrForCallbackCheck.find("protocols") != std::string::npos && - outStrForCallbackCheck.find("debuggerId") != std::string::npos && - outStrForCallbackCheck.find("saveAllPossibleBreakpoints") != std::string::npos; - EXPECT_TRUE(condition); - EXPECT_TRUE(ecmaVm->GetJsDebuggerManager()->IsDebugMode()); - if (protocolChannel) { - delete protocolChannel; - protocolChannel = nullptr; - } -} - HWTEST_F_L0(DebuggerImplTest, Dispatcher_Dispatch_Disable__001) { std::string outStrForCallbackCheck = ""; diff --git a/tooling/test/debugger_params_test.cpp b/tooling/test/debugger_params_test.cpp index f01dcc53..07877ed9 100644 --- a/tooling/test/debugger_params_test.cpp +++ b/tooling/test/debugger_params_test.cpp @@ -224,45 +224,6 @@ HWTEST_F_L0(DebuggerParamsTest, EnableParamsCreateTest) EXPECT_EQ(enableParams->GetMaxScriptsCacheSize(), 100); } -HWTEST_F_L0(DebuggerParamsTest, EnableParamsAccelerateLaunchModeCreateTest) -{ - std::string msg; - std::unique_ptr enableParams; - - // abnormal - msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; - enableParams = EnableParams::Create(DispatchRequest(msg).GetParams()); - ASSERT_NE(enableParams, nullptr); - EXPECT_FALSE(enableParams->HasMaxScriptsCacheSize()); - - // normal - msg = std::string() + R"({"id":0,"method":"Debugger.Test", - "params":{"options":["enableLaunchAccelerate"], "maxScriptsCacheSize":100}})"; - enableParams = EnableParams::Create(DispatchRequest(msg).GetParams()); - ASSERT_NE(enableParams, nullptr); - EXPECT_EQ(enableParams->GetMaxScriptsCacheSize(), 100); - EXPECT_EQ(enableParams->GetEnableOptionsList().size(), 1); -} - -HWTEST_F_L0(DebuggerParamsTest, SaveAllPossibleBreakpointsParamsCreateTest) -{ - std::string msg; - std::unique_ptr params; - - // abnormal - msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; - params = SaveAllPossibleBreakpointsParams::Create(DispatchRequest(msg).GetParams()); - ASSERT_EQ(params, nullptr); - - // normal - msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ - "locations":{"actualUrl/actualFileName.ts":[{"lineNumber": 7, "columnNumber": 8}]}}})"; - params = SaveAllPossibleBreakpointsParams::Create(DispatchRequest(msg).GetParams()); - ASSERT_NE(params, nullptr); - EXPECT_TRUE(params->HasBreakpointsMap()); - EXPECT_EQ(params->GetBreakpointsMap()->size(), 1); -} - HWTEST_F_L0(DebuggerParamsTest, StartSamplingParamsCreateTest) { std::string msg; diff --git a/tooling/test/debugger_returns_test.cpp b/tooling/test/debugger_returns_test.cpp index abe1dfd4..28062b6b 100644 --- a/tooling/test/debugger_returns_test.cpp +++ b/tooling/test/debugger_returns_test.cpp @@ -417,12 +417,12 @@ HWTEST_F_L0(DebuggerReturnsTest, SearchInContentReturnsToJsonTest) HWTEST_F_L0(DebuggerReturnsTest, GetPossibleAndSetBreakpointByUrlReturnsToJsonTest) { - auto locations = std::vector>(); - std::shared_ptr breakpointReturnInfo = std::make_shared(); + auto locations = std::vector>(); + std::unique_ptr breakpointReturnInfo = std::make_unique(); breakpointReturnInfo->SetScriptId(11).SetLineNumber(1).SetColumnNumber(44); - locations.emplace_back(breakpointReturnInfo); + locations.emplace_back(std::move(breakpointReturnInfo)); std::unique_ptr getPossibleAndSetBreakpointByUrlReturns = std::make_unique - (locations); + (std::move(locations)); std::unique_ptr locationsJS; ASSERT_EQ(getPossibleAndSetBreakpointByUrlReturns->ToJson()->GetArray("locations", &locationsJS), Result::SUCCESS); ASSERT_NE(locationsJS, nullptr); diff --git a/tooling/test/debugger_script_test.cpp b/tooling/test/debugger_script_test.cpp index 38562947..ce1492c3 100644 --- a/tooling/test/debugger_script_test.cpp +++ b/tooling/test/debugger_script_test.cpp @@ -106,16 +106,4 @@ HWTEST_F_L0(DebuggerScriptTest, EndLineTest) script->SetEndLine(200); ASSERT_EQ(script->GetEndLine(), 200); } - -HWTEST_F_L0(DebuggerScriptTest, LocationsTest) -{ - std::unique_ptr script = std::make_unique(1, "name_1", "url_1", "source_1"); - std::vector> locations {}; - std::shared_ptr bpInfo = std::make_shared(); - std::string invalidBpId = "invalid"; - bpInfo->SetId(invalidBpId).SetLineNumber(1).SetColumnNumber(0); - locations.emplace_back(bpInfo); - script->SetLocations(locations); - ASSERT_EQ(script->GetLocations().size(), 1); -} } // namespace panda::test \ No newline at end of file diff --git a/tooling/test/pt_json_test.cpp b/tooling/test/pt_json_test.cpp index c128aedb..9f42e46a 100644 --- a/tooling/test/pt_json_test.cpp +++ b/tooling/test/pt_json_test.cpp @@ -313,15 +313,4 @@ HWTEST_F_L0(PtJsonTest, ResultUInt64Test) ASSERT_EQ(test->GetUInt64("b", &ui64), Result::SUCCESS); EXPECT_EQ(ui64, static_cast(100)); } - -HWTEST_F_L0(PtJsonTest, GetKeysArraytest) -{ - auto test = PtJson::CreateObject(); - test->Add("a", "ResultUInt64Test"); - test->Add("b", 100); - auto keys = test->GetKeysArray(); - EXPECT_EQ(keys.size(), 2); - EXPECT_TRUE(keys.at(0) == "a"); - EXPECT_TRUE(keys.at(1) == "b"); -} } \ No newline at end of file diff --git a/tooling/test/testcases/js_accelerate_launch_test.h b/tooling/test/testcases/js_accelerate_launch_test.h deleted file mode 100644 index 45366e4a..00000000 --- a/tooling/test/testcases/js_accelerate_launch_test.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * 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_TEST_TESTCASES_JS_ACCELERATE_LAUNCH_TEST_H -#define ECMASCRIPT_TOOLING_TEST_TESTCASES_JS_ACCELERATE_LAUNCH_TEST_H - -#include "tooling/test/client_utils/test_util.h" - -namespace panda::ecmascript::tooling::test { -class JsAccelerateLaunchTest : public TestActions { -public: - JsAccelerateLaunchTest() - { - testAction = { - // Enable Accelerate Launch Mode - {SocketAction::SEND, "enable-acc"}, - {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, - {SocketAction::SEND, "runtime-enable"}, - {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, - // Debugger.saveAllPossibleBreakpoints - {SocketAction::SEND, "b-new " DEBUGGER_JS_DIR "sample.js 22"}, - {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, - {SocketAction::SEND, "run"}, - {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, - // load sample.js - {SocketAction::RECV, "Debugger.scriptParsed", ActionRule::STRING_CONTAIN}, - {SocketAction::RECV, "Debugger.paused", ActionRule::STRING_CONTAIN}, - {SocketAction::SEND, "resume"}, - {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN}, - {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, - {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE, [this] (auto recv, auto, auto) -> bool { - std::unique_ptr json = PtJson::Parse(recv); - Result ret; - std::string method; - ret = json->GetString("method", &method); - if (ret != Result::SUCCESS || method != "Debugger.paused") { - return false; - } - - std::unique_ptr params = nullptr; - ret = json->GetObject("params", ¶ms); - if (ret != Result::SUCCESS) { - return false; - } - - std::unique_ptr hitBreakpoints = nullptr; - ret = params->GetArray("hitBreakpoints", &hitBreakpoints); - if (ret != Result::SUCCESS) { - return false; - } - - std::string breakpoint; - breakpoint = hitBreakpoints->Get(0)->GetString(); - if (ret != Result::SUCCESS || breakpoint.find(sourceFile_) == std::string::npos || - breakpoint.find("21") == std::string::npos) { - return false; - } - return true; - }}, - {SocketAction::SEND, "b " DEBUGGER_JS_DIR "sample.js 23"}, - {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, - {SocketAction::SEND, "resume"}, - {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN}, - {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, - {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE, [this] (auto recv, auto, auto) -> bool { - std::unique_ptr json = PtJson::Parse(recv); - Result ret; - std::string method; - ret = json->GetString("method", &method); - if (ret != Result::SUCCESS || method != "Debugger.paused") { - return false; - } - - std::unique_ptr params = nullptr; - ret = json->GetObject("params", ¶ms); - if (ret != Result::SUCCESS) { - return false; - } - - std::unique_ptr hitBreakpoints = nullptr; - ret = params->GetArray("hitBreakpoints", &hitBreakpoints); - if (ret != Result::SUCCESS) { - return false; - } - - std::string breakpoint; - breakpoint = hitBreakpoints->Get(0)->GetString(); - if (ret != Result::SUCCESS || breakpoint.find(sourceFile_) == std::string::npos || - breakpoint.find("22") == std::string::npos) { - return false; - } - return true; - }}, - {SocketAction::SEND, "success"}, - {SocketAction::SEND, "resume"}, - {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN}, - {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, - }; - } - - std::pair GetEntryPoint() override - { - return {pandaFile_, entryPoint_}; - } - ~JsAccelerateLaunchTest() = default; - -private: - std::string pandaFile_ = DEBUGGER_ABC_DIR "sample.abc"; - std::string sourceFile_ = DEBUGGER_JS_DIR "sample.js"; - std::string entryPoint_ = "_GLOBAL::func_main_0"; -}; - -std::unique_ptr GetJsAccelerateLaunchTest() -{ - return std::make_unique(); -} -} // namespace panda::ecmascript::tooling::test - -#endif // ECMASCRIPT_TOOLING_TEST_TESTCASES_JS_ACCELERATE_LAUNCH_TEST_H diff --git a/tooling/test/utils/test_hooks.h b/tooling/test/utils/test_hooks.h index 1fd7e2bd..88cda04a 100644 --- a/tooling/test/utils/test_hooks.h +++ b/tooling/test/utils/test_hooks.h @@ -118,8 +118,6 @@ public: void SendableMethodEntry([[maybe_unused]] JSHandle method) override {} - void DisableFirstTimeFlag() override {} - void TerminateTest() { debugInterface_->UnregisterHooks(); -- Gitee From e092528160ea60870b282acd23b3f06328217662 Mon Sep 17 00:00:00 2001 From: wuzhefengh Date: Tue, 3 Dec 2024 22:47:37 +0800 Subject: [PATCH 11/48] [Bug]: Fix macos's standalone compilation failure When using standalone compilation for macpro, there is a failure when compiling ark_multi target. The root cause is the missing of a log implementation in the BUILD.gn. Issue: https://gitee.com/openharmony/arkcompiler_toolchain/issues/IB8TVI Testing: pass related compilation. Signed-off-by: wuzhefengh Change-Id: I48fdf549bf992112944c6b852f51482af7eebbcb --- tooling/client/ark_multi/BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/tooling/client/ark_multi/BUILD.gn b/tooling/client/ark_multi/BUILD.gn index d7b63e2e..f4e9d1fe 100644 --- a/tooling/client/ark_multi/BUILD.gn +++ b/tooling/client/ark_multi/BUILD.gn @@ -15,6 +15,7 @@ import("//arkcompiler/toolchain/toolchain.gni") ohos_executable("ark_multi") { sources = [ + "../../../common/log_wrapper.cpp", "../../utils/utils.cpp", "main.cpp", ] -- Gitee From d526fc57edb5f72ce834b2fbbd8004124ca1ef7d Mon Sep 17 00:00:00 2001 From: fangting Date: Wed, 6 Nov 2024 08:50:20 +0800 Subject: [PATCH 12/48] new inspector instead of return Issue:#IB2C5R Signed-off-by: fangting --- inspector/connect_inspector.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inspector/connect_inspector.cpp b/inspector/connect_inspector.cpp index 4fdb8579..e145c15a 100644 --- a/inspector/connect_inspector.cpp +++ b/inspector/connect_inspector.cpp @@ -238,7 +238,7 @@ void StoreInspectorInfo(const std::string& jsonTreeStr, const std::string& jsonS { std::lock_guard lock(g_connectMutex); if (g_inspector == nullptr) { - return; + g_inspector = std::make_unique(); } g_inspector->layoutInspectorInfo_.tree = jsonTreeStr; g_inspector->layoutInspectorInfo_.snapShot = jsonSnapshotStr; -- Gitee From f41fc3260a066ccf734c11e1cfab88862e3bd0aa Mon Sep 17 00:00:00 2001 From: fangting Date: Fri, 6 Dec 2024 15:24:29 +0800 Subject: [PATCH 13/48] fix bug change log Issue:#IB9KQ4 Signed-off-by: fangting --- bundle.json | 2 +- tooling/agent/debugger_impl.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bundle.json b/bundle.json index 4b3ca904..9b231fae 100644 --- a/bundle.json +++ b/bundle.json @@ -3,7 +3,7 @@ "version": "3.1", "description": "arkcompiler toolchain", "homePage": "https://gitee.com/openharmony", - "license": "Apache Liscense 2.0", + "license": "Apache License 2.0", "publishAs": "code-segment", "scripts": {}, "dirs": [], diff --git a/tooling/agent/debugger_impl.cpp b/tooling/agent/debugger_impl.cpp index 4d111cb5..e614a656 100755 --- a/tooling/agent/debugger_impl.cpp +++ b/tooling/agent/debugger_impl.cpp @@ -141,7 +141,7 @@ bool DebuggerImpl::CheckScriptParsed([[maybe_unused]] const std::string &fileNam && !defined(PANDA_TARGET_ANDROID) && !defined(PANDA_TARGET_IOS) \ && !defined(PANDA_TARGET_LINUX) if (fileName.substr(0, DATA_APP_PATH.length()) != DATA_APP_PATH) { - LOG_DEBUGGER(DEBUG) << "SendableScriptParsed: unsupport file: " << fileName; + LOG_DEBUGGER(DEBUG) << "CheckScriptParsed: unsupport file: " << fileName; return false; } #endif -- Gitee From 31fb38bcdc256c7a3816c83a93cc006478d08366 Mon Sep 17 00:00:00 2001 From: fangting Date: Mon, 9 Dec 2024 15:29:01 +0800 Subject: [PATCH 14/48] fix url error Issue:#IB9XC2 Signed-off-by: fangting --- tooling/agent/debugger_impl.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tooling/agent/debugger_impl.cpp b/tooling/agent/debugger_impl.cpp index e614a656..188af24b 100755 --- a/tooling/agent/debugger_impl.cpp +++ b/tooling/agent/debugger_impl.cpp @@ -88,6 +88,11 @@ bool DebuggerImpl::NotifyScriptParsed(const std::string &fileName, std::string_v return false; } + if (!vm_->GetJsDebuggerManager()->GetFaApp() && jsPandaFile->IsBundlePack()) { + LOG_DEBUGGER(DEBUG) << "NotifyScriptParsed: Unmerge file: " << fileName; + return false; + } + const char *recordName = entryPoint.data(); auto mainMethodIndex = panda_file::File::EntityId(jsPandaFile->GetMainMethodIndex(recordName)); const std::string &source = extractor->GetSourceCode(mainMethodIndex); -- Gitee From 7045cc12522622802d951a1275693cda727844c1 Mon Sep 17 00:00:00 2001 From: yanzhiqi1 Date: Wed, 11 Dec 2024 16:52:52 +0800 Subject: [PATCH 15/48] Check the parameters before using stoi Issue: #IBANS6 Signed-off-by: yanzhiqi1 --- tooling/client/utils/cli_command.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tooling/client/utils/cli_command.cpp b/tooling/client/utils/cli_command.cpp index 8fb86ac2..b6b0f170 100644 --- a/tooling/client/utils/cli_command.cpp +++ b/tooling/client/utils/cli_command.cpp @@ -505,6 +505,9 @@ ErrCode CliCommand::PrintCommand(const std::string &cmd) Session *session = SessionManager::getInstance().GetSessionById(sessionId_); RuntimeClient &runtimeClient = session->GetDomainManager().GetRuntimeClient(); if (GetArgList().size() == 1) { + if (!Utils::IsNumber(GetArgList()[0])) { + return ErrCode::ERR_FAIL; + } runtimeClient.SetIsInitializeTree(false); VariableManager &variableManager = session->GetVariableManager(); int32_t objectId = variableManager.FindObjectIdWithIndex(std::stoi(GetArgList()[0])); -- Gitee From 3151df6cb1a9e9e7e0ec5aa4ef00be5752112ba2 Mon Sep 17 00:00:00 2001 From: fangting Date: Fri, 13 Dec 2024 14:34:45 +0800 Subject: [PATCH 16/48] export jsframes Issue:#IBAFAY Signed-off-by: fangting --- inspector/inspector.cpp | 23 ++++++++++++++++++++++- inspector/inspector.h | 3 ++- tooling/agent/debugger_impl.cpp | 19 +++++++++++++++++++ tooling/agent/debugger_impl.h | 2 ++ tooling/debugger_service.cpp | 22 ++++++++++++++++++++++ tooling/debugger_service.h | 2 ++ tooling/dispatcher.cpp | 10 ++++++++++ tooling/dispatcher.h | 1 + tooling/protocol_handler.h | 4 ++++ 9 files changed, 84 insertions(+), 2 deletions(-) diff --git a/inspector/inspector.cpp b/inspector/inspector.cpp index 030dbdde..ad49ee3d 100644 --- a/inspector/inspector.cpp +++ b/inspector/inspector.cpp @@ -51,6 +51,7 @@ using WaitForDebugger = void(*)(void*); using OnMessage = void(*)(void*, std::string&&); using ProcessMessage = void(*)(void*); using GetDispatchStatus = int32_t(*)(void*); +using GetCallFrames = char*(*)(void*); OnMessage g_onMessage = nullptr; InitializeDebugger g_initializeDebugger = nullptr; @@ -58,6 +59,7 @@ UninitializeDebugger g_uninitializeDebugger = nullptr; WaitForDebugger g_waitForDebugger = nullptr; ProcessMessage g_processMessage = nullptr; GetDispatchStatus g_getDispatchStatus = nullptr; +GetCallFrames g_getCallFrames = nullptr; std::atomic g_hasArkFuncsInited = false; std::unordered_map g_inspectors; @@ -216,6 +218,12 @@ bool InitializeArkFunctionsOthers() ResetServiceLocked(g_vm, true); return false; } + g_getCallFrames = reinterpret_cast( + GetArkDynFunction("GetCallFrames")); + if (g_getCallFrames == nullptr) { + ResetServiceLocked(g_vm, true); + return false; + } return true; } #else @@ -228,6 +236,7 @@ bool InitializeArkFunctionsIOS() g_onMessage = reinterpret_cast(&tooling::OnMessage); g_getDispatchStatus = reinterpret_cast(&tooling::GetDispatchStatus); g_processMessage = reinterpret_cast(&tooling::ProcessMessage); + g_getCallFrames = reinterpret_cast(&tooling::GetCallFrames); return true; } #endif @@ -282,7 +291,7 @@ void Inspector::OnMessage(std::string&& msg) }); } else { #if defined(OHOS_PLATFORM) - debuggerPostTask_([tid = tidForSocketPair_, vm = vm_, this] { + debuggerPostTask_([tid = tidForSocketPair_, vm = vm_] { uint64_t threadOrTaskId = GetThreadOrTaskId(); if (tid != static_cast(threadOrTaskId)) { LOGE("Task not in debugger thread for socketpair"); @@ -456,4 +465,16 @@ void StoreDebuggerInfo(int tid, void* vm, const DebuggerPostTask& debuggerPostTa g_debuggerInfo.emplace(tid, std::make_pair(vm, debuggerPostTask)); } } + +// The returned pointer must be released using free() after it is no longer needed. +// Failure to release the memory will result in memory leaks. +const char* GetJsBacktrace() +{ +#if defined(OHOS_PLATFORM) + void* vm = GetEcmaVM(Inspector::GetThreadOrTaskId()); + return g_getCallFrames(vm); +#else + return ""; +#endif +} } // namespace OHOS::ArkCompiler::Toolchain diff --git a/inspector/inspector.h b/inspector/inspector.h index 893eac98..93e0af60 100644 --- a/inspector/inspector.h +++ b/inspector/inspector.h @@ -47,6 +47,7 @@ void WaitForDebugger(void* vm); void StoreDebuggerInfo(int tid, void* vm, const DebuggerPostTask& debuggerPostTask); +const char* GetJsBacktrace(); #if __cplusplus } #endif @@ -58,7 +59,7 @@ public: void OnMessage(std::string&& msg); #if defined(OHOS_PLATFORM) - uint64_t GetThreadOrTaskId(); + static uint64_t GetThreadOrTaskId(); #endif // defined(OHOS_PLATFORM) static constexpr int32_t DELAY_CHECK_DISPATCH_STATUS = 100; diff --git a/tooling/agent/debugger_impl.cpp b/tooling/agent/debugger_impl.cpp index 188af24b..59172e19 100755 --- a/tooling/agent/debugger_impl.cpp +++ b/tooling/agent/debugger_impl.cpp @@ -459,6 +459,25 @@ void DebuggerImpl::InitializeExtendedProtocolsList() debuggerExtendedProtocols_ = std::move(debuggerProtocolList); } +std::string DebuggerImpl::DispatcherImpl::GetJsFrames() +{ + std::vector nativePointers = debugger_->NativeAddr(); + if (nativePointers.empty()) { + return ""; + } + tooling::MixedStack mixedStack; + mixedStack.SetNativePointers(nativePointers); + std::vector> callFrames; + if (debugger_->GenerateCallFrames(&callFrames, false)) { + mixedStack.SetCallFrames(std::move(callFrames)); + } + return mixedStack.ToJson()->Stringify(); +} + +std::vector DebuggerImpl::NativeAddr() +{ + return DebuggerApi::GetNativePointer(vm_); +} void DebuggerImpl::DispatcherImpl::Dispatch(const DispatchRequest &request) { Method method = GetMethodEnum(request.GetMethod()); diff --git a/tooling/agent/debugger_impl.h b/tooling/agent/debugger_impl.h index c8b35633..8b142e17 100644 --- a/tooling/agent/debugger_impl.h +++ b/tooling/agent/debugger_impl.h @@ -52,6 +52,7 @@ public: const Local &exception); bool NotifyNativeOut(); void NotifyHandleProtocolCommand(); + std::vector NativeAddr(); void NotifyNativeCalling(const void *nativeAddress); void NotifyNativeReturn(const void *nativeAddress); void NotifyReturnNative(); @@ -151,6 +152,7 @@ public: ~DispatcherImpl() override = default; void ContinueToLocation(const DispatchRequest &request); + std::string GetJsFrames(); void Dispatch(const DispatchRequest &request) override; void Enable(const DispatchRequest &request); void Disable(const DispatchRequest &request); diff --git a/tooling/debugger_service.cpp b/tooling/debugger_service.cpp index 88ca7270..865d274a 100644 --- a/tooling/debugger_service.cpp +++ b/tooling/debugger_service.cpp @@ -21,6 +21,7 @@ #include "ecmascript/ecma_vm.h" namespace panda::ecmascript::tooling { +#define EMPTY_STRING "" void InitializeDebugger(::panda::ecmascript::EcmaVM *vm, const std::function &onResponse) { @@ -95,4 +96,25 @@ int32_t GetDispatchStatus(const ::panda::ecmascript::EcmaVM *vm) } return ProtocolHandler::DispatchStatus::UNKNOWN; } + +// strdup allocates memory; caller is responsible for freeing it +// Return the dynamically allocated string (must be freed by the caller) +const char* GetCallFrames(const ::panda::ecmascript::EcmaVM *vm) +{ + if (vm == nullptr || vm->GetJsDebuggerManager() == nullptr) { + LOG_DEBUGGER(ERROR) << "VM has already been destroyed"; + return EMPTY_STRING; + } + ProtocolHandler *handler = vm->GetJsDebuggerManager()->GetDebuggerHandler(); + if (LIKELY(handler != nullptr)) { + auto dispatcher = handler->GetDispatcher(); + if (LIKELY(dispatcher != nullptr)) { + auto mixStack = dispatcher->GetJsFrames(); + const char* buffer = strdup(mixStack.c_str()); + return buffer; + } + return EMPTY_STRING; + } + return EMPTY_STRING; +} } // namespace panda::ecmascript::tooling \ No newline at end of file diff --git a/tooling/debugger_service.h b/tooling/debugger_service.h index 464c8610..95bd86d9 100644 --- a/tooling/debugger_service.h +++ b/tooling/debugger_service.h @@ -45,6 +45,8 @@ TOOLCHAIN_EXPORT void ProcessMessage(const ::panda::ecmascript::EcmaVM *vm); TOOLCHAIN_EXPORT int32_t GetDispatchStatus(const ::panda::ecmascript::EcmaVM *vm); +TOOLCHAIN_EXPORT const char* GetCallFrames(const ::panda::ecmascript::EcmaVM *vm); + #ifdef __cplusplus #if __cplusplus } diff --git a/tooling/dispatcher.cpp b/tooling/dispatcher.cpp index b83d8ae6..f25842e2 100644 --- a/tooling/dispatcher.cpp +++ b/tooling/dispatcher.cpp @@ -200,4 +200,14 @@ void Dispatcher::Dispatch(const DispatchRequest &request) } } } + +std::string Dispatcher::GetJsFrames() const +{ + auto dispatcher = dispatchers_.find("Debugger"); + if (dispatcher != dispatchers_.end()) { + auto debuggerImpl = reinterpret_cast(dispatcher->second.get()); + return debuggerImpl->GetJsFrames(); + } + return ""; +} } // namespace panda::ecmascript::tooling diff --git a/tooling/dispatcher.h b/tooling/dispatcher.h index d8206e08..92c1f1e5 100644 --- a/tooling/dispatcher.h +++ b/tooling/dispatcher.h @@ -148,6 +148,7 @@ public: explicit Dispatcher(const EcmaVM *vm, ProtocolChannel *channel); ~Dispatcher() = default; void Dispatch(const DispatchRequest &request); + std::string GetJsFrames() const; private: std::unordered_map> dispatchers_ {}; diff --git a/tooling/protocol_handler.h b/tooling/protocol_handler.h index 124cea26..971a5d7f 100644 --- a/tooling/protocol_handler.h +++ b/tooling/protocol_handler.h @@ -48,6 +48,10 @@ public: std::unique_ptr CreateErrorReply(const DispatchResponse &response); void SendReply(const PtJson &reply); + const Dispatcher* GetDispatcher() const + { + return &dispatcher_; + } private: NO_MOVE_SEMANTIC(ProtocolHandler); -- Gitee From 66e9a903be582dc083a48680912647071275360f Mon Sep 17 00:00:00 2001 From: fangting Date: Wed, 18 Dec 2024 10:10:00 +0800 Subject: [PATCH 17/48] fix some advise Issue:#IBC09Q Signed-off-by: fangting --- inspector/inspector.cpp | 4 ++++ inspector/inspector.h | 2 ++ tooling/agent/debugger_impl.cpp | 4 ++-- tooling/agent/debugger_impl.h | 2 +- tooling/debugger_service.cpp | 7 +++---- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/inspector/inspector.cpp b/inspector/inspector.cpp index ad49ee3d..dbbfe9bd 100644 --- a/inspector/inspector.cpp +++ b/inspector/inspector.cpp @@ -472,6 +472,10 @@ const char* GetJsBacktrace() { #if defined(OHOS_PLATFORM) void* vm = GetEcmaVM(Inspector::GetThreadOrTaskId()); + if (g_getCallFrames == nullptr) { + LOGE("GetCallFrames symbol resolve failed"); + return ""; + } return g_getCallFrames(vm); #else return ""; diff --git a/inspector/inspector.h b/inspector/inspector.h index 93e0af60..9b4db968 100644 --- a/inspector/inspector.h +++ b/inspector/inspector.h @@ -47,6 +47,8 @@ void WaitForDebugger(void* vm); void StoreDebuggerInfo(int tid, void* vm, const DebuggerPostTask& debuggerPostTask); +// The returned pointer must be released using free() after it is no longer needed. +// Failure to release the memory will result in memory leaks. const char* GetJsBacktrace(); #if __cplusplus } diff --git a/tooling/agent/debugger_impl.cpp b/tooling/agent/debugger_impl.cpp index 59172e19..ac6387c8 100755 --- a/tooling/agent/debugger_impl.cpp +++ b/tooling/agent/debugger_impl.cpp @@ -461,7 +461,7 @@ void DebuggerImpl::InitializeExtendedProtocolsList() std::string DebuggerImpl::DispatcherImpl::GetJsFrames() { - std::vector nativePointers = debugger_->NativeAddr(); + std::vector nativePointers = debugger_->GetNativeAddr(); if (nativePointers.empty()) { return ""; } @@ -474,7 +474,7 @@ std::string DebuggerImpl::DispatcherImpl::GetJsFrames() return mixedStack.ToJson()->Stringify(); } -std::vector DebuggerImpl::NativeAddr() +std::vector DebuggerImpl::GetNativeAddr() { return DebuggerApi::GetNativePointer(vm_); } diff --git a/tooling/agent/debugger_impl.h b/tooling/agent/debugger_impl.h index 8b142e17..d9b4dbd5 100644 --- a/tooling/agent/debugger_impl.h +++ b/tooling/agent/debugger_impl.h @@ -52,7 +52,7 @@ public: const Local &exception); bool NotifyNativeOut(); void NotifyHandleProtocolCommand(); - std::vector NativeAddr(); + std::vector GetNativeAddr(); void NotifyNativeCalling(const void *nativeAddress); void NotifyNativeReturn(const void *nativeAddress); void NotifyReturnNative(); diff --git a/tooling/debugger_service.cpp b/tooling/debugger_service.cpp index 865d274a..b9b24887 100644 --- a/tooling/debugger_service.cpp +++ b/tooling/debugger_service.cpp @@ -21,7 +21,6 @@ #include "ecmascript/ecma_vm.h" namespace panda::ecmascript::tooling { -#define EMPTY_STRING "" void InitializeDebugger(::panda::ecmascript::EcmaVM *vm, const std::function &onResponse) { @@ -103,7 +102,7 @@ const char* GetCallFrames(const ::panda::ecmascript::EcmaVM *vm) { if (vm == nullptr || vm->GetJsDebuggerManager() == nullptr) { LOG_DEBUGGER(ERROR) << "VM has already been destroyed"; - return EMPTY_STRING; + return ""; } ProtocolHandler *handler = vm->GetJsDebuggerManager()->GetDebuggerHandler(); if (LIKELY(handler != nullptr)) { @@ -113,8 +112,8 @@ const char* GetCallFrames(const ::panda::ecmascript::EcmaVM *vm) const char* buffer = strdup(mixStack.c_str()); return buffer; } - return EMPTY_STRING; + return ""; } - return EMPTY_STRING; + return ""; } } // namespace panda::ecmascript::tooling \ No newline at end of file -- Gitee From aec161b63e01b49f3864c329f10f7424f36e82ab Mon Sep 17 00:00:00 2001 From: yanzhiqi1 Date: Mon, 23 Dec 2024 10:40:28 +0800 Subject: [PATCH 18/48] Fix bug in setting global variables Issue: #IBD01R Signed-off-by: yanzhiqi1 --- tooling/backend/debugger_executor.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tooling/backend/debugger_executor.cpp b/tooling/backend/debugger_executor.cpp index a7417159..b27f92ce 100644 --- a/tooling/backend/debugger_executor.cpp +++ b/tooling/backend/debugger_executor.cpp @@ -232,10 +232,11 @@ bool DebuggerExecutor::SetModuleValue(const EcmaVM *vm, const FrameHandler *fram } JSThread *thread = vm->GetJSThread(); JSHandle currentModule(thread, DebuggerApi::GetCurrentModule(vm)); + bool result = false; if (currentModule->IsSourceTextModule()) { - DebuggerApi::SetModuleValue(vm, currentModule, varName, value); + result = DebuggerApi::SetModuleValue(vm, currentModule, varName, value); vm->GetJsDebuggerManager()->NotifyScopeUpdated(varName, value, Scope::Type::Module()); } - return true; + return result; } } // namespace panda::ecmascript::tooling -- Gitee From 257dd2a5421f925d0db2ec281509cdda2635500e Mon Sep 17 00:00:00 2001 From: shixiaowei4 Date: Thu, 26 Dec 2024 16:03:49 +0800 Subject: [PATCH 19/48] Fix failure of runtime_core Issue: https://gitee.com/openharmony/arkcompiler_toolchain/issues/IBDXRO Signed-off-by: shixiaowei4 Change-Id: I14fe69f17a6bcee055df2295d630345d3e89b99c --- build/scripts/generate_js_bytecode.py | 29 +++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/build/scripts/generate_js_bytecode.py b/build/scripts/generate_js_bytecode.py index f978b33d..ea7ae832 100755 --- a/build/scripts/generate_js_bytecode.py +++ b/build/scripts/generate_js_bytecode.py @@ -48,6 +48,16 @@ def parse_args(): help='dump symbol table of base abc') parser.add_argument("--input-symbol-table", help='input symbol table for patch abc') + parser.add_argument("--target-api-sub-version", + help='input symbol table for patch abc') + parser.add_argument("--module-record-field-name", + help='specify the field name of module record in unmerged abc. This argument is optional, ' + + 'its value will be the path of input file if not specified') + parser.add_argument("--source-file", + help='specify the file path info recorded in generated abc. This argument is optional, ' + + 'its value will be the path of input file if not specified') + parser.add_argument("--enable-annotations", action='store_true', + help='whether annotations are enabled or not') arguments = parser.parse_args() return arguments @@ -56,6 +66,8 @@ def run_command(cmd, execution_path): print(" ".join(cmd) + " | execution_path: " + execution_path) proc = subprocess.Popen(cmd, cwd=execution_path) proc.wait() + if proc.returncode != 0: + raise subprocess.CalledProcessError(proc.returncode, cmd) def gen_abc_info(input_arguments): @@ -88,9 +100,22 @@ def gen_abc_info(input_arguments): if input_arguments.generate_patch: src_index = cmd.index(input_arguments.src_js) cmd.insert(src_index, '--generate-patch') + if input_arguments.module_record_field_name: + cmd += ["--module-record-field-name", input_arguments.module_record_field_name] + if input_arguments.source_file: + cmd += ["--source-file", input_arguments.source_file] + if input_arguments.enable_annotations: + src_index = cmd.index(input_arguments.src_js) + cmd.insert(src_index, '--enable-annotations') # insert d.ts option to cmd later - run_command(cmd, path) + cmd.append("--target-api-sub-version=beta3") + + try: + run_command(cmd, path) + except subprocess.CalledProcessError as e: + exit(e.returncode) if __name__ == '__main__': - gen_abc_info(parse_args()) \ No newline at end of file + gen_abc_info(parse_args()) + -- Gitee From 7409435ced2f7a1027d38c0b2c6420f694958bde Mon Sep 17 00:00:00 2001 From: fangting Date: Thu, 26 Dec 2024 11:04:53 +0800 Subject: [PATCH 20/48] add testcases Issue:#IBDBHH Signed-off-by: fangting --- tooling/test/BUILD.gn | 1 + tooling/test/client_utils/test_list.cpp | 2 + tooling/test/testcases/js/closure_variable.js | 23 +++ .../js_watch_closure_variable_test.h | 157 ++++++++++++++++++ 4 files changed, 183 insertions(+) create mode 100644 tooling/test/testcases/js/closure_variable.js create mode 100644 tooling/test/testcases/js_watch_closure_variable_test.h diff --git a/tooling/test/BUILD.gn b/tooling/test/BUILD.gn index f694e1b7..8848f4de 100644 --- a/tooling/test/BUILD.gn +++ b/tooling/test/BUILD.gn @@ -54,6 +54,7 @@ test_js_files = [ "local_variable_scope", "container", "closure_scope", + "closure_variable", "branch", "common_func", "watch_variable", diff --git a/tooling/test/client_utils/test_list.cpp b/tooling/test/client_utils/test_list.cpp index cdd96ac0..c9326fbb 100644 --- a/tooling/test/client_utils/test_list.cpp +++ b/tooling/test/client_utils/test_list.cpp @@ -45,6 +45,7 @@ #include "tooling/test/testcases/js_breakpoint_cannot_hit_test.h" #include "tooling/test/testcases/js_breakpoint_in_different_branch.h" #include "tooling/test/testcases/js_watch_variable_test.h" +#include "tooling/test/testcases/js_watch_closure_variable_test.h" #include "tooling/test/testcases/js_stepinto_arrow_test.h" #include "tooling/test/testcases/js_stepinto_async_test.h" #include "tooling/test/testcases/js_stepout_arrow_test.h" @@ -114,6 +115,7 @@ static void RegisterTests() TestUtil::RegisterTest("JsJsWatchBasicTypeTest", GetJsWatchBasicTypeTest()); TestUtil::RegisterTest("JsJsWatchSetTypeTest", GetJsWatchSetTypeTest()); TestUtil::RegisterTest("JsJsWatchOtherTypeTest", GetJsWatchOtherTypeTest()); + TestUtil::RegisterTest("JsWatchClosureVariableTest", GetJsWatchClosureVariableTest()); TestUtil::RegisterTest("JsStepintoLoopTest", GetJsStepintoLoopTest()); TestUtil::RegisterTest("JsStepintoRecursionTest", GetJsStepintoRecursionTest()); TestUtil::RegisterTest("JsStepintoSwitchTest", GetJsStepintoSwitchTest()); diff --git a/tooling/test/testcases/js/closure_variable.js b/tooling/test/testcases/js/closure_variable.js new file mode 100644 index 00000000..215fa941 --- /dev/null +++ b/tooling/test/testcases/js/closure_variable.js @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 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. + */ +function funA() { + let a=1; + { + let a=2; + } + a=3; +} + +funA() \ No newline at end of file diff --git a/tooling/test/testcases/js_watch_closure_variable_test.h b/tooling/test/testcases/js_watch_closure_variable_test.h new file mode 100644 index 00000000..83584c06 --- /dev/null +++ b/tooling/test/testcases/js_watch_closure_variable_test.h @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2024 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_TEST_TESTCASES_JS_WATCH_CLOSURE_VARIABLE_TEST_H +#define ECMASCRIPT_TOOLING_TEST_TESTCASES_JS_WATCH_CLOSURE_VARIABLE_TEST_H + +#include "tooling/test/client_utils/test_util.h" + +namespace panda::ecmascript::tooling::test { +class JsWatchClosureVariableTest : public TestActions { +public: + JsWatchClosureVariableTest() + { + testAction = { + {SocketAction::SEND, "enable"}, + {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, + {SocketAction::SEND, "runtime-enable"}, + {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, + {SocketAction::SEND, "run"}, + {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, + // load closure_variable.js + {SocketAction::RECV, "Debugger.scriptParsed", ActionRule::STRING_CONTAIN}, + // break on start + {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE, + [](auto recv, auto, auto) -> bool { + std::unique_ptr json = PtJson::Parse(recv); + DebuggerClient debuggerClient(0); + debuggerClient.RecvReply(std::move(json)); + return true; + }}, + + // set breakpoint + {SocketAction::SEND, "b " DEBUGGER_JS_DIR "closure_variable.js 20"}, + {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, + + // hit breakpoint after resume first time + {SocketAction::SEND, "resume"}, + {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN}, + {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, + {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE, + [this](auto recv, auto, auto) -> bool { return RecvHitBreakInfo(recv, 19); }}, + + {SocketAction::SEND, "watch a"}, + {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, + [this](auto recv, auto, auto) -> bool { return RecvWatchInfo(recv); }}, + + // reply success and run + {SocketAction::SEND, "success"}, + {SocketAction::SEND, "resume"}, + {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN}, + {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, + }; + } + + bool RecvHitBreakInfo(std::string recv, int line) + { + std::unique_ptr json = PtJson::Parse(recv); + Result ret; + std::string method = ""; + ret = json->GetString("method", &method); + if (ret != Result::SUCCESS || method != "Debugger.paused") { + return false; + } + + std::unique_ptr params = nullptr; + ret = json->GetObject("params", ¶ms); + if (ret != Result::SUCCESS) { + return false; + } + + std::unique_ptr hitBreakpoints = nullptr; + ret = params->GetArray("hitBreakpoints", &hitBreakpoints); + if (ret != Result::SUCCESS) { + return false; + } + + std::string breakpoint = ""; + breakpoint = hitBreakpoints->Get(0)->GetString(); + if (ret != Result::SUCCESS || breakpoint.find(sourceFile_) == std::string::npos || + breakpoint.find(std::to_string(line)) == std::string::npos) { + return false; + } + return true; + } + bool RecvWatchInfo(std::string recv) + { + std::unique_ptr json = PtJson::Parse(recv); + Result ret; + int id; + ret = json->GetInt("id", &id); + if (ret != Result::SUCCESS) { + return false; + } + + std::unique_ptr result = nullptr; + ret = json->GetObject("result", &result); + if (ret != Result::SUCCESS) { + return false; + } + + std::unique_ptr watchResult = nullptr; + ret = result->GetObject("result", &watchResult); + if (ret != Result::SUCCESS) { + return false; + } + + std::string type = ""; + ret = watchResult->GetString("type", &type); + if (ret != Result::SUCCESS || type != "number") { + return false; + } + + std::string value = ""; + ret = watchResult->GetString("unserializableValue", &value); + if (ret != Result::SUCCESS || value != "1") { + return false; + } + + std::string description = ""; + ret = watchResult->GetString("description", &description); + if (ret != Result::SUCCESS || description != "1") { + return false; + } + return true; + } + + std::pair GetEntryPoint() override + { + return {pandaFile_, entryPoint_}; + } + ~JsWatchClosureVariableTest() = default; + +private: + std::string pandaFile_ = DEBUGGER_ABC_DIR "closure_variable.abc"; + std::string sourceFile_ = DEBUGGER_JS_DIR "closure_variable.js"; + std::string entryPoint_ = "_GLOBAL::func_main_0"; +}; + +std::unique_ptr GetJsWatchClosureVariableTest() +{ + return std::make_unique(); +} +} // namespace panda::ecmascript::tooling::test + +#endif // ECMASCRIPT_TOOLING_TEST_TESTCASES_JS_WATCH_CLOSURE_VARIABLE_TEST_H -- Gitee From 7cd722a0fba654281c266704c920c59917b5d6d8 Mon Sep 17 00:00:00 2001 From: huangtianzhi Date: Mon, 23 Dec 2024 17:27:43 +0800 Subject: [PATCH 21/48] Debugger scriptparsed optimization Issue: #IBD4GE Signed-off-by: huangtianzhi --- tooling/agent/debugger_impl.cpp | 227 ++++++++++++++---- tooling/agent/debugger_impl.h | 36 ++- tooling/backend/js_pt_hooks.cpp | 17 +- tooling/backend/js_pt_hooks.h | 1 + tooling/base/pt_events.cpp | 9 + tooling/base/pt_events.h | 7 + tooling/base/pt_json.cpp | 16 ++ tooling/base/pt_json.h | 3 + tooling/base/pt_params.cpp | 61 +++++ tooling/base/pt_params.h | 40 +++ tooling/base/pt_returns.h | 4 +- tooling/base/pt_script.h | 11 + tooling/base/pt_types.cpp | 12 + tooling/base/pt_types.h | 11 + tooling/client/domain/debugger_client.cpp | 55 +++++ tooling/client/domain/debugger_client.h | 2 + tooling/client/utils/cli_command.cpp | 9 + tooling/client/utils/cli_command.h | 1 + tooling/test/client_utils/test_list.cpp | 2 + tooling/test/debugger_impl_test.cpp | 37 +++ tooling/test/debugger_params_test.cpp | 39 +++ tooling/test/debugger_returns_test.cpp | 8 +- tooling/test/debugger_script_test.cpp | 12 + tooling/test/pt_json_test.cpp | 11 + .../testcases/js_accelerate_launch_test.h | 131 ++++++++++ tooling/test/utils/test_hooks.h | 2 + 26 files changed, 699 insertions(+), 65 deletions(-) create mode 100644 tooling/test/testcases/js_accelerate_launch_test.h diff --git a/tooling/agent/debugger_impl.cpp b/tooling/agent/debugger_impl.cpp index ac6387c8..bceed3ce 100755 --- a/tooling/agent/debugger_impl.cpp +++ b/tooling/agent/debugger_impl.cpp @@ -97,47 +97,40 @@ bool DebuggerImpl::NotifyScriptParsed(const std::string &fileName, std::string_v auto mainMethodIndex = panda_file::File::EntityId(jsPandaFile->GetMainMethodIndex(recordName)); const std::string &source = extractor->GetSourceCode(mainMethodIndex); const std::string &url = extractor->GetSourceFile(mainMethodIndex); - - recordNames_[url].insert(recordName); - // if load module, it needs to check whether clear singlestepper_ ClearSingleStepper(); if (MatchUrlAndFileName(url, fileName)) { + LOG_DEBUGGER(WARN) << "DebuggerImpl::NotifyScriptParsed: Script already been parsed: " + << "url: " << url << " fileName: " << fileName; return false; } - urlFileNameMap_[url].insert(fileName); - - // Notify script parsed event - std::unique_ptr script = std::make_unique(g_scriptId++, fileName, url, source); - - frontend_.ScriptParsed(vm_, *script); - // Store parsed script in map - scripts_[script->GetScriptId()] = std::move(script); + SaveParsedScriptsAndUrl(fileName, url, recordName, source); return true; } -bool DebuggerImpl::SendableScriptParsed(const std::string &fileName, const std::string &url, - const std::string &source, const std::string &recordName) +std::vector> DebuggerImpl::SetBreakpointsWhenParsingScript(const std::string &url) { - if (!CheckScriptParsed(fileName)) { - return false; + std::vector> outLocations {}; + for (const auto &breakpoint : breakpointPendingMap_[url]) { + if (!ProcessSingleBreakpoint(*breakpoint, outLocations)) { + std::string invalidBpId = "invalid"; + std::shared_ptr bpInfo = std::make_shared(); + bpInfo->SetId(invalidBpId) + .SetLineNumber(breakpoint->GetLineNumber()) + .SetColumnNumber(breakpoint->GetColumnNumber()); + outLocations.emplace_back(bpInfo); + } } + return outLocations; +} - recordNames_[url].insert(recordName); - - // if load module, it needs to check whether clear singlestepper_ - ClearSingleStepper(); - - urlFileNameMap_[url].insert(fileName); - // Notify script parsed event - std::unique_ptr script = std::make_unique(g_scriptId++, fileName, url, source); - - frontend_.ScriptParsed(vm_, *script); - - // Store parsed script in map - scripts_[script->GetScriptId()] = std::move(script); - return true; +bool DebuggerImpl::NeedToSetBreakpointsWhenParsingScript(const std::string &url) +{ + if (breakpointPendingMap_.find(url) != breakpointPendingMap_.end()) { + return !breakpointPendingMap_[url].empty(); + } + return false; } bool DebuggerImpl::CheckScriptParsed([[maybe_unused]] const std::string &fileName) @@ -151,7 +144,7 @@ bool DebuggerImpl::CheckScriptParsed([[maybe_unused]] const std::string &fileNam } #endif - // The release application does not require scriptParsed + // check if Debugable flag is true in module.json if (!vm_->GetJsDebuggerManager()->IsDebugApp()) { return false; } @@ -159,8 +152,27 @@ bool DebuggerImpl::CheckScriptParsed([[maybe_unused]] const std::string &fileNam return true; } -bool DebuggerImpl::SendableMethodEntry(JSHandle method) +void DebuggerImpl::SaveParsedScriptsAndUrl(const std::string &fileName, const std::string &url, + const std::string &recordName, const std::string &source) +{ + // Save recordName to its corresponding url + recordNames_[url].insert(recordName); + // Save parsed fileName to its corresponding url + urlFileNameMap_[url].insert(fileName); + // Create and save script + std::shared_ptr script = std::make_shared(g_scriptId++, fileName, url, source); + scripts_[script->GetScriptId()] = script; + // Check if is launch accelerate mode & has pending bps to set + if (IsLaunchAccelerateMode() && NeedToSetBreakpointsWhenParsingScript(url)) { + script->SetLocations(SetBreakpointsWhenParsingScript(url)); + } + // Notify frontend ScriptParsed event + frontend_.ScriptParsed(vm_, *script); +} + +bool DebuggerImpl::NotifyScriptParsedBySendable(JSHandle method) { + // Find extractor and retrieve infos const JSPandaFile *jsPandaFile = method->GetJSPandaFile(); if (jsPandaFile == nullptr) { LOG_DEBUGGER(ERROR) << "JSPandaFile is nullptr"; @@ -174,14 +186,23 @@ bool DebuggerImpl::SendableMethodEntry(JSHandle method) auto methodId = method->GetMethodId(); const std::string &url = extractor->GetSourceFile(methodId); const std::string &fileName = std::string(jsPandaFile->GetJSPandaFileDesc()); - if (!MatchUrlAndFileName(url, fileName)) { - // scriptParsed - const std::string &source = extractor->GetSourceCode(methodId); - const std::string &recordName = std::string(method->GetRecordNameStr()); - SendableScriptParsed(fileName, url, source, recordName); - return true; + // Check url path & is debugable in module.json + if (!CheckScriptParsed(fileName)) { + return false; } - return false; + // Clear SingleStepper before notify + ClearSingleStepper(); + // Check if this (url, fileName) pair has already been parsed + if (MatchUrlAndFileName(url, fileName)) { + LOG_DEBUGGER(WARN) << "DebuggerImpl::NotifyScriptParsedBySendable: Script already been parsed: " + << "url: " << url << " fileName: " << fileName; + return false; + } + // Parse and save this file + const std::string &source = extractor->GetSourceCode(methodId); + const std::string &recordName = std::string(method->GetRecordNameStr()); + SaveParsedScriptsAndUrl(fileName, url, recordName, source); + return true; } bool DebuggerImpl::MatchUrlAndFileName(const std::string &url, const std::string &fileName) @@ -189,7 +210,6 @@ bool DebuggerImpl::MatchUrlAndFileName(const std::string &url, const std::string auto urlFileNameIter = urlFileNameMap_.find(url); if (urlFileNameIter != urlFileNameMap_.end()) { if (urlFileNameIter->second.find(fileName) != urlFileNameIter->second.end()) { - LOG_DEBUGGER(WARN) << "MatchUrlAndFileName: already loaded: " << url; return true; } } @@ -454,7 +474,8 @@ void DebuggerImpl::InitializeExtendedProtocolsList() "setNativeRange", "resetSingleStepper", "callFunctionOn", - "smartStepInto" + "smartStepInto", + "saveAllPossibleBreakpoints" }; debuggerExtendedProtocols_ = std::move(debuggerProtocolList); } @@ -567,6 +588,9 @@ void DebuggerImpl::DispatcherImpl::Dispatch(const DispatchRequest &request) case Method::CALL_FUNCTION_ON: CallFunctionOn(request); break; + case Method::SAVE_ALL_POSSIBLE_BREAKPOINTS: + SaveAllPossibleBreakpoints(request); + break; default: SendResponse(request, DispatchResponse::Fail("Unknown method: " + request.GetMethod())); break; @@ -631,6 +655,8 @@ DebuggerImpl::DispatcherImpl::Method DebuggerImpl::DispatcherImpl::GetMethodEnum return Method::CLIENT_DISCONNECT; } else if (method == "callFunctionOn") { return Method::CALL_FUNCTION_ON; + } else if (method == "saveAllPossibleBreakpoints") { + return Method::SAVE_ALL_POSSIBLE_BREAKPOINTS; } else { return Method::UNKNOWN; } @@ -795,12 +821,24 @@ void DebuggerImpl::DispatcherImpl::GetPossibleAndSetBreakpointByUrl(const Dispat return; } - std::vector> outLocation; + std::vector> outLocation; DispatchResponse response = debugger_->GetPossibleAndSetBreakpointByUrl(*params, outLocation); GetPossibleAndSetBreakpointByUrlReturns result(std::move(outLocation)); SendResponse(request, response, result); } +void DebuggerImpl::DispatcherImpl::SaveAllPossibleBreakpoints(const DispatchRequest &request) +{ + std::unique_ptr params = + SaveAllPossibleBreakpointsParams::Create(request.GetParams()); + if (params == nullptr) { + SendResponse(request, DispatchResponse::Fail("wrong params")); + return; + } + DispatchResponse response = debugger_->SaveAllPossibleBreakpoints(*params); + SendResponse(request, response); +} + void DebuggerImpl::DispatcherImpl::SetPauseOnExceptions(const DispatchRequest &request) { std::unique_ptr params = SetPauseOnExceptionsParams::Create(request.GetParams()); @@ -1032,7 +1070,8 @@ void DebuggerImpl::Frontend::ScriptParsed(const EcmaVM *vm, const PtScript &scri .SetEndLine(script.GetEndLine()) .SetEndColumn(0) .SetExecutionContextId(0) - .SetHash(script.GetHash()); + .SetHash(script.GetHash()) + .SetLocations(script.GetLocations()); channel_->SendNotification(scriptParsed); } @@ -1069,6 +1108,8 @@ DispatchResponse DebuggerImpl::Enable([[maybe_unused]] const EnableParams ¶m ASSERT(id != nullptr); *id = 0; vm_->GetJsDebuggerManager()->SetDebugMode(true); + // Enable corresponding features requested by IDE + EnableDebuggerFeatures(params); for (auto &script : scripts_) { frontend_.ScriptParsed(vm_, *script.second); } @@ -1076,6 +1117,42 @@ DispatchResponse DebuggerImpl::Enable([[maybe_unused]] const EnableParams ¶m return DispatchResponse::Ok(); } +void DebuggerImpl::EnableDebuggerFeatures(const EnableParams ¶ms) +{ + if (!params.HasEnableOptionsList()) { + return; + } + auto enableOptionsList = params.GetEnableOptionsList(); + if (enableOptionsList.empty()) { + return; + } + for (auto &option : enableOptionsList) { + LOG_DEBUGGER(INFO) << "Debugger feature " << option << " is enabled"; + EnableFeature(GetDebuggerFeatureEnum(option)); + } +} + +DebuggerFeature DebuggerImpl::GetDebuggerFeatureEnum(std::string &option) +{ + if (option == "enableLaunchAccelerate") { + return DebuggerFeature::LAUNCH_ACCELERATE; + } + // Future features could be added here to parse as DebuggerFeatureEnum + return DebuggerFeature::UNKNOWN; +} + +void DebuggerImpl::EnableFeature(DebuggerFeature feature) +{ + switch (feature) { + case DebuggerFeature::LAUNCH_ACCELERATE: + EnableLaunchAccelerateMode(); + DebuggerApi::DisableFirstTimeFlag(jsDebugger_); + break; + default: + break; + } +} + DispatchResponse DebuggerImpl::Disable() { DebuggerApi::RemoveAllBreakpoints(jsDebugger_); @@ -1230,6 +1307,9 @@ DispatchResponse DebuggerImpl::RemoveBreakpointsByUrl(const RemoveBreakpointsByU } LOG_DEBUGGER(INFO) << "All breakpoints on " << url << " are removed"; + if (IsLaunchAccelerateMode()) { + breakpointPendingMap_.erase(url); + } return DispatchResponse::Ok(); } @@ -1324,7 +1404,7 @@ DispatchResponse DebuggerImpl::SetBreakpointsActive(const SetBreakpointsActivePa } DispatchResponse DebuggerImpl::GetPossibleAndSetBreakpointByUrl(const GetPossibleAndSetBreakpointParams ¶ms, - std::vector> &outLocations) + std::vector> &outLocations) { if (!vm_->GetJsDebuggerManager()->IsDebugMode()) { return DispatchResponse::Fail("GetPossibleAndSetBreakpointByUrl: debugger agent is not enabled"); @@ -1336,18 +1416,69 @@ DispatchResponse DebuggerImpl::GetPossibleAndSetBreakpointByUrl(const GetPossibl for (const auto &breakpoint : *breakpointList) { if (!ProcessSingleBreakpoint(*breakpoint, outLocations)) { std::string invalidBpId = "invalid"; - std::unique_ptr bpInfo = std::make_unique(); + std::shared_ptr bpInfo = std::make_shared(); bpInfo->SetId(invalidBpId) .SetLineNumber(breakpoint->GetLineNumber()) .SetColumnNumber(breakpoint->GetColumnNumber()); - outLocations.emplace_back(std::move(bpInfo)); + outLocations.emplace_back(bpInfo); + } + // Insert this bp into bp pending map + if (IsLaunchAccelerateMode()) { + InsertIntoPendingBreakpoints(*breakpoint); } } return DispatchResponse::Ok(); } +bool DebuggerImpl::InsertIntoPendingBreakpoints(const BreakpointInfo &breakpoint) +{ + auto condition = breakpoint.HasCondition() ? breakpoint.GetCondition() : std::optional {}; + auto bpShared = BreakpointInfo::CreateAsSharedPtr(breakpoint.GetLineNumber(), breakpoint.GetColumnNumber(), + breakpoint.GetUrl(), (condition.has_value() ? condition.value() : "")); + if (breakpointPendingMap_.empty() || + breakpointPendingMap_.find(breakpoint.GetUrl()) == breakpointPendingMap_.end()) { + CUnorderedSet, HashBreakpointInfo> set {}; + set.insert(bpShared); + breakpointPendingMap_[breakpoint.GetUrl()] = set; + return true; + } + return (breakpointPendingMap_[breakpoint.GetUrl()].insert(bpShared)).second; +} + +DispatchResponse DebuggerImpl::SaveAllPossibleBreakpoints(const SaveAllPossibleBreakpointsParams ¶ms) +{ + if (!vm_->GetJsDebuggerManager()->IsDebugMode()) { + return DispatchResponse::Fail("SaveAllPossibleBreakpoints: debugger agent is not enabled"); + } + if (!IsLaunchAccelerateMode()) { + return DispatchResponse::Fail("SaveAllPossibleBreakpoints: protocol is not enabled"); + } + if (!params.HasBreakpointsMap()) { + return DispatchResponse::Fail("SaveAllPossibleBreakpoints: no pending breakpoint exists"); + } + SavePendingBreakpoints(params); + return DispatchResponse::Ok(); +} + +void DebuggerImpl::SavePendingBreakpoints(const SaveAllPossibleBreakpointsParams ¶ms) +{ + for (const auto &entry : *(params.GetBreakpointsMap())) { + if (breakpointPendingMap_.find(entry.first) == breakpointPendingMap_.end()) { + CUnorderedSet, HashBreakpointInfo> set {}; + for (auto &info : entry.second) { + set.insert(info); + } + breakpointPendingMap_[entry.first] = set; + } else { + for (auto &info : entry.second) { + breakpointPendingMap_[entry.first].insert(info); + } + } + } +} + bool DebuggerImpl::ProcessSingleBreakpoint(const BreakpointInfo &breakpoint, - std::vector> &outLocations) + std::vector> &outLocations) { const std::string &url = breakpoint.GetUrl(); int32_t lineNumber = breakpoint.GetLineNumber(); @@ -1391,9 +1522,9 @@ bool DebuggerImpl::ProcessSingleBreakpoint(const BreakpointInfo &breakpoint, BreakpointDetails bpMetaData {lineNumber, 0, url}; std::string outId = BreakpointDetails::ToString(bpMetaData); - std::unique_ptr bpInfo = std::make_unique(); + std::shared_ptr bpInfo = std::make_unique(); bpInfo->SetScriptId(scriptId).SetLineNumber(lineNumber).SetColumnNumber(0).SetId(outId); - outLocations.emplace_back(std::move(bpInfo)); + outLocations.emplace_back(bpInfo); return true; } diff --git a/tooling/agent/debugger_impl.h b/tooling/agent/debugger_impl.h index d9b4dbd5..c3a0ddad 100644 --- a/tooling/agent/debugger_impl.h +++ b/tooling/agent/debugger_impl.h @@ -32,6 +32,7 @@ class TestHooks; } // namespace test enum class DebuggerState { DISABLED, ENABLED, PAUSED }; +enum class DebuggerFeature { LAUNCH_ACCELERATE, UNKNOWN }; class DebuggerImpl final { public: DebuggerImpl(const EcmaVM *vm, ProtocolChannel *channel, RuntimeImpl *runtime); @@ -40,10 +41,8 @@ public: // event bool NotifyScriptParsed(const std::string &fileName, std::string_view entryPoint = "func_main_0"); - bool SendableScriptParsed(const std::string &fileName, const std::string &url, - const std::string &source, const std::string &recordName); bool CheckScriptParsed(const std::string &fileName); - bool SendableMethodEntry(JSHandle method); + bool NotifyScriptParsedBySendable(JSHandle method); bool MatchUrlAndFileName(const std::string &url, const std::string &fileName); bool NotifySingleStep(const JSPtLocation &location); void NotifyPaused(std::optional location, PauseReason reason); @@ -80,7 +79,7 @@ public: bool isSmartBreakpoint = false); DispatchResponse SetBreakpointsActive(const SetBreakpointsActiveParams ¶ms); DispatchResponse GetPossibleAndSetBreakpointByUrl(const GetPossibleAndSetBreakpointParams ¶ms, - std::vector> &outLocations); + std::vector> &outLocations); DispatchResponse SetPauseOnExceptions(const SetPauseOnExceptionsParams ¶ms); DispatchResponse SetSkipAllPauses(const SetSkipAllPausesParams ¶ms); DispatchResponse SetNativeRange(const SetNativeRangeParams ¶ms); @@ -98,7 +97,7 @@ public: const CallFunctionOnParams ¶ms, std::unique_ptr *outRemoteObject, std::optional> *outExceptionDetails); - + DispatchResponse SaveAllPossibleBreakpoints(const SaveAllPossibleBreakpointsParams ¶ms); /** * @brief: match first script and callback * @@ -181,6 +180,7 @@ public: void DropFrame(const DispatchRequest &request); void ClientDisconnect(const DispatchRequest &request); void CallFunctionOn(const DispatchRequest &request); + void SaveAllPossibleBreakpoints(const DispatchRequest &request); enum class Method { CONTINUE_TO_LOCATION, @@ -211,6 +211,7 @@ public: RESET_SINGLE_STEPPER, CLIENT_DISCONNECT, CALL_FUNCTION_ON, + SAVE_ALL_POSSIBLE_BREAKPOINTS, UNKNOWN }; Method GetMethodEnum(const std::string& method); @@ -254,10 +255,19 @@ private: bool CheckPauseOnException(); bool IsWithinVariableScope(const LocalVariableInfo &localVariableInfo, uint32_t bcOffset); bool ProcessSingleBreakpoint(const BreakpointInfo &breakpoint, - std::vector> &outLocations); + std::vector> &outLocations); bool IsVariableSkipped(const std::string &varName); Local CheckAndGenerateCondFunc(const std::optional &condition); void InitializeExtendedProtocolsList(); + bool NeedToSetBreakpointsWhenParsingScript(const std::string &url); + std::vector> SetBreakpointsWhenParsingScript(const std::string &url); + void SavePendingBreakpoints(const SaveAllPossibleBreakpointsParams ¶ms); + bool InsertIntoPendingBreakpoints(const BreakpointInfo &breakpoint); + void SaveParsedScriptsAndUrl(const std::string &fileName, const std::string &url, + const std::string &recordName, const std::string &source = ""); + void EnableDebuggerFeatures(const EnableParams ¶ms); + DebuggerFeature GetDebuggerFeatureEnum(std::string &option); + void EnableFeature(DebuggerFeature feature); const std::unordered_set &GetRecordName(const std::string &url) { @@ -268,6 +278,14 @@ private: } return recordName; } + void EnableLaunchAccelerateMode() + { + breakOnStartEnable_ = false; + } + bool IsLaunchAccelerateMode() const + { + return !breakOnStartEnable_; + } class Frontend { public: @@ -299,7 +317,7 @@ private: std::unordered_map> recordNames_ {}; std::unordered_map> urlFileNameMap_ {}; - std::unordered_map> scripts_ {}; + std::unordered_map> scripts_ {}; PauseOnExceptionsState pauseOnException_ {PauseOnExceptionsState::NONE}; DebuggerState debuggerState_ {DebuggerState::ENABLED}; bool pauseOnNextByteCode_ {false}; @@ -321,6 +339,10 @@ private: JsDebuggerManager::SingleStepperFunc stepperFunc_ {nullptr}; JsDebuggerManager::ReturnNativeFunc returnNative_ {nullptr}; std::vector debuggerExtendedProtocols_ {}; + // For launch accelerate mode + std::unordered_map, HashBreakpointInfo>> + breakpointPendingMap_ {}; + bool breakOnStartEnable_ {true}; friend class JSPtHooks; friend class test::TestHooks; diff --git a/tooling/backend/js_pt_hooks.cpp b/tooling/backend/js_pt_hooks.cpp index b704d8b6..4c484ed4 100644 --- a/tooling/backend/js_pt_hooks.cpp +++ b/tooling/backend/js_pt_hooks.cpp @@ -84,7 +84,9 @@ void JSPtHooks::LoadModule(std::string_view pandaFileName, std::string_view entr [[maybe_unused]] LocalScope scope(debugger_->vm_); if (debugger_->NotifyScriptParsed(pandaFileName.data(), entryPoint)) { - firstTime_ = true; + if (!debugger_->IsLaunchAccelerateMode()) { + firstTime_ = true; + } } } @@ -110,8 +112,15 @@ void JSPtHooks::SendableMethodEntry(JSHandle method) [[maybe_unused]] LocalScope scope(debugger_->vm_); - if (debugger_->SendableMethodEntry(method)) { - firstTime_ = true; - }; + if (debugger_->NotifyScriptParsedBySendable(method)) { + if (!debugger_->IsLaunchAccelerateMode()) { + firstTime_ = true; + } + } +} + +void JSPtHooks::DisableFirstTimeFlag() +{ + firstTime_ = false; } } // namespace panda::ecmascript::tooling diff --git a/tooling/backend/js_pt_hooks.h b/tooling/backend/js_pt_hooks.h index a8429053..58c76e4f 100644 --- a/tooling/backend/js_pt_hooks.h +++ b/tooling/backend/js_pt_hooks.h @@ -41,6 +41,7 @@ public: void VmStart() override {} void VmDeath() override {} void SendableMethodEntry(JSHandle method) override; + void DisableFirstTimeFlag() override; private: NO_COPY_SEMANTIC(JSPtHooks); diff --git a/tooling/base/pt_events.cpp b/tooling/base/pt_events.cpp index 88f7ef01..f3a4e608 100644 --- a/tooling/base/pt_events.cpp +++ b/tooling/base/pt_events.cpp @@ -191,6 +191,15 @@ std::unique_ptr ScriptParsed::ToJson() const result->Add("embedderName", embedderName_->c_str()); } + std::unique_ptr array = PtJson::CreateArray(); + size_t len = locations_.size(); + for (size_t i = 0; i < len; i++) { + ASSERT(locations_[i] != nullptr); + std::unique_ptr location = locations_[i]->ToJson(); + array->Push(location); + } + result->Add("locations", array); + std::unique_ptr object = PtJson::CreateObject(); object->Add("method", GetName().c_str()); object->Add("params", result); diff --git a/tooling/base/pt_events.h b/tooling/base/pt_events.h index 47aa85d5..9d1bea7e 100644 --- a/tooling/base/pt_events.h +++ b/tooling/base/pt_events.h @@ -808,6 +808,12 @@ public: return embedderName_.has_value(); } + ScriptParsed &SetLocations(std::vector> locations) + { + locations_ = locations; + return *this; + } + private: NO_COPY_SEMANTIC(ScriptParsed); NO_MOVE_SEMANTIC(ScriptParsed); @@ -829,6 +835,7 @@ private: std::optional codeOffset_ {}; std::optional scriptLanguage_ {}; std::optional embedderName_ {}; + std::vector> locations_ {}; }; class AddHeapSnapshotChunk final : public PtBaseEvents { diff --git a/tooling/base/pt_json.cpp b/tooling/base/pt_json.cpp index 94b592e7..d265606c 100644 --- a/tooling/base/pt_json.cpp +++ b/tooling/base/pt_json.cpp @@ -249,6 +249,22 @@ std::string PtJson::GetKey() const return std::string(object_->string); } +std::vector PtJson::GetKeysArray() const +{ + std::vector result; + if (object_ == nullptr) { + return result; + } + cJSON *node = object_->child; + while (node != nullptr) { + if (node->string != nullptr) { + result.emplace_back(std::string(node->string)); + } + node = node->next; + } + return result; +} + cJSON *PtJson::GetJson() const { return object_; diff --git a/tooling/base/pt_json.h b/tooling/base/pt_json.h index d66e0d7f..dcaa0b8b 100644 --- a/tooling/base/pt_json.h +++ b/tooling/base/pt_json.h @@ -18,6 +18,7 @@ #include #include +#include #include "cJSON.h" #include "common/macros.h" @@ -73,6 +74,8 @@ public: std::string GetKey() const; + std::vector GetKeysArray() const; + cJSON *GetJson() const; // Type check diff --git a/tooling/base/pt_params.cpp b/tooling/base/pt_params.cpp index 293db741..3f5934db 100644 --- a/tooling/base/pt_params.cpp +++ b/tooling/base/pt_params.cpp @@ -30,6 +30,22 @@ std::unique_ptr EnableParams::Create(const PtJson ¶ms) error += "Wrong type of 'maxScriptsCacheSize';"; } + std::unique_ptr options; + std::vector enableOptionsList; + ret = params.GetArray("options", &options); + if (ret == Result::SUCCESS) { + int32_t length = options->GetSize(); + for (int32_t i = 0; i < length; i++) { + auto option = options->Get(i); + if (option != nullptr && option->IsString()) { + enableOptionsList.emplace_back(option->GetString()); + } + } + paramsObject->enableOptionList_ = enableOptionsList; + } else if (ret == Result::TYPE_ERROR) { + error += "Wrong type of 'options';"; + } + if (!error.empty()) { LOG_DEBUGGER(ERROR) << "EnableParams::Create " << error; return nullptr; @@ -1301,4 +1317,49 @@ std::unique_ptr SeriliazationTimeoutCheck } return paramsObject; } + +std::unique_ptr SaveAllPossibleBreakpointsParams::Create(const PtJson ¶ms) +{ + auto paramsObject = std::make_unique(); + std::unordered_map>> breakpointMap {}; + std::string error; + Result ret; + + std::unique_ptr locationList; + ret = params.GetObject("locations", &locationList); + if (ret != Result::SUCCESS) { + LOG_DEBUGGER(ERROR) << "SaveAllPossibleBreakpointsParams::Get Breakpoints location: " << error; + return nullptr; + } + + auto keys = locationList->GetKeysArray(); + std::unique_ptr breakpoints; + for (const auto &key : keys) { + ret = locationList->GetArray(key.c_str(), &breakpoints); + if (ret == Result::SUCCESS) { + int32_t length = breakpoints->GetSize(); + std::vector> breakpointList; + for (int32_t i = 0; i < length; i++) { + auto json = *breakpoints->Get(i); + json.Add("url", key.c_str()); + std::shared_ptr info = BreakpointInfo::Create(json); + if (info == nullptr) { + error += "'breakpoints' items BreakpointInfo is invalid;"; + break; + } + breakpointList.emplace_back(std::move(info)); + } + breakpointMap[key] = breakpointList; + } else if (ret == Result::TYPE_ERROR) { + error += "Wrong type of 'breakpoints'"; + } + } + if (!error.empty()) { + LOG_DEBUGGER(ERROR) << "SaveAllPossibleBreakpointsParams::Create " << error; + return nullptr; + } + paramsObject->breakpointsMap_ = breakpointMap; + + return paramsObject; +} } // namespace panda::ecmascript::tooling diff --git a/tooling/base/pt_params.h b/tooling/base/pt_params.h index ea8a5110..404616ef 100644 --- a/tooling/base/pt_params.h +++ b/tooling/base/pt_params.h @@ -74,11 +74,23 @@ public: return maxScriptsCacheSize_.has_value(); } + bool HasEnableOptionsList() const + { + return enableOptionList_.has_value(); + } + + std::vector GetEnableOptionsList() const + { + ASSERT(HasEnableOptionsList()); + return enableOptionList_.value(); + } + private: NO_COPY_SEMANTIC(EnableParams); NO_MOVE_SEMANTIC(EnableParams); std::optional maxScriptsCacheSize_ {}; + std::optional> enableOptionList_ {}; }; class EvaluateOnCallFrameParams : public PtBaseParams { @@ -1370,5 +1382,33 @@ private: static constexpr int32_t DEFAULT_THRESHOLD = 8; int32_t threshold_ { DEFAULT_THRESHOLD }; }; + +class SaveAllPossibleBreakpointsParams : public PtBaseParams { +public: + SaveAllPossibleBreakpointsParams() = default; + ~SaveAllPossibleBreakpointsParams() = default; + + static std::unique_ptr Create(const PtJson ¶ms); + + const std::unordered_map>> *GetBreakpointsMap() const + { + if (!HasBreakpointsMap()) { + return nullptr; + } + return &(breakpointsMap_.value()); + } + + bool HasBreakpointsMap() const + { + return breakpointsMap_.has_value(); + } + +private: + NO_COPY_SEMANTIC(SaveAllPossibleBreakpointsParams); + NO_MOVE_SEMANTIC(SaveAllPossibleBreakpointsParams); + + std::optional>>> + breakpointsMap_ {}; +}; } // namespace panda::ecmascript::tooling #endif \ No newline at end of file diff --git a/tooling/base/pt_returns.h b/tooling/base/pt_returns.h index dea06ed9..d9dfa1ef 100644 --- a/tooling/base/pt_returns.h +++ b/tooling/base/pt_returns.h @@ -85,7 +85,7 @@ private: class GetPossibleAndSetBreakpointByUrlReturns : public PtBaseReturns { public: - explicit GetPossibleAndSetBreakpointByUrlReturns(std::vector> locations) + explicit GetPossibleAndSetBreakpointByUrlReturns(std::vector> locations) : locations_(std::move(locations)) {} ~GetPossibleAndSetBreakpointByUrlReturns() override = default; @@ -97,7 +97,7 @@ private: NO_COPY_SEMANTIC(GetPossibleAndSetBreakpointByUrlReturns); NO_MOVE_SEMANTIC(GetPossibleAndSetBreakpointByUrlReturns); - std::vector> locations_ {}; + std::vector> locations_ {}; }; class EvaluateOnCallFrameReturns : public PtBaseReturns { diff --git a/tooling/base/pt_script.h b/tooling/base/pt_script.h index d401881c..2d797e2b 100644 --- a/tooling/base/pt_script.h +++ b/tooling/base/pt_script.h @@ -102,6 +102,16 @@ public: endLine_ = endLine; } + std::vector> GetLocations() const + { + return locations_; + } + + void SetLocations(std::vector> locations) + { + locations_ = locations; + } + private: NO_COPY_SEMANTIC(PtScript); NO_MOVE_SEMANTIC(PtScript); @@ -113,6 +123,7 @@ private: std::string scriptSource_ {}; // js source code std::string sourceMapUrl_ {}; // source map url int32_t endLine_ {0}; // total line number of source file + std::vector> locations_ {}; }; } // namespace panda::ecmascript::tooling #endif diff --git a/tooling/base/pt_types.cpp b/tooling/base/pt_types.cpp index 73aab2f7..a161ce9a 100644 --- a/tooling/base/pt_types.cpp +++ b/tooling/base/pt_types.cpp @@ -3386,6 +3386,18 @@ std::unique_ptr BreakpointInfo::Create(const PtJson ¶ms) return paramsObject; } +std::shared_ptr BreakpointInfo::CreateAsSharedPtr(int32_t line, int32_t column, + std::string url, std::string condition) +{ + auto result = std::make_shared(); + result->lineNumber_ = line; + result->columnNumber_ = column; + result->url_ = url; + result->condition_ = condition; + + return result; +} + std::unique_ptr BreakpointInfo::ToJson() const { std::unique_ptr result = PtJson::CreateObject(); diff --git a/tooling/base/pt_types.h b/tooling/base/pt_types.h index 03a2b66b..39efb84e 100644 --- a/tooling/base/pt_types.h +++ b/tooling/base/pt_types.h @@ -100,6 +100,8 @@ public: ~BreakpointInfo() override = default; static std::unique_ptr Create(const PtJson ¶ms); + static std::shared_ptr CreateAsSharedPtr(int32_t line, int32_t column, + std::string url, std::string condition = ""); std::unique_ptr ToJson() const override; int32_t GetLineNumber() const @@ -173,6 +175,15 @@ private: std::optional restrictToFunction_ {}; }; +class HashBreakpointInfo { +public: + size_t operator()(const std::shared_ptr &bpoint) const + { + return (std::hash()(bpoint->GetUrl())) ^ + (std::hash()(bpoint->GetLineNumber())) ^ + (std::hash()(bpoint->GetColumnNumber())); + } +}; // Runtime.ScriptId using ScriptId = int32_t; diff --git a/tooling/client/domain/debugger_client.cpp b/tooling/client/domain/debugger_client.cpp index 1e21e836..7c5612e8 100644 --- a/tooling/client/domain/debugger_client.cpp +++ b/tooling/client/domain/debugger_client.cpp @@ -54,6 +54,8 @@ bool DebuggerClient::DispatcherCmd(const std::string &cmd) { "step-into", std::bind(&DebuggerClient::StepIntoCommand, this)}, { "step-out", std::bind(&DebuggerClient::StepOutCommand, this)}, { "step-over", std::bind(&DebuggerClient::StepOverCommand, this)}, + { "enable-launch-accelerate", std::bind(&DebuggerClient::EnableLaunchAccelerateCommand, this)}, + { "saveAllPossibleBreakpoints", std::bind(&DebuggerClient::SaveAllPossibleBreakpointsCommand, this)}, }; auto entry = dispatcherTable.find(cmd); @@ -433,4 +435,57 @@ void DebuggerClient::handleResponse(std::unique_ptr json) } return; } + +int DebuggerClient::SaveAllPossibleBreakpointsCommand() +{ + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + + std::unique_ptr request = PtJson::CreateObject(); + request->Add("id", id); + request->Add("method", "Debugger.saveAllPossibleBreakpoints"); + + std::unique_ptr params = PtJson::CreateObject(); + std::unique_ptr locations = PtJson::CreateObject(); + std::unique_ptr vector = PtJson::CreateArray(); + + std::unique_ptr bp = PtJson::CreateObject(); + bp->Add("lineNumber", breakPointInfoList_.back().lineNumber); + bp->Add("columnNumber", breakPointInfoList_.back().columnNumber); + vector->Push(bp); + locations->Add(breakPointInfoList_.back().url.c_str(), vector); + params->Add("locations", locations); + request->Add("params", params); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "Debugger"); + } + + return 0; +} + +int DebuggerClient::EnableLaunchAccelerateCommand() +{ + Session *session = SessionManager::getInstance().GetSessionById(sessionId_); + uint32_t id = session->GetMessageId(); + + std::unique_ptr request = PtJson::CreateObject(); + request->Add("id", id); + request->Add("method", "Debugger.enable"); + + std::unique_ptr params = PtJson::CreateObject(); + std::unique_ptr options = PtJson::CreateArray(); + + options->Push("enableLaunchAccelerate"); + params->Add("options", options); + request->Add("params", params); + + std::string message = request->Stringify(); + if (session->ClientSendReq(message)) { + session->GetDomainManager().SetDomainById(id, "Debugger"); + } + + return 0; +} } // OHOS::ArkCompiler::Toolchain \ No newline at end of file diff --git a/tooling/client/domain/debugger_client.h b/tooling/client/domain/debugger_client.h index ddf03031..aaeffd40 100644 --- a/tooling/client/domain/debugger_client.h +++ b/tooling/client/domain/debugger_client.h @@ -59,6 +59,8 @@ public: int StepIntoCommand(); int StepOutCommand(); int StepOverCommand(); + int EnableLaunchAccelerateCommand(); + int SaveAllPossibleBreakpointsCommand(); void AddBreakPointInfo(const std::string& url, const int& lineNumber, const int& columnNumber = 0); void RecvReply(std::unique_ptr json); diff --git a/tooling/client/utils/cli_command.cpp b/tooling/client/utils/cli_command.cpp index b6b0f170..3abf2751 100644 --- a/tooling/client/utils/cli_command.cpp +++ b/tooling/client/utils/cli_command.cpp @@ -182,6 +182,10 @@ void CliCommand::CreateCommandMap() {std::make_pair("enable", "enable"), std::bind(&CliCommand::DebuggerCommand, this, "enable")}, {std::make_pair("finish", "fin"), std::bind(&CliCommand::DebuggerCommand, this, "finish")}, {std::make_pair("frame", "f"), std::bind(&CliCommand::DebuggerCommand, this, "frame")}, + {std::make_pair("enable-launch-accelerate", "enable-acc"), + std::bind(&CliCommand::DebuggerCommand, this, "enable-launch-accelerate")}, + {std::make_pair("saveAllPossibleBreakpoints", "b-new"), + std::bind(&CliCommand::SaveAllPossibleBreakpointsCommand, this, "saveAllPossibleBreakpoints")}, }; CreateOtherCommandMap(); } @@ -625,6 +629,11 @@ ErrCode CliCommand::TestCommand(const std::string &cmd) return ErrCode::ERR_OK; } +ErrCode CliCommand::SaveAllPossibleBreakpointsCommand(const std::string &cmd) +{ + return BreakCommand(cmd); +} + ErrCode CliCommand::ExecHelpCommand() { std::cout << HELP_MSG; diff --git a/tooling/client/utils/cli_command.h b/tooling/client/utils/cli_command.h index 2720521d..88cafd29 100644 --- a/tooling/client/utils/cli_command.h +++ b/tooling/client/utils/cli_command.h @@ -72,6 +72,7 @@ public: ErrCode SessionSwitchCommand(const std::string &cmd); ErrCode TestCommand(const std::string &cmd); ErrCode ExecHelpCommand(); + ErrCode SaveAllPossibleBreakpointsCommand(const std::string &cmd); void OutputCommand(const std::string &cmd, bool flag); VecStr GetArgList() diff --git a/tooling/test/client_utils/test_list.cpp b/tooling/test/client_utils/test_list.cpp index c9326fbb..1c39f718 100644 --- a/tooling/test/client_utils/test_list.cpp +++ b/tooling/test/client_utils/test_list.cpp @@ -71,6 +71,7 @@ #include "tooling/test/testcases/js_heapusage_loop_test.h" #include "tooling/test/testcases/js_heapusage_recursion_test.h" #include "tooling/test/testcases/js_smart_stepInto_test.h" +#include "tooling/test/testcases/js_accelerate_launch_test.h" namespace panda::ecmascript::tooling::test { static std::string g_currentTestName = ""; @@ -131,6 +132,7 @@ static void RegisterTests() TestUtil::RegisterTest("JsHeapusageLoopTest", GetJsHeapusageLoopTest()); TestUtil::RegisterTest("JsHeapusageRecursionTest", GetJsHeapusageRecursionTest()); TestUtil::RegisterTest("JsSmartStepoutTest", GetJsSmartStepoutTest()); + TestUtil::RegisterTest("JsAccelerateLaunchTest", GetJsAccelerateLaunchTest()); } std::vector GetTestList() diff --git a/tooling/test/debugger_impl_test.cpp b/tooling/test/debugger_impl_test.cpp index 0fbb8811..7d0e3654 100644 --- a/tooling/test/debugger_impl_test.cpp +++ b/tooling/test/debugger_impl_test.cpp @@ -194,6 +194,43 @@ HWTEST_F_L0(DebuggerImplTest, Dispatcher_Dispatch_Enable__002) } } +HWTEST_F_L0(DebuggerImplTest, Dispatcher_Dispatch_Enable_Accelerate_Launch_Mode) +{ + std::string outStrForCallbackCheck = ""; + std::function callback = + [&outStrForCallbackCheck]([[maybe_unused]] const void *ptr, const std::string &inStrOfReply) { + outStrForCallbackCheck = inStrOfReply;}; + ProtocolChannel *protocolChannel = new ProtocolHandler(callback, ecmaVm); + auto runtimeImpl = std::make_unique(ecmaVm, protocolChannel); + auto debuggerImpl = std::make_unique(ecmaVm, protocolChannel, runtimeImpl.get()); + auto dispatcherImpl = std::make_unique(protocolChannel, std::move(debuggerImpl)); + EXPECT_FALSE(ecmaVm->GetJsDebuggerManager()->IsDebugMode()); + + std::string msg = std::string() + + R"({ + "id":0, + "method":"Debugger.enable", + "params":{ + "maxScriptsCacheSize":1024, + "options":[ + "enableLaunchAccelerate" + ] + } + })"; + DispatchRequest request(msg); + dispatcherImpl->Dispatch(request); + + bool condition = outStrForCallbackCheck.find("protocols") != std::string::npos && + outStrForCallbackCheck.find("debuggerId") != std::string::npos && + outStrForCallbackCheck.find("saveAllPossibleBreakpoints") != std::string::npos; + EXPECT_TRUE(condition); + EXPECT_TRUE(ecmaVm->GetJsDebuggerManager()->IsDebugMode()); + if (protocolChannel) { + delete protocolChannel; + protocolChannel = nullptr; + } +} + HWTEST_F_L0(DebuggerImplTest, Dispatcher_Dispatch_Disable__001) { std::string outStrForCallbackCheck = ""; diff --git a/tooling/test/debugger_params_test.cpp b/tooling/test/debugger_params_test.cpp index 07877ed9..f01dcc53 100644 --- a/tooling/test/debugger_params_test.cpp +++ b/tooling/test/debugger_params_test.cpp @@ -224,6 +224,45 @@ HWTEST_F_L0(DebuggerParamsTest, EnableParamsCreateTest) EXPECT_EQ(enableParams->GetMaxScriptsCacheSize(), 100); } +HWTEST_F_L0(DebuggerParamsTest, EnableParamsAccelerateLaunchModeCreateTest) +{ + std::string msg; + std::unique_ptr enableParams; + + // abnormal + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + enableParams = EnableParams::Create(DispatchRequest(msg).GetParams()); + ASSERT_NE(enableParams, nullptr); + EXPECT_FALSE(enableParams->HasMaxScriptsCacheSize()); + + // normal + msg = std::string() + R"({"id":0,"method":"Debugger.Test", + "params":{"options":["enableLaunchAccelerate"], "maxScriptsCacheSize":100}})"; + enableParams = EnableParams::Create(DispatchRequest(msg).GetParams()); + ASSERT_NE(enableParams, nullptr); + EXPECT_EQ(enableParams->GetMaxScriptsCacheSize(), 100); + EXPECT_EQ(enableParams->GetEnableOptionsList().size(), 1); +} + +HWTEST_F_L0(DebuggerParamsTest, SaveAllPossibleBreakpointsParamsCreateTest) +{ + std::string msg; + std::unique_ptr params; + + // abnormal + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + params = SaveAllPossibleBreakpointsParams::Create(DispatchRequest(msg).GetParams()); + ASSERT_EQ(params, nullptr); + + // normal + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ + "locations":{"actualUrl/actualFileName.ts":[{"lineNumber": 7, "columnNumber": 8}]}}})"; + params = SaveAllPossibleBreakpointsParams::Create(DispatchRequest(msg).GetParams()); + ASSERT_NE(params, nullptr); + EXPECT_TRUE(params->HasBreakpointsMap()); + EXPECT_EQ(params->GetBreakpointsMap()->size(), 1); +} + HWTEST_F_L0(DebuggerParamsTest, StartSamplingParamsCreateTest) { std::string msg; diff --git a/tooling/test/debugger_returns_test.cpp b/tooling/test/debugger_returns_test.cpp index 28062b6b..abe1dfd4 100644 --- a/tooling/test/debugger_returns_test.cpp +++ b/tooling/test/debugger_returns_test.cpp @@ -417,12 +417,12 @@ HWTEST_F_L0(DebuggerReturnsTest, SearchInContentReturnsToJsonTest) HWTEST_F_L0(DebuggerReturnsTest, GetPossibleAndSetBreakpointByUrlReturnsToJsonTest) { - auto locations = std::vector>(); - std::unique_ptr breakpointReturnInfo = std::make_unique(); + auto locations = std::vector>(); + std::shared_ptr breakpointReturnInfo = std::make_shared(); breakpointReturnInfo->SetScriptId(11).SetLineNumber(1).SetColumnNumber(44); - locations.emplace_back(std::move(breakpointReturnInfo)); + locations.emplace_back(breakpointReturnInfo); std::unique_ptr getPossibleAndSetBreakpointByUrlReturns = std::make_unique - (std::move(locations)); + (locations); std::unique_ptr locationsJS; ASSERT_EQ(getPossibleAndSetBreakpointByUrlReturns->ToJson()->GetArray("locations", &locationsJS), Result::SUCCESS); ASSERT_NE(locationsJS, nullptr); diff --git a/tooling/test/debugger_script_test.cpp b/tooling/test/debugger_script_test.cpp index ce1492c3..38562947 100644 --- a/tooling/test/debugger_script_test.cpp +++ b/tooling/test/debugger_script_test.cpp @@ -106,4 +106,16 @@ HWTEST_F_L0(DebuggerScriptTest, EndLineTest) script->SetEndLine(200); ASSERT_EQ(script->GetEndLine(), 200); } + +HWTEST_F_L0(DebuggerScriptTest, LocationsTest) +{ + std::unique_ptr script = std::make_unique(1, "name_1", "url_1", "source_1"); + std::vector> locations {}; + std::shared_ptr bpInfo = std::make_shared(); + std::string invalidBpId = "invalid"; + bpInfo->SetId(invalidBpId).SetLineNumber(1).SetColumnNumber(0); + locations.emplace_back(bpInfo); + script->SetLocations(locations); + ASSERT_EQ(script->GetLocations().size(), 1); +} } // namespace panda::test \ No newline at end of file diff --git a/tooling/test/pt_json_test.cpp b/tooling/test/pt_json_test.cpp index 9f42e46a..c128aedb 100644 --- a/tooling/test/pt_json_test.cpp +++ b/tooling/test/pt_json_test.cpp @@ -313,4 +313,15 @@ HWTEST_F_L0(PtJsonTest, ResultUInt64Test) ASSERT_EQ(test->GetUInt64("b", &ui64), Result::SUCCESS); EXPECT_EQ(ui64, static_cast(100)); } + +HWTEST_F_L0(PtJsonTest, GetKeysArraytest) +{ + auto test = PtJson::CreateObject(); + test->Add("a", "ResultUInt64Test"); + test->Add("b", 100); + auto keys = test->GetKeysArray(); + EXPECT_EQ(keys.size(), 2); + EXPECT_TRUE(keys.at(0) == "a"); + EXPECT_TRUE(keys.at(1) == "b"); +} } \ No newline at end of file diff --git a/tooling/test/testcases/js_accelerate_launch_test.h b/tooling/test/testcases/js_accelerate_launch_test.h new file mode 100644 index 00000000..45366e4a --- /dev/null +++ b/tooling/test/testcases/js_accelerate_launch_test.h @@ -0,0 +1,131 @@ +/* + * 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_TEST_TESTCASES_JS_ACCELERATE_LAUNCH_TEST_H +#define ECMASCRIPT_TOOLING_TEST_TESTCASES_JS_ACCELERATE_LAUNCH_TEST_H + +#include "tooling/test/client_utils/test_util.h" + +namespace panda::ecmascript::tooling::test { +class JsAccelerateLaunchTest : public TestActions { +public: + JsAccelerateLaunchTest() + { + testAction = { + // Enable Accelerate Launch Mode + {SocketAction::SEND, "enable-acc"}, + {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, + {SocketAction::SEND, "runtime-enable"}, + {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, + // Debugger.saveAllPossibleBreakpoints + {SocketAction::SEND, "b-new " DEBUGGER_JS_DIR "sample.js 22"}, + {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, + {SocketAction::SEND, "run"}, + {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, + // load sample.js + {SocketAction::RECV, "Debugger.scriptParsed", ActionRule::STRING_CONTAIN}, + {SocketAction::RECV, "Debugger.paused", ActionRule::STRING_CONTAIN}, + {SocketAction::SEND, "resume"}, + {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN}, + {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, + {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE, [this] (auto recv, auto, auto) -> bool { + std::unique_ptr json = PtJson::Parse(recv); + Result ret; + std::string method; + ret = json->GetString("method", &method); + if (ret != Result::SUCCESS || method != "Debugger.paused") { + return false; + } + + std::unique_ptr params = nullptr; + ret = json->GetObject("params", ¶ms); + if (ret != Result::SUCCESS) { + return false; + } + + std::unique_ptr hitBreakpoints = nullptr; + ret = params->GetArray("hitBreakpoints", &hitBreakpoints); + if (ret != Result::SUCCESS) { + return false; + } + + std::string breakpoint; + breakpoint = hitBreakpoints->Get(0)->GetString(); + if (ret != Result::SUCCESS || breakpoint.find(sourceFile_) == std::string::npos || + breakpoint.find("21") == std::string::npos) { + return false; + } + return true; + }}, + {SocketAction::SEND, "b " DEBUGGER_JS_DIR "sample.js 23"}, + {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, + {SocketAction::SEND, "resume"}, + {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN}, + {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, + {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE, [this] (auto recv, auto, auto) -> bool { + std::unique_ptr json = PtJson::Parse(recv); + Result ret; + std::string method; + ret = json->GetString("method", &method); + if (ret != Result::SUCCESS || method != "Debugger.paused") { + return false; + } + + std::unique_ptr params = nullptr; + ret = json->GetObject("params", ¶ms); + if (ret != Result::SUCCESS) { + return false; + } + + std::unique_ptr hitBreakpoints = nullptr; + ret = params->GetArray("hitBreakpoints", &hitBreakpoints); + if (ret != Result::SUCCESS) { + return false; + } + + std::string breakpoint; + breakpoint = hitBreakpoints->Get(0)->GetString(); + if (ret != Result::SUCCESS || breakpoint.find(sourceFile_) == std::string::npos || + breakpoint.find("22") == std::string::npos) { + return false; + } + return true; + }}, + {SocketAction::SEND, "success"}, + {SocketAction::SEND, "resume"}, + {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN}, + {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess}, + }; + } + + std::pair GetEntryPoint() override + { + return {pandaFile_, entryPoint_}; + } + ~JsAccelerateLaunchTest() = default; + +private: + std::string pandaFile_ = DEBUGGER_ABC_DIR "sample.abc"; + std::string sourceFile_ = DEBUGGER_JS_DIR "sample.js"; + std::string entryPoint_ = "_GLOBAL::func_main_0"; +}; + +std::unique_ptr GetJsAccelerateLaunchTest() +{ + return std::make_unique(); +} +} // namespace panda::ecmascript::tooling::test + +#endif // ECMASCRIPT_TOOLING_TEST_TESTCASES_JS_ACCELERATE_LAUNCH_TEST_H diff --git a/tooling/test/utils/test_hooks.h b/tooling/test/utils/test_hooks.h index 88cda04a..1fd7e2bd 100644 --- a/tooling/test/utils/test_hooks.h +++ b/tooling/test/utils/test_hooks.h @@ -118,6 +118,8 @@ public: void SendableMethodEntry([[maybe_unused]] JSHandle method) override {} + void DisableFirstTimeFlag() override {} + void TerminateTest() { debugInterface_->UnregisterHooks(); -- Gitee From 69057a5ad9b307948dda2a82acd7f79e86c09dc7 Mon Sep 17 00:00:00 2001 From: fangting Date: Fri, 27 Dec 2024 11:13:37 +0800 Subject: [PATCH 22/48] =?UTF-8?q?DT=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B?= =?UTF-8?q?=E5=B4=A9=E6=BA=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue:#IBE47P Signed-off-by: fangting --- test/resource/tooling/ohos_test.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/resource/tooling/ohos_test.xml b/test/resource/tooling/ohos_test.xml index 5b9dc623..7ef9ebae 100755 --- a/test/resource/tooling/ohos_test.xml +++ b/test/resource/tooling/ohos_test.xml @@ -91,6 +91,7 @@