From 17eb5611844cda29218291bafe3ac94567a2710f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Sat, 3 Jul 2021 11:57:07 +0200 Subject: [PATCH 001/140] deps: V8: backport 1b1eda0876aa MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Original commit message: tracing: Update proto library build rule and roll Perfetto This patch removes use of the deprecated sources_assignment_filter GN feature from gni/proto_library.gni, since the extra descriptor files are no longer being generated. We also roll Perfetto to match the version used in Chrome and update test expectations accordingly. Bug: v8:10995 Change-Id: I65cb3b79feb6e5a7e5c8d99fdb8bf999a6048539 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2454079 Commit-Queue: Michael Achenbach Auto-Submit: Sami Kyöstilä Reviewed-by: Peter Marshall Reviewed-by: Michael Achenbach Cr-Commit-Position: refs/heads/master@{#70381} Refs: https://github.com/v8/v8/commit/1b1eda0876aa20bc1dc71caa6baf3a52c0c1540d PR-URL: https://github.com/nodejs/node/pull/39244 Refs: https://github.com/nodejs/build/issues/2696 Reviewed-By: Richard Lau --- common.gypi | 2 +- deps/v8/DEPS | 2 +- deps/v8/gni/proto_library.gni | 11 ++++++----- deps/v8/test/cctest/libplatform/test-tracing.cc | 9 +++++---- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/common.gypi b/common.gypi index 8fdb6d36df0b74..bc7a232129701a 100644 --- a/common.gypi +++ b/common.gypi @@ -36,7 +36,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.67', + 'v8_embedder_string': '-node.68', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/DEPS b/deps/v8/DEPS index 7b38c3dcd07b17..07a28de315de66 100644 --- a/deps/v8/DEPS +++ b/deps/v8/DEPS @@ -266,7 +266,7 @@ deps = { 'dep_type': 'cipd', }, 'v8/third_party/perfetto': - Var('android_url') + '/platform/external/perfetto.git' + '@' + 'ff70e0d273ed10995866c803f23e11250eb3dc52', + Var('android_url') + '/platform/external/perfetto.git' + '@' + '7cdc44f903d3bcfd1d0f67188bfa797a24756868', 'v8/third_party/protobuf': Var('chromium_url') + '/external/github.com/google/protobuf'+ '@' + 'b68a347f56137b4b1a746e8c7438495a6ac1bd91', 'v8/third_party/zlib': diff --git a/deps/v8/gni/proto_library.gni b/deps/v8/gni/proto_library.gni index eca3ffb84e55ac..0b72d7b8a4533c 100644 --- a/deps/v8/gni/proto_library.gni +++ b/deps/v8/gni/proto_library.gni @@ -11,8 +11,6 @@ template("proto_library") { assert(defined(invoker.sources)) proto_sources = invoker.sources - set_sources_assignment_filter([]) - if (host_os == "win") { host_executable_suffix = ".exe" } else { @@ -141,6 +139,12 @@ template("proto_library") { ] } + if (defined(invoker.import_dirs)) { + foreach(path, invoker.import_dirs) { + args += [ "--import-dir=" + rebase_path(path, root_build_dir) ] + } + } + if (generate_with_plugin) { plugin_path_rebased = rebase_path(plugin_path, root_build_dir) plugin_out_args = "" @@ -187,10 +191,7 @@ template("proto_library") { "visibility", ]) - # Exclude the config.descriptor file which is an output for some reason. - set_sources_assignment_filter([ "*.descriptor" ]) sources = get_target_outputs(":$action_name") - set_sources_assignment_filter(sources_assignment_filter) # configs -= [ "//gn/standalone:extra_warnings" ] if (defined(invoker.extra_configs)) { diff --git a/deps/v8/test/cctest/libplatform/test-tracing.cc b/deps/v8/test/cctest/libplatform/test-tracing.cc index 81ad57b9c915e8..7572b887a175ff 100644 --- a/deps/v8/test/cctest/libplatform/test-tracing.cc +++ b/deps/v8/test/cctest/libplatform/test-tracing.cc @@ -860,10 +860,11 @@ TEST(JsonIntegrationTest) { std::vector all_args; GetJSONStrings(&all_args, json, "\"args\"", "{", "}"); - CHECK_EQ("\"1\":1e+100", all_args[0]); - CHECK_EQ("\"2\":\"NaN\"", all_args[1]); - CHECK_EQ("\"3\":\"Infinity\"", all_args[2]); - CHECK_EQ("\"4\":\"-Infinity\"", all_args[3]); + // Ignore the first metadata event. + CHECK_EQ("\"1\":1e+100", all_args[1]); + CHECK_EQ("\"2\":\"NaN\"", all_args[2]); + CHECK_EQ("\"3\":\"Infinity\"", all_args[3]); + CHECK_EQ("\"4\":\"-Infinity\"", all_args[4]); } #endif // V8_USE_PERFETTO From a83b01a4afd8af7ae912a69ce37a4de0f62ff3e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Sat, 3 Jul 2021 11:57:22 +0200 Subject: [PATCH 002/140] deps: V8: cherry-pick 92e6d3317082 Original commit message: build: Remove no-op calls to set_sources_assignment_filter Chromiun no longer use set_sources_assignment_filter() anywhere in the build, so these are no longer needed. Bug: chromium:1018739 Change-Id: I7b33612d925563ebca0d93a7d3c9183d7305b7b0 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2456988 Reviewed-by: Nico Weber Commit-Queue: Nico Weber Cr-Commit-Position: refs/heads/master@{#70405} Refs: https://github.com/v8/v8/commit/92e6d3317082e492ff11fd50a1f3481368f6cafc PR-URL: https://github.com/nodejs/node/pull/39244 Refs: https://github.com/nodejs/build/issues/2696 Reviewed-By: Richard Lau --- common.gypi | 2 +- deps/v8/testing/gtest/BUILD.gn | 18 ++++-------------- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/common.gypi b/common.gypi index bc7a232129701a..cc9504be2bae92 100644 --- a/common.gypi +++ b/common.gypi @@ -36,7 +36,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.68', + 'v8_embedder_string': '-node.69', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/testing/gtest/BUILD.gn b/deps/v8/testing/gtest/BUILD.gn index fe7ba6d4839da5..6636b2d9acf448 100644 --- a/deps/v8/testing/gtest/BUILD.gn +++ b/deps/v8/testing/gtest/BUILD.gn @@ -4,9 +4,9 @@ import("//build_overrides/gtest.gni") if (is_ios) { + import("//build/buildflag_header.gni") import("//build/config/coverage/coverage.gni") import("//build/config/ios/ios_sdk.gni") - import("//build/buildflag_header.gni") } config("gtest_direct_config") { @@ -40,9 +40,7 @@ static_library("gtest") { # Android. https://codereview.chromium.org/2852613002/#ps20001 "empty.cc", ] - public_deps = [ - "//third_party/googletest:gtest", - ] + public_deps = [ "//third_party/googletest:gtest" ] public_configs = [ ":gtest_direct_config" ] @@ -58,9 +56,6 @@ static_library("gtest") { } if ((is_mac || is_ios) && gtest_include_objc_support) { - if (is_ios) { - set_sources_assignment_filter([]) - } sources += [ "../gtest_mac.h", "../gtest_mac.mm", @@ -68,7 +63,6 @@ static_library("gtest") { if (gtest_include_platform_test) { sources += [ "../platform_test_mac.mm" ] } - set_sources_assignment_filter(sources_assignment_filter) } if (is_ios && gtest_include_ios_coverage) { @@ -76,9 +70,7 @@ static_library("gtest") { "../coverage_util_ios.h", "../coverage_util_ios.mm", ] - deps = [ - ":ios_enable_coverage", - ] + deps = [ ":ios_enable_coverage" ] } } @@ -87,9 +79,7 @@ static_library("gtest") { # into //third_party/googletest. source_set("gtest_main") { testonly = true - deps = [ - "//third_party/googletest:gtest_main", - ] + deps = [ "//third_party/googletest:gtest_main" ] } if (is_ios) { From 4be2e878b7515504d534ef9632429cf194d857ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Wed, 7 Jul 2021 13:21:50 +0200 Subject: [PATCH 003/140] deps: V8: cherry-pick 7c182bd65f42 Original commit message: Fix visiblity rules for configs enforced by the latest GN version. Prior versions of GN had a bug (gn:22) where visibility rules for configs weren't being enforced properly. This CL tweaks the visibility settings of some configs to conform to the latest version. Change-Id: Ic5d827a1f2774278d3894f67fe52bfca836c0409 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2360909 Commit-Queue: Dirk Pranke Reviewed-by: Adam Klein Cr-Commit-Position: refs/heads/master@{#69463} Refs: https://github.com/v8/v8/commit/7c182bd65f424db19dc3e3d9aca601030af30d7e PR-URL: https://github.com/nodejs/node/pull/39244 Refs: https://github.com/nodejs/build/issues/2696 Reviewed-By: Richard Lau --- common.gypi | 2 +- deps/v8/BUILD.gn | 12 ++++++++---- deps/v8/third_party/inspector_protocol/BUILD.gn | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/common.gypi b/common.gypi index cc9504be2bae92..0f91d3744130a4 100644 --- a/common.gypi +++ b/common.gypi @@ -36,7 +36,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.69', + 'v8_embedder_string': '-node.70', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/BUILD.gn b/deps/v8/BUILD.gn index eaaeadfce3f6cd..a8100ad6c62522 100644 --- a/deps/v8/BUILD.gn +++ b/deps/v8/BUILD.gn @@ -308,7 +308,8 @@ v8_toolset_for_shell = "host" # config("internal_config_base") { - visibility = [ ":*" ] # Only targets in this file can depend on this. + # Only targets in this file and its subdirs can depend on this. + visibility = [ "./*" ] configs = [ ":v8_tracing_config" ] @@ -321,7 +322,8 @@ config("internal_config_base") { config("internal_config") { defines = [] - visibility = [ ":*" ] # Only targets in this file can depend on this. + # Only targets in this file and its subdirs can depend on this. + visibility = [ "./*" ] configs = [ "//build/config/compiler:wexit_time_destructors", @@ -429,7 +431,8 @@ config("v8_header_features") { # Put defines here that are only used in our internal files and NEVER in # external headers that embedders (such as chromium and node) might include. config("features") { - visibility = [ ":*" ] # Only targets in this file can depend on this. + # Only targets in this file and its subdirs can depend on this. + visibility = [ "./*" ] defines = [] @@ -559,7 +562,8 @@ config("features") { } config("toolchain") { - visibility = [ ":*" ] # Only targets in this file can depend on this. + # Only targets in this file and its subdirs can depend on this. + visibility = [ "./*" ] defines = [] cflags = [] diff --git a/deps/v8/third_party/inspector_protocol/BUILD.gn b/deps/v8/third_party/inspector_protocol/BUILD.gn index 33ef78c24b5397..98d89456f1d1cb 100644 --- a/deps/v8/third_party/inspector_protocol/BUILD.gn +++ b/deps/v8/third_party/inspector_protocol/BUILD.gn @@ -5,7 +5,7 @@ import("../../gni/v8.gni") config("crdtp_config") { - visibility = [ "../../src/inspector:*" ] + visibility = [ "../../src/inspector:*", ":*" ] configs = [ "../../:internal_config" ] include_dirs = [ "../../include" ] } From 7fdd6ecbb41198d9e54e34de9ceeb8d2c45fa172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Wed, 7 Jul 2021 13:22:13 +0200 Subject: [PATCH 004/140] deps: V8: cherry-pick 0b3a4ecf7083 Original commit message: Fix implicit conversion loses integer precision warning The type of m is long in 64 bits build, and results implicit conversion loses integer precision, which was found by improved clang warning (-Wshorten-64-to-32) Bug: chromium:1124085 Change-Id: Ic9f22508bd817a06d5c90162b1ac3554a7171529 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2391323 Commit-Queue: Zequan Wu Auto-Submit: Zequan Wu Reviewed-by: Nico Weber Reviewed-by: Igor Sheludko Cr-Commit-Position: refs/heads/master@{#69686} Refs: https://github.com/v8/v8/commit/0b3a4ecf708334ff20dd5a978c3765e75675b40b PR-URL: https://github.com/nodejs/node/pull/39244 Refs: https://github.com/nodejs/build/issues/2696 Reviewed-By: Richard Lau --- common.gypi | 2 +- deps/v8/src/base/macros.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/common.gypi b/common.gypi index 0f91d3744130a4..b622b61086d434 100644 --- a/common.gypi +++ b/common.gypi @@ -36,7 +36,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.70', + 'v8_embedder_string': '-node.71', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/base/macros.h b/deps/v8/src/base/macros.h index e22dd00895ab7b..067a9115b26f5c 100644 --- a/deps/v8/src/base/macros.h +++ b/deps/v8/src/base/macros.h @@ -339,14 +339,14 @@ inline T RoundDown(T x, intptr_t m) { STATIC_ASSERT(std::is_integral::value); // m must be a power of two. DCHECK(m != 0 && ((m & (m - 1)) == 0)); - return x & -m; + return x & static_cast(-m); } template constexpr inline T RoundDown(T x) { STATIC_ASSERT(std::is_integral::value); // m must be a power of two. STATIC_ASSERT(m != 0 && ((m & (m - 1)) == 0)); - return x & -m; + return x & static_cast(-m); } // Return the smallest multiple of m which is >= x. From a60a9604064375c54aff535dc4020c595fa1b38a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Wed, 7 Jul 2021 13:22:38 +0200 Subject: [PATCH 005/140] deps: V8: cherry-pick 895949419186 Original commit message: Add -Wno-string-concatenation to test/cctest:cctest_sources v8/test/cctest/interpreter/test-bytecode-generator.cc contains lots of string arrays with intentional concatenation. Bug: chromium:1114873 Change-Id: Ie9d35c3849b5b0a6d1d01b6ce21fb80a320d8736 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2366829 Commit-Queue: Arthur Eubanks Reviewed-by: Sathya Gunasekaran Cr-Commit-Position: refs/heads/master@{#69625} Refs: https://github.com/v8/v8/commit/8959494191869ff483927916f9f46eb419784f07 PR-URL: https://github.com/nodejs/node/pull/39244 Refs: https://github.com/nodejs/build/issues/2696 Reviewed-By: Richard Lau --- common.gypi | 2 +- deps/v8/test/cctest/BUILD.gn | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/common.gypi b/common.gypi index b622b61086d434..8b81a0a39dd09d 100644 --- a/common.gypi +++ b/common.gypi @@ -36,7 +36,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.71', + 'v8_embedder_string': '-node.72', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/test/cctest/BUILD.gn b/deps/v8/test/cctest/BUILD.gn index 66e1473ed28d3a..037947c009a556 100644 --- a/deps/v8/test/cctest/BUILD.gn +++ b/deps/v8/test/cctest/BUILD.gn @@ -60,6 +60,12 @@ v8_header_set("cctest_headers") { sources = [ "cctest.h" ] } +config("cctest_sources_config") { + if (is_clang) { + cflags = [ "-Wno-string-concatenation" ] + } +} + v8_source_set("cctest_sources") { testonly = true @@ -398,6 +404,7 @@ v8_source_set("cctest_sources") { "../..:external_config", "../..:internal_config_base", "../..:v8_tracing_config", + ":cctest_sources_config", ] public_deps = [ From 7557e74cf41f3f1a7e12ac98710c422a10cc1be0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Wed, 7 Jul 2021 13:30:03 +0200 Subject: [PATCH 006/140] deps: V8: update build dependencies These updates are necessary to build V8 with recent GN versions. PR-URL: https://github.com/nodejs/node/pull/39244 Refs: https://github.com/nodejs/build/issues/2696 Reviewed-By: Richard Lau --- deps/v8/DEPS | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/deps/v8/DEPS b/deps/v8/DEPS index 07a28de315de66..9c347a078ba69e 100644 --- a/deps/v8/DEPS +++ b/deps/v8/DEPS @@ -72,15 +72,15 @@ vars = { deps = { 'v8/build': - Var('chromium_url') + '/chromium/src/build.git' + '@' + '1b904cc30093c25d5fd48389bd58e3f7409bcf80', + Var('chromium_url') + '/chromium/src/build.git' + '@' + 'c854b8178a7e0a20b168ffded4f2d2cb1e136e42', 'v8/third_party/depot_tools': - Var('chromium_url') + '/chromium/tools/depot_tools.git' + '@' + '454f4ba4b3a69feb03c73f93d789062033433b4c', + Var('chromium_url') + '/chromium/tools/depot_tools.git' + '@' + 'd4e6fb6573e0955110a2c69be29557f6626d9ae6', 'v8/third_party/icu': Var('chromium_url') + '/chromium/deps/icu.git' + '@' + 'f2223961702f00a8833874b0560d615a2cc42738', 'v8/third_party/instrumented_libraries': Var('chromium_url') + '/chromium/src/third_party/instrumented_libraries.git' + '@' + 'bb3f1802c237dd19105dd0f7919f99e536a39d10', 'v8/buildtools': - Var('chromium_url') + '/chromium/src/buildtools.git' + '@' + '204a35a2a64f7179f8b76d7a0385653690839e21', + Var('chromium_url') + '/chromium/src/buildtools.git' + '@' + '6302c1175607a436e18947a5abe9df2209e845fc', 'v8/buildtools/clang_format/script': Var('chromium_url') + '/chromium/llvm-project/cfe/tools/clang-format.git' + '@' + '96636aa0e9f047f17447f2d45a094d0b59ed7917', 'v8/buildtools/linux64': { @@ -168,7 +168,7 @@ deps = { 'dep_type': 'cipd', }, 'v8/third_party/catapult': { - 'url': Var('chromium_url') + '/catapult.git' + '@' + 'e9a8d378c950ee44beec5dd5207e151f48e5b5be', + 'url': Var('chromium_url') + '/catapult.git' + '@' + 'f92a7636da65f28dad15bc524e6b681d1c311de0', 'condition': 'checkout_android', }, 'v8/third_party/colorama/src': { @@ -236,7 +236,7 @@ deps = { 'dep_type': 'cipd', }, 'v8/tools/clang': - Var('chromium_url') + '/chromium/src/tools/clang.git' + '@' + 'de3e20662b84f0ee361a5ae11c99a9513df7c8e8', + Var('chromium_url') + '/chromium/src/tools/clang.git' + '@' + 'c72342ce992ebd9cc02c0d65f0af5941d29eb217', 'v8/tools/luci-go': { 'packages': [ { From ccecea5f72211e84612e4417abbb357d488407e5 Mon Sep 17 00:00:00 2001 From: Richard Lau Date: Thu, 17 Jun 2021 16:10:14 -0400 Subject: [PATCH 007/140] deps: restore minimum ICU version to 65 This modifies 40df0dc so that the changes it applies are only used if ICU 67 or greater is used, and restores the previous code path for versions of ICU below 67. The minimum ICU version was bumped to 67 in Node.js 14.6.0 by https://github.com/nodejs/node/pull/34356 but the referenced V8 commit[1] isn't on `v14.x-staging` and appears to have been reverted on V8 8.4[2] so this PR also restores the minimum ICU version to 65. [1] https://github.com/v8/v8/commit/611e412768a7bc87a20d0315635b0bf76a5bab46 [2] https://github.com/v8/v8/commit/eeccedee1882f1f870b37d12978cd818934b375d PR-URL: https://github.com/nodejs/node/pull/39068 Reviewed-By: Michael Dawson Reviewed-By: Colin Ihrig Reviewed-By: Beth Griggs --- deps/v8/src/objects/js-list-format.cc | 51 +++++++++++++++++++++++++++ tools/icu/icu_versions.json | 2 +- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/deps/v8/src/objects/js-list-format.cc b/deps/v8/src/objects/js-list-format.cc index 0cd7d1bb6b58bb..2294a6f77499b2 100644 --- a/deps/v8/src/objects/js-list-format.cc +++ b/deps/v8/src/objects/js-list-format.cc @@ -24,12 +24,58 @@ #include "unicode/fpositer.h" #include "unicode/listformatter.h" #include "unicode/ulistformatter.h" +#include "unicode/uvernum.h" namespace v8 { namespace internal { namespace { +#if U_ICU_VERSION_MAJOR_NUM < 67 +const char* kStandard = "standard"; +const char* kOr = "or"; +const char* kUnit = "unit"; +const char* kStandardShort = "standard-short"; +const char* kOrShort = "or-short"; +const char* kUnitShort = "unit-short"; +const char* kStandardNarrow = "standard-narrow"; +const char* kOrNarrow = "or-narrow"; +const char* kUnitNarrow = "unit-narrow"; + +const char* GetIcuStyleString(JSListFormat::Style style, + JSListFormat::Type type) { + switch (type) { + case JSListFormat::Type::CONJUNCTION: + switch (style) { + case JSListFormat::Style::LONG: + return kStandard; + case JSListFormat::Style::SHORT: + return kStandardShort; + case JSListFormat::Style::NARROW: + return kStandardNarrow; + } + case JSListFormat::Type::DISJUNCTION: + switch (style) { + case JSListFormat::Style::LONG: + return kOr; + case JSListFormat::Style::SHORT: + return kOrShort; + case JSListFormat::Style::NARROW: + return kOrNarrow; + } + case JSListFormat::Type::UNIT: + switch (style) { + case JSListFormat::Style::LONG: + return kUnit; + case JSListFormat::Style::SHORT: + return kUnitShort; + case JSListFormat::Style::NARROW: + return kUnitNarrow; + } + } + UNREACHABLE(); +} +#else UListFormatterWidth GetIcuWidth(JSListFormat::Style style) { switch (style) { case JSListFormat::Style::LONG: @@ -53,6 +99,7 @@ UListFormatterType GetIcuType(JSListFormat::Type type) { } UNREACHABLE(); } +#endif } // namespace @@ -124,7 +171,11 @@ MaybeHandle JSListFormat::New(Isolate* isolate, Handle map, icu::Locale icu_locale = r.icu_locale; UErrorCode status = U_ZERO_ERROR; icu::ListFormatter* formatter = icu::ListFormatter::createInstance( +#if U_ICU_VERSION_MAJOR_NUM < 67 + icu_locale, GetIcuStyleString(style_enum, type_enum), status); +#else icu_locale, GetIcuType(type_enum), GetIcuWidth(style_enum), status); +#endif if (U_FAILURE(status) || formatter == nullptr) { delete formatter; THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kIcuError), diff --git a/tools/icu/icu_versions.json b/tools/icu/icu_versions.json index 19a05a679a987b..a14ea6db2887ae 100644 --- a/tools/icu/icu_versions.json +++ b/tools/icu/icu_versions.json @@ -1,3 +1,3 @@ { - "minimum_icu": 67 + "minimum_icu": 65 } From 4213e97d268dd8bfee6fb799313563f8389cf59d Mon Sep 17 00:00:00 2001 From: thomasmichaelwallace Date: Mon, 28 Jun 2021 20:53:38 +0000 Subject: [PATCH 008/140] deps: V8: cherry-pick 81181a8ad80a MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Original commit message: [JSON] Fix GC issue in BuildJsonObject We must ensure that the sweeper is not running or has already swept mutable_double_buffer. Otherwise the GC can add it to the free list. Bug: v8:11837 Change-Id: Ifd9cf15f1c94f664fd6489c70bb38b59730cdd78 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2928181 Commit-Queue: Victor Gomes Reviewed-by: Toon Verwaest Reviewed-by: Dominik Inführ Cr-Commit-Position: refs/heads/master@{#74859} Refs: v8/v8@81181a8 PR-URL: https://github.com/nodejs/node/pull/39187 Fixes: https://github.com/nodejs/node/issues/37553 Refs: https://github.com/v8/v8/commit/81181a8 Reviewed-By: Michaël Zasso Reviewed-By: Richard Lau Reviewed-By: Gireesh Punathil Reviewed-By: Matteo Collina --- common.gypi | 2 +- deps/v8/src/heap/heap.cc | 4 ++++ deps/v8/src/heap/heap.h | 2 ++ deps/v8/src/json/json-parser.cc | 5 +++++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/common.gypi b/common.gypi index 8b81a0a39dd09d..bb27df43d5cb7c 100644 --- a/common.gypi +++ b/common.gypi @@ -36,7 +36,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.72', + 'v8_embedder_string': '-node.73', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/heap/heap.cc b/deps/v8/src/heap/heap.cc index 5d5eaae0683b74..62033444ed0427 100644 --- a/deps/v8/src/heap/heap.cc +++ b/deps/v8/src/heap/heap.cc @@ -3347,6 +3347,10 @@ void Heap::MakeHeapIterable() { mark_compact_collector()->EnsureSweepingCompleted(); } +void Heap::EnsureSweepingCompleted() { + mark_compact_collector()->EnsureSweepingCompleted(); +} + namespace { double ComputeMutatorUtilizationImpl(double mutator_speed, double gc_speed) { diff --git a/deps/v8/src/heap/heap.h b/deps/v8/src/heap/heap.h index b2105a96badc2f..4ca8c3b201fb03 100644 --- a/deps/v8/src/heap/heap.h +++ b/deps/v8/src/heap/heap.h @@ -1001,6 +1001,8 @@ class Heap { Reservation* reservations, const std::vector& large_objects, const std::vector
& maps); + void EnsureSweepingCompleted(); + IncrementalMarking* incremental_marking() { return incremental_marking_.get(); } diff --git a/deps/v8/src/json/json-parser.cc b/deps/v8/src/json/json-parser.cc index da2f60d3209b4a..2ac4e727e0bdb3 100644 --- a/deps/v8/src/json/json-parser.cc +++ b/deps/v8/src/json/json-parser.cc @@ -633,6 +633,11 @@ Handle JsonParser::BuildJsonObject( DCHECK_EQ(mutable_double_address, end); } #endif + // Before setting the length of mutable_double_buffer back to zero, we + // must ensure that the sweeper is not running or has already swept the + // object's page. Otherwise the GC can add the contents of + // mutable_double_buffer to the free list. + isolate()->heap()->EnsureSweepingCompleted(); mutable_double_buffer->set_length(0); } } From 8bd2a3926a06cb687cb9970ddb8a4de4d0de6b72 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Thu, 8 Apr 2021 03:49:53 -0700 Subject: [PATCH 009/140] debugger: move node-inspect to internal library MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit node-inspect developers have agreed to move node-inspect into core rather than vendor it as a dependency. Refs: https://github.com/nodejs/node/discussions/36481 PR-URL: https://github.com/nodejs/node/pull/38161 Backport-PR-URL: https://github.com/nodejs/node/pull/38858 Reviewed-By: Matteo Collina Reviewed-By: Jan Krems Reviewed-By: Colin Ihrig Reviewed-By: Stephen Belanger Reviewed-By: Gerhard Stöbich Reviewed-By: Michaël Zasso --- lib/internal/inspector/_inspect.js | 369 +++++++ lib/internal/inspector/inspect_client.js | 355 +++++++ lib/internal/inspector/inspect_repl.js | 1112 ++++++++++++++++++++++ lib/internal/main/inspect.js | 2 +- node.gyp | 6 +- 5 files changed, 1840 insertions(+), 4 deletions(-) create mode 100644 lib/internal/inspector/_inspect.js create mode 100644 lib/internal/inspector/inspect_client.js create mode 100644 lib/internal/inspector/inspect_repl.js diff --git a/lib/internal/inspector/_inspect.js b/lib/internal/inspector/_inspect.js new file mode 100644 index 00000000000000..df4e53979db8fd --- /dev/null +++ b/lib/internal/inspector/_inspect.js @@ -0,0 +1,369 @@ +/* + * Copyright Node.js contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +// TODO(trott): enable ESLint +/* eslint-disable */ + +'use strict'; +const { spawn } = require('child_process'); +const { EventEmitter } = require('events'); +const net = require('net'); +const util = require('util'); + +const runAsStandalone = typeof __dirname !== 'undefined'; + +const { 0: InspectClient, 1: createRepl } = + runAsStandalone ? + // This copy of node-inspect is on-disk, relative paths make sense. + [ + require('./inspect_client'), + require('./inspect_repl'), + ] : + // This copy of node-inspect is built into the node executable. + [ + require('internal/inspector/inspect_client'), + require('internal/inspector/inspect_repl'), + ]; + +const debuglog = util.debuglog('inspect'); + +class StartupError extends Error { + constructor(message) { + super(message); + this.name = 'StartupError'; + } +} + +function portIsFree(host, port, timeout = 9999) { + if (port === 0) return Promise.resolve(); // Binding to a random port. + + const retryDelay = 150; + let didTimeOut = false; + + return new Promise((resolve, reject) => { + setTimeout(() => { + didTimeOut = true; + reject(new StartupError( + `Timeout (${timeout}) waiting for ${host}:${port} to be free`)); + }, timeout); + + function pingPort() { + if (didTimeOut) return; + + const socket = net.connect(port, host); + let didRetry = false; + function retry() { + if (!didRetry && !didTimeOut) { + didRetry = true; + setTimeout(pingPort, retryDelay); + } + } + + socket.on('error', (error) => { + if (error.code === 'ECONNREFUSED') { + resolve(); + } else { + retry(); + } + }); + socket.on('connect', () => { + socket.destroy(); + retry(); + }); + } + pingPort(); + }); +} + +function runScript(script, scriptArgs, inspectHost, inspectPort, childPrint) { + return portIsFree(inspectHost, inspectPort) + .then(() => { + return new Promise((resolve) => { + const needDebugBrk = process.version.match(/^v(6|7)\./); + const args = (needDebugBrk ? + ['--inspect', `--debug-brk=${inspectPort}`] : + [`--inspect-brk=${inspectPort}`]) + .concat([script], scriptArgs); + const child = spawn(process.execPath, args); + child.stdout.setEncoding('utf8'); + child.stderr.setEncoding('utf8'); + child.stdout.on('data', childPrint); + child.stderr.on('data', childPrint); + + let output = ''; + function waitForListenHint(text) { + output += text; + if (/Debugger listening on ws:\/\/\[?(.+?)\]?:(\d+)\//.test(output)) { + const host = RegExp.$1; + const port = Number.parseInt(RegExp.$2); + child.stderr.removeListener('data', waitForListenHint); + resolve([child, port, host]); + } + } + + child.stderr.on('data', waitForListenHint); + }); + }); +} + +function createAgentProxy(domain, client) { + const agent = new EventEmitter(); + agent.then = (...args) => { + // TODO: potentially fetch the protocol and pretty-print it here. + const descriptor = { + [util.inspect.custom](depth, { stylize }) { + return stylize(`[Agent ${domain}]`, 'special'); + }, + }; + return Promise.resolve(descriptor).then(...args); + }; + + return new Proxy(agent, { + get(target, name) { + if (name in target) return target[name]; + return function callVirtualMethod(params) { + return client.callMethod(`${domain}.${name}`, params); + }; + }, + }); +} + +class NodeInspector { + constructor(options, stdin, stdout) { + this.options = options; + this.stdin = stdin; + this.stdout = stdout; + + this.paused = true; + this.child = null; + + if (options.script) { + this._runScript = runScript.bind(null, + options.script, + options.scriptArgs, + options.host, + options.port, + this.childPrint.bind(this)); + } else { + this._runScript = + () => Promise.resolve([null, options.port, options.host]); + } + + this.client = new InspectClient(); + + this.domainNames = ['Debugger', 'HeapProfiler', 'Profiler', 'Runtime']; + this.domainNames.forEach((domain) => { + this[domain] = createAgentProxy(domain, this.client); + }); + this.handleDebugEvent = (fullName, params) => { + const { 0: domain, 1: name } = fullName.split('.'); + if (domain in this) { + this[domain].emit(name, params); + } + }; + this.client.on('debugEvent', this.handleDebugEvent); + const startRepl = createRepl(this); + + // Handle all possible exits + process.on('exit', () => this.killChild()); + process.once('SIGTERM', process.exit.bind(process, 0)); + process.once('SIGHUP', process.exit.bind(process, 0)); + + this.run() + .then(() => startRepl()) + .then((repl) => { + this.repl = repl; + this.repl.on('exit', () => { + process.exit(0); + }); + this.paused = false; + }) + .then(null, (error) => process.nextTick(() => { throw error; })); + } + + suspendReplWhile(fn) { + if (this.repl) { + this.repl.pause(); + } + this.stdin.pause(); + this.paused = true; + return new Promise((resolve) => { + resolve(fn()); + }).then(() => { + this.paused = false; + if (this.repl) { + this.repl.resume(); + this.repl.displayPrompt(); + } + this.stdin.resume(); + }).then(null, (error) => process.nextTick(() => { throw error; })); + } + + killChild() { + this.client.reset(); + if (this.child) { + this.child.kill(); + this.child = null; + } + } + + run() { + this.killChild(); + + return this._runScript().then(({ 0: child, 1: port, 2: host }) => { + this.child = child; + + let connectionAttempts = 0; + const attemptConnect = () => { + ++connectionAttempts; + debuglog('connection attempt #%d', connectionAttempts); + this.stdout.write('.'); + return this.client.connect(port, host) + .then(() => { + debuglog('connection established'); + this.stdout.write(' ok'); + }, (error) => { + debuglog('connect failed', error); + // If it's failed to connect 10 times then print failed message + if (connectionAttempts >= 10) { + this.stdout.write(' failed to connect, please retry\n'); + process.exit(1); + } + + return new Promise((resolve) => setTimeout(resolve, 500)) + .then(attemptConnect); + }); + }; + + this.print(`connecting to ${host}:${port} ..`, true); + return attemptConnect(); + }); + } + + clearLine() { + if (this.stdout.isTTY) { + this.stdout.cursorTo(0); + this.stdout.clearLine(1); + } else { + this.stdout.write('\b'); + } + } + + print(text, oneline = false) { + this.clearLine(); + this.stdout.write(oneline ? text : `${text}\n`); + } + + childPrint(text) { + this.print( + text.toString() + .split(/\r\n|\r|\n/g) + .filter((chunk) => !!chunk) + .map((chunk) => `< ${chunk}`) + .join('\n') + ); + if (!this.paused) { + this.repl.displayPrompt(true); + } + if (/Waiting for the debugger to disconnect\.\.\.\n$/.test(text)) { + this.killChild(); + } + } +} + +function parseArgv([target, ...args]) { + let host = '127.0.0.1'; + let port = 9229; + let isRemote = false; + let script = target; + let scriptArgs = args; + + const hostMatch = target.match(/^([^:]+):(\d+)$/); + const portMatch = target.match(/^--port=(\d+)$/); + + if (hostMatch) { + // Connecting to remote debugger + host = hostMatch[1]; + port = parseInt(hostMatch[2], 10); + isRemote = true; + script = null; + } else if (portMatch) { + // Start on custom port + port = parseInt(portMatch[1], 10); + script = args[0]; + scriptArgs = args.slice(1); + } else if (args.length === 1 && /^\d+$/.test(args[0]) && target === '-p') { + // Start debugger against a given pid + const pid = parseInt(args[0], 10); + try { + process._debugProcess(pid); + } catch (e) { + if (e.code === 'ESRCH') { + console.error(`Target process: ${pid} doesn't exist.`); + process.exit(1); + } + throw e; + } + script = null; + isRemote = true; + } + + return { + host, port, isRemote, script, scriptArgs, + }; +} + +function startInspect(argv = process.argv.slice(2), + stdin = process.stdin, + stdout = process.stdout) { + if (argv.length < 1) { + const invokedAs = runAsStandalone ? + 'node-inspect' : + `${process.argv0} ${process.argv[1]}`; + + console.error(`Usage: ${invokedAs} script.js`); + console.error(` ${invokedAs} :`); + console.error(` ${invokedAs} -p `); + process.exit(1); + } + + const options = parseArgv(argv); + const inspector = new NodeInspector(options, stdin, stdout); + + stdin.resume(); + + function handleUnexpectedError(e) { + if (!(e instanceof StartupError)) { + console.error('There was an internal error in Node.js. ' + + 'Please report this bug.'); + console.error(e.message); + console.error(e.stack); + } else { + console.error(e.message); + } + if (inspector.child) inspector.child.kill(); + process.exit(1); + } + + process.on('uncaughtException', handleUnexpectedError); +} +exports.start = startInspect; diff --git a/lib/internal/inspector/inspect_client.js b/lib/internal/inspector/inspect_client.js new file mode 100644 index 00000000000000..6010f4ac09389d --- /dev/null +++ b/lib/internal/inspector/inspect_client.js @@ -0,0 +1,355 @@ +/* + * Copyright Node.js contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +// TODO(trott): enable ESLint +/* eslint-disable */ + +'use strict'; +const Buffer = require('buffer').Buffer; +const { EventEmitter } = require('events'); +const http = require('http'); +const URL = require('url'); +const util = require('util'); + +const debuglog = util.debuglog('inspect'); + +const kOpCodeText = 0x1; +const kOpCodeClose = 0x8; + +const kFinalBit = 0x80; +const kReserved1Bit = 0x40; +const kReserved2Bit = 0x20; +const kReserved3Bit = 0x10; +const kOpCodeMask = 0xF; +const kMaskBit = 0x80; +const kPayloadLengthMask = 0x7F; + +const kMaxSingleBytePayloadLength = 125; +const kMaxTwoBytePayloadLength = 0xFFFF; +const kTwoBytePayloadLengthField = 126; +const kEightBytePayloadLengthField = 127; +const kMaskingKeyWidthInBytes = 4; + +function isEmpty(obj) { + return Object.keys(obj).length === 0; +} + +function unpackError({ code, message, data }) { + const err = new Error(`${message} - ${data}`); + err.code = code; + Error.captureStackTrace(err, unpackError); + return err; +} + +function encodeFrameHybi17(payload) { + var i; + + const dataLength = payload.length; + + let singleByteLength; + let additionalLength; + if (dataLength > kMaxTwoBytePayloadLength) { + singleByteLength = kEightBytePayloadLengthField; + additionalLength = Buffer.alloc(8); + let remaining = dataLength; + for (i = 0; i < 8; ++i) { + additionalLength[7 - i] = remaining & 0xFF; + remaining >>= 8; + } + } else if (dataLength > kMaxSingleBytePayloadLength) { + singleByteLength = kTwoBytePayloadLengthField; + additionalLength = Buffer.alloc(2); + additionalLength[0] = (dataLength & 0xFF00) >> 8; + additionalLength[1] = dataLength & 0xFF; + } else { + additionalLength = Buffer.alloc(0); + singleByteLength = dataLength; + } + + const header = Buffer.from([ + kFinalBit | kOpCodeText, + kMaskBit | singleByteLength, + ]); + + const mask = Buffer.alloc(4); + const masked = Buffer.alloc(dataLength); + for (i = 0; i < dataLength; ++i) { + masked[i] = payload[i] ^ mask[i % kMaskingKeyWidthInBytes]; + } + + return Buffer.concat([header, additionalLength, mask, masked]); +} + +function decodeFrameHybi17(data) { + const dataAvailable = data.length; + const notComplete = { closed: false, payload: null, rest: data }; + let payloadOffset = 2; + if ((dataAvailable - payloadOffset) < 0) return notComplete; + + const firstByte = data[0]; + const secondByte = data[1]; + + const final = (firstByte & kFinalBit) !== 0; + const reserved1 = (firstByte & kReserved1Bit) !== 0; + const reserved2 = (firstByte & kReserved2Bit) !== 0; + const reserved3 = (firstByte & kReserved3Bit) !== 0; + const opCode = firstByte & kOpCodeMask; + const masked = (secondByte & kMaskBit) !== 0; + const compressed = reserved1; + if (compressed) { + throw new Error('Compressed frames not supported'); + } + if (!final || reserved2 || reserved3) { + throw new Error('Only compression extension is supported'); + } + + if (masked) { + throw new Error('Masked server frame - not supported'); + } + + let closed = false; + switch (opCode) { + case kOpCodeClose: + closed = true; + break; + case kOpCodeText: + break; + default: + throw new Error(`Unsupported op code ${opCode}`); + } + + let payloadLength = secondByte & kPayloadLengthMask; + switch (payloadLength) { + case kTwoBytePayloadLengthField: + payloadOffset += 2; + payloadLength = (data[2] << 8) + data[3]; + break; + + case kEightBytePayloadLengthField: + payloadOffset += 8; + payloadLength = 0; + for (var i = 0; i < 8; ++i) { + payloadLength <<= 8; + payloadLength |= data[2 + i]; + } + break; + + default: + // Nothing. We already have the right size. + } + if ((dataAvailable - payloadOffset - payloadLength) < 0) return notComplete; + + const payloadEnd = payloadOffset + payloadLength; + return { + payload: data.slice(payloadOffset, payloadEnd), + rest: data.slice(payloadEnd), + closed, + }; +} + +class Client extends EventEmitter { + constructor() { + super(); + this.handleChunk = this._handleChunk.bind(this); + + this._port = undefined; + this._host = undefined; + + this.reset(); + } + + _handleChunk(chunk) { + this._unprocessed = Buffer.concat([this._unprocessed, chunk]); + + while (this._unprocessed.length > 2) { + const { + closed, + payload: payloadBuffer, + rest + } = decodeFrameHybi17(this._unprocessed); + this._unprocessed = rest; + + if (closed) { + this.reset(); + return; + } + if (payloadBuffer === null || payloadBuffer.length === 0) break; + + const payloadStr = payloadBuffer.toString(); + debuglog('< %s', payloadStr); + const lastChar = payloadStr[payloadStr.length - 1]; + if (payloadStr[0] !== '{' || lastChar !== '}') { + throw new Error(`Payload does not look like JSON: ${payloadStr}`); + } + let payload; + try { + payload = JSON.parse(payloadStr); + } catch (parseError) { + parseError.string = payloadStr; + throw parseError; + } + + const { id, method, params, result, error } = payload; + if (id) { + const handler = this._pending[id]; + if (handler) { + delete this._pending[id]; + handler(error, result); + } + } else if (method) { + this.emit('debugEvent', method, params); + this.emit(method, params); + } else { + throw new Error(`Unsupported response: ${payloadStr}`); + } + } + } + + reset() { + if (this._http) { + this._http.destroy(); + } + this._http = null; + this._lastId = 0; + this._socket = null; + this._pending = {}; + this._unprocessed = Buffer.alloc(0); + } + + callMethod(method, params) { + return new Promise((resolve, reject) => { + if (!this._socket) { + reject(new Error('Use `run` to start the app again.')); + return; + } + const data = { id: ++this._lastId, method, params }; + this._pending[data.id] = (error, result) => { + if (error) reject(unpackError(error)); + else resolve(isEmpty(result) ? undefined : result); + }; + const json = JSON.stringify(data); + debuglog('> %s', json); + this._socket.write(encodeFrameHybi17(Buffer.from(json))); + }); + } + + _fetchJSON(urlPath) { + return new Promise((resolve, reject) => { + const httpReq = http.get({ + host: this._host, + port: this._port, + path: urlPath, + }); + + const chunks = []; + + function onResponse(httpRes) { + function parseChunks() { + const resBody = Buffer.concat(chunks).toString(); + if (httpRes.statusCode !== 200) { + reject(new Error(`Unexpected ${httpRes.statusCode}: ${resBody}`)); + return; + } + try { + resolve(JSON.parse(resBody)); + } catch (parseError) { + reject(new Error(`Response didn't contain JSON: ${resBody}`)); + + } + } + + httpRes.on('error', reject); + httpRes.on('data', (chunk) => chunks.push(chunk)); + httpRes.on('end', parseChunks); + } + + httpReq.on('error', reject); + httpReq.on('response', onResponse); + }); + } + + connect(port, host) { + this._port = port; + this._host = host; + return this._discoverWebsocketPath() + .then((urlPath) => this._connectWebsocket(urlPath)); + } + + _discoverWebsocketPath() { + return this._fetchJSON('/json') + .then(({ 0: { webSocketDebuggerUrl } }) => + URL.parse(webSocketDebuggerUrl).path); + } + + _connectWebsocket(urlPath) { + this.reset(); + + const key1 = require('crypto').randomBytes(16).toString('base64'); + debuglog('request websocket', key1); + + const httpReq = this._http = http.request({ + host: this._host, + port: this._port, + path: urlPath, + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'websocket', + 'Sec-WebSocket-Key': key1, + 'Sec-WebSocket-Version': '13', + }, + }); + httpReq.on('error', (e) => { + this.emit('error', e); + }); + httpReq.on('response', (httpRes) => { + if (httpRes.statusCode >= 400) { + process.stderr.write(`Unexpected HTTP code: ${httpRes.statusCode}\n`); + httpRes.pipe(process.stderr); + } else { + httpRes.pipe(process.stderr); + } + }); + + const handshakeListener = (res, socket) => { + // TODO: we *could* validate res.headers[sec-websocket-accept] + debuglog('websocket upgrade'); + + this._socket = socket; + socket.on('data', this.handleChunk); + socket.on('close', () => { + this.emit('close'); + }); + + this.emit('ready'); + }; + + return new Promise((resolve, reject) => { + this.once('error', reject); + this.once('ready', resolve); + + httpReq.on('upgrade', handshakeListener); + httpReq.end(); + }); + } +} + +module.exports = Client; diff --git a/lib/internal/inspector/inspect_repl.js b/lib/internal/inspector/inspect_repl.js new file mode 100644 index 00000000000000..7d5b019e28506d --- /dev/null +++ b/lib/internal/inspector/inspect_repl.js @@ -0,0 +1,1112 @@ +/* + * Copyright Node.js contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +// TODO(trott): enable ESLint +/* eslint-disable */ + +'use strict'; +const FS = require('fs'); +const Path = require('path'); +const Repl = require('repl'); +const util = require('util'); +const vm = require('vm'); +const fileURLToPath = require('url').fileURLToPath; + +const debuglog = util.debuglog('inspect'); + +const SHORTCUTS = { + cont: 'c', + next: 'n', + step: 's', + out: 'o', + backtrace: 'bt', + setBreakpoint: 'sb', + clearBreakpoint: 'cb', + run: 'r', +}; + +const HELP = ` +run, restart, r Run the application or reconnect +kill Kill a running application or disconnect + +cont, c Resume execution +next, n Continue to next line in current file +step, s Step into, potentially entering a function +out, o Step out, leaving the current function +backtrace, bt Print the current backtrace +list Print the source around the current line where execution + is currently paused + +setBreakpoint, sb Set a breakpoint +clearBreakpoint, cb Clear a breakpoint +breakpoints List all known breakpoints +breakOnException Pause execution whenever an exception is thrown +breakOnUncaught Pause execution whenever an exception isn't caught +breakOnNone Don't pause on exceptions (this is the default) + +watch(expr) Start watching the given expression +unwatch(expr) Stop watching an expression +watchers Print all watched expressions and their current values + +exec(expr) Evaluate the expression and print the value +repl Enter a debug repl that works like exec + +scripts List application scripts that are currently loaded +scripts(true) List all scripts (including node-internals) + +profile Start CPU profiling session. +profileEnd Stop current CPU profiling session. +profiles Array of completed CPU profiling sessions. +profiles[n].save(filepath = 'node.cpuprofile') + Save CPU profiling session to disk as JSON. + +takeHeapSnapshot(filepath = 'node.heapsnapshot') + Take a heap snapshot and save to disk as JSON. +`.trim(); + +const FUNCTION_NAME_PATTERN = /^(?:function\*? )?([^(\s]+)\(/; +function extractFunctionName(description) { + const fnNameMatch = description.match(FUNCTION_NAME_PATTERN); + return fnNameMatch ? `: ${fnNameMatch[1]}` : ''; +} + +const PUBLIC_BUILTINS = require('module').builtinModules; +const NATIVES = PUBLIC_BUILTINS ? process.binding('natives') : {}; +function isNativeUrl(url) { + url = url.replace(/\.js$/, ''); + if (PUBLIC_BUILTINS) { + if (url.startsWith('internal/') || PUBLIC_BUILTINS.includes(url)) + return true; + } + + return url in NATIVES || url === 'bootstrap_node'; +} + +function getRelativePath(filenameOrURL) { + const dir = Path.join(Path.resolve(), 'x').slice(0, -1); + + const filename = filenameOrURL.startsWith('file://') ? + fileURLToPath(filenameOrURL) : filenameOrURL; + + // Change path to relative, if possible + if (filename.indexOf(dir) === 0) { + return filename.slice(dir.length); + } + return filename; +} + +function toCallback(promise, callback) { + function forward(...args) { + process.nextTick(() => callback(...args)); + } + promise.then(forward.bind(null, null), forward); +} + +// Adds spaces and prefix to number +// maxN is a maximum number we should have space for +function leftPad(n, prefix, maxN) { + const s = n.toString(); + const nchars = Math.max(2, String(maxN).length) + 1; + const nspaces = nchars - s.length - 1; + + return prefix + ' '.repeat(nspaces) + s; +} + +function markSourceColumn(sourceText, position, useColors) { + if (!sourceText) return ''; + + const head = sourceText.slice(0, position); + let tail = sourceText.slice(position); + + // Colourize char if stdout supports colours + if (useColors) { + tail = tail.replace(/(.+?)([^\w]|$)/, '\u001b[32m$1\u001b[39m$2'); + } + + // Return source line with coloured char at `position` + return [head, tail].join(''); +} + +function extractErrorMessage(stack) { + if (!stack) return ''; + const m = stack.match(/^\w+: ([^\n]+)/); + return m ? m[1] : stack; +} + +function convertResultToError(result) { + const { className, description } = result; + const err = new Error(extractErrorMessage(description)); + err.stack = description; + Object.defineProperty(err, 'name', { value: className }); + return err; +} + +class RemoteObject { + constructor(attributes) { + Object.assign(this, attributes); + if (this.type === 'number') { + this.value = + this.unserializableValue ? +this.unserializableValue : +this.value; + } + } + + [util.inspect.custom](depth, opts) { + function formatProperty(prop) { + switch (prop.type) { + case 'string': + case 'undefined': + return util.inspect(prop.value, opts); + + case 'number': + case 'boolean': + return opts.stylize(prop.value, prop.type); + + case 'object': + case 'symbol': + if (prop.subtype === 'date') { + return util.inspect(new Date(prop.value), opts); + } + if (prop.subtype === 'array') { + return opts.stylize(prop.value, 'special'); + } + return opts.stylize(prop.value, prop.subtype || 'special'); + + default: + return prop.value; + } + } + switch (this.type) { + case 'boolean': + case 'number': + case 'string': + case 'undefined': + return util.inspect(this.value, opts); + + case 'symbol': + return opts.stylize(this.description, 'special'); + + case 'function': { + const fnName = extractFunctionName(this.description); + const formatted = `[${this.className}${fnName}]`; + return opts.stylize(formatted, 'special'); + } + + case 'object': + switch (this.subtype) { + case 'date': + return util.inspect(new Date(this.description), opts); + + case 'null': + return util.inspect(null, opts); + + case 'regexp': + return opts.stylize(this.description, 'regexp'); + + default: + break; + } + if (this.preview) { + const props = this.preview.properties + .map((prop, idx) => { + const value = formatProperty(prop); + if (prop.name === `${idx}`) return value; + return `${prop.name}: ${value}`; + }); + if (this.preview.overflow) { + props.push('...'); + } + const singleLine = props.join(', '); + const propString = + singleLine.length > 60 ? props.join(',\n ') : singleLine; + + return this.subtype === 'array' ? + `[ ${propString} ]` : `{ ${propString} }`; + } + return this.description; + + default: + return this.description; + } + } + + static fromEvalResult({ result, wasThrown }) { + if (wasThrown) return convertResultToError(result); + return new RemoteObject(result); + } +} + +class ScopeSnapshot { + constructor(scope, properties) { + Object.assign(this, scope); + this.properties = new Map(properties.map((prop) => { + const value = new RemoteObject(prop.value); + return [prop.name, value]; + })); + this.completionGroup = properties.map((prop) => prop.name); + } + + [util.inspect.custom](depth, opts) { + const type = `${this.type[0].toUpperCase()}${this.type.slice(1)}`; + const name = this.name ? `<${this.name}>` : ''; + const prefix = `${type}${name} `; + return util.inspect(this.properties, opts) + .replace(/^Map /, prefix); + } +} + +function copyOwnProperties(target, source) { + Object.getOwnPropertyNames(source).forEach((prop) => { + const descriptor = Object.getOwnPropertyDescriptor(source, prop); + Object.defineProperty(target, prop, descriptor); + }); +} + +function aliasProperties(target, mapping) { + Object.keys(mapping).forEach((key) => { + const descriptor = Object.getOwnPropertyDescriptor(target, key); + Object.defineProperty(target, mapping[key], descriptor); + }); +} + +function createRepl(inspector) { + const { Debugger, HeapProfiler, Profiler, Runtime } = inspector; + + let repl; + + // Things we want to keep around + const history = { control: [], debug: [] }; + const watchedExpressions = []; + const knownBreakpoints = []; + let pauseOnExceptionState = 'none'; + let lastCommand; + + // Things we need to reset when the app restarts + let knownScripts; + let currentBacktrace; + let selectedFrame; + let exitDebugRepl; + + function resetOnStart() { + knownScripts = {}; + currentBacktrace = null; + selectedFrame = null; + + if (exitDebugRepl) exitDebugRepl(); + exitDebugRepl = null; + } + resetOnStart(); + + const INSPECT_OPTIONS = { colors: inspector.stdout.isTTY }; + function inspect(value) { + return util.inspect(value, INSPECT_OPTIONS); + } + + function print(value, oneline = false) { + const text = typeof value === 'string' ? value : inspect(value); + return inspector.print(text, oneline); + } + + function getCurrentLocation() { + if (!selectedFrame) { + throw new Error('Requires execution to be paused'); + } + return selectedFrame.location; + } + + function isCurrentScript(script) { + return selectedFrame && getCurrentLocation().scriptId === script.scriptId; + } + + function formatScripts(displayNatives = false) { + function isVisible(script) { + if (displayNatives) return true; + return !script.isNative || isCurrentScript(script); + } + + return Object.keys(knownScripts) + .map((scriptId) => knownScripts[scriptId]) + .filter(isVisible) + .map((script) => { + const isCurrent = isCurrentScript(script); + const { isNative, url } = script; + const name = `${getRelativePath(url)}${isNative ? ' ' : ''}`; + return `${isCurrent ? '*' : ' '} ${script.scriptId}: ${name}`; + }) + .join('\n'); + } + function listScripts(displayNatives = false) { + print(formatScripts(displayNatives)); + } + listScripts[util.inspect.custom] = function listWithoutInternal() { + return formatScripts(); + }; + + const profiles = []; + class Profile { + constructor(data) { + this.data = data; + } + + static createAndRegister({ profile }) { + const p = new Profile(profile); + profiles.push(p); + return p; + } + + [util.inspect.custom](depth, { stylize }) { + const { startTime, endTime } = this.data; + return stylize(`[Profile ${endTime - startTime}μs]`, 'special'); + } + + save(filename = 'node.cpuprofile') { + const absoluteFile = Path.resolve(filename); + const json = JSON.stringify(this.data); + FS.writeFileSync(absoluteFile, json); + print('Saved profile to ' + absoluteFile); + } + } + + class SourceSnippet { + constructor(location, delta, scriptSource) { + Object.assign(this, location); + this.scriptSource = scriptSource; + this.delta = delta; + } + + [util.inspect.custom](depth, options) { + const { scriptId, lineNumber, columnNumber, delta, scriptSource } = this; + const start = Math.max(1, lineNumber - delta + 1); + const end = lineNumber + delta + 1; + + const lines = scriptSource.split('\n'); + return lines.slice(start - 1, end).map((lineText, offset) => { + const i = start + offset; + const isCurrent = i === (lineNumber + 1); + + const markedLine = isCurrent + ? markSourceColumn(lineText, columnNumber, options.colors) + : lineText; + + let isBreakpoint = false; + knownBreakpoints.forEach(({ location }) => { + if (!location) return; + if (scriptId === location.scriptId && + i === (location.lineNumber + 1)) { + isBreakpoint = true; + } + }); + + let prefixChar = ' '; + if (isCurrent) { + prefixChar = '>'; + } else if (isBreakpoint) { + prefixChar = '*'; + } + return `${leftPad(i, prefixChar, end)} ${markedLine}`; + }).join('\n'); + } + } + + function getSourceSnippet(location, delta = 5) { + const { scriptId } = location; + return Debugger.getScriptSource({ scriptId }) + .then(({ scriptSource }) => + new SourceSnippet(location, delta, scriptSource)); + } + + class CallFrame { + constructor(callFrame) { + Object.assign(this, callFrame); + } + + loadScopes() { + return Promise.all( + this.scopeChain + .filter((scope) => scope.type !== 'global') + .map((scope) => { + const { objectId } = scope.object; + return Runtime.getProperties({ + objectId, + generatePreview: true, + }).then(({ result }) => new ScopeSnapshot(scope, result)); + }) + ); + } + + list(delta = 5) { + return getSourceSnippet(this.location, delta); + } + } + + class Backtrace extends Array { + [util.inspect.custom]() { + return this.map((callFrame, idx) => { + const { + location: { scriptId, lineNumber, columnNumber }, + functionName + } = callFrame; + const name = functionName || '(anonymous)'; + + const script = knownScripts[scriptId]; + const relativeUrl = + (script && getRelativePath(script.url)) || ''; + const frameLocation = + `${relativeUrl}:${lineNumber + 1}:${columnNumber}`; + + return `#${idx} ${name} ${frameLocation}`; + }).join('\n'); + } + + static from(callFrames) { + return super.from(Array.from(callFrames).map((callFrame) => { + if (callFrame instanceof CallFrame) { + return callFrame; + } + return new CallFrame(callFrame); + })); + } + } + + function prepareControlCode(input) { + if (input === '\n') return lastCommand; + // exec process.title => exec("process.title"); + const match = input.match(/^\s*exec\s+([^\n]*)/); + if (match) { + lastCommand = `exec(${JSON.stringify(match[1])})`; + } else { + lastCommand = input; + } + return lastCommand; + } + + function evalInCurrentContext(code) { + // Repl asked for scope variables + if (code === '.scope') { + if (!selectedFrame) { + return Promise.reject(new Error('Requires execution to be paused')); + } + return selectedFrame.loadScopes().then((scopes) => { + return scopes.map((scope) => scope.completionGroup); + }); + } + + if (selectedFrame) { + return Debugger.evaluateOnCallFrame({ + callFrameId: selectedFrame.callFrameId, + expression: code, + objectGroup: 'node-inspect', + generatePreview: true, + }).then(RemoteObject.fromEvalResult); + } + return Runtime.evaluate({ + expression: code, + objectGroup: 'node-inspect', + generatePreview: true, + }).then(RemoteObject.fromEvalResult); + } + + function controlEval(input, context, filename, callback) { + debuglog('eval:', input); + function returnToCallback(error, result) { + debuglog('end-eval:', input, error); + callback(error, result); + } + + try { + const code = prepareControlCode(input); + const result = vm.runInContext(code, context, filename); + + if (result && typeof result.then === 'function') { + toCallback(result, returnToCallback); + return; + } + returnToCallback(null, result); + } catch (e) { + returnToCallback(e); + } + } + + function debugEval(input, context, filename, callback) { + debuglog('eval:', input); + function returnToCallback(error, result) { + debuglog('end-eval:', input, error); + callback(error, result); + } + + try { + const result = evalInCurrentContext(input); + + if (result && typeof result.then === 'function') { + toCallback(result, returnToCallback); + return; + } + returnToCallback(null, result); + } catch (e) { + returnToCallback(e); + } + } + + function formatWatchers(verbose = false) { + if (!watchedExpressions.length) { + return Promise.resolve(''); + } + + const inspectValue = (expr) => + evalInCurrentContext(expr) + // .then(formatValue) + .catch((error) => `<${error.message}>`); + const lastIndex = watchedExpressions.length - 1; + + return Promise.all(watchedExpressions.map(inspectValue)) + .then((values) => { + const lines = watchedExpressions + .map((expr, idx) => { + const prefix = `${leftPad(idx, ' ', lastIndex)}: ${expr} =`; + const value = inspect(values[idx], { colors: true }); + if (value.indexOf('\n') === -1) { + return `${prefix} ${value}`; + } + return `${prefix}\n ${value.split('\n').join('\n ')}`; + }); + return lines.join('\n'); + }) + .then((valueList) => { + return verbose ? `Watchers:\n${valueList}\n` : valueList; + }); + } + + function watchers(verbose = false) { + return formatWatchers(verbose).then(print); + } + + // List source code + function list(delta = 5) { + return selectedFrame.list(delta) + .then(null, (error) => { + print('You can\'t list source code right now'); + throw error; + }); + } + + function handleBreakpointResolved({ breakpointId, location }) { + const script = knownScripts[location.scriptId]; + const scriptUrl = script && script.url; + if (scriptUrl) { + Object.assign(location, { scriptUrl }); + } + const isExisting = knownBreakpoints.some((bp) => { + if (bp.breakpointId === breakpointId) { + Object.assign(bp, { location }); + return true; + } + return false; + }); + if (!isExisting) { + knownBreakpoints.push({ breakpointId, location }); + } + } + + function listBreakpoints() { + if (!knownBreakpoints.length) { + print('No breakpoints yet'); + return; + } + + function formatLocation(location) { + if (!location) return ''; + const script = knownScripts[location.scriptId]; + const scriptUrl = script ? script.url : location.scriptUrl; + return `${getRelativePath(scriptUrl)}:${location.lineNumber + 1}`; + } + const breaklist = knownBreakpoints + .map((bp, idx) => `#${idx} ${formatLocation(bp.location)}`) + .join('\n'); + print(breaklist); + } + + function setBreakpoint(script, line, condition, silent) { + function registerBreakpoint({ breakpointId, actualLocation }) { + handleBreakpointResolved({ breakpointId, location: actualLocation }); + if (actualLocation && actualLocation.scriptId) { + if (!silent) return getSourceSnippet(actualLocation, 5); + } else { + print(`Warning: script '${script}' was not loaded yet.`); + } + return undefined; + } + + // setBreakpoint(): set breakpoint at current location + if (script === undefined) { + return Debugger + .setBreakpoint({ location: getCurrentLocation(), condition }) + .then(registerBreakpoint); + } + + // setBreakpoint(line): set breakpoint in current script at specific line + if (line === undefined && typeof script === 'number') { + const location = { + scriptId: getCurrentLocation().scriptId, + lineNumber: script - 1, + }; + return Debugger.setBreakpoint({ location, condition }) + .then(registerBreakpoint); + } + + if (typeof script !== 'string') { + throw new TypeError(`setBreakpoint() expects a string, got ${script}`); + } + + // setBreakpoint('fn()'): Break when a function is called + if (script.endsWith('()')) { + const debugExpr = `debug(${script.slice(0, -2)})`; + const debugCall = selectedFrame + ? Debugger.evaluateOnCallFrame({ + callFrameId: selectedFrame.callFrameId, + expression: debugExpr, + includeCommandLineAPI: true, + }) + : Runtime.evaluate({ + expression: debugExpr, + includeCommandLineAPI: true, + }); + return debugCall.then(({ result, wasThrown }) => { + if (wasThrown) return convertResultToError(result); + return undefined; // This breakpoint can't be removed the same way + }); + } + + // setBreakpoint('scriptname') + let scriptId = null; + let ambiguous = false; + if (knownScripts[script]) { + scriptId = script; + } else { + for (const id of Object.keys(knownScripts)) { + const scriptUrl = knownScripts[id].url; + if (scriptUrl && scriptUrl.indexOf(script) !== -1) { + if (scriptId !== null) { + ambiguous = true; + } + scriptId = id; + } + } + } + + if (ambiguous) { + print('Script name is ambiguous'); + return undefined; + } + if (line <= 0) { + print('Line should be a positive value'); + return undefined; + } + + if (scriptId !== null) { + const location = { scriptId, lineNumber: line - 1 }; + return Debugger.setBreakpoint({ location, condition }) + .then(registerBreakpoint); + } + + const escapedPath = script.replace(/([/\\.?*()^${}|[\]])/g, '\\$1'); + const urlRegex = `^(.*[\\/\\\\])?${escapedPath}$`; + + return Debugger + .setBreakpointByUrl({ urlRegex, lineNumber: line - 1, condition }) + .then((bp) => { + // TODO: handle bp.locations in case the regex matches existing files + if (!bp.location) { // Fake it for now. + Object.assign(bp, { + actualLocation: { + scriptUrl: `.*/${script}$`, + lineNumber: line - 1, + }, + }); + } + return registerBreakpoint(bp); + }); + } + + function clearBreakpoint(url, line) { + const breakpoint = knownBreakpoints.find(({ location }) => { + if (!location) return false; + const script = knownScripts[location.scriptId]; + if (!script) return false; + return ( + script.url.indexOf(url) !== -1 && (location.lineNumber + 1) === line + ); + }); + if (!breakpoint) { + print(`Could not find breakpoint at ${url}:${line}`); + return Promise.resolve(); + } + return Debugger.removeBreakpoint({ breakpointId: breakpoint.breakpointId }) + .then(() => { + const idx = knownBreakpoints.indexOf(breakpoint); + knownBreakpoints.splice(idx, 1); + }); + } + + function restoreBreakpoints() { + const lastBreakpoints = knownBreakpoints.slice(); + knownBreakpoints.length = 0; + const newBreakpoints = lastBreakpoints + .filter(({ location }) => !!location.scriptUrl) + .map(({ location }) => + setBreakpoint(location.scriptUrl, location.lineNumber + 1)); + if (!newBreakpoints.length) return Promise.resolve(); + return Promise.all(newBreakpoints).then((results) => { + print(`${results.length} breakpoints restored.`); + }); + } + + function setPauseOnExceptions(state) { + return Debugger.setPauseOnExceptions({ state }) + .then(() => { + pauseOnExceptionState = state; + }); + } + + Debugger.on('paused', ({ callFrames, reason /* , hitBreakpoints */ }) => { + if (process.env.NODE_INSPECT_RESUME_ON_START === '1' && + reason === 'Break on start') { + debuglog('Paused on start, but NODE_INSPECT_RESUME_ON_START' + + ' environment variable is set to 1, resuming'); + inspector.client.callMethod('Debugger.resume'); + return; + } + + // Save execution context's data + currentBacktrace = Backtrace.from(callFrames); + selectedFrame = currentBacktrace[0]; + const { scriptId, lineNumber } = selectedFrame.location; + + const breakType = reason === 'other' ? 'break' : reason; + const script = knownScripts[scriptId]; + const scriptUrl = script ? getRelativePath(script.url) : '[unknown]'; + + const header = `${breakType} in ${scriptUrl}:${lineNumber + 1}`; + + inspector.suspendReplWhile(() => + Promise.all([formatWatchers(true), selectedFrame.list(2)]) + .then(([watcherList, context]) => { + if (watcherList) { + return `${watcherList}\n${inspect(context)}`; + } + return inspect(context); + }).then((breakContext) => { + print(`${header}\n${breakContext}`); + })); + }); + + function handleResumed() { + currentBacktrace = null; + selectedFrame = null; + } + + Debugger.on('resumed', handleResumed); + + Debugger.on('breakpointResolved', handleBreakpointResolved); + + Debugger.on('scriptParsed', (script) => { + const { scriptId, url } = script; + if (url) { + knownScripts[scriptId] = Object.assign({ + isNative: isNativeUrl(url), + }, script); + } + }); + + Profiler.on('consoleProfileFinished', ({ profile }) => { + Profile.createAndRegister({ profile }); + print([ + 'Captured new CPU profile.', + `Access it with profiles[${profiles.length - 1}]` + ].join('\n')); + }); + + function initializeContext(context) { + inspector.domainNames.forEach((domain) => { + Object.defineProperty(context, domain, { + value: inspector[domain], + enumerable: true, + configurable: true, + writeable: false, + }); + }); + + copyOwnProperties(context, { + get help() { + print(HELP); + }, + + get run() { + return inspector.run(); + }, + + get kill() { + return inspector.killChild(); + }, + + get restart() { + return inspector.run(); + }, + + get cont() { + handleResumed(); + return Debugger.resume(); + }, + + get next() { + handleResumed(); + return Debugger.stepOver(); + }, + + get step() { + handleResumed(); + return Debugger.stepInto(); + }, + + get out() { + handleResumed(); + return Debugger.stepOut(); + }, + + get pause() { + return Debugger.pause(); + }, + + get backtrace() { + return currentBacktrace; + }, + + get breakpoints() { + return listBreakpoints(); + }, + + exec(expr) { + return evalInCurrentContext(expr); + }, + + get profile() { + return Profiler.start(); + }, + + get profileEnd() { + return Profiler.stop() + .then(Profile.createAndRegister); + }, + + get profiles() { + return profiles; + }, + + takeHeapSnapshot(filename = 'node.heapsnapshot') { + return new Promise((resolve, reject) => { + const absoluteFile = Path.resolve(filename); + const writer = FS.createWriteStream(absoluteFile); + let sizeWritten = 0; + function onProgress({ done, total, finished }) { + if (finished) { + print('Heap snaphost prepared.'); + } else { + print(`Heap snapshot: ${done}/${total}`, true); + } + } + function onChunk({ chunk }) { + sizeWritten += chunk.length; + writer.write(chunk); + print(`Writing snapshot: ${sizeWritten}`, true); + } + function onResolve() { + writer.end(() => { + teardown(); + print(`Wrote snapshot: ${absoluteFile}`); + resolve(); + }); + } + function onReject(error) { + teardown(); + reject(error); + } + function teardown() { + HeapProfiler.removeListener( + 'reportHeapSnapshotProgress', onProgress); + HeapProfiler.removeListener('addHeapSnapshotChunk', onChunk); + } + + HeapProfiler.on('reportHeapSnapshotProgress', onProgress); + HeapProfiler.on('addHeapSnapshotChunk', onChunk); + + print('Heap snapshot: 0/0', true); + HeapProfiler.takeHeapSnapshot({ reportProgress: true }) + .then(onResolve, onReject); + }); + }, + + get watchers() { + return watchers(); + }, + + watch(expr) { + watchedExpressions.push(expr); + }, + + unwatch(expr) { + const index = watchedExpressions.indexOf(expr); + + // Unwatch by expression + // or + // Unwatch by watcher number + watchedExpressions.splice(index !== -1 ? index : +expr, 1); + }, + + get repl() { + // Don't display any default messages + const listeners = repl.listeners('SIGINT').slice(0); + repl.removeAllListeners('SIGINT'); + + const oldContext = repl.context; + + exitDebugRepl = () => { + // Restore all listeners + process.nextTick(() => { + listeners.forEach((listener) => { + repl.on('SIGINT', listener); + }); + }); + + // Exit debug repl + repl.eval = controlEval; + + // Swap history + history.debug = repl.history; + repl.history = history.control; + + repl.context = oldContext; + repl.setPrompt('debug> '); + repl.displayPrompt(); + + repl.removeListener('SIGINT', exitDebugRepl); + repl.removeListener('exit', exitDebugRepl); + + exitDebugRepl = null; + }; + + // Exit debug repl on SIGINT + repl.on('SIGINT', exitDebugRepl); + + // Exit debug repl on repl exit + repl.on('exit', exitDebugRepl); + + // Set new + repl.eval = debugEval; + repl.context = {}; + + // Swap history + history.control = repl.history; + repl.history = history.debug; + + repl.setPrompt('> '); + + print('Press Ctrl + C to leave debug repl'); + repl.displayPrompt(); + }, + + get version() { + return Runtime.evaluate({ + expression: 'process.versions.v8', + contextId: 1, + returnByValue: true, + }).then(({ result }) => { + print(result.value); + }); + }, + + scripts: listScripts, + + setBreakpoint, + clearBreakpoint, + setPauseOnExceptions, + get breakOnException() { + return setPauseOnExceptions('all'); + }, + get breakOnUncaught() { + return setPauseOnExceptions('uncaught'); + }, + get breakOnNone() { + return setPauseOnExceptions('none'); + }, + + list, + }); + aliasProperties(context, SHORTCUTS); + } + + function initAfterStart() { + const setupTasks = [ + Runtime.enable(), + Profiler.enable(), + Profiler.setSamplingInterval({ interval: 100 }), + Debugger.enable(), + Debugger.setPauseOnExceptions({ state: 'none' }), + Debugger.setAsyncCallStackDepth({ maxDepth: 0 }), + Debugger.setBlackboxPatterns({ patterns: [] }), + Debugger.setPauseOnExceptions({ state: pauseOnExceptionState }), + restoreBreakpoints(), + Runtime.runIfWaitingForDebugger(), + ]; + return Promise.all(setupTasks); + } + + return function startRepl() { + inspector.client.on('close', () => { + resetOnStart(); + }); + inspector.client.on('ready', () => { + initAfterStart(); + }); + + const replOptions = { + prompt: 'debug> ', + input: inspector.stdin, + output: inspector.stdout, + eval: controlEval, + useGlobal: false, + ignoreUndefined: true, + }; + + repl = Repl.start(replOptions); + initializeContext(repl.context); + repl.on('reset', initializeContext); + + repl.defineCommand('interrupt', () => { + // We want this for testing purposes where sending CTRL-C can be tricky. + repl.emit('SIGINT'); + }); + + // Init once for the initial connection + initAfterStart(); + + return repl; + }; +} +module.exports = createRepl; diff --git a/lib/internal/main/inspect.js b/lib/internal/main/inspect.js index f6777fe852bcfc..10e7cbf2c2b48a 100644 --- a/lib/internal/main/inspect.js +++ b/lib/internal/main/inspect.js @@ -18,5 +18,5 @@ markBootstrapComplete(); // Start the debugger agent. process.nextTick(() => { - require('internal/deps/node-inspect/lib/_inspect').start(); + require('internal/inspector/_inspect').start(); }); diff --git a/node.gyp b/node.gyp index 59ba758e73fecc..e199ac99ce7799 100644 --- a/node.gyp +++ b/node.gyp @@ -148,6 +148,9 @@ 'lib/internal/heap_utils.js', 'lib/internal/histogram.js', 'lib/internal/idna.js', + 'lib/internal/inspector/_inspect.js', + 'lib/internal/inspector/inspect_client.js', + 'lib/internal/inspector/inspect_repl.js', 'lib/internal/inspector_async_hook.js', 'lib/internal/js_stream_socket.js', 'lib/internal/linkedlist.js', @@ -250,9 +253,6 @@ 'deps/v8/tools/tickprocessor.js', 'deps/v8/tools/SourceMap.js', 'deps/v8/tools/tickprocessor-driver.js', - 'deps/node-inspect/lib/_inspect.js', - 'deps/node-inspect/lib/internal/inspect_client.js', - 'deps/node-inspect/lib/internal/inspect_repl.js', 'deps/acorn/acorn/dist/acorn.js', 'deps/acorn/acorn-walk/dist/walk.js', 'deps/acorn-plugins/acorn-class-fields/index.js', From fc219d862c0f53e647c42b188671d42802a7825c Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Thu, 8 Apr 2021 03:51:24 -0700 Subject: [PATCH 010/140] tools: remove node-inspect from license MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/38161 Backport-PR-URL: https://github.com/nodejs/node/pull/38858 Refs: https://github.com/nodejs/node/discussions/36481 Reviewed-By: Matteo Collina Reviewed-By: Jan Krems Reviewed-By: Colin Ihrig Reviewed-By: Stephen Belanger Reviewed-By: Gerhard Stöbich Reviewed-By: Michaël Zasso --- LICENSE | 23 ----------------------- tools/license-builder.sh | 3 --- 2 files changed, 26 deletions(-) diff --git a/LICENSE b/LICENSE index a62f3ad825834e..5b71fd3d6483c6 100644 --- a/LICENSE +++ b/LICENSE @@ -1333,29 +1333,6 @@ The externally maintained libraries used by Node.js are: WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ -- node-inspect, located at deps/node-inspect, is licensed as follows: - """ - Copyright Node.js contributors. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to - deal in the Software without restriction, including without limitation the - rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - sell copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - IN THE SOFTWARE. - """ - - large_pages, located at src/large_pages, is licensed as follows: """ Copyright (C) 2018 Intel Corporation diff --git a/tools/license-builder.sh b/tools/license-builder.sh index e1790aca4978a8..6bce09803c9d16 100755 --- a/tools/license-builder.sh +++ b/tools/license-builder.sh @@ -89,9 +89,6 @@ addlicense "gtest" "test/cctest/gtest" "$(cat "${rootdir}"/test/cctest/gtest/LIC # nghttp2 addlicense "nghttp2" "deps/nghttp2" "$(cat "${rootdir}"/deps/nghttp2/COPYING)" -# node-inspect -addlicense "node-inspect" "deps/node-inspect" "$(cat "${rootdir}"/deps/node-inspect/LICENSE)" - # large_pages addlicense "large_pages" "src/large_pages" "$(sed -e '/SPDX-License-Identifier/,$d' -e 's/^\/\///' "${rootdir}"/src/large_pages/node_large_page.h)" From 0321c5b194552f04602b14e6145d0e3ba046ffd7 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Thu, 8 Apr 2021 04:05:12 -0700 Subject: [PATCH 011/140] debugger: remove unused code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove code that was for when `node-inspect` was called as a standalone process. PR-URL: https://github.com/nodejs/node/pull/38161 Backport-PR-URL: https://github.com/nodejs/node/pull/38858 Refs: https://github.com/nodejs/node/discussions/36481 Reviewed-By: Matteo Collina Reviewed-By: Jan Krems Reviewed-By: Colin Ihrig Reviewed-By: Stephen Belanger Reviewed-By: Gerhard Stöbich Reviewed-By: Michaël Zasso --- lib/internal/inspector/_inspect.js | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/lib/internal/inspector/_inspect.js b/lib/internal/inspector/_inspect.js index df4e53979db8fd..8bc1f13e5726f0 100644 --- a/lib/internal/inspector/_inspect.js +++ b/lib/internal/inspector/_inspect.js @@ -29,16 +29,7 @@ const { EventEmitter } = require('events'); const net = require('net'); const util = require('util'); -const runAsStandalone = typeof __dirname !== 'undefined'; - const { 0: InspectClient, 1: createRepl } = - runAsStandalone ? - // This copy of node-inspect is on-disk, relative paths make sense. - [ - require('./inspect_client'), - require('./inspect_repl'), - ] : - // This copy of node-inspect is built into the node executable. [ require('internal/inspector/inspect_client'), require('internal/inspector/inspect_repl'), @@ -336,9 +327,7 @@ function startInspect(argv = process.argv.slice(2), stdin = process.stdin, stdout = process.stdout) { if (argv.length < 1) { - const invokedAs = runAsStandalone ? - 'node-inspect' : - `${process.argv0} ${process.argv[1]}`; + const invokedAs = `${process.argv0} ${process.argv[1]}`; console.error(`Usage: ${invokedAs} script.js`); console.error(` ${invokedAs} :`); From 1da692185a6359b11797ce401b0308047323abb5 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Tue, 20 Apr 2021 07:17:28 -0700 Subject: [PATCH 012/140] debugger: fix inspect restart on Windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: https://github.com/nodejs/node/issues/37224 PR-URL: https://github.com/nodejs/node/pull/38161 Backport-PR-URL: https://github.com/nodejs/node/pull/38858 Refs: https://github.com/nodejs/node/discussions/36481 Reviewed-By: Matteo Collina Reviewed-By: Jan Krems Reviewed-By: Colin Ihrig Reviewed-By: Stephen Belanger Reviewed-By: Gerhard Stöbich Reviewed-By: Michaël Zasso --- lib/internal/inspector/inspect_client.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/internal/inspector/inspect_client.js b/lib/internal/inspector/inspect_client.js index 6010f4ac09389d..831a7fda1cdff1 100644 --- a/lib/internal/inspector/inspect_client.js +++ b/lib/internal/inspector/inspect_client.js @@ -228,6 +228,9 @@ class Client extends EventEmitter { if (this._http) { this._http.destroy(); } + if (this._socket) { + this._socket.destroy(); + } this._http = null; this._lastId = 0; this._socket = null; From b172e6f43655fe7d2be5dcab58fc1dff4b4a9d40 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Tue, 20 Apr 2021 22:46:42 -0700 Subject: [PATCH 013/140] debugger: accommodate line chunking in Windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/38161 Backport-PR-URL: https://github.com/nodejs/node/pull/38858 Refs: https://github.com/nodejs/node/discussions/36481 Reviewed-By: Matteo Collina Reviewed-By: Jan Krems Reviewed-By: Colin Ihrig Reviewed-By: Stephen Belanger Reviewed-By: Gerhard Stöbich Reviewed-By: Michaël Zasso --- lib/internal/inspector/_inspect.js | 43 ++++++++++++++++---------- lib/internal/inspector/inspect_repl.js | 10 +++--- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/lib/internal/inspector/_inspect.js b/lib/internal/inspector/_inspect.js index 8bc1f13e5726f0..b58b4b695e8505 100644 --- a/lib/internal/inspector/_inspect.js +++ b/lib/internal/inspector/_inspect.js @@ -97,8 +97,8 @@ function runScript(script, scriptArgs, inspectHost, inspectPort, childPrint) { const child = spawn(process.execPath, args); child.stdout.setEncoding('utf8'); child.stderr.setEncoding('utf8'); - child.stdout.on('data', childPrint); - child.stderr.on('data', childPrint); + child.stdout.on('data', (chunk) => childPrint(chunk, 'stdout')); + child.stderr.on('data', (chunk) => childPrint(chunk, 'stderr')); let output = ''; function waitForListenHint(text) { @@ -231,7 +231,7 @@ class NodeInspector { return this.client.connect(port, host) .then(() => { debuglog('connection established'); - this.stdout.write(' ok'); + this.stdout.write(' ok\n'); }, (error) => { debuglog('connect failed', error); // If it's failed to connect 10 times then print failed message @@ -245,7 +245,7 @@ class NodeInspector { }); }; - this.print(`connecting to ${host}:${port} ..`, true); + this.print(`connecting to ${host}:${port} ..`, false); return attemptConnect(); }); } @@ -259,23 +259,32 @@ class NodeInspector { } } - print(text, oneline = false) { + print(text, appendNewline = false) { this.clearLine(); - this.stdout.write(oneline ? text : `${text}\n`); + this.stdout.write(appendNewline ? `${text}\n` : text); } - childPrint(text) { - this.print( - text.toString() - .split(/\r\n|\r|\n/g) - .filter((chunk) => !!chunk) - .map((chunk) => `< ${chunk}`) - .join('\n') - ); - if (!this.paused) { - this.repl.displayPrompt(true); + #stdioBuffers = {stdout: '', stderr: ''}; + childPrint(text, which) { + const lines = (this.#stdioBuffers[which] + text) + .split(/\r\n|\r|\n/g); + + this.#stdioBuffers[which] = ''; + + if (lines[lines.length - 1] !== '') { + this.#stdioBuffers[which] = lines.pop(); + } + + const textToPrint = lines.map((chunk) => `< ${chunk}`).join('\n'); + + if (lines.length) { + this.print(textToPrint, true); + if (!this.paused) { + this.repl.displayPrompt(true); + } } - if (/Waiting for the debugger to disconnect\.\.\.\n$/.test(text)) { + + if (textToPrint.endsWith('Waiting for the debugger to disconnect...\n')) { this.killChild(); } } diff --git a/lib/internal/inspector/inspect_repl.js b/lib/internal/inspector/inspect_repl.js index 7d5b019e28506d..7fd9772eef733b 100644 --- a/lib/internal/inspector/inspect_repl.js +++ b/lib/internal/inspector/inspect_repl.js @@ -320,9 +320,9 @@ function createRepl(inspector) { return util.inspect(value, INSPECT_OPTIONS); } - function print(value, oneline = false) { + function print(value, addNewline = true) { const text = typeof value === 'string' ? value : inspect(value); - return inspector.print(text, oneline); + return inspector.print(text, addNewline); } function getCurrentLocation() { @@ -928,13 +928,13 @@ function createRepl(inspector) { if (finished) { print('Heap snaphost prepared.'); } else { - print(`Heap snapshot: ${done}/${total}`, true); + print(`Heap snapshot: ${done}/${total}`, false); } } function onChunk({ chunk }) { sizeWritten += chunk.length; writer.write(chunk); - print(`Writing snapshot: ${sizeWritten}`, true); + print(`Writing snapshot: ${sizeWritten}`, false); } function onResolve() { writer.end(() => { @@ -956,7 +956,7 @@ function createRepl(inspector) { HeapProfiler.on('reportHeapSnapshotProgress', onProgress); HeapProfiler.on('addHeapSnapshotChunk', onChunk); - print('Heap snapshot: 0/0', true); + print('Heap snapshot: 0/0', false); HeapProfiler.takeHeapSnapshot({ reportProgress: true }) .then(onResolve, onReject); }); From 22afb7cbe695b47eee1f79da356cb24be926e016 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 21 Apr 2021 16:22:36 -0700 Subject: [PATCH 014/140] debugger: allow longer time to connect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make five attempts with a timeout of 1 second each rather than 10 attempts with a timeout of 500ms each. This is to allow for slower-connecting devices like Raspberry Pi. PR-URL: https://github.com/nodejs/node/pull/38161 Backport-PR-URL: https://github.com/nodejs/node/pull/38858 Refs: https://github.com/nodejs/node/discussions/36481 Reviewed-By: Matteo Collina Reviewed-By: Jan Krems Reviewed-By: Colin Ihrig Reviewed-By: Stephen Belanger Reviewed-By: Gerhard Stöbich Reviewed-By: Michaël Zasso --- lib/internal/inspector/_inspect.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/internal/inspector/_inspect.js b/lib/internal/inspector/_inspect.js index b58b4b695e8505..b326a772fd39c9 100644 --- a/lib/internal/inspector/_inspect.js +++ b/lib/internal/inspector/_inspect.js @@ -234,13 +234,13 @@ class NodeInspector { this.stdout.write(' ok\n'); }, (error) => { debuglog('connect failed', error); - // If it's failed to connect 10 times then print failed message - if (connectionAttempts >= 10) { + // If it's failed to connect 5 times then print failed message + if (connectionAttempts >= 5) { this.stdout.write(' failed to connect, please retry\n'); process.exit(1); } - return new Promise((resolve) => setTimeout(resolve, 500)) + return new Promise((resolve) => setTimeout(resolve, 1000)) .then(attemptConnect); }); }; From 193ea8fd912758879824f0b797fed847999e4826 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Thu, 22 Apr 2021 10:40:12 -0700 Subject: [PATCH 015/140] test: fix test-inspector-cli-address MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The test was assuming that the entire string being sought would arrive in a single data chunk, but it can be split across multiple chunks. PR-URL: https://github.com/nodejs/node/pull/38161 Backport-PR-URL: https://github.com/nodejs/node/pull/38858 Refs: https://github.com/nodejs/node/discussions/36481 Reviewed-By: Matteo Collina Reviewed-By: Jan Krems Reviewed-By: Colin Ihrig Reviewed-By: Stephen Belanger Reviewed-By: Gerhard Stöbich Reviewed-By: Michaël Zasso --- deps/node-inspect/test/cli/address.test.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/deps/node-inspect/test/cli/address.test.js b/deps/node-inspect/test/cli/address.test.js index 1dbe4f37b42175..b55a2d078ea4a4 100644 --- a/deps/node-inspect/test/cli/address.test.js +++ b/deps/node-inspect/test/cli/address.test.js @@ -16,7 +16,9 @@ function launchTarget(...args) { }; childProc.on('exit', onExit); childProc.stderr.setEncoding('utf8'); - childProc.stderr.on('data', (data) => { + let data = ''; + childProc.stderr.on('data', (chunk) => { + data += chunk; const ret = kDebuggerMsgReg.exec(data); childProc.removeListener('exit', onExit); if (ret) { From a62826bbe69b86dc3c4cf59929f5d7c1b0984e44 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Thu, 8 Apr 2021 23:55:45 -0700 Subject: [PATCH 016/140] test,debugger: migrate node-inspect tests to core MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Migrate the node-inspect tests to core (where node-inspect code now lives) and remove node-inspect from deps directory. PR-URL: https://github.com/nodejs/node/pull/38161 Backport-PR-URL: https://github.com/nodejs/node/pull/38858 Refs: https://github.com/nodejs/node/discussions/36481 Reviewed-By: Matteo Collina Reviewed-By: Jan Krems Reviewed-By: Colin Ihrig Reviewed-By: Stephen Belanger Reviewed-By: Gerhard Stöbich Reviewed-By: Michaël Zasso --- Makefile | 4 - deps/node-inspect/.editorconfig | 11 - deps/node-inspect/.eslintrc | 147 --- deps/node-inspect/.github/workflows/ci.yml | 31 - deps/node-inspect/.gitignore | 4 - deps/node-inspect/.npmrc | 2 - deps/node-inspect/.travis.yml | 13 - deps/node-inspect/CHANGELOG.md | 296 ----- deps/node-inspect/CONTRIBUTING.md | 181 --- deps/node-inspect/GOVERNANCE.md | 4 - deps/node-inspect/LICENSE | 19 - deps/node-inspect/README.md | 29 - deps/node-inspect/appveyor.yml | 13 - deps/node-inspect/cli.js | 2 - deps/node-inspect/lib/_inspect.js | 371 ------ deps/node-inspect/lib/cli.js | 24 - .../lib/internal/inspect_client.js | 352 ------ .../node-inspect/lib/internal/inspect_repl.js | 1108 ----------------- deps/node-inspect/package.json | 45 - deps/node-inspect/test/cli/backtrace.test.js | 30 - deps/node-inspect/test/cli/break.test.js | 195 --- deps/node-inspect/test/cli/exec.test.js | 77 -- .../test/cli/heap-profiler.test.js | 34 - deps/node-inspect/test/cli/help.test.js | 22 - .../test/cli/invalid-args.test.js | 54 - deps/node-inspect/test/cli/launch.test.js | 196 --- deps/node-inspect/test/cli/pid.test.js | 52 - .../test/cli/preserve-breaks.test.js | 64 - .../eslint-rules/align-function-arguments.js | 76 -- .../align-multiline-assignment.js | 68 - .../assert-fail-single-argument.js | 30 - .../tools/eslint-rules/buffer-constructor.js | 25 - .../tools/eslint-rules/new-with-error.js | 31 - .../eslint-rules/no-let-in-for-declaration.js | 46 - .../eslint-rules/prefer-assert-methods.js | 39 - .../tools/eslint-rules/require-buffer.js | 19 - .../tools/eslint-rules/required-modules.js | 99 -- lib/internal/inspector/inspect_repl.js | 2 +- test/README.md | 1 + test/common/README.md | 29 + .../common/inspector-cli.js | 75 +- .../fixtures/inspector-cli}/alive.js | 0 .../fixtures/inspector-cli}/backtrace.js | 0 .../fixtures/inspector-cli}/break.js | 0 .../fixtures/inspector-cli}/cjs/index.js | 0 .../fixtures/inspector-cli}/cjs/other.js | 0 .../fixtures/inspector-cli}/empty.js | 0 .../fixtures/inspector-cli}/exceptions.js | 0 .../fixtures/inspector-cli}/three-lines.js | 0 .../fixtures/inspector-cli}/use-strict.js | 0 test/inspector-cli/inspector-cli.status | 7 + .../test-inspector-cli-address.js | 28 +- .../test-inspector-cli-auto-resume.js | 36 + .../test-inspector-cli-backtrace.js | 36 + .../inspector-cli/test-inspector-cli-break.js | 131 ++ .../test-inspector-cli-clear-breakpoints.js | 53 + .../test-inspector-cli-custom-port.js | 30 + .../test-inspector-cli-exceptions.js | 44 +- .../test-inspector-cli-exec-scope.js | 38 + test/inspector-cli/test-inspector-cli-exec.js | 67 + .../test-inspector-cli-heap-profiler.js | 37 + test/inspector-cli/test-inspector-cli-help.js | 27 + .../test-inspector-cli-invalid-args.js | 59 + .../test-inspector-cli-launch.js | 47 + .../test-inspector-cli-low-level.js | 21 +- test/inspector-cli/test-inspector-cli-pid.js | 61 + .../test-inspector-cli-preserve-breaks.js | 72 ++ .../test-inspector-cli-profile.js | 22 +- ...ector-cli-random-port-with-inspect-port.js | 30 + .../test-inspector-cli-random-port.js | 30 + ...st-inspector-cli-run-after-quit-restart.js | 90 ++ .../test-inspector-cli-sb-before-load.js | 44 + .../test-inspector-cli-scripts.js | 32 +- .../test-inspector-cli-use-strict.js | 18 +- .../test-inspector-cli-watchers.js | 30 +- test/inspector-cli/testcfg.py | 6 + 76 files changed, 1083 insertions(+), 3933 deletions(-) delete mode 100644 deps/node-inspect/.editorconfig delete mode 100644 deps/node-inspect/.eslintrc delete mode 100644 deps/node-inspect/.github/workflows/ci.yml delete mode 100644 deps/node-inspect/.gitignore delete mode 100644 deps/node-inspect/.npmrc delete mode 100644 deps/node-inspect/.travis.yml delete mode 100644 deps/node-inspect/CHANGELOG.md delete mode 100644 deps/node-inspect/CONTRIBUTING.md delete mode 100644 deps/node-inspect/GOVERNANCE.md delete mode 100644 deps/node-inspect/LICENSE delete mode 100644 deps/node-inspect/README.md delete mode 100644 deps/node-inspect/appveyor.yml delete mode 100755 deps/node-inspect/cli.js delete mode 100644 deps/node-inspect/lib/_inspect.js delete mode 100644 deps/node-inspect/lib/cli.js delete mode 100644 deps/node-inspect/lib/internal/inspect_client.js delete mode 100644 deps/node-inspect/lib/internal/inspect_repl.js delete mode 100644 deps/node-inspect/package.json delete mode 100644 deps/node-inspect/test/cli/backtrace.test.js delete mode 100644 deps/node-inspect/test/cli/break.test.js delete mode 100644 deps/node-inspect/test/cli/exec.test.js delete mode 100644 deps/node-inspect/test/cli/heap-profiler.test.js delete mode 100644 deps/node-inspect/test/cli/help.test.js delete mode 100644 deps/node-inspect/test/cli/invalid-args.test.js delete mode 100644 deps/node-inspect/test/cli/launch.test.js delete mode 100644 deps/node-inspect/test/cli/pid.test.js delete mode 100644 deps/node-inspect/test/cli/preserve-breaks.test.js delete mode 100644 deps/node-inspect/tools/eslint-rules/align-function-arguments.js delete mode 100644 deps/node-inspect/tools/eslint-rules/align-multiline-assignment.js delete mode 100644 deps/node-inspect/tools/eslint-rules/assert-fail-single-argument.js delete mode 100644 deps/node-inspect/tools/eslint-rules/buffer-constructor.js delete mode 100644 deps/node-inspect/tools/eslint-rules/new-with-error.js delete mode 100644 deps/node-inspect/tools/eslint-rules/no-let-in-for-declaration.js delete mode 100644 deps/node-inspect/tools/eslint-rules/prefer-assert-methods.js delete mode 100644 deps/node-inspect/tools/eslint-rules/require-buffer.js delete mode 100644 deps/node-inspect/tools/eslint-rules/required-modules.js rename deps/node-inspect/test/cli/start-cli.js => test/common/inspector-cli.js (67%) rename {deps/node-inspect/examples => test/fixtures/inspector-cli}/alive.js (100%) rename {deps/node-inspect/examples => test/fixtures/inspector-cli}/backtrace.js (100%) rename {deps/node-inspect/examples => test/fixtures/inspector-cli}/break.js (100%) rename {deps/node-inspect/examples => test/fixtures/inspector-cli}/cjs/index.js (100%) rename {deps/node-inspect/examples => test/fixtures/inspector-cli}/cjs/other.js (100%) rename {deps/node-inspect/examples => test/fixtures/inspector-cli}/empty.js (100%) rename {deps/node-inspect/examples => test/fixtures/inspector-cli}/exceptions.js (100%) rename {deps/node-inspect/examples => test/fixtures/inspector-cli}/three-lines.js (100%) rename {deps/node-inspect/examples => test/fixtures/inspector-cli}/use-strict.js (100%) create mode 100644 test/inspector-cli/inspector-cli.status rename deps/node-inspect/test/cli/address.test.js => test/inspector-cli/test-inspector-cli-address.js (74%) create mode 100644 test/inspector-cli/test-inspector-cli-auto-resume.js create mode 100644 test/inspector-cli/test-inspector-cli-backtrace.js create mode 100644 test/inspector-cli/test-inspector-cli-break.js create mode 100644 test/inspector-cli/test-inspector-cli-clear-breakpoints.js create mode 100644 test/inspector-cli/test-inspector-cli-custom-port.js rename deps/node-inspect/test/cli/exceptions.test.js => test/inspector-cli/test-inspector-cli-exceptions.js (55%) create mode 100644 test/inspector-cli/test-inspector-cli-exec-scope.js create mode 100644 test/inspector-cli/test-inspector-cli-exec.js create mode 100644 test/inspector-cli/test-inspector-cli-heap-profiler.js create mode 100644 test/inspector-cli/test-inspector-cli-help.js create mode 100644 test/inspector-cli/test-inspector-cli-invalid-args.js create mode 100644 test/inspector-cli/test-inspector-cli-launch.js rename deps/node-inspect/test/cli/low-level.test.js => test/inspector-cli/test-inspector-cli-low-level.js (57%) create mode 100644 test/inspector-cli/test-inspector-cli-pid.js create mode 100644 test/inspector-cli/test-inspector-cli-preserve-breaks.js rename deps/node-inspect/test/cli/profile.test.js => test/inspector-cli/test-inspector-cli-profile.js (52%) create mode 100644 test/inspector-cli/test-inspector-cli-random-port-with-inspect-port.js create mode 100644 test/inspector-cli/test-inspector-cli-random-port.js create mode 100644 test/inspector-cli/test-inspector-cli-run-after-quit-restart.js create mode 100644 test/inspector-cli/test-inspector-cli-sb-before-load.js rename deps/node-inspect/test/cli/scripts.test.js => test/inspector-cli/test-inspector-cli-scripts.js (51%) rename deps/node-inspect/test/cli/use-strict.test.js => test/inspector-cli/test-inspector-cli-use-strict.js (54%) rename deps/node-inspect/test/cli/watchers.test.js => test/inspector-cli/test-inspector-cli-watchers.js (56%) create mode 100644 test/inspector-cli/testcfg.py diff --git a/Makefile b/Makefile index ebe2fc0c83556f..dfea6ee2d3e3cf 100644 --- a/Makefile +++ b/Makefile @@ -563,10 +563,6 @@ test-pummel: all test-internet: all $(PYTHON) tools/test.py $(PARALLEL_ARGS) internet -test-node-inspect: $(NODE_EXE) - USE_EMBEDDED_NODE_INSPECT=1 $(NODE) tools/test-npm-package \ - --install deps/node-inspect test - test-benchmark: | bench-addons-build $(PYTHON) tools/test.py $(PARALLEL_ARGS) benchmark diff --git a/deps/node-inspect/.editorconfig b/deps/node-inspect/.editorconfig deleted file mode 100644 index beffa3084e7a69..00000000000000 --- a/deps/node-inspect/.editorconfig +++ /dev/null @@ -1,11 +0,0 @@ -root = true - -[*] -indent_style = space -indent_size = 2 -charset = utf-8 -trim_trailing_whitespace = true -insert_final_newline = true - -[*.md] -trim_trailing_whitespace = false diff --git a/deps/node-inspect/.eslintrc b/deps/node-inspect/.eslintrc deleted file mode 100644 index b6d45aa499655b..00000000000000 --- a/deps/node-inspect/.eslintrc +++ /dev/null @@ -1,147 +0,0 @@ -root: true - -env: - node: true - es6: true - -parserOptions: - ecmaVersion: 2017 - -rules: - # Possible Errors - # http://eslint.org/docs/rules/#possible-errors - comma-dangle: [2, only-multiline] - no-control-regex: 2 - no-debugger: 2 - no-dupe-args: 2 - no-dupe-keys: 2 - no-duplicate-case: 2 - no-empty-character-class: 2 - no-ex-assign: 2 - no-extra-boolean-cast: 2 - no-extra-parens: [2, functions] - no-extra-semi: 2 - no-func-assign: 2 - no-invalid-regexp: 2 - no-irregular-whitespace: 2 - no-obj-calls: 2 - no-proto: 2 - no-template-curly-in-string: 2 - no-unexpected-multiline: 2 - no-unreachable: 2 - no-unsafe-negation: 2 - use-isnan: 2 - valid-typeof: 2 - - # Best Practices - # http://eslint.org/docs/rules/#best-practices - dot-location: [2, property] - no-fallthrough: 2 - no-global-assign: 2 - no-multi-spaces: 2 - no-octal: 2 - no-redeclare: 2 - no-self-assign: 2 - no-unused-labels: 2 - no-useless-call: 2 - no-useless-escape: 2 - no-void: 2 - no-with: 2 - - # Strict Mode - # http://eslint.org/docs/rules/#strict-mode - strict: [2, global] - - # Variables - # http://eslint.org/docs/rules/#variables - no-delete-var: 2 - no-undef: 2 - no-unused-vars: [2, {args: none}] - - # Node.js and CommonJS - # http://eslint.org/docs/rules/#nodejs-and-commonjs - no-mixed-requires: 2 - no-new-require: 2 - no-path-concat: 2 - no-restricted-modules: [2, sys, _linklist] - no-restricted-properties: [2, { - object: assert, - property: deepEqual, - message: Please use assert.deepStrictEqual(). - }, { - property: __defineGetter__, - message: __defineGetter__ is deprecated. - }, { - property: __defineSetter__, - message: __defineSetter__ is deprecated. - }] - - # Stylistic Issues - # http://eslint.org/docs/rules/#stylistic-issues - brace-style: [2, 1tbs, {allowSingleLine: true}] - comma-spacing: 2 - comma-style: 2 - computed-property-spacing: 2 - eol-last: 2 - func-call-spacing: 2 - func-name-matching: 2 - indent: [2, 2, {SwitchCase: 1, MemberExpression: 1}] - key-spacing: [2, {mode: minimum}] - keyword-spacing: 2 - linebreak-style: [2, unix] - max-len: [2, 80, 2] - new-parens: 2 - no-mixed-spaces-and-tabs: 2 - no-multiple-empty-lines: [2, {max: 2, maxEOF: 0, maxBOF: 0}] - no-tabs: 2 - no-trailing-spaces: 2 - quotes: [2, single, avoid-escape] - semi: 2 - semi-spacing: 2 - space-before-blocks: [2, always] - space-before-function-paren: [2, never] - space-in-parens: [2, never] - space-infix-ops: 2 - space-unary-ops: 2 - - # ECMAScript 6 - # http://eslint.org/docs/rules/#ecmascript-6 - arrow-parens: [2, always] - arrow-spacing: [2, {before: true, after: true}] - constructor-super: 2 - no-class-assign: 2 - no-confusing-arrow: 2 - no-const-assign: 2 - no-dupe-class-members: 2 - no-new-symbol: 2 - no-this-before-super: 2 - prefer-const: [2, {ignoreReadBeforeAssign: true}] - rest-spread-spacing: 2 - template-curly-spacing: 2 - - # Custom rules in tools/eslint-rules - align-function-arguments: 2 - align-multiline-assignment: 2 - assert-fail-single-argument: 2 - new-with-error: [2, Error, RangeError, TypeError, SyntaxError, ReferenceError] - -# Global scoped method and vars -globals: - COUNTER_HTTP_CLIENT_REQUEST: false - COUNTER_HTTP_CLIENT_RESPONSE: false - COUNTER_HTTP_SERVER_REQUEST: false - COUNTER_HTTP_SERVER_RESPONSE: false - COUNTER_NET_SERVER_CONNECTION: false - COUNTER_NET_SERVER_CONNECTION_CLOSE: false - DTRACE_HTTP_CLIENT_REQUEST: false - DTRACE_HTTP_CLIENT_RESPONSE: false - DTRACE_HTTP_SERVER_REQUEST: false - DTRACE_HTTP_SERVER_RESPONSE: false - DTRACE_NET_SERVER_CONNECTION: false - DTRACE_NET_STREAM_END: false - LTTNG_HTTP_CLIENT_REQUEST: false - LTTNG_HTTP_CLIENT_RESPONSE: false - LTTNG_HTTP_SERVER_REQUEST: false - LTTNG_HTTP_SERVER_RESPONSE: false - LTTNG_NET_SERVER_CONNECTION: false - LTTNG_NET_STREAM_END: false diff --git a/deps/node-inspect/.github/workflows/ci.yml b/deps/node-inspect/.github/workflows/ci.yml deleted file mode 100644 index 968316a34779a5..00000000000000 --- a/deps/node-inspect/.github/workflows/ci.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Node CI - -on: [push, pull_request] - -jobs: - build: - - runs-on: ubuntu-latest - - strategy: - fail-fast: false - matrix: - node-version: - # See https://github.com/nodejs/node-inspect/pull/78 - # - 10.x - - 12.x - - 13.x - - steps: - - uses: actions/checkout@v2 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - name: npm install, build, and test - run: | - npm install - npm run build --if-present - npm test - env: - CI: true diff --git a/deps/node-inspect/.gitignore b/deps/node-inspect/.gitignore deleted file mode 100644 index 72e2c8c18012a8..00000000000000 --- a/deps/node-inspect/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -node_modules/ -npm-debug.log -/tmp -/.vs diff --git a/deps/node-inspect/.npmrc b/deps/node-inspect/.npmrc deleted file mode 100644 index b7c8444fee52a6..00000000000000 --- a/deps/node-inspect/.npmrc +++ /dev/null @@ -1,2 +0,0 @@ -registry=https://registry.npmjs.org -package-lock=false diff --git a/deps/node-inspect/.travis.yml b/deps/node-inspect/.travis.yml deleted file mode 100644 index 07418a91eb7986..00000000000000 --- a/deps/node-inspect/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: node_js -node_js: - - '6.8' -before_deploy: - - git config --global user.email "jan.krems@gmail.com" - - git config --global user.name "Jan Krems" -deploy: - provider: script - script: ./node_modules/.bin/nlm release - skip_cleanup: true - 'on': - branch: master - node: '6.8' diff --git a/deps/node-inspect/CHANGELOG.md b/deps/node-inspect/CHANGELOG.md deleted file mode 100644 index 73aeb4df93fe8b..00000000000000 --- a/deps/node-inspect/CHANGELOG.md +++ /dev/null @@ -1,296 +0,0 @@ -### 1.11.6 - -* fix: replace the deprecated "repl.cli" with "repl" - **[@oyyd](https://github.com/oyyd)** [#66](https://github.com/nodejs/node-inspect/pull/66) - - [`5c1d771`](https://github.com/nodejs/node-inspect/commit/5c1d7716523b73e26f98f4f594ee34b7daa920a0) **fix:** replace the deprecated "repl.cli" with "repl" - see: [26260](Refs: https://github.com/nodejs/node/pull/26260) -* Address regressions due to changes in node - **[@jkrems](https://github.com/jkrems)** [#67](https://github.com/nodejs/node-inspect/pull/67) - - [`5b3511e`](https://github.com/nodejs/node-inspect/commit/5b3511ef21d0eba8304d8b2fed33f33aae22f308) **fix:** Address regressions due to changes in node - - -### 1.11.5 - -* Fix eslint issues - **[@jkrems](https://github.com/jkrems)** [#63](https://github.com/nodejs/node-inspect/pull/63) - - [`2adadbc`](https://github.com/nodejs/node-inspect/commit/2adadbc1086d2e374c425acbf96260a122705db2) **style:** Fix eslint issues - - [`a6d2f88`](https://github.com/nodejs/node-inspect/commit/a6d2f882c026409696a1b063ff40ceba7e1ddb86) **doc:** Remove redundant newline at the end - - -### 1.11.4 - -* Handle blocked port - **[@jkrems](https://github.com/jkrems)** [#62](https://github.com/nodejs/node-inspect/pull/62) - - [`3388969`](https://github.com/nodejs/node-inspect/commit/3388969d0032a78ff0cdb8146f170b978ec13b7b) **chore:** Disable package-lock - - [`d278b23`](https://github.com/nodejs/node-inspect/commit/d278b233ae5e11a2b62d01ccbaae594f39b32a96) **fix:** Stop asking to report a blocked port - see: [#60](https://github.com/nodejs/node-inspect/issues/60) - - -### 1.11.3 - -* [`93caa0f`](https://github.com/nodejs/node-inspect/commit/93caa0f5267c7ab452b258d3b03329a0bb5ac7f7) **docs:** Add missing oc in protocol -* [`2d87cbe`](https://github.com/nodejs/node-inspect/commit/2d87cbe76aa968dfc1ac69d9571af1be81abd8e0) **fix:** Make --inspect-port=0 work -* [`ebfd02e`](https://github.com/nodejs/node-inspect/commit/ebfd02ece9b642586023f7791da71defeb13d746) **chore:** Bump tap to 10.7 -* [`c07adb1`](https://github.com/nodejs/node-inspect/commit/c07adb17b164c1cf3da8d38659ea9f5d7ff42e9c) **test:** Use useful break location -* [`94f0bf9`](https://github.com/nodejs/node-inspect/commit/94f0bf97d24c376baf3ecced2088d81715a73464) **fix:** Fix `takeHeapSnapshot()` truncation bug - - -### 1.11.2 - -* [`42e0cd1`](https://github.com/nodejs/node-inspect/commit/42e0cd111d89ed09faba1c0ec45089b0b44de011) **fix:** look for generic hint text - - -### 1.11.1 - -* Prefer --inspect-brk over --debug-brk - **[@ofrobots](https://github.com/ofrobots)** [#43](https://github.com/nodejs/node-inspect/pull/43) - - [`2c1ed27`](https://github.com/nodejs/node-inspect/commit/2c1ed27ee44d9aebb3c5ac50039abae8166a54e3) **fix:** use --inspect-brk with Node 8+ - - -### 1.11.0 - -* doc: add profile and heap to help - **[@joshgav](https://github.com/joshgav)** [#39](https://github.com/nodejs/node-inspect/pull/39) - - [`f64c920`](https://github.com/nodejs/node-inspect/commit/f64c9205bd8382289660aa677d3ac192a9c81fd5) **doc:** add profile and heap to help -* Update test suite to pass on latest nightly - **[@jkrems](https://github.com/jkrems)** [#36](https://github.com/nodejs/node-inspect/pull/36) - - [`41148d7`](https://github.com/nodejs/node-inspect/commit/41148d74a2d563eea3b7ad5463622b6b9fd4c46e) **test:** Remove outdated test - - [`2c224c5`](https://github.com/nodejs/node-inspect/commit/2c224c551619e386e80fc3154cc14562cac063b9) **test:** Accept any kind of "break" - - [`22bf349`](https://github.com/nodejs/node-inspect/commit/22bf349bc86d7bf6fd449791c9d1e7eaf66c2681) **test:** Adjust for v8 5.7 - - [`6ce8c16`](https://github.com/nodejs/node-inspect/commit/6ce8c165c45a491bea8cfb3c67d2ae80e7c34dcb) **test:** Revert to old assertions -* Verify custom port support - **[@jkrems](https://github.com/jkrems)** [#41](https://github.com/nodejs/node-inspect/pull/41) - - [`e3a489f`](https://github.com/nodejs/node-inspect/commit/e3a489f23b089d3d57a25d5efe40daf06de63e23) **test:** custom port -* Support for debugging a pid - **[@jkrems](https://github.com/jkrems)** [#37](https://github.com/nodejs/node-inspect/pull/37) - - [`4179506`](https://github.com/nodejs/node-inspect/commit/4179506a4d546bac2c93b2a7ff491b1fa4494fd9) **feat:** Support for debugging a pid - - -### 1.10.6 - -* chore: Fix usage text for embedded mode - **[@addaleax](https://github.com/addaleax)** [#20](https://github.com/nodejs/node-inspect/pull/20) - - [`b0779f5`](https://github.com/nodejs/node-inspect/commit/b0779f597104e9ada5681f64d7e714525b753511) **chore:** Fix usage text for embedded mode -* print 'ok' after connection - **[@ofrobots](https://github.com/ofrobots)** [#25](https://github.com/nodejs/node-inspect/pull/25) - - [`2a47125`](https://github.com/nodejs/node-inspect/commit/2a4712577f6996fbb078dcfcd7320c397685d76a) **fix:** print 'ok' after connection -* Make autocompletion in REPL work - **[@aqrln](https://github.com/aqrln)** [#28](https://github.com/nodejs/node-inspect/pull/28) - - [`ccab737`](https://github.com/nodejs/node-inspect/commit/ccab737399249a8c2230ed6adfec579c7d724364) **fix:** Make autocompletion in REPL work -* Remove console.error() statement - **[@aqrln](https://github.com/aqrln)** [#30](https://github.com/nodejs/node-inspect/pull/30) - - [`032b045`](https://github.com/nodejs/node-inspect/commit/032b045d4d73622c77b7ebcc26781c6ad98200b3) **style:** Remove console.error() statement -* Take --debug-port into account - **[@jkrems](https://github.com/jkrems)** [#26](https://github.com/nodejs/node-inspect/pull/26) - - [`054d4b1`](https://github.com/nodejs/node-inspect/commit/054d4b10e65f12a3a4b10b4c0ab2a4768cc5e893) **fix:** Take --debug-port into account -* Delay run until breakpoints are restored - **[@jkrems](https://github.com/jkrems)** [#34](https://github.com/nodejs/node-inspect/pull/34) - - [`802b88c`](https://github.com/nodejs/node-inspect/commit/802b88c8ad0a57608cb9e0cb4bf46ed683bb6344) **fix:** Delay run until breakpoints are restored - - [`2b93173`](https://github.com/nodejs/node-inspect/commit/2b93173d95e7f8b30d85603613cb2ae3b3ec18db) **fix:** Use single string for paused notice - - [`b4d5ee2`](https://github.com/nodejs/node-inspect/commit/b4d5ee2a3d25613b35a2e8e10a0eb75582cc5654) **fix:** Work around inconsistent handling of strict directive - - [`f6ccfc7`](https://github.com/nodejs/node-inspect/commit/f6ccfc7f4d00ad4fdf3b581b677f8d7f1699c44c) **fix:** Only restart after port is free - - [`8b101bf`](https://github.com/nodejs/node-inspect/commit/8b101bf669ca102df4980bfad3e0436ef1c2f1a4) **test:** Skip exact match on AIX -* [`a4e4b6f`](https://github.com/nodejs/node-inspect/commit/a4e4b6feeba4dedfd2c89ef32f39e813314d3bbd) **chore:** Fix repo info in package.json - - -### 1.10.5 - -* docs: minor edits to governance docs - **[@joshgav](https://github.com/joshgav)** [#17](https://github.com/buggerjs/node-inspect/pull/17) - - [`a70fe04`](https://github.com/buggerjs/node-inspect/commit/a70fe04bdde9b7c74588685066291f9b11183328) **docs:** minor edits to governance docs - - -### 1.10.4 - -* [`1c31bf7`](https://github.com/buggerjs/node-inspect/commit/1c31bf7d1b3ea1b424ae0662526596670cb506c9) **chore:** Support embedded mode - - -### 1.10.3 - -* [`7b20379`](https://github.com/buggerjs/node-inspect/commit/7b20379069af692a9038a31a4465f72db9eb532f) **chore:** Mark .eslintrc as root - - -### 1.10.2 - -* Run tests on windows - **[@jkrems](https://github.com/jkrems)** [#16](https://github.com/buggerjs/node-inspect/pull/16) - - [`5a57f98`](https://github.com/buggerjs/node-inspect/commit/5a57f9865e02eef0763c2a7f26236c34a632ccdd) **chore:** Run tests on windows - - [`0a04b50`](https://github.com/buggerjs/node-inspect/commit/0a04b50cc8b4dc6ce868927c635c479d75ce71f4) **chore:** Bump nlm to get rid of postinstall - - [`4a8b27c`](https://github.com/buggerjs/node-inspect/commit/4a8b27cea814a37895effd2a0c1b85dbfee3a7f4) **test:** Remove unix path assumptions - - -### 1.10.1 - -* [`4ba3c72`](https://github.com/buggerjs/node-inspect/commit/4ba3c72270fae9a71343ddca11aa27980678a67c) **refactor:** Undo weird bundling into one file - - -### 1.10.0 - -* [`3e1a66a`](https://github.com/buggerjs/node-inspect/commit/3e1a66a489bef19beaa5f859e99e027274ff43cb) **feat:** Support CPU & heap profiles - - -### 1.9.3 - -* Move back to single file - **[@jkrems](https://github.com/jkrems)** [#15](https://github.com/buggerjs/node-inspect/pull/15) - - [`9877660`](https://github.com/buggerjs/node-inspect/commit/9877660a73ff0ec0885ad7f939ba62020a46b4b6) **refactor:** Wrap client in IIFE - - [`7795c53`](https://github.com/buggerjs/node-inspect/commit/7795c533f0605eb128db610a5874b27e555251ef) **refactor:** Move more code in createRepl scope - - [`be34a39`](https://github.com/buggerjs/node-inspect/commit/be34a398e823612bdf5ac90bad5222af27035a00) **refactor:** Move back to single file - - [`ab45b62`](https://github.com/buggerjs/node-inspect/commit/ab45b6273dc0d3a49d3cf46a80cb48ab79d1caf8) **refactor:** Remove single-use functions - - [`37a711e`](https://github.com/buggerjs/node-inspect/commit/37a711ed5334c06ed4d85f995e567a9f176a68d5) **style:** Stop using `new Buffer` - - [`d669dc5`](https://github.com/buggerjs/node-inspect/commit/d669dc593f5ad5ca7a48f19f0905ef66ec0e540d) **chore:** Switch to node eslint rules - - [`15e7917`](https://github.com/buggerjs/node-inspect/commit/15e79177918d96dcffd2384715faf0308e97a26c) **style:** Use var in classical for loops - - -### 1.9.2 - -* [`c9dc4be`](https://github.com/buggerjs/node-inspect/commit/c9dc4beb08236e33d64f19417682cf5b3f5aeed6) **doc:** Link directly to GOVERNANCE file - - -### 1.9.1 - -* Handle big ws frames correctly - **[@jkrems](https://github.com/jkrems)** [#14](https://github.com/buggerjs/node-inspect/pull/14) - - [`f80100e`](https://github.com/buggerjs/node-inspect/commit/f80100e932710d232d074b239cbf8fefa564c789) **fix:** Handle big ws frames correctly - see: [#10](https://github.com/buggerjs/node-inspect/issues/10) - - -### 1.9.0 - -* Support for low-level agent access - **[@jkrems](https://github.com/jkrems)** [#13](https://github.com/buggerjs/node-inspect/pull/13) - - [`90ed431`](https://github.com/buggerjs/node-inspect/commit/90ed4310c62d130637c12f8ecdb752075c43ac36) **feat:** Support for low-level agent access - - -### 1.8.4 - -* Use proper path for websocket - **[@jkrems](https://github.com/jkrems)** [#12](https://github.com/buggerjs/node-inspect/pull/12) - - [`3405225`](https://github.com/buggerjs/node-inspect/commit/3405225979dfc2058bcc6d1b90f41c060dbd1f92) **fix:** Use proper path for websocket - see: [#11](https://github.com/buggerjs/node-inspect/issues/11) - - -### 1.8.3 - -* [`6f9883d`](https://github.com/buggerjs/node-inspect/commit/6f9883d4b29419831133988981b83e891b19739a) **fix:** Breakpoints & scripts work when not paused -* [`ecb1362`](https://github.com/buggerjs/node-inspect/commit/ecb1362c842e6ed5bc28c091a32bfd540742db75) **chore:** Pin node to 6.8 - - -### 1.8.2 - -* [`4219a98`](https://github.com/buggerjs/node-inspect/commit/4219a98d6514f1068feabce2945c21a0d5ba6561) **refactor:** Decouple source snippet from repl - - -### 1.8.1 - -* [`95402ee`](https://github.com/buggerjs/node-inspect/commit/95402ee5dff04057f074677d39db2f61ec74c151) **refactor:** Move `list` into CallFrame - - -### 1.8.0 - -* [`d0e6499`](https://github.com/buggerjs/node-inspect/commit/d0e6499084f5d656ef0c5fd470d3ab21f2e9a6b4) **feat:** `exec .scope` - - -### 1.7.0 - -* `breakOn{Exception,Uncaught,None}` - **[@jkrems](https://github.com/jkrems)** [#8](https://github.com/buggerjs/node-inspect/pull/8) - - [`fa8c4c7`](https://github.com/buggerjs/node-inspect/commit/fa8c4c7d7bb6972733c92da4d04fdd62c02b0e3b) **feat:** `breakOn{Exception,Uncaught,None}` - see: [#6](https://github.com/buggerjs/node-inspect/issues/6) - - -### 1.6.0 - -* Add `help` command - **[@jkrems](https://github.com/jkrems)** [#7](https://github.com/buggerjs/node-inspect/pull/7) - - [`09b37a0`](https://github.com/buggerjs/node-inspect/commit/09b37a02e04e16a38ce27f69538d3b098548b47c) **feat:** Add `help` command - see: [#5](https://github.com/buggerjs/node-inspect/issues/5) - - -### 1.5.0 - -* [`7e0fd99`](https://github.com/buggerjs/node-inspect/commit/7e0fd99fcfc65d8b647a2259df78f4cabf1d3d63) **feat:** Add `r` shortcut for `run` - - -### 1.4.1 - -* [`484d098`](https://github.com/buggerjs/node-inspect/commit/484d0983f06d6ff9639ab5197ba0a58313f532df) **chore:** Remove old implementation - - -### 1.4.0 - -* Properly tested implementation - **[@jkrems](https://github.com/jkrems)** [#4](https://github.com/buggerjs/node-inspect/pull/4) - - [`ba060d3`](https://github.com/buggerjs/node-inspect/commit/ba060d3ef65ae84df2a3a9b9f16d563f3c4b29be) **feat:** Error handling w/o args - - [`b39b3bc`](https://github.com/buggerjs/node-inspect/commit/b39b3bc07c13adc48fc8bb720889285c51e62548) **feat:** Launch child - - [`481693f`](https://github.com/buggerjs/node-inspect/commit/481693f676ee099b7787cd2426b980858e973602) **feat:** Connect debug client - - [`3bba0f2`](https://github.com/buggerjs/node-inspect/commit/3bba0f2416b2e3b4e6010de675003fcc328b16e8) **chore:** Disable lint for inactive code - - [`cc7bdfc`](https://github.com/buggerjs/node-inspect/commit/cc7bdfcf7f21ef5cd5c32c7800407238b0d4f100) **feat:** Properly fail with invalid host:port - - [`73f34f9`](https://github.com/buggerjs/node-inspect/commit/73f34f902634e9778597e129f46895aa8b643d72) **refactor:** Remove unused field - - [`6a23e0c`](https://github.com/buggerjs/node-inspect/commit/6a23e0cf3179f43ca6fc5a0fa2b1dd18ebc044b5) **refactor:** Better debug output & support node 6.6 - - [`63b0f9b`](https://github.com/buggerjs/node-inspect/commit/63b0f9b6ef8bd9af0f7cb14a5938a45838731fc9) **test:** Add timeout to waitFor(pattern) - - [`cfa197b`](https://github.com/buggerjs/node-inspect/commit/cfa197bf8325a1a4ca1b296f8d6971d368bfbfbb) **refactor:** Move REPL setup into own file - - [`3f46c2c`](https://github.com/buggerjs/node-inspect/commit/3f46c2c43f836e1135b66871087aa74969f6b330) **feat:** Working repl eval - - [`6911eb1`](https://github.com/buggerjs/node-inspect/commit/6911eb1a00b964bc5683506d433fa4f665f5a82c) **feat:** Enter repeats last command - - [`7d20b7d`](https://github.com/buggerjs/node-inspect/commit/7d20b7deadf1b251ea8cf2cc9167c175624932c4) **chore:** Add missing license header - - [`23c62f8`](https://github.com/buggerjs/node-inspect/commit/23c62f8375ca7c8b71d032047e728dace02f4efa) **feat:** Print break context - - [`5dbc83d`](https://github.com/buggerjs/node-inspect/commit/5dbc83df31171f9c38a974c99340bde26f2e24ec) **feat:** Stepping and breakpoints - - [`8deb8cc`](https://github.com/buggerjs/node-inspect/commit/8deb8cc36b9fca432ab8df63a82e9de7ab5adaf0) **feat:** list for printing source - - [`1ed2ec9`](https://github.com/buggerjs/node-inspect/commit/1ed2ec9937070652be611dbb6b11dfb42cb840f8) **chore:** Disable verbose output on CI - - [`625a435`](https://github.com/buggerjs/node-inspect/commit/625a435925dd8fd980bed2dc9e3fd73dd27df4ef) **fix:** Gracefully handle delayed scriptParsed - - [`8823c60`](https://github.com/buggerjs/node-inspect/commit/8823c60d347600b2313cfdd8cb5e96fe02419a8a) **chore:** Run all the tests - - [`00506f7`](https://github.com/buggerjs/node-inspect/commit/00506f763928cc440505a81030167a11b9a84e00) **feat:** backtrace/bt - - [`e1ee02d`](https://github.com/buggerjs/node-inspect/commit/e1ee02d5cc389916489d387d07d5dd161230427a) **refactor:** Leverage util.inspect.custom - - [`5dcc319`](https://github.com/buggerjs/node-inspect/commit/5dcc31922d40f56c7435319d1538390a442e8e4b) **feat:** scripts and scripts(true) - - [`085cd5a`](https://github.com/buggerjs/node-inspect/commit/085cd5a76a961edfcaa342fff5eb09bf2f9c8983) **refactor:** Consistent import style - - [`1c60f91`](https://github.com/buggerjs/node-inspect/commit/1c60f91f233848c05d865617dc7f5aacb36270b6) **feat:** Set breakpoint before file is loaded - - [`bc82ecc`](https://github.com/buggerjs/node-inspect/commit/bc82eccb2a1a7c0f5332371254f6584e748216aa) **feat:** breakpoints to list breakpoints - - [`7f48c95`](https://github.com/buggerjs/node-inspect/commit/7f48c9510696ec400d51afaca8d23a9c292640f8) **feat:** watchers & exec - - [`0f8cd13`](https://github.com/buggerjs/node-inspect/commit/0f8cd13a092e5dbeb395ff04cbe2ed97cb986423) **feat:** clearBreakpoint - - [`0d31560`](https://github.com/buggerjs/node-inspect/commit/0d315603bdcb9f4da42fab24dc569c325151269e) **feat:** version to print v8 version - - [`df6b89d`](https://github.com/buggerjs/node-inspect/commit/df6b89df580a9afcb3b8883b0e4224cbcebb384f) **feat:** Paused & global exec - - [`9e97d73`](https://github.com/buggerjs/node-inspect/commit/9e97d73073ceffd70974d45887c84fadb9159d5c) **feat:** repl to enter exec mode - - [`9ee9f90`](https://github.com/buggerjs/node-inspect/commit/9ee9f903d6202f54ed2b3b3559da4006b65d39b5) **feat:** run & restart -* [`3a752aa`](https://github.com/buggerjs/node-inspect/commit/3a752aaa773968bfe16c5f543bd739feed598bea) **feat:** kill -* [`a67e470`](https://github.com/buggerjs/node-inspect/commit/a67e47018b20d46aeeaa7abd27eb8e7770fd0b8f) **feat:** Restore breakpoints on restart - - -### 1.3.3 - -* [`eb7a54c`](https://github.com/buggerjs/node-inspect/commit/eb7a54c6fa731ed3276072c72034046fc5ffbac6) **chore:** Switch to tap for tests - - -### 1.3.2 - -* Add notes about governance - **[@jkrems](https://github.com/jkrems)** [#3](https://github.com/buggerjs/node-inspect/pull/3) - - [`e94089d`](https://github.com/buggerjs/node-inspect/commit/e94089d93689cacf5c953e94563463d1e174452d) **chore:** Add notes about governance - - -### 1.3.1 - -* [`8767137`](https://github.com/buggerjs/node-inspect/commit/8767137c53a2f6b1d36970074ea95be9871e50e3) **style:** Remove rogue console.log - - -### 1.3.0 - -* [`3ac6232`](https://github.com/buggerjs/node-inspect/commit/3ac623219ba44b0af40ef66826610a26a46c7966) **feat:** Add `version` command - - -### 1.2.0 - -* [`86b5812`](https://github.com/buggerjs/node-inspect/commit/86b581218ccab44e6bde259a17ad1e71645a6137) **feat:** scripts & listScripts(true) - - -### 1.1.1 - -* [`feaea38`](https://github.com/buggerjs/node-inspect/commit/feaea385a981e6b72a8d99277fbf575c54e15fc6) **style:** Typo in comment - - -### 1.1.0 - -* [`c64155f`](https://github.com/buggerjs/node-inspect/commit/c64155faa552f71463842a26330aa5bcbfc31670) **feat:** repl command - - -### 1.0.0 - -* [`44c4c79`](https://github.com/buggerjs/node-inspect/commit/44c4c79af5a228ccfd8906f11409b2a33390b878) **chore:** Initial commit -* [`985873c`](https://github.com/buggerjs/node-inspect/commit/985873cfb97146b38480080f9907219c473f1f6f) **feat:** Launching the example works -* [`3d92d05`](https://github.com/buggerjs/node-inspect/commit/3d92d05cca152a2c2647aa64eefc80432638bc4d) **chore:** Proper license and passing tests -* [`b3f99d9`](https://github.com/buggerjs/node-inspect/commit/b3f99d981038b17663fcfd984d2f5d6d9b51ee18) **feat:** Futile attempts to send a valid ws frame -* [`465cfb7`](https://github.com/buggerjs/node-inspect/commit/465cfb7b295aebb48b285c26f6de9c4657fe590d) **feat:** Working ws connection -* [`da9f011`](https://github.com/buggerjs/node-inspect/commit/da9f01118e2b144f2da8cd370113a608526774a1) **fix:** Fix remote connect -* [`5ef33d7`](https://github.com/buggerjs/node-inspect/commit/5ef33d7892cc49becb4c66098fc7927bc74b014a) **feat:** Working step-by-step -* [`534e1e4`](https://github.com/buggerjs/node-inspect/commit/534e1e46b307d61d51eb4c0aab4a3b17c17aea3d) **chore:** Add bin entry -* [`8cff9cf`](https://github.com/buggerjs/node-inspect/commit/8cff9cfb0138b5ecff0f5f6a7839dbfddc0684fd) **style:** Use simpler key thingy -* [`720ec53`](https://github.com/buggerjs/node-inspect/commit/720ec53a5b251ab3caf27f06b60924efb9e03a92) **doc:** Add instructions -* [`b89ad60`](https://github.com/buggerjs/node-inspect/commit/b89ad601b885a417e6433b1609477d8453f498a1) **doc:** More helpful docs -* [`de9243c`](https://github.com/buggerjs/node-inspect/commit/de9243c95eabe733d05952229340808c3cebf129) **feat:** Watchers -* [`e16978f`](https://github.com/buggerjs/node-inspect/commit/e16978ff8e4b2b2bdccf88fd7d3905f525822981) **docs:** Working usage hints -* [`2dbc204`](https://github.com/buggerjs/node-inspect/commit/2dbc2042145fd97169fc7536186a449715e27810) **refactor:** Use proxies -* [`b8c9b14`](https://github.com/buggerjs/node-inspect/commit/b8c9b147713f63181396d5a7fe4c2f737b733b4c) **style:** Remove unused var -* [`f6b4b20`](https://github.com/buggerjs/node-inspect/commit/f6b4b20a1d28d91cfe452b995f7dbe5f7c749e89) **feat:** Nicer inspect of remote values -* [`36887c6`](https://github.com/buggerjs/node-inspect/commit/36887c66bbf26d540f087f80ddfec38462a33bdf) **fix:** Properly print watchers -* [`7729442`](https://github.com/buggerjs/node-inspect/commit/77294426157a28cc76e339cb13916a205182641e) **feat:** Add pause command -* [`e39a713`](https://github.com/buggerjs/node-inspect/commit/e39a7134873f06da37baaa9b6252cede4ad38d7a) **fix:** Properly format boolean properties -* [`f8f51d7`](https://github.com/buggerjs/node-inspect/commit/f8f51d7a01e8d74023306a08a3d6e2da63d123e1) **fix:** Properly format numeric properties -* [`89e6e08`](https://github.com/buggerjs/node-inspect/commit/89e6e087220f3c3cb628ac7541c44298485a2e04) **feat:** Add backtrace command -* [`82362ac`](https://github.com/buggerjs/node-inspect/commit/82362acfc7ce22b4cccc64889ec136dedc8895ec) **feat:** Add setBreakpoint() -* [`7064cce`](https://github.com/buggerjs/node-inspect/commit/7064ccec3b103683088d532abfe5b4e7c066948b) **feat:** Add `setBreakpoint(line)` -* [`360580e`](https://github.com/buggerjs/node-inspect/commit/360580eba4353e81311e56df018eec0ca233da11) **feat:** Add run/kill/restart -* [`b1b576e`](https://github.com/buggerjs/node-inspect/commit/b1b576e2645723a8575df544e0bfb672d60d9d91) **feat:** Add `help` command -* [`2db4660`](https://github.com/buggerjs/node-inspect/commit/2db46609cd1c8543d31ebd5dc47e4c27ec254841) **feat:** Add remaining sb() variants -* [`f2ad1ae`](https://github.com/buggerjs/node-inspect/commit/f2ad1aeedafb154043d70bb9195b10986d311d26) **fix:** Display breakpoints set into the future -* [`73272f9`](https://github.com/buggerjs/node-inspect/commit/73272f9ace1f8546f8cad1d53627dbffba50bb4e) **refactor:** Make breakpoints more inspect friendly -* [`507a71d`](https://github.com/buggerjs/node-inspect/commit/507a71de345a3de7fe144517e9f5ea264ff993e3) **feat:** Add breakpoints command -* [`5fb3e5d`](https://github.com/buggerjs/node-inspect/commit/5fb3e5d17bbcfd45b264431547b3cf0b781c7640) **docs:** Link to Command Line API docs -* [`81af501`](https://github.com/buggerjs/node-inspect/commit/81af501bbf85397e2078310c7f24a9ac5b7f02dc) **chore:** Fix license field diff --git a/deps/node-inspect/CONTRIBUTING.md b/deps/node-inspect/CONTRIBUTING.md deleted file mode 100644 index 012d29471462de..00000000000000 --- a/deps/node-inspect/CONTRIBUTING.md +++ /dev/null @@ -1,181 +0,0 @@ -# Contributing - -🎉🏅 Thanks for helping us improve this project! 🙏 - -This document outlines some of the practices we care about. -If you have any questions or suggestions about the process, -feel free to [open an issue](#reporting-issues). - -## Code of Conduct - -The [Node.js Code of Conduct][] applies to this repo. - -[Node.js Code of Conduct]: https://github.com/nodejs/node/blob/master/CODE_OF_CONDUCT.md - -## Governance - -This project falls under the governance of the Node.js Diagnostics WG as -described at . - -## Developer's Certificate of Origin 1.1 - -By making a contribution to this project, I certify that: - -* (a) The contribution was created in whole or in part by me and I - have the right to submit it under the open source license - indicated in the file; or - -* (b) The contribution is based upon previous work that, to the best - of my knowledge, is covered under an appropriate open source - license and I have the right under that license to submit that - work with modifications, whether created in whole or in part - by me, under the same open source license (unless I am - permitted to submit under a different license), as indicated - in the file; or - -* (c) The contribution was provided directly to me by some other - person who certified (a), (b) or (c) and I have not modified - it. - -* (d) I understand and agree that this project and the contribution - are public and that a record of the contribution (including all - personal information I submit with it, including my sign-off) is - maintained indefinitely and may be redistributed consistent with - this project or the open source license(s) involved. - -## How Can I Contribute? - -### Reporting Issues - -If you find any mistakes in the docs or a bug in the code, -please [open an issue in Github](https://github.com/nodejs/node-inspect/issues/new) so we can look into it. -You can also [create a PR](#contributing-code) fixing it yourself of course. - -If you report a bug, please follow these guidelines: - -* Make sure the bug exists in the latest version. -* Include instructions on how to reproduce the issue. - The instructions should be as minimal as possible - and answer the three big questions: - 1. What are the exact steps you took? This includes the exact versions of node, npm, and any packages involved. - 1. What result are you expecting? - 1. What is the actual result? - -### Improving Documentation - -For small documentation changes, you can use [Github's editing feature](https://help.github.com/articles/editing-files-in-another-user-s-repository/). -The only thing to keep in mind is to prefix the commit message with "docs: ". -The default commit message generated by Github will lead to a failing CI build. - -For larger updates to the documentation -it might be better to follow the [instructions for contributing code below](#contributing-code). - -### Contributing Code - -**Note:** If you're planning on making substantial changes, -please [open an issue first to discuss your idea](#reporting-issues). -Otherwise you might end up investing a lot of work -only to discover that it conflicts with plans the maintainers might have. - -The general steps for creating a pull request are: - -1. Create a branch for your change. - Always start your branch from the latest `master`. - We often prefix the branch name with our initials, e.g. `jk-a-change`. -1. Run `npm install` to install the dependencies. -1. If you're fixing a bug, be sure to write a test *first*. - That way you can validate that the test actually catches the bug and doesn't pass. -1. Make your changes to the code. - Remember to update the tests if you add new features or change behavior. -1. Run the tests via `npm test`. This will also run style checks and other validations. - You might see errors about uncommitted files. - This is expected until you commit your changes. -1. Once you're done, `git add .` and `git commit`. - Please follow the [commit message conventions](#commits--commit-messages) described below. -1. Push your branch to Github & create a PR. - -#### Code Style - -In addition to any linting rules the project might include, -a few general rules of thumb: - -* Try to match the style of the rest of the code. -* We prefer simple code that is easy to understand over terse, expressive code. -* We try to structure projects by semantics instead of role. - E.g. we'd rather have a `tree.js` module that contains tree traversal-related helpers - than a `helpers.js` module. -* Actually, if you create helpers you might want to put those into a separate package. - That way it's easier to reuse them. - -#### Commits & Commit Messages - -Please follow the [angular commit message conventions](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#-git-commit-guidelines). -We use an automated tool for generating releases -that depends on the conventions to determine the next version and the content of the changelog. -Commit messages that don't follow the conventions will cause `npm test` (and thus CI) to fail. - -The short summary - a commit message should look like this: - -``` -: - - - - - -