在NodeJS调试器中添加条件断点

时间:2014-02-04 14:16:54

标签: node.js debugging conditional-breakpoint

node.js help命令输出以下内容:

debug> help
Commands: run (r), cont (c), next (n), step (s), out (o), backtrace (bt), setBreakpoint (sb), clearBreakpoint (cb),
watch, unwatch, watchers, repl, restart, kill, list, scripts, breakOnException, breakpoints, version

我可以使用setBreakpoint添加新的断点:

debug> setBreakpoint(12)
...

但我可以让它有条件吗?例如:

*only if `foo() === true`, stop here*

另一种方法是在脚本中将其添加为if

if (foo()) { debugger; }

这可以通过NodeJS调试器实现吗?

2 个答案:

答案 0 :(得分:0)

我相信这可以通过使用#include <iostream> #include <tuple> #include <vector> #include <type_traits> #include <utility> template <typename T> struct Identity { using type = T; }; template <typename...> struct concat; template <template <typename...> class P, typename... Ts, typename... Us> struct concat<P<Ts...>, P<Us...>> { using type = P<Ts..., Us...>; }; template <typename Pack> struct concat<Pack> : Identity<Pack> {}; template <typename Pack1, typename Pack2, typename... Packs> struct concat<Pack1, Pack2, Packs...> { using type = typename concat<Pack1, typename concat<Pack2, Packs...>::type>::type; }; template <std::size_t N, typename Intput, typename... Output> struct split; template <std::size_t N, template <typename...> class P, typename First, typename... Rest, typename... Output> struct split<N, P<First, Rest...>, Output...> : split<N-1, P<Rest...>, Output..., First> {}; template <template <typename...> class P, typename First, typename... Rest, typename... Output> struct split<0, P<First, Rest...>, Output...> { using head = P<Output...>; using tail = P<First, Rest...>; }; template <template <typename...> class P, typename... Output> struct split<0, P<>, Output...> { using head = P<Output...>; using tail = P<>; }; template <typename Pack> struct pack_size; template <template <typename...> class P, typename... Ts> struct pack_size<P<Ts...>> : std::integral_constant<std::size_t, sizeof...(Ts)> {}; struct Failed; template <typename Pack, typename Untried, typename Output, typename Match> struct FindPacksToMergeImpl; template <typename Pack, typename Untried, typename Output, typename Match, typename Result> struct Check; template <typename Pack, typename Untried, typename Output, typename Match> struct FindPacksToMergeHelper; template <typename Pack, typename Untried, typename Output, typename Match, bool> struct CheckIfPackTooBig; template <typename Pack, typename Untried, typename Output, typename Match, bool> struct CheckIfAnswerFound; template <typename Pack, typename Untried, typename Output, typename Match, bool> struct CheckHead; template <typename Pack, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match> struct CheckIfPackTooBig<Pack, P<First, Rest...>, P<Output...>, Match, true> : FindPacksToMergeImpl<Pack, P<Rest...>, P<Output...>, Match> {}; // Move on to the next of the untried packs. template <typename Pack, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match> struct CheckIfPackTooBig<Pack, P<First, Rest...>, P<Output...>, Match, false> : CheckIfAnswerFound<Pack, P<First, Rest...>, P<Output...>, Match, std::is_same<typename First::argument_type, Match>::value> {}; template <typename Pack, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match> struct CheckIfAnswerFound<Pack, P<First, Rest...>, P<Output...>, Match, true> : Identity<P<Output..., First>> {}; // We are done. template <typename Pack, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match> struct CheckIfAnswerFound<Pack, P<First, Rest...>, P<Output...>, Match, false> : CheckHead<Pack, P<First, Rest...>, P<Output...>, Match, std::is_same<typename First::argument_type, typename split<pack_size<typename First::argument_type>::value, Match>::head>::value> {}; // Check if the head of Match is the same as First::argument_type. template <typename Pack, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match> struct CheckHead<Pack, P<First, Rest...>, P<Output...>, Match, true> : FindPacksToMergeImpl<Pack, Pack, P<Output..., First>, typename split<pack_size<typename First::argument_type>::value, Match>::tail> {}; // Try with the tail now, starting back at the first type in Pack. template <typename Pack, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match> struct CheckHead<Pack, P<First, Rest...>, P<Output...>, Match, false> : FindPacksToMergeImpl<Pack, P<Rest...>, P<Output...>, Match> {}; // Move on to the next of the untried packs. template <typename Pack, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match> struct FindPacksToMergeHelper<Pack, P<First, Rest...>, P<Output...>, Match> : CheckIfPackTooBig<Pack, P<First, Rest...>, P<Output...>, Match, pack_size<Match>::value < pack_size<typename First::argument_type>::value> {}; template <typename Pack, template <typename...> class P, typename... Output, typename Match> struct FindPacksToMergeHelper<Pack, P<>, P<Output...>, Match> : Identity<Failed> {}; template <typename Pack, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match, typename Result> struct Check<Pack, P<First, Rest...>, P<Output...>, Match, Result> : Identity<Result> {}; // We are done. template <typename Pack, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match> struct Check<Pack, P<First, Rest...>, P<Output...>, Match, Failed> : FindPacksToMergeImpl<Pack, P<Rest...>, P<Output...>, Match> {}; // Move on to the next of the untried packs. template <typename Pack, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match> struct FindPacksToMergeImpl<Pack, P<First, Rest...>, P<Output...>, Match> : Check<Pack, P<First, Rest...>, P<Output...>, Match, typename FindPacksToMergeHelper<Pack, P<First, Rest...>, P<Output...>, Match>::type> {}; template <typename Pack, template <typename...> class P, typename... Output, typename Match> struct FindPacksToMergeImpl<Pack, P<>, P<Output...>, Match> : Identity<Failed> {}; // This should never be reached, but is needed to compile (it was really hard to check why though). template <typename> struct EmptyPack; template <template <typename...> class P, typename... Ts> struct EmptyPack<P<Ts...>> { using type = P<>; }; template <typename Pack, typename Match> using FindPacksToMerge = typename FindPacksToMergeImpl<Pack, Pack, typename EmptyPack<Pack>::type, Match>::type; template <typename... Ts> class Storage { std::tuple<std::vector<Ts*>...> inventory; template <typename> struct AddDifferentTypes; public: template <typename... Args> void addDifferentTypes (Args&&... args) { using TypesTuple = FindPacksToMerge<std::tuple<Ts...>, std::tuple<Args...>>; // FindPacksToMerge adapted from the FindPacksToMerge.cpp program. AddDifferentTypes<TypesTuple>::execute(this, std::forward<Args>(args)...); } template <typename T> const std::vector<T*>& get() const {return std::get<std::vector<T*>>(inventory);} private: template <typename T, typename... Args> void addItem (Args&&... args) { std::get<std::vector<T*>>(inventory).emplace_back(new T{std::forward<Args>(args)...}); } }; template <typename... Ts> template <template <typename...> class P, typename... Vs> struct Storage<Ts...>::AddDifferentTypes<P<Vs...>> { template <typename... Args> static void execute (Storage<Ts...>* storage, Args&&... args) { executeHelper<0, 0, P<Vs...>, std::tuple_size<typename Vs::argument_type>::value...>(storage, std::tie(args...)); } private: template <std::size_t N, std::size_t Offset, typename TypesTuple, std::size_t First, std::size_t... Rest, typename ArgsTuple> static void executeHelper (Storage<Ts...>* storage, const ArgsTuple& tuple) { add<N, Offset, TypesTuple>(storage, tuple, std::make_index_sequence<First>{}); executeHelper<N + 1, Offset + First, TypesTuple, Rest...>(storage, tuple); } template <std::size_t N, std::size_t Offset, typename TypesTuple, typename ArgsTuple> static void executeHelper (Storage<Ts...>*, const ArgsTuple&) {} // End of recursion. template <std::size_t N, std::size_t Offset, typename TypesTuple, typename ArgsTuple, std::size_t... Is> static void add (Storage<Ts...>* storage, const ArgsTuple& tuple, std::index_sequence<Is...>) { storage->template addItem<std::tuple_element_t<N, TypesTuple>>(std::get<Offset + Is>(tuple)...); } }; // Testing struct Object { int a; bool b; char c; double d; using argument_type = std::tuple<int, bool, char, double>; }; struct Thing { int a, b; char c; using argument_type = std::tuple<int, int, char>; }; struct Number { int num; using argument_type = std::tuple<int>; }; struct SemiObject { int a; bool b; char c; using argument_type = std::tuple<int, bool, char>; }; int main() { Storage<Number, SemiObject, Object, Thing> storage; storage.addDifferentTypes (1,true,'a',3.5, 1,2,'t', 5,6,'p', 3,false,'b',1.8, 3,true,'t', 8, 3, 4,5,'s'); // Object, Thing, Thing, Object, SemiObject, Number, Number, Thing std::cout << "Objects: " << storage.get<Object>().size() << '\n'; // 2 std::cout << "Things: " << storage.get<Thing>().size() << '\n'; // 3 std::cout << "Numbers: " << storage.get<Number>().size() << '\n'; // 2 std::cout << "SemiObjects: " << storage.get<SemiObject>().size() << '\n'; // 1 } 来实现。我不太熟悉它的用例或语法,所以我没有任何例子。

文档似乎用变量名描述了这种用法。它还可能取决于我们正在谈论的node.js的版本。

https://nodejs.org/api/debugger.html#debugger_info

答案 1 :(得分:0)

使用Object.defineProperty。例如:

function setter () { debugger; }

Object.defineProperty(Math, 'name', { set: setter });
如果在name对象上设置了Math属性,

将添加调试器语句。

<强>参考