/src/node/src/inspector_js_api.cc
Line | Count | Source |
1 | | #include "base_object-inl.h" |
2 | | #include "inspector/network_resource_manager.h" |
3 | | #include "inspector/protocol_helper.h" |
4 | | #include "inspector_agent.h" |
5 | | #include "inspector_io.h" |
6 | | #include "memory_tracker-inl.h" |
7 | | #include "node_external_reference.h" |
8 | | #include "util-inl.h" |
9 | | #include "v8-inspector.h" |
10 | | #include "v8.h" |
11 | | |
12 | | #include <memory> |
13 | | |
14 | | namespace node { |
15 | | namespace inspector { |
16 | | namespace { |
17 | | |
18 | | using v8::Context; |
19 | | using v8::Function; |
20 | | using v8::FunctionCallbackInfo; |
21 | | using v8::FunctionTemplate; |
22 | | using v8::Global; |
23 | | using v8::HandleScope; |
24 | | using v8::Isolate; |
25 | | using v8::Local; |
26 | | using v8::MaybeLocal; |
27 | | using v8::Object; |
28 | | using v8::String; |
29 | | using v8::Uint32; |
30 | | using v8::Value; |
31 | | using v8_inspector::StringView; |
32 | | |
33 | | struct LocalConnection { |
34 | | static std::unique_ptr<InspectorSession> Connect( |
35 | 0 | Agent* inspector, std::unique_ptr<InspectorSessionDelegate> delegate) { |
36 | 0 | return inspector->Connect(std::move(delegate), false); |
37 | 0 | } |
38 | | |
39 | 35 | static Local<String> GetClassName(Environment* env) { |
40 | 35 | return FIXED_ONE_BYTE_STRING(env->isolate(), "Connection"); |
41 | 35 | } |
42 | | }; |
43 | | |
44 | | struct MainThreadConnection { |
45 | | static std::unique_ptr<InspectorSession> Connect( |
46 | 0 | Agent* inspector, std::unique_ptr<InspectorSessionDelegate> delegate) { |
47 | 0 | return inspector->ConnectToMainThread(std::move(delegate), true); |
48 | 0 | } |
49 | | |
50 | 35 | static Local<String> GetClassName(Environment* env) { |
51 | 35 | return FIXED_ONE_BYTE_STRING(env->isolate(), "MainThreadConnection"); |
52 | 35 | } |
53 | | }; |
54 | | |
55 | | template <typename ConnectionType> |
56 | | class JSBindingsConnection : public BaseObject { |
57 | | public: |
58 | | class JSBindingsSessionDelegate : public InspectorSessionDelegate { |
59 | | public: |
60 | | JSBindingsSessionDelegate(Environment* env, |
61 | | JSBindingsConnection* connection) |
62 | 0 | : env_(env), |
63 | 0 | connection_(connection) { |
64 | 0 | } Unexecuted instantiation: inspector_js_api.cc:node::inspector::(anonymous namespace)::JSBindingsConnection<node::inspector::(anonymous namespace)::LocalConnection>::JSBindingsSessionDelegate::JSBindingsSessionDelegate(node::Environment*, node::inspector::(anonymous namespace)::JSBindingsConnection<node::inspector::(anonymous namespace)::LocalConnection>*) Unexecuted instantiation: inspector_js_api.cc:node::inspector::(anonymous namespace)::JSBindingsConnection<node::inspector::(anonymous namespace)::MainThreadConnection>::JSBindingsSessionDelegate::JSBindingsSessionDelegate(node::Environment*, node::inspector::(anonymous namespace)::JSBindingsConnection<node::inspector::(anonymous namespace)::MainThreadConnection>*) |
65 | | |
66 | | void SendMessageToFrontend(const v8_inspector::StringView& message) |
67 | 0 | override { |
68 | 0 | Isolate* isolate = env_->isolate(); |
69 | 0 | HandleScope handle_scope(isolate); |
70 | 0 | Context::Scope context_scope(env_->context()); |
71 | 0 | Local<Value> argument; |
72 | 0 | if (!ToV8Value(env_->context(), message, isolate).ToLocal(&argument)) |
73 | 0 | return; |
74 | 0 | connection_->OnMessage(argument); |
75 | 0 | } Unexecuted instantiation: inspector_js_api.cc:node::inspector::(anonymous namespace)::JSBindingsConnection<node::inspector::(anonymous namespace)::LocalConnection>::JSBindingsSessionDelegate::SendMessageToFrontend(v8_inspector::StringView const&) Unexecuted instantiation: inspector_js_api.cc:node::inspector::(anonymous namespace)::JSBindingsConnection<node::inspector::(anonymous namespace)::MainThreadConnection>::JSBindingsSessionDelegate::SendMessageToFrontend(v8_inspector::StringView const&) |
76 | | |
77 | | private: |
78 | | Environment* env_; |
79 | | BaseObjectPtr<JSBindingsConnection> connection_; |
80 | | }; |
81 | | |
82 | | JSBindingsConnection(Environment* env, |
83 | | Local<Object> wrap, |
84 | | Local<Function> callback) |
85 | 0 | : BaseObject(env, wrap), callback_(env->isolate(), callback) { |
86 | 0 | Agent* inspector = env->inspector_agent(); |
87 | 0 | session_ = ConnectionType::Connect( |
88 | 0 | inspector, std::make_unique<JSBindingsSessionDelegate>(env, this)); |
89 | 0 | } Unexecuted instantiation: inspector_js_api.cc:node::inspector::(anonymous namespace)::JSBindingsConnection<node::inspector::(anonymous namespace)::LocalConnection>::JSBindingsConnection(node::Environment*, v8::Local<v8::Object>, v8::Local<v8::Function>) Unexecuted instantiation: inspector_js_api.cc:node::inspector::(anonymous namespace)::JSBindingsConnection<node::inspector::(anonymous namespace)::MainThreadConnection>::JSBindingsConnection(node::Environment*, v8::Local<v8::Object>, v8::Local<v8::Function>) |
90 | | |
91 | 0 | void OnMessage(Local<Value> value) { |
92 | 0 | auto result = callback_.Get(env()->isolate()) |
93 | 0 | ->Call(env()->context(), object(), 1, &value); |
94 | 0 | (void)result; |
95 | 0 | } Unexecuted instantiation: inspector_js_api.cc:node::inspector::(anonymous namespace)::JSBindingsConnection<node::inspector::(anonymous namespace)::LocalConnection>::OnMessage(v8::Local<v8::Value>) Unexecuted instantiation: inspector_js_api.cc:node::inspector::(anonymous namespace)::JSBindingsConnection<node::inspector::(anonymous namespace)::MainThreadConnection>::OnMessage(v8::Local<v8::Value>) |
96 | | |
97 | 70 | static void Bind(Environment* env, Local<Object> target) { |
98 | 70 | Isolate* isolate = env->isolate(); |
99 | 70 | Local<FunctionTemplate> tmpl = |
100 | 70 | NewFunctionTemplate(isolate, JSBindingsConnection::New); |
101 | 70 | tmpl->InstanceTemplate()->SetInternalFieldCount( |
102 | 70 | JSBindingsConnection::kInternalFieldCount); |
103 | 70 | SetProtoMethod(isolate, tmpl, "dispatch", JSBindingsConnection::Dispatch); |
104 | 70 | SetProtoMethod( |
105 | 70 | isolate, tmpl, "disconnect", JSBindingsConnection::Disconnect); |
106 | 70 | SetConstructorFunction( |
107 | 70 | env->context(), target, ConnectionType::GetClassName(env), tmpl); |
108 | 70 | } inspector_js_api.cc:node::inspector::(anonymous namespace)::JSBindingsConnection<node::inspector::(anonymous namespace)::LocalConnection>::Bind(node::Environment*, v8::Local<v8::Object>) Line | Count | Source | 97 | 35 | static void Bind(Environment* env, Local<Object> target) { | 98 | 35 | Isolate* isolate = env->isolate(); | 99 | 35 | Local<FunctionTemplate> tmpl = | 100 | 35 | NewFunctionTemplate(isolate, JSBindingsConnection::New); | 101 | 35 | tmpl->InstanceTemplate()->SetInternalFieldCount( | 102 | 35 | JSBindingsConnection::kInternalFieldCount); | 103 | 35 | SetProtoMethod(isolate, tmpl, "dispatch", JSBindingsConnection::Dispatch); | 104 | 35 | SetProtoMethod( | 105 | 35 | isolate, tmpl, "disconnect", JSBindingsConnection::Disconnect); | 106 | 35 | SetConstructorFunction( | 107 | 35 | env->context(), target, ConnectionType::GetClassName(env), tmpl); | 108 | 35 | } |
inspector_js_api.cc:node::inspector::(anonymous namespace)::JSBindingsConnection<node::inspector::(anonymous namespace)::MainThreadConnection>::Bind(node::Environment*, v8::Local<v8::Object>) Line | Count | Source | 97 | 35 | static void Bind(Environment* env, Local<Object> target) { | 98 | 35 | Isolate* isolate = env->isolate(); | 99 | 35 | Local<FunctionTemplate> tmpl = | 100 | 35 | NewFunctionTemplate(isolate, JSBindingsConnection::New); | 101 | 35 | tmpl->InstanceTemplate()->SetInternalFieldCount( | 102 | 35 | JSBindingsConnection::kInternalFieldCount); | 103 | 35 | SetProtoMethod(isolate, tmpl, "dispatch", JSBindingsConnection::Dispatch); | 104 | 35 | SetProtoMethod( | 105 | 35 | isolate, tmpl, "disconnect", JSBindingsConnection::Disconnect); | 106 | 35 | SetConstructorFunction( | 107 | 35 | env->context(), target, ConnectionType::GetClassName(env), tmpl); | 108 | 35 | } |
|
109 | | |
110 | 0 | static void New(const FunctionCallbackInfo<Value>& info) { |
111 | 0 | Environment* env = Environment::GetCurrent(info); |
112 | 0 | CHECK(info[0]->IsFunction()); |
113 | 0 | Local<Function> callback = info[0].As<Function>(); |
114 | 0 | new JSBindingsConnection(env, info.This(), callback); |
115 | 0 | } Unexecuted instantiation: inspector_js_api.cc:node::inspector::(anonymous namespace)::JSBindingsConnection<node::inspector::(anonymous namespace)::LocalConnection>::New(v8::FunctionCallbackInfo<v8::Value> const&) Unexecuted instantiation: inspector_js_api.cc:node::inspector::(anonymous namespace)::JSBindingsConnection<node::inspector::(anonymous namespace)::MainThreadConnection>::New(v8::FunctionCallbackInfo<v8::Value> const&) |
116 | | |
117 | | // See https://github.com/nodejs/node/pull/46942 |
118 | 0 | void Disconnect() { |
119 | 0 | BaseObjectPtr<JSBindingsConnection> strong_ref{this}; |
120 | 0 | session_.reset(); |
121 | 0 | Detach(); |
122 | 0 | } Unexecuted instantiation: inspector_js_api.cc:node::inspector::(anonymous namespace)::JSBindingsConnection<node::inspector::(anonymous namespace)::LocalConnection>::Disconnect() Unexecuted instantiation: inspector_js_api.cc:node::inspector::(anonymous namespace)::JSBindingsConnection<node::inspector::(anonymous namespace)::MainThreadConnection>::Disconnect() |
123 | | |
124 | 0 | static void Disconnect(const FunctionCallbackInfo<Value>& info) { |
125 | 0 | JSBindingsConnection* session; |
126 | 0 | ASSIGN_OR_RETURN_UNWRAP(&session, info.This()); |
127 | 0 | session->Disconnect(); |
128 | 0 | } Unexecuted instantiation: inspector_js_api.cc:node::inspector::(anonymous namespace)::JSBindingsConnection<node::inspector::(anonymous namespace)::LocalConnection>::Disconnect(v8::FunctionCallbackInfo<v8::Value> const&) Unexecuted instantiation: inspector_js_api.cc:node::inspector::(anonymous namespace)::JSBindingsConnection<node::inspector::(anonymous namespace)::MainThreadConnection>::Disconnect(v8::FunctionCallbackInfo<v8::Value> const&) |
129 | | |
130 | 0 | static void Dispatch(const FunctionCallbackInfo<Value>& info) { |
131 | 0 | JSBindingsConnection* session; |
132 | 0 | ASSIGN_OR_RETURN_UNWRAP(&session, info.This()); |
133 | 0 | CHECK(info[0]->IsString()); |
134 | | |
135 | 0 | if (session->session_) { |
136 | 0 | session->session_->Dispatch( |
137 | 0 | ToInspectorString(info.GetIsolate(), info[0])->string()); |
138 | 0 | } |
139 | 0 | } Unexecuted instantiation: inspector_js_api.cc:node::inspector::(anonymous namespace)::JSBindingsConnection<node::inspector::(anonymous namespace)::LocalConnection>::Dispatch(v8::FunctionCallbackInfo<v8::Value> const&) Unexecuted instantiation: inspector_js_api.cc:node::inspector::(anonymous namespace)::JSBindingsConnection<node::inspector::(anonymous namespace)::MainThreadConnection>::Dispatch(v8::FunctionCallbackInfo<v8::Value> const&) |
140 | | |
141 | 0 | void MemoryInfo(MemoryTracker* tracker) const override { |
142 | 0 | tracker->TrackField("callback", callback_); |
143 | 0 | tracker->TrackFieldWithSize( |
144 | 0 | "session", sizeof(*session_), "InspectorSession"); |
145 | 0 | } Unexecuted instantiation: inspector_js_api.cc:node::inspector::(anonymous namespace)::JSBindingsConnection<node::inspector::(anonymous namespace)::LocalConnection>::MemoryInfo(node::MemoryTracker*) const Unexecuted instantiation: inspector_js_api.cc:node::inspector::(anonymous namespace)::JSBindingsConnection<node::inspector::(anonymous namespace)::MainThreadConnection>::MemoryInfo(node::MemoryTracker*) const |
146 | | |
147 | | SET_MEMORY_INFO_NAME(JSBindingsConnection) |
148 | | SET_SELF_SIZE(JSBindingsConnection) |
149 | | |
150 | 0 | bool IsNotIndicativeOfMemoryLeakAtExit() const override { |
151 | 0 | return true; // Binding connections emit events on their own. |
152 | 0 | } Unexecuted instantiation: inspector_js_api.cc:node::inspector::(anonymous namespace)::JSBindingsConnection<node::inspector::(anonymous namespace)::LocalConnection>::IsNotIndicativeOfMemoryLeakAtExit() const Unexecuted instantiation: inspector_js_api.cc:node::inspector::(anonymous namespace)::JSBindingsConnection<node::inspector::(anonymous namespace)::MainThreadConnection>::IsNotIndicativeOfMemoryLeakAtExit() const |
153 | | |
154 | | private: |
155 | | std::unique_ptr<InspectorSession> session_; |
156 | | Global<Function> callback_; |
157 | | }; |
158 | | |
159 | 0 | static bool InspectorEnabled(Environment* env) { |
160 | 0 | Agent* agent = env->inspector_agent(); |
161 | 0 | return agent->IsActive(); |
162 | 0 | } |
163 | | |
164 | 35 | void SetConsoleExtensionInstaller(const FunctionCallbackInfo<Value>& info) { |
165 | 35 | Realm* realm = Realm::GetCurrent(info); |
166 | | |
167 | 35 | CHECK_EQ(info.Length(), 1); |
168 | 35 | CHECK(info[0]->IsFunction()); |
169 | | |
170 | 35 | realm->set_inspector_console_extension_installer(info[0].As<Function>()); |
171 | 35 | } |
172 | | |
173 | 0 | void CallAndPauseOnStart(const FunctionCallbackInfo<v8::Value>& args) { |
174 | 0 | Environment* env = Environment::GetCurrent(args); |
175 | 0 | THROW_IF_INSUFFICIENT_PERMISSIONS(env, |
176 | 0 | permission::PermissionScope::kInspector, |
177 | 0 | "PauseOnNextJavascriptStatement"); |
178 | 0 | CHECK_GT(args.Length(), 1); |
179 | 0 | CHECK(args[0]->IsFunction()); |
180 | 0 | SlicedArguments call_args(args, /* start */ 2); |
181 | 0 | env->inspector_agent()->PauseOnNextJavascriptStatement("Break on start"); |
182 | 0 | Local<Value> ret; |
183 | 0 | if (args[0] |
184 | 0 | .As<v8::Function>() |
185 | 0 | ->Call(env->context(), args[1], call_args.length(), call_args.out()) |
186 | 0 | .ToLocal(&ret)) { |
187 | 0 | args.GetReturnValue().Set(ret); |
188 | 0 | } |
189 | 0 | } |
190 | | |
191 | 0 | void InspectorConsoleCall(const FunctionCallbackInfo<Value>& info) { |
192 | 0 | Environment* env = Environment::GetCurrent(info); |
193 | 0 | Isolate* isolate = env->isolate(); |
194 | 0 | Local<Context> context = isolate->GetCurrentContext(); |
195 | 0 | CHECK_GE(info.Length(), 2); |
196 | 0 | SlicedArguments call_args(info, /* start */ 2); |
197 | 0 | if (InspectorEnabled(env)) { |
198 | 0 | Local<Value> inspector_method = info[0]; |
199 | 0 | CHECK(inspector_method->IsFunction()); |
200 | 0 | if (!env->is_in_inspector_console_call()) { |
201 | 0 | env->set_is_in_inspector_console_call(true); |
202 | 0 | MaybeLocal<Value> ret = inspector_method.As<Function>()->Call( |
203 | 0 | context, info.This(), call_args.length(), call_args.out()); |
204 | 0 | env->set_is_in_inspector_console_call(false); |
205 | 0 | if (ret.IsEmpty()) |
206 | 0 | return; |
207 | 0 | } |
208 | 0 | } |
209 | | |
210 | 0 | Local<Value> node_method = info[1]; |
211 | 0 | CHECK(node_method->IsFunction()); |
212 | 0 | USE(node_method.As<Function>()->Call( |
213 | 0 | context, info.This(), call_args.length(), call_args.out())); |
214 | 0 | } |
215 | | |
216 | 0 | static void* GetAsyncTask(int64_t asyncId) { |
217 | | // The inspector assumes that when other clients use its asyncTask* API, |
218 | | // they use real pointers, or at least something aligned like real pointer. |
219 | | // In general it means that our task_id should always be even. |
220 | | // |
221 | | // On 32bit platforms, the 64bit asyncId would get truncated when converted |
222 | | // to a 32bit pointer. However, the javascript part will never enable |
223 | | // the async_hook on 32bit platforms, therefore the truncation will never |
224 | | // happen in practice. |
225 | 0 | return reinterpret_cast<void*>(asyncId << 1); |
226 | 0 | } |
227 | | |
228 | | template <void (Agent::*asyncTaskFn)(void*)> |
229 | 0 | static void InvokeAsyncTaskFnWithId(const FunctionCallbackInfo<Value>& args) { |
230 | 0 | Environment* env = Environment::GetCurrent(args); |
231 | 0 | CHECK(args[0]->IsNumber()); |
232 | 0 | int64_t task_id; |
233 | 0 | if (args[0]->IntegerValue(env->context()).To(&task_id)) { |
234 | 0 | (env->inspector_agent()->*asyncTaskFn)(GetAsyncTask(task_id)); |
235 | 0 | } |
236 | 0 | } Unexecuted instantiation: inspector_js_api.cc:void node::inspector::(anonymous namespace)::InvokeAsyncTaskFnWithId<&node::inspector::Agent::AsyncTaskCanceled>(v8::FunctionCallbackInfo<v8::Value> const&) Unexecuted instantiation: inspector_js_api.cc:void node::inspector::(anonymous namespace)::InvokeAsyncTaskFnWithId<&node::inspector::Agent::AsyncTaskStarted>(v8::FunctionCallbackInfo<v8::Value> const&) Unexecuted instantiation: inspector_js_api.cc:void node::inspector::(anonymous namespace)::InvokeAsyncTaskFnWithId<&node::inspector::Agent::AsyncTaskFinished>(v8::FunctionCallbackInfo<v8::Value> const&) |
237 | | |
238 | 0 | static void AsyncTaskScheduledWrapper(const FunctionCallbackInfo<Value>& args) { |
239 | 0 | Environment* env = Environment::GetCurrent(args); |
240 | |
|
241 | 0 | CHECK(args[0]->IsString()); |
242 | 0 | Local<String> task_name = args[0].As<String>(); |
243 | 0 | TwoByteValue task_name_value(args.GetIsolate(), task_name); |
244 | 0 | StringView task_name_view(task_name_value.out(), task_name_value.length()); |
245 | |
|
246 | 0 | CHECK(args[1]->IsNumber()); |
247 | 0 | int64_t task_id; |
248 | 0 | if (!args[1]->IntegerValue(env->context()).To(&task_id)) { |
249 | 0 | return; |
250 | 0 | } |
251 | 0 | void* task = GetAsyncTask(task_id); |
252 | |
|
253 | 0 | CHECK(args[2]->IsBoolean()); |
254 | 0 | bool recurring = args[2]->BooleanValue(args.GetIsolate()); |
255 | |
|
256 | 0 | env->inspector_agent()->AsyncTaskScheduled(task_name_view, task, recurring); |
257 | 0 | } |
258 | | |
259 | 35 | static void RegisterAsyncHookWrapper(const FunctionCallbackInfo<Value>& args) { |
260 | 35 | Environment* env = Environment::GetCurrent(args); |
261 | | |
262 | 35 | CHECK(args[0]->IsFunction()); |
263 | 35 | Local<Function> enable_function = args[0].As<Function>(); |
264 | 35 | CHECK(args[1]->IsFunction()); |
265 | 35 | Local<Function> disable_function = args[1].As<Function>(); |
266 | 35 | env->inspector_agent()->RegisterAsyncHook(env->isolate(), |
267 | 35 | enable_function, disable_function); |
268 | 35 | } |
269 | | |
270 | 0 | void EmitProtocolEvent(const FunctionCallbackInfo<Value>& args) { |
271 | 0 | Environment* env = Environment::GetCurrent(args); |
272 | 0 | CHECK(args[0]->IsString()); |
273 | 0 | Local<String> eventName = args[0].As<String>(); |
274 | 0 | CHECK(args[1]->IsObject()); |
275 | 0 | Local<Object> params = args[1].As<Object>(); |
276 | |
|
277 | 0 | env->inspector_agent()->EmitProtocolEvent( |
278 | 0 | args.GetIsolate()->GetCurrentContext(), |
279 | 0 | ToInspectorString(env->isolate(), eventName)->string(), |
280 | 0 | params); |
281 | 0 | } |
282 | | |
283 | 0 | void SetupNetworkTracking(const FunctionCallbackInfo<Value>& args) { |
284 | 0 | Environment* env = Environment::GetCurrent(args); |
285 | |
|
286 | 0 | CHECK(args[0]->IsFunction()); |
287 | 0 | Local<Function> enable_function = args[0].As<Function>(); |
288 | 0 | CHECK(args[1]->IsFunction()); |
289 | 0 | Local<Function> disable_function = args[1].As<Function>(); |
290 | |
|
291 | 0 | env->inspector_agent()->SetupNetworkTracking(enable_function, |
292 | 0 | disable_function); |
293 | 0 | } |
294 | | |
295 | 0 | void IsEnabled(const FunctionCallbackInfo<Value>& args) { |
296 | 0 | Environment* env = Environment::GetCurrent(args); |
297 | 0 | args.GetReturnValue().Set(env->inspector_agent()->IsListening()); |
298 | 0 | } |
299 | | |
300 | 0 | void Open(const FunctionCallbackInfo<Value>& args) { |
301 | 0 | Environment* env = Environment::GetCurrent(args); |
302 | 0 | Agent* agent = env->inspector_agent(); |
303 | |
|
304 | 0 | if (args.Length() > 0 && args[0]->IsUint32()) { |
305 | 0 | uint32_t port = args[0].As<Uint32>()->Value(); |
306 | 0 | CHECK_LE(port, std::numeric_limits<uint16_t>::max()); |
307 | 0 | ExclusiveAccess<HostPort>::Scoped host_port(agent->host_port()); |
308 | 0 | host_port->set_port(static_cast<int>(port)); |
309 | 0 | } |
310 | | |
311 | 0 | if (args.Length() > 1 && args[1]->IsString()) { |
312 | 0 | Utf8Value host(env->isolate(), args[1].As<String>()); |
313 | 0 | ExclusiveAccess<HostPort>::Scoped host_port(agent->host_port()); |
314 | 0 | host_port->set_host(*host); |
315 | 0 | } |
316 | |
|
317 | 0 | agent->StartIoThread(); |
318 | 0 | } |
319 | | |
320 | 0 | void WaitForDebugger(const FunctionCallbackInfo<Value>& args) { |
321 | 0 | Environment* env = Environment::GetCurrent(args); |
322 | 0 | Agent* agent = env->inspector_agent(); |
323 | 0 | if (agent->IsActive()) |
324 | 0 | agent->WaitForConnect(); |
325 | 0 | args.GetReturnValue().Set(agent->IsActive()); |
326 | 0 | } |
327 | | |
328 | 0 | void Url(const FunctionCallbackInfo<Value>& args) { |
329 | 0 | Environment* env = Environment::GetCurrent(args); |
330 | 0 | std::string url = env->inspector_agent()->GetWsUrl(); |
331 | 0 | if (url.empty()) { |
332 | 0 | return; |
333 | 0 | } |
334 | 0 | args.GetReturnValue().Set(OneByteString(env->isolate(), url)); |
335 | 0 | } |
336 | | |
337 | 0 | void PutNetworkResource(const v8::FunctionCallbackInfo<v8::Value>& args) { |
338 | 0 | Environment* env = Environment::GetCurrent(args); |
339 | 0 | CHECK_GE(args.Length(), 2); |
340 | 0 | CHECK(args[0]->IsString()); |
341 | 0 | CHECK(args[1]->IsString()); |
342 | | |
343 | 0 | Utf8Value url(env->isolate(), args[0].As<String>()); |
344 | 0 | Utf8Value data(env->isolate(), args[1].As<String>()); |
345 | |
|
346 | 0 | env->inspector_agent()->GetNetworkResourceManager()->Put(*url, *data); |
347 | 0 | } |
348 | | |
349 | | void Initialize(Local<Object> target, Local<Value> unused, |
350 | 35 | Local<Context> context, void* priv) { |
351 | 35 | Environment* env = Environment::GetCurrent(context); |
352 | 35 | Isolate* isolate = env->isolate(); |
353 | | |
354 | 35 | v8::Local<v8::Function> consoleCallFunc = |
355 | 35 | NewFunctionTemplate(isolate, |
356 | 35 | InspectorConsoleCall, |
357 | 35 | v8::Local<v8::Signature>(), |
358 | 35 | v8::ConstructorBehavior::kThrow, |
359 | 35 | v8::SideEffectType::kHasSideEffect) |
360 | 35 | ->GetFunction(context) |
361 | 35 | .ToLocalChecked(); |
362 | 35 | auto name_string = FIXED_ONE_BYTE_STRING(isolate, "consoleCall"); |
363 | 35 | target->Set(context, name_string, consoleCallFunc).Check(); |
364 | 35 | consoleCallFunc->SetName(name_string); |
365 | | |
366 | 35 | SetMethod(context, |
367 | 35 | target, |
368 | 35 | "setConsoleExtensionInstaller", |
369 | 35 | SetConsoleExtensionInstaller); |
370 | 35 | SetMethod(context, target, "callAndPauseOnStart", CallAndPauseOnStart); |
371 | 35 | SetMethod(context, target, "open", Open); |
372 | 35 | SetMethodNoSideEffect(context, target, "url", Url); |
373 | 35 | SetMethod(context, target, "waitForDebugger", WaitForDebugger); |
374 | | |
375 | 35 | SetMethod(context, target, "asyncTaskScheduled", AsyncTaskScheduledWrapper); |
376 | 35 | SetMethod(context, |
377 | 35 | target, |
378 | 35 | "asyncTaskCanceled", |
379 | 35 | InvokeAsyncTaskFnWithId<&Agent::AsyncTaskCanceled>); |
380 | 35 | SetMethod(context, |
381 | 35 | target, |
382 | 35 | "asyncTaskStarted", |
383 | 35 | InvokeAsyncTaskFnWithId<&Agent::AsyncTaskStarted>); |
384 | 35 | SetMethod(context, |
385 | 35 | target, |
386 | 35 | "asyncTaskFinished", |
387 | 35 | InvokeAsyncTaskFnWithId<&Agent::AsyncTaskFinished>); |
388 | | |
389 | 35 | SetMethod(context, target, "registerAsyncHook", RegisterAsyncHookWrapper); |
390 | 35 | SetMethodNoSideEffect(context, target, "isEnabled", IsEnabled); |
391 | 35 | SetMethod(context, target, "emitProtocolEvent", EmitProtocolEvent); |
392 | 35 | SetMethod(context, target, "setupNetworkTracking", SetupNetworkTracking); |
393 | 35 | SetMethod(context, target, "putNetworkResource", PutNetworkResource); |
394 | | |
395 | 35 | Local<String> console_string = FIXED_ONE_BYTE_STRING(isolate, "console"); |
396 | | |
397 | | // Grab the console from the binding object and expose those to our binding |
398 | | // layer. |
399 | 35 | Local<Object> binding = context->GetExtrasBindingObject(); |
400 | 35 | target |
401 | 35 | ->Set(context, |
402 | 35 | console_string, |
403 | 35 | binding->Get(context, console_string).ToLocalChecked()) |
404 | 35 | .Check(); |
405 | | |
406 | 35 | JSBindingsConnection<LocalConnection>::Bind(env, target); |
407 | 35 | JSBindingsConnection<MainThreadConnection>::Bind(env, target); |
408 | 35 | } |
409 | | |
410 | | } // namespace |
411 | | |
412 | 0 | void RegisterExternalReferences(ExternalReferenceRegistry* registry) { |
413 | 0 | registry->Register(InspectorConsoleCall); |
414 | 0 | registry->Register(SetConsoleExtensionInstaller); |
415 | 0 | registry->Register(CallAndPauseOnStart); |
416 | 0 | registry->Register(Open); |
417 | 0 | registry->Register(Url); |
418 | 0 | registry->Register(WaitForDebugger); |
419 | |
|
420 | 0 | registry->Register(AsyncTaskScheduledWrapper); |
421 | 0 | registry->Register(InvokeAsyncTaskFnWithId<&Agent::AsyncTaskCanceled>); |
422 | 0 | registry->Register(InvokeAsyncTaskFnWithId<&Agent::AsyncTaskStarted>); |
423 | 0 | registry->Register(InvokeAsyncTaskFnWithId<&Agent::AsyncTaskFinished>); |
424 | |
|
425 | 0 | registry->Register(RegisterAsyncHookWrapper); |
426 | 0 | registry->Register(IsEnabled); |
427 | 0 | registry->Register(EmitProtocolEvent); |
428 | 0 | registry->Register(SetupNetworkTracking); |
429 | |
|
430 | 0 | registry->Register(JSBindingsConnection<LocalConnection>::New); |
431 | 0 | registry->Register(JSBindingsConnection<LocalConnection>::Dispatch); |
432 | 0 | registry->Register(JSBindingsConnection<LocalConnection>::Disconnect); |
433 | 0 | registry->Register(JSBindingsConnection<MainThreadConnection>::New); |
434 | 0 | registry->Register(JSBindingsConnection<MainThreadConnection>::Dispatch); |
435 | 0 | registry->Register(JSBindingsConnection<MainThreadConnection>::Disconnect); |
436 | 0 | registry->Register(PutNetworkResource); |
437 | 0 | } |
438 | | |
439 | | } // namespace inspector |
440 | | } // namespace node |
441 | | |
442 | | NODE_BINDING_CONTEXT_AWARE_INTERNAL(inspector, node::inspector::Initialize) |
443 | | NODE_BINDING_EXTERNAL_REFERENCE(inspector, |
444 | | node::inspector::RegisterExternalReferences) |