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调试器实现吗?
答案 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的版本。
答案 1 :(得分:0)
使用Object.defineProperty
。例如:
function setter () { debugger; }
Object.defineProperty(Math, 'name', { set: setter });
如果在name
对象上设置了Math
属性,将添加调试器语句。
<强>参考强>