• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "base_object-inl.h"
2 #include "env-inl.h"
3 #include "memory_tracker-inl.h"
4 #include "node.h"
5 #include "node_external_reference.h"
6 #include "node_internals.h"
7 #include "node_v8_platform-inl.h"
8 #include "tracing/agent.h"
9 #include "util-inl.h"
10 
11 #include <set>
12 #include <string>
13 
14 namespace node {
15 
16 class ExternalReferenceRegistry;
17 
18 using v8::Array;
19 using v8::Context;
20 using v8::Function;
21 using v8::FunctionCallbackInfo;
22 using v8::FunctionTemplate;
23 using v8::Isolate;
24 using v8::Local;
25 using v8::NewStringType;
26 using v8::Object;
27 using v8::String;
28 using v8::Value;
29 
30 class NodeCategorySet : public BaseObject {
31  public:
32   static void Initialize(Local<Object> target,
33                   Local<Value> unused,
34                   Local<Context> context,
35                   void* priv);
36   static void RegisterExternalReferences(ExternalReferenceRegistry* registry);
37   static void New(const FunctionCallbackInfo<Value>& args);
38   static void Enable(const FunctionCallbackInfo<Value>& args);
39   static void Disable(const FunctionCallbackInfo<Value>& args);
40 
GetCategories() const41   const std::set<std::string>& GetCategories() const { return categories_; }
42 
MemoryInfo(MemoryTracker * tracker) const43   void MemoryInfo(MemoryTracker* tracker) const override {
44     tracker->TrackField("categories", categories_);
45   }
46 
47   SET_MEMORY_INFO_NAME(NodeCategorySet)
48   SET_SELF_SIZE(NodeCategorySet)
49 
50  private:
NodeCategorySet(Environment * env,Local<Object> wrap,std::set<std::string> && categories)51   NodeCategorySet(Environment* env,
52                   Local<Object> wrap,
53                   std::set<std::string>&& categories) :
54         BaseObject(env, wrap), categories_(std::move(categories)) {
55     MakeWeak();
56   }
57 
58   bool enabled_ = false;
59   const std::set<std::string> categories_;
60 };
61 
New(const FunctionCallbackInfo<Value> & args)62 void NodeCategorySet::New(const FunctionCallbackInfo<Value>& args) {
63   Environment* env = Environment::GetCurrent(args);
64   std::set<std::string> categories;
65   CHECK(args[0]->IsArray());
66   Local<Array> cats = args[0].As<Array>();
67   for (size_t n = 0; n < cats->Length(); n++) {
68     Local<Value> category;
69     if (!cats->Get(env->context(), n).ToLocal(&category)) return;
70     Utf8Value val(env->isolate(), category);
71     if (!*val) return;
72     categories.emplace(*val);
73   }
74   CHECK_NOT_NULL(GetTracingAgentWriter());
75   new NodeCategorySet(env, args.This(), std::move(categories));
76 }
77 
Enable(const FunctionCallbackInfo<Value> & args)78 void NodeCategorySet::Enable(const FunctionCallbackInfo<Value>& args) {
79   NodeCategorySet* category_set;
80   ASSIGN_OR_RETURN_UNWRAP(&category_set, args.Holder());
81   CHECK_NOT_NULL(category_set);
82   const auto& categories = category_set->GetCategories();
83   if (!category_set->enabled_ && !categories.empty()) {
84     // Starts the Tracing Agent if it wasn't started already (e.g. through
85     // a command line flag.)
86     StartTracingAgent();
87     GetTracingAgentWriter()->Enable(categories);
88     category_set->enabled_ = true;
89   }
90 }
91 
Disable(const FunctionCallbackInfo<Value> & args)92 void NodeCategorySet::Disable(const FunctionCallbackInfo<Value>& args) {
93   NodeCategorySet* category_set;
94   ASSIGN_OR_RETURN_UNWRAP(&category_set, args.Holder());
95   CHECK_NOT_NULL(category_set);
96   const auto& categories = category_set->GetCategories();
97   if (category_set->enabled_ && !categories.empty()) {
98     GetTracingAgentWriter()->Disable(categories);
99     category_set->enabled_ = false;
100   }
101 }
102 
GetEnabledCategories(const FunctionCallbackInfo<Value> & args)103 void GetEnabledCategories(const FunctionCallbackInfo<Value>& args) {
104   Environment* env = Environment::GetCurrent(args);
105   std::string categories =
106       GetTracingAgentWriter()->agent()->GetEnabledCategories();
107   if (!categories.empty()) {
108     args.GetReturnValue().Set(
109       String::NewFromUtf8(env->isolate(),
110                           categories.c_str(),
111                           NewStringType::kNormal,
112                           categories.size()).ToLocalChecked());
113   }
114 }
115 
SetTraceCategoryStateUpdateHandler(const FunctionCallbackInfo<Value> & args)116 static void SetTraceCategoryStateUpdateHandler(
117     const FunctionCallbackInfo<Value>& args) {
118   Environment* env = Environment::GetCurrent(args);
119   CHECK(args[0]->IsFunction());
120   env->set_trace_category_state_function(args[0].As<Function>());
121 }
122 
Initialize(Local<Object> target,Local<Value> unused,Local<Context> context,void * priv)123 void NodeCategorySet::Initialize(Local<Object> target,
124                 Local<Value> unused,
125                 Local<Context> context,
126                 void* priv) {
127   Environment* env = Environment::GetCurrent(context);
128   Isolate* isolate = env->isolate();
129 
130   SetMethod(context, target, "getEnabledCategories", GetEnabledCategories);
131   SetMethod(context,
132             target,
133             "setTraceCategoryStateUpdateHandler",
134             SetTraceCategoryStateUpdateHandler);
135 
136   Local<FunctionTemplate> category_set =
137       NewFunctionTemplate(isolate, NodeCategorySet::New);
138   category_set->InstanceTemplate()->SetInternalFieldCount(
139       NodeCategorySet::kInternalFieldCount);
140   category_set->Inherit(BaseObject::GetConstructorTemplate(env));
141   SetProtoMethod(isolate, category_set, "enable", NodeCategorySet::Enable);
142   SetProtoMethod(isolate, category_set, "disable", NodeCategorySet::Disable);
143 
144   SetConstructorFunction(context, target, "CategorySet", category_set);
145 
146   Local<String> isTraceCategoryEnabled =
147       FIXED_ONE_BYTE_STRING(env->isolate(), "isTraceCategoryEnabled");
148   Local<String> trace = FIXED_ONE_BYTE_STRING(env->isolate(), "trace");
149 
150   // Grab the trace and isTraceCategoryEnabled intrinsics from the binding
151   // object and expose those to our binding layer.
152   Local<Object> binding = context->GetExtrasBindingObject();
153   target->Set(context, isTraceCategoryEnabled,
154               binding->Get(context, isTraceCategoryEnabled).ToLocalChecked())
155                   .Check();
156   target->Set(context, trace,
157               binding->Get(context, trace).ToLocalChecked()).Check();
158 }
159 
RegisterExternalReferences(ExternalReferenceRegistry * registry)160 void NodeCategorySet::RegisterExternalReferences(
161     ExternalReferenceRegistry* registry) {
162   registry->Register(GetEnabledCategories);
163   registry->Register(SetTraceCategoryStateUpdateHandler);
164   registry->Register(NodeCategorySet::New);
165   registry->Register(NodeCategorySet::Enable);
166   registry->Register(NodeCategorySet::Disable);
167 }
168 
169 }  // namespace node
170 
171 NODE_BINDING_CONTEXT_AWARE_INTERNAL(trace_events,
172                                     node::NodeCategorySet::Initialize)
173 NODE_BINDING_EXTERNAL_REFERENCE(
174     trace_events, node::NodeCategorySet::RegisterExternalReferences)
175