7 #include "v8-inspector.h" 8 #include "v8-platform.h" 12 #include "libplatform/libplatform.h" 16 #include <unordered_map> 34 using v8::FunctionCallbackInfo;
35 using v8::HandleScope;
42 using v8::NewStringType;
49 using v8_inspector::StringBuffer;
50 using v8_inspector::StringView;
51 using v8_inspector::V8Inspector;
52 using v8_inspector::V8InspectorClient;
54 static uv_sem_t start_io_thread_semaphore;
55 static uv_async_t start_io_thread_async;
57 class StartIoTask :
public v8::Task {
59 explicit StartIoTask(
Agent* agent) : agent(agent) {}
69 std::unique_ptr<StringBuffer> ToProtocolString(Isolate* isolate,
71 TwoByteValue buffer(isolate, value);
72 return StringBuffer::create(StringView(*buffer, buffer.length()));
76 void StartIoThreadAsyncCallback(uv_async_t* handle) {
77 static_cast<Agent*
>(handle->data)->StartIoThread(
false);
80 void StartIoInterrupt(Isolate* isolate,
void* agent) {
81 static_cast<Agent*
>(agent)->StartIoThread(
false);
86 static void StartIoThreadWakeup(
int signo) {
87 uv_sem_post(&start_io_thread_semaphore);
90 inline void* StartIoThreadMain(
void* unused) {
92 uv_sem_wait(&start_io_thread_semaphore);
93 Agent* agent =
static_cast<Agent*
>(start_io_thread_async.data);
100 static int StartDebugSignalHandler() {
104 CHECK_EQ(0, uv_sem_init(&start_io_thread_semaphore, 0));
106 CHECK_EQ(0, pthread_attr_init(&attr));
111 CHECK_EQ(0, pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN));
112 #endif // __FreeBSD__ 113 CHECK_EQ(0, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED));
116 sigfillset(&sigmask);
117 CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &sigmask, &sigmask));
119 const int err = pthread_create(&thread, &attr,
120 StartIoThreadMain,
nullptr);
122 CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &sigmask,
nullptr));
123 CHECK_EQ(0, pthread_attr_destroy(&attr));
125 fprintf(stderr,
"node[%d]: pthread_create: %s\n", getpid(), strerror(err));
131 RegisterSignalHandler(SIGUSR1, StartIoThreadWakeup);
133 sigemptyset(&sigmask);
134 sigaddset(&sigmask, SIGUSR1);
135 CHECK_EQ(0, pthread_sigmask(SIG_UNBLOCK, &sigmask,
nullptr));
142 DWORD WINAPI StartIoThreadProc(
void* arg) {
143 Agent* agent =
static_cast<Agent*
>(start_io_thread_async.data);
144 if (agent !=
nullptr)
149 static int GetDebugSignalHandlerMappingName(DWORD pid,
wchar_t*
buf,
151 return _snwprintf(buf, buf_len, L
"node-debug-handler-%u", pid);
154 static int StartDebugSignalHandler() {
155 wchar_t mapping_name[32];
156 HANDLE mapping_handle;
158 LPTHREAD_START_ROUTINE* handler;
160 pid = GetCurrentProcessId();
162 if (GetDebugSignalHandlerMappingName(pid,
164 arraysize(mapping_name)) < 0) {
168 mapping_handle = CreateFileMappingW(INVALID_HANDLE_VALUE,
174 if (mapping_handle ==
nullptr) {
178 handler =
reinterpret_cast<LPTHREAD_START_ROUTINE*
>(
179 MapViewOfFile(mapping_handle,
184 if (handler ==
nullptr) {
185 CloseHandle(mapping_handle);
189 *handler = StartIoThreadProc;
191 UnmapViewOfFile(static_cast<void*>(handler));
199 JsBindingsSessionDelegate(Environment* env,
200 Local<Object> session,
201 Local<Object> receiver,
202 Local<Function> callback)
204 session_(env->isolate(), session),
205 receiver_(env->isolate(), receiver),
206 callback_(env->isolate(), callback) {
207 session_.SetWeak(
this, JsBindingsSessionDelegate::Release,
208 v8::WeakCallbackType::kParameter);
211 ~JsBindingsSessionDelegate()
override {
217 bool WaitForFrontendMessageWhilePaused()
override {
221 void SendMessageToFrontend(
const v8_inspector::StringView& message)
override {
222 Isolate* isolate =
env_->isolate();
223 v8::HandleScope handle_scope(isolate);
224 Context::Scope context_scope(
env_->context());
225 MaybeLocal<String> v8string =
226 String::NewFromTwoByte(isolate, message.characters16(),
227 NewStringType::kNormal, message.length());
228 Local<Value> argument = v8string.ToLocalChecked().As<Value>();
229 Local<Function> callback = callback_.Get(isolate);
230 Local<Object> receiver = receiver_.Get(isolate);
231 callback->Call(
env_->context(), receiver, 1, &argument)
232 .FromMaybe(Local<Value>());
243 const v8::WeakCallbackInfo<JsBindingsSessionDelegate>& info) {
244 info.SetSecondPassCallback(ReleaseSecondPass);
245 info.GetParameter()->session_.Reset();
248 static void ReleaseSecondPass(
249 const v8::WeakCallbackInfo<JsBindingsSessionDelegate>& info) {
250 JsBindingsSessionDelegate* delegate = info.GetParameter();
251 delegate->Disconnect();
256 Persistent<Object> session_;
257 Persistent<Object> receiver_;
258 Persistent<Function> callback_;
261 void SetDelegate(Environment* env, Local<Object> inspector,
262 JsBindingsSessionDelegate* delegate) {
263 inspector->SetPrivate(env->context(),
264 env->inspector_delegate_private_symbol(),
268 Maybe<JsBindingsSessionDelegate*> GetDelegate(
269 const FunctionCallbackInfo<Value>& info) {
270 Environment* env = Environment::GetCurrent(info);
271 Local<Value> delegate;
272 MaybeLocal<Value> maybe_delegate =
273 info.This()->GetPrivate(env->context(),
274 env->inspector_delegate_private_symbol());
276 if (maybe_delegate.ToLocal(&delegate)) {
277 CHECK(delegate->IsExternal());
278 void* value = delegate.As<External>()->Value();
279 if (value !=
nullptr) {
280 return v8::Just(static_cast<JsBindingsSessionDelegate*>(value));
283 env->ThrowError(
"Inspector is not connected");
284 return v8::Nothing<JsBindingsSessionDelegate*>();
287 void Dispatch(
const FunctionCallbackInfo<Value>& info) {
288 Environment* env = Environment::GetCurrent(info);
289 if (!info[0]->IsString()) {
290 env->ThrowError(
"Inspector message must be a string");
293 Maybe<JsBindingsSessionDelegate*> maybe_delegate = GetDelegate(info);
294 if (maybe_delegate.IsNothing())
296 Agent* inspector = env->inspector_agent();
297 CHECK_EQ(maybe_delegate.ToChecked(), inspector->
delegate());
298 inspector->
Dispatch(ToProtocolString(env->isolate(), info[0])->
string());
301 void Disconnect(
const FunctionCallbackInfo<Value>& info) {
302 Environment* env = Environment::GetCurrent(info);
303 Maybe<JsBindingsSessionDelegate*> delegate = GetDelegate(info);
304 if (delegate.IsNothing()) {
307 delegate.ToChecked()->Disconnect();
308 SetDelegate(env, info.This(),
nullptr);
309 delete delegate.ToChecked();
312 void ConnectJSBindingsSession(
const FunctionCallbackInfo<Value>& info) {
313 Environment* env = Environment::GetCurrent(info);
314 if (!info[0]->IsFunction()) {
315 env->ThrowError(
"Message callback is required");
318 Agent* inspector = env->inspector_agent();
319 if (inspector->
delegate() !=
nullptr) {
320 env->ThrowError(
"Session is already attached");
323 Local<Object> session =
Object::New(env->isolate());
324 env->SetMethod(session,
"dispatch", Dispatch);
325 env->SetMethod(session,
"disconnect", Disconnect);
326 info.GetReturnValue().Set(session);
328 JsBindingsSessionDelegate* delegate =
329 new JsBindingsSessionDelegate(env, session, info.Holder(),
330 info[0].As<Function>());
332 SetDelegate(env, session, delegate);
335 void InspectorConsoleCall(
const v8::FunctionCallbackInfo<Value>& info) {
336 Isolate* isolate = info.GetIsolate();
337 HandleScope handle_scope(isolate);
338 Local<Context> context = isolate->GetCurrentContext();
339 CHECK_LT(2, info.Length());
340 std::vector<Local<Value>> call_args;
341 for (
int i = 3; i < info.Length(); ++i) {
342 call_args.push_back(info[i]);
344 Environment* env = Environment::GetCurrent(isolate);
345 if (env->inspector_agent()->enabled()) {
346 Local<Value> inspector_method = info[0];
347 CHECK(inspector_method->IsFunction());
348 Local<Value> config_value = info[2];
349 CHECK(config_value->IsObject());
350 Local<Object> config_object = config_value.As<Object>();
351 Local<String> in_call_key = FIXED_ONE_BYTE_STRING(isolate,
"in_call");
352 if (!config_object->Has(context, in_call_key).FromMaybe(
false)) {
353 CHECK(config_object->Set(context,
355 v8::True(isolate)).FromJust());
356 CHECK(!inspector_method.As<Function>()->Call(context,
359 call_args.data()).IsEmpty());
361 CHECK(config_object->Delete(context, in_call_key).FromJust());
364 Local<Value> node_method = info[1];
365 CHECK(node_method->IsFunction());
366 node_method.As<Function>()->Call(context,
369 call_args.data()).FromMaybe(Local<Value>());
372 void CallAndPauseOnStart(
373 const v8::FunctionCallbackInfo<v8::Value>& args) {
374 Environment* env = Environment::GetCurrent(args);
375 CHECK_GT(args.Length(), 1);
376 CHECK(args[0]->IsFunction());
377 std::vector<v8::Local<v8::Value>> call_args;
378 for (
int i = 2; i < args.Length(); i++) {
379 call_args.push_back(args[i]);
382 env->inspector_agent()->PauseOnNextJavascriptStatement(
"Break on start");
383 v8::MaybeLocal<v8::Value> retval =
384 args[0].As<v8::Function>()->Call(env->context(), args[1],
385 call_args.size(), call_args.data());
386 if (!retval.IsEmpty()) {
387 args.GetReturnValue().Set(retval.ToLocalChecked());
392 const int NANOS_PER_MSEC = 1000000;
393 const int CONTEXT_GROUP_ID = 1;
395 class ChannelImpl final :
public v8_inspector::V8Inspector::Channel {
397 explicit ChannelImpl(V8Inspector* inspector,
399 : delegate_(delegate) {
400 session_ = inspector->connect(1,
this, StringView());
403 virtual ~ChannelImpl() {}
405 void dispatchProtocolMessage(
const StringView& message) {
406 session_->dispatchProtocolMessage(message);
409 bool waitForFrontendMessage() {
410 return delegate_->WaitForFrontendMessageWhilePaused();
413 void schedulePauseOnNextStatement(
const std::string& reason) {
415 session_->schedulePauseOnNextStatement(buffer->string(), buffer->string());
425 std::unique_ptr<v8_inspector::StringBuffer> message)
override {
426 sendMessageToFrontend(message->string());
429 void sendNotification(
430 std::unique_ptr<v8_inspector::StringBuffer> message)
override {
431 sendMessageToFrontend(message->string());
434 void flushProtocolNotifications()
override { }
436 void sendMessageToFrontend(
const StringView& message) {
437 delegate_->SendMessageToFrontend(message);
441 std::unique_ptr<v8_inspector::V8InspectorSession> session_;
444 class InspectorTimer {
446 InspectorTimer(uv_loop_t* loop,
448 V8InspectorClient::TimerCallback callback,
449 void*
data) : timer_(),
452 uv_timer_init(loop, &timer_);
453 int64_t interval_ms = 1000 * interval_s;
454 uv_timer_start(&timer_, OnTimer, interval_ms, interval_ms);
457 InspectorTimer(
const InspectorTimer&) =
delete;
460 uv_timer_stop(&timer_);
461 uv_close(reinterpret_cast<uv_handle_t*>(&timer_), TimerClosedCb);
465 static void OnTimer(uv_timer_t* uvtimer) {
466 InspectorTimer* timer = node::ContainerOf(&InspectorTimer::timer_, uvtimer);
467 timer->callback_(timer->data_);
470 static void TimerClosedCb(uv_handle_t* uvtimer) {
471 InspectorTimer* timer =
472 node::ContainerOf(&InspectorTimer::timer_,
473 reinterpret_cast<uv_timer_t*>(uvtimer));
480 V8InspectorClient::TimerCallback callback_;
484 class InspectorTimerHandle {
486 InspectorTimerHandle(uv_loop_t* loop,
double interval_s,
487 V8InspectorClient::TimerCallback callback,
void*
data) {
488 timer_ =
new InspectorTimer(loop, interval_s, callback, data);
491 InspectorTimerHandle(
const InspectorTimerHandle&) =
delete;
493 ~InspectorTimerHandle() {
494 CHECK_NE(timer_,
nullptr);
499 InspectorTimer* timer_;
506 :
env_(env), platform_(platform), terminated_(false),
507 running_nested_loop_(false) {
508 client_ = V8Inspector::create(env->isolate(),
this);
509 contextCreated(env->context(),
"Node.js Main Context");
513 CHECK_NE(channel_,
nullptr);
514 if (running_nested_loop_)
517 running_nested_loop_ =
true;
518 while (!terminated_ && channel_->waitForFrontendMessage()) {
519 platform_->FlushForegroundTasksInternal();
522 running_nested_loop_ =
false;
526 return uv_hrtime() * 1.0 / NANOS_PER_MSEC;
531 v8_inspector::V8ContextInfo info(context, CONTEXT_GROUP_ID,
532 name_buffer->string());
533 client_->contextCreated(info);
537 client_->contextDestroyed(context);
545 CHECK_EQ(channel_,
nullptr);
546 channel_ = std::unique_ptr<ChannelImpl>(
547 new ChannelImpl(client_.get(), delegate));
551 quitMessageLoopOnPause();
556 CHECK_NE(channel_,
nullptr);
557 channel_->dispatchProtocolMessage(message);
561 return env_->context();
565 Local<Object> target)
override {
566 Local<Object> console_api =
env_->inspector_console_api_object();
568 Local<Array> properties =
569 console_api->GetOwnPropertyNames(context).ToLocalChecked();
570 for (uint32_t i = 0; i < properties->Length(); ++i) {
571 Local<Value> key = properties->Get(context, i).ToLocalChecked();
574 console_api->Get(context, key).ToLocalChecked()).FromJust();
579 Local<Context> context =
env_->context();
581 int script_id = message->GetScriptOrigin().ScriptID()->Value();
583 Local<v8::StackTrace> stack_trace = message->GetStackTrace();
585 if (!stack_trace.IsEmpty() &&
586 stack_trace->GetFrameCount() > 0 &&
587 script_id == stack_trace->GetFrame(0)->GetScriptId()) {
591 const uint8_t DETAILS[] =
"Uncaught";
593 Isolate* isolate = context->GetIsolate();
595 client_->exceptionThrown(
597 StringView(DETAILS,
sizeof(DETAILS) - 1),
599 ToProtocolString(isolate, message->Get())->
string(),
600 ToProtocolString(isolate, message->GetScriptResourceName())->
string(),
601 message->GetLineNumber(context).FromMaybe(0),
602 message->GetStartColumn(context).FromMaybe(0),
603 client_->createStackTrace(stack_trace),
608 return channel_.get();
612 TimerCallback callback,
613 void*
data)
override {
614 timers_.emplace(std::piecewise_construct, std::make_tuple(data),
615 std::make_tuple(
env_->event_loop(), interval_s, callback,
626 client_->asyncTaskScheduled(task_name, task, recurring);
630 client_->asyncTaskCanceled(task);
634 client_->asyncTaskStarted(task);
638 client_->asyncTaskFinished(task);
642 client_->allAsyncTasksCanceled();
646 node::Environment*
env_;
649 bool running_nested_loop_;
650 std::unique_ptr<V8Inspector> client_;
651 std::unique_ptr<ChannelImpl> channel_;
652 std::unordered_map<void*, InspectorTimerHandle> timers_;
659 next_context_number_(1) {}
668 path_ = path ==
nullptr ?
"" : path;
669 debug_options_ = options;
671 std::unique_ptr<NodeInspectorClient>(
673 platform_ = platform;
674 CHECK_EQ(0, uv_async_init(uv_default_loop(),
675 &start_io_thread_async,
676 StartIoThreadAsyncCallback));
677 start_io_thread_async.data =
this;
678 uv_unref(reinterpret_cast<uv_handle_t*>(&start_io_thread_async));
681 StartDebugSignalHandler();
693 CHECK_NE(client_,
nullptr);
696 io_ = std::unique_ptr<InspectorIo>(
697 new InspectorIo(parent_env_, platform_, path_, debug_options_,
704 v8::Isolate* isolate = parent_env_->isolate();
705 HandleScope handle_scope(isolate);
708 if (!enable_async_hook_function_.IsEmpty()) {
709 Local<Function> enable_fn = enable_async_hook_function_.Get(isolate);
710 auto context = parent_env_->context();
711 auto result = enable_fn->Call(context, Undefined(isolate), 0,
nullptr);
712 if (result.IsEmpty()) {
714 "node::InspectorAgent::StartIoThread",
715 "Cannot enable Inspector's AsyncHook, please report this.");
720 Local<Object> process_object = parent_env_->process_object();
721 Local<Value> emit_fn =
722 process_object->Get(FIXED_ONE_BYTE_STRING(isolate,
"emit"));
724 if (!emit_fn->IsFunction())
728 message->Set(FIXED_ONE_BYTE_STRING(isolate,
"cmd"),
729 FIXED_ONE_BYTE_STRING(isolate,
"NODE_DEBUG_ENABLED"));
730 Local<Value> argv[] = {
731 FIXED_ONE_BYTE_STRING(isolate,
"internalMessage"),
734 MakeCallback(parent_env_->isolate(), process_object, emit_fn.As<Function>(),
735 arraysize(argv), argv, {0, 0});
740 static void AddCommandLineAPI(
741 const FunctionCallbackInfo<Value>& info) {
742 auto env = Environment::GetCurrent(info);
743 Local<Context> context = env->context();
745 if (info.Length() != 2 || !info[0]->IsString()) {
746 return env->ThrowTypeError(
"inspector.addCommandLineAPI takes " 747 "exactly 2 arguments: a string and a value.");
750 Local<Object> console_api = env->inspector_console_api_object();
751 console_api->Set(context, info[0], info[1]).FromJust();
755 if (io_ !=
nullptr) {
761 v8::Isolate* isolate = parent_env_->isolate();
762 HandleScope handle_scope(isolate);
765 if (!disable_async_hook_function_.IsEmpty()) {
766 Local<Function> disable_fn = disable_async_hook_function_.Get(isolate);
767 auto result = disable_fn->Call(parent_env_->context(),
768 Undefined(parent_env_->isolate()), 0,
nullptr);
769 if (result.IsEmpty()) {
771 "node::InspectorAgent::Stop",
772 "Cannot disable Inspector's AsyncHook, please report this.");
780 v8::Isolate* isolate = parent_env_->isolate();
781 HandleScope handle_scope(isolate);
782 auto context = parent_env_->context();
783 Local<Function> enable_fn = enable_async_hook_function_.Get(isolate);
784 auto result = enable_fn->Call(context, Undefined(isolate), 0,
nullptr);
785 if (result.IsEmpty()) {
787 "node::InspectorAgent::Connect",
788 "Cannot enable Inspector's AsyncHook, please report this.");
793 client_->connectFrontend(delegate);
797 return io_ && io_->IsConnected();
801 CHECK_NE(client_,
nullptr);
802 client_->contextDestroyed(parent_env_->context());
803 if (io_ !=
nullptr) {
804 io_->WaitForDisconnect();
811 client_->FatalException(error, message);
816 CHECK_NE(client_,
nullptr);
817 client_->dispatchMessageFromFrontend(message);
821 CHECK_NE(client_,
nullptr);
822 client_->disconnectFrontend();
826 CHECK_NE(client_,
nullptr);
827 client_->runMessageLoopOnPause(CONTEXT_GROUP_ID);
831 CHECK_NE(client_,
nullptr);
832 ChannelImpl*
channel = client_->channel();
833 if (channel ==
nullptr)
835 return channel->delegate();
839 ChannelImpl*
channel = client_->channel();
840 if (channel !=
nullptr)
841 channel->schedulePauseOnNextStatement(reason);
845 v8::Local<v8::Function> enable_function,
846 v8::Local<v8::Function> disable_function) {
847 enable_async_hook_function_.Reset(isolate, enable_function);
848 disable_async_hook_function_.Reset(isolate, disable_function);
853 client_->AsyncTaskScheduled(task_name, task, recurring);
857 client_->AsyncTaskCanceled(task);
861 client_->AsyncTaskStarted(task);
865 client_->AsyncTaskFinished(task);
869 client_->AllAsyncTasksCanceled();
872 void Open(
const FunctionCallbackInfo<Value>& args) {
873 Environment* env = Environment::GetCurrent(args);
875 bool wait_for_connect =
false;
877 if (args.Length() > 0 && args[0]->IsUint32()) {
878 uint32_t port = args[0]->Uint32Value();
882 if (args.Length() > 1 && args[1]->IsString()) {
883 node::Utf8Value
host(env->isolate(), args[1].As<String>());
887 if (args.Length() > 2 && args[2]->IsBoolean()) {
888 wait_for_connect = args[2]->BooleanValue();
894 void Url(
const FunctionCallbackInfo<Value>& args) {
895 Environment* env = Environment::GetCurrent(args);
903 if (ids.empty())
return;
906 args.GetReturnValue().Set(OneByteString(env->isolate(), url.c_str()));
909 static void* GetAsyncTask(int64_t asyncId) {
918 return reinterpret_cast<void*
>(asyncId << 1);
921 template<
void (Agent::*asyncTaskFn)(
void*)>
922 static void InvokeAsyncTaskFnWithId(
const FunctionCallbackInfo<Value>& args) {
923 Environment* env = Environment::GetCurrent(args);
924 CHECK(args[0]->IsNumber());
925 int64_t task_id = args[0]->IntegerValue(env->context()).FromJust();
926 (env->inspector_agent()->*asyncTaskFn)(GetAsyncTask(task_id));
929 static void AsyncTaskScheduledWrapper(
const FunctionCallbackInfo<Value>& args) {
930 Environment* env = Environment::GetCurrent(args);
932 CHECK(args[0]->IsString());
933 Local<String> task_name = args[0].As<String>();
934 String::Value task_name_value(task_name);
935 StringView task_name_view(*task_name_value, task_name_value.length());
937 CHECK(args[1]->IsNumber());
938 int64_t task_id = args[1]->IntegerValue(env->context()).FromJust();
939 void* task = GetAsyncTask(task_id);
941 CHECK(args[2]->IsBoolean());
942 bool recurring = args[2]->BooleanValue(env->context()).FromJust();
944 env->inspector_agent()->AsyncTaskScheduled(task_name_view, task, recurring);
947 static void RegisterAsyncHookWrapper(
const FunctionCallbackInfo<Value>& args) {
948 Environment* env = Environment::GetCurrent(args);
950 CHECK(args[0]->IsFunction());
951 v8::Local<v8::Function> enable_function = args[0].As<Function>();
952 CHECK(args[1]->IsFunction());
953 v8::Local<v8::Function> disable_function = args[1].As<Function>();
954 env->inspector_agent()->RegisterAsyncHook(env->isolate(),
955 enable_function, disable_function);
958 static void IsEnabled(
const FunctionCallbackInfo<Value>& args) {
959 Environment* env = Environment::GetCurrent(args);
960 args.GetReturnValue().Set(env->inspector_agent()->enabled());
965 Local<Context> context,
void* priv) {
966 Environment* env = Environment::GetCurrent(context);
969 auto null = Null(env->isolate());
970 CHECK(obj->SetPrototype(context, null).FromJust());
971 env->set_inspector_console_api_object(obj);
974 Agent* agent = env->inspector_agent();
975 env->SetMethod(target,
"consoleCall", InspectorConsoleCall);
976 env->SetMethod(target,
"addCommandLineAPI", AddCommandLineAPI);
978 env->SetMethod(target,
"callAndPauseOnStart", CallAndPauseOnStart);
979 env->SetMethod(target,
"connect", ConnectJSBindingsSession);
980 env->SetMethod(target,
"open",
Open);
981 env->SetMethod(target,
"url",
Url);
983 env->SetMethod(target,
"asyncTaskScheduled", AsyncTaskScheduledWrapper);
984 env->SetMethod(target,
"asyncTaskCanceled",
985 InvokeAsyncTaskFnWithId<&Agent::AsyncTaskCanceled>);
986 env->SetMethod(target,
"asyncTaskStarted",
987 InvokeAsyncTaskFnWithId<&Agent::AsyncTaskStarted>);
988 env->SetMethod(target,
"asyncTaskFinished",
989 InvokeAsyncTaskFnWithId<&Agent::AsyncTaskFinished>);
991 env->SetMethod(target,
"registerAsyncHook", RegisterAsyncHookWrapper);
992 env->SetMethod(target,
"isEnabled", IsEnabled);
999 uv_async_send(&start_io_thread_async);
1000 v8::Isolate* isolate = parent_env_->isolate();
1001 platform_->CallOnForegroundThread(isolate,
new StartIoTask(
this));
1002 isolate->RequestInterrupt(StartIoInterrupt,
this);
1003 uv_async_send(&start_io_thread_async);
1007 if (client_ ==
nullptr)
1009 std::ostringstream name;
1010 name <<
"VM Context " << next_context_number_++;
1011 client_->contextCreated(context, name.str());
std::unique_ptr< StringBuffer > Utf8ToStringView(const std::string &message)
void AsyncTaskScheduled(const v8_inspector::StringView &taskName, void *task, bool recurring)
void AllAsyncTasksCanceled()
NODE_MODULE_CONTEXT_AWARE_BUILTIN(inspector, node::inspector::Agent::InitInspector)
bool inspector_enabled() const
void runMessageLoopOnPause(int context_group_id) override
void set_host_name(std::string host_name)
void AllAsyncTasksCanceled()
void quitMessageLoopOnPause() override
void AsyncTaskFinished(void *task)
NO_RETURN void FatalError(const char *location, const char *message)
void FatalException(Local< Value > error, Local< v8::Message > message)
union node::cares_wrap::@8::CaresAsyncData::@0 data
void RequestIoThreadStart()
std::string FormatWsAddress(const std::string &host, int port, const std::string &target_id, bool include_protocol)
void Dispatch(const v8_inspector::StringView &message)
void dispatchMessageFromFrontend(const StringView &message)
void installAdditionalCommandLineAPI(Local< Context > context, Local< Object > target) override
NodeInspectorClient(node::Environment *env, node::NodePlatform *platform)
void ContextCreated(v8::Local< v8::Context > context)
void contextDestroyed(Local< Context > context)
void Open(const FunctionCallbackInfo< Value > &args)
void Url(const FunctionCallbackInfo< Value > &args)
bool Start(node::NodePlatform *platform, const char *path, const DebugOptions &options)
void AsyncTaskScheduled(const StringView &task_name, void *task, bool recurring)
void AsyncTaskCanceled(void *task)
void FatalException(v8::Local< v8::Value > error, v8::Local< v8::Message > message)
void AsyncTaskStarted(void *task)
void AsyncTaskFinished(void *task)
void Connect(InspectorSessionDelegate *delegate)
void AsyncTaskCanceled(void *task)
double currentTimeMS() override
bool StartIoThread(bool wait_for_connect)
void disconnectFrontend()
std::vector< std::string > GetTargetIds() const
Agent(node::Environment *env)
InspectorSessionDelegate * delegate()
MaybeLocal< Object > New(Isolate *isolate, Local< String > string, enum encoding enc)
bool wait_for_connect() const
MaybeLocal< Value > MakeCallback(Isolate *isolate, Local< Object > recv, Local< Function > callback, int argc, Local< Value > *argv, async_id asyncId, async_id triggerAsyncId)
void cancelTimer(void *data) override
void connectFrontend(InspectorSessionDelegate *delegate)
void startRepeatingTimer(double interval_s, TimerCallback callback, void *data) override
void RegisterAsyncHook(v8::Isolate *isolate, v8::Local< v8::Function > enable_function, v8::Local< v8::Function > disable_function)
Local< Context > ensureDefaultContextInGroup(int contextGroupId) override
static void InitInspector(v8::Local< v8::Object > target, v8::Local< v8::Value > unused, v8::Local< v8::Context > context, void *priv)
void contextCreated(Local< Context > context, const std::string &name)
void PauseOnNextJavascriptStatement(const std::string &reason)
void AsyncTaskStarted(void *task)