• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #pragma once
2 
3 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
4 
5 #if !HAVE_INSPECTOR
6 #error("This header can only be used when inspector is enabled")
7 #endif
8 
9 #include "node_options.h"
10 #include "v8.h"
11 
12 #include <cstddef>
13 #include <memory>
14 
15 namespace v8_inspector {
16 class StringView;
17 }  // namespace v8_inspector
18 
19 namespace node {
20 // Forward declaration to break recursive dependency chain with src/env.h.
21 class Environment;
22 struct ContextInfo;
23 
24 namespace inspector {
25 class InspectorIo;
26 class ParentInspectorHandle;
27 class NodeInspectorClient;
28 class WorkerManager;
29 
30 class InspectorSession {
31  public:
32   virtual ~InspectorSession() = default;
33   virtual void Dispatch(const v8_inspector::StringView& message) = 0;
34 };
35 
36 class InspectorSessionDelegate {
37  public:
38   virtual ~InspectorSessionDelegate() = default;
39   virtual void SendMessageToFrontend(const v8_inspector::StringView& message)
40                                      = 0;
41 };
42 
43 class Agent {
44  public:
45   explicit Agent(node::Environment* env);
46   ~Agent();
47 
48   // Create client_, may create io_ if option enabled
49   bool Start(const std::string& path,
50              const DebugOptions& options,
51              std::shared_ptr<ExclusiveAccess<HostPort>> host_port,
52              bool is_main);
53   // Stop and destroy io_
54   void Stop();
55 
IsListening()56   bool IsListening() { return io_ != nullptr; }
57   // Returns true if the Node inspector is actually in use. It will be true
58   // if either the user explicitly opted into inspector (e.g. with the
59   // --inspect command line flag) or if inspector JS API had been used.
60   bool IsActive();
61 
62   // Blocks till frontend connects and sends "runIfWaitingForDebugger"
63   void WaitForConnect();
64   // Blocks till all the sessions with "WaitForDisconnectOnShutdown" disconnect
65   void WaitForDisconnect();
66   void ReportUncaughtException(v8::Local<v8::Value> error,
67                                v8::Local<v8::Message> message);
68 
69   // Async stack traces instrumentation.
70   void AsyncTaskScheduled(const v8_inspector::StringView& taskName, void* task,
71                           bool recurring);
72   void AsyncTaskCanceled(void* task);
73   void AsyncTaskStarted(void* task);
74   void AsyncTaskFinished(void* task);
75   void AllAsyncTasksCanceled();
76 
77   void RegisterAsyncHook(v8::Isolate* isolate,
78     v8::Local<v8::Function> enable_function,
79     v8::Local<v8::Function> disable_function);
80   void EnableAsyncHook();
81   void DisableAsyncHook();
82 
83   void SetParentHandle(std::unique_ptr<ParentInspectorHandle> parent_handle);
84   std::unique_ptr<ParentInspectorHandle> GetParentHandle(
85       uint64_t thread_id, const std::string& url);
86 
87   // Called to create inspector sessions that can be used from the same thread.
88   // The inspector responds by using the delegate to send messages back.
89   std::unique_ptr<InspectorSession> Connect(
90       std::unique_ptr<InspectorSessionDelegate> delegate,
91       bool prevent_shutdown);
92 
93   // Called from the worker to create inspector sessions that is connected
94   // to the main thread.
95   // The inspector responds by using the delegate to send messages back.
96   std::unique_ptr<InspectorSession> ConnectToMainThread(
97       std::unique_ptr<InspectorSessionDelegate> delegate,
98       bool prevent_shutdown);
99 
100   void PauseOnNextJavascriptStatement(const std::string& reason);
101 
102   std::string GetWsUrl() const;
103 
104   // Can only be called from the main thread.
105   bool StartIoThread();
106 
107   // Calls StartIoThread() from off the main thread.
108   void RequestIoThreadStart();
109 
options()110   const DebugOptions& options() { return debug_options_; }
host_port()111   std::shared_ptr<ExclusiveAccess<HostPort>> host_port() { return host_port_; }
112   void ContextCreated(v8::Local<v8::Context> context, const ContextInfo& info);
113 
114   // Interface for interacting with inspectors in worker threads
115   std::shared_ptr<WorkerManager> GetWorkerManager();
116 
env()117   inline Environment* env() const { return parent_env_; }
118 
119  private:
120   void ToggleAsyncHook(v8::Isolate* isolate, v8::Local<v8::Function> fn);
121 
122   node::Environment* parent_env_;
123   // Encapsulates majority of the Inspector functionality
124   std::shared_ptr<NodeInspectorClient> client_;
125   // Interface for transports, e.g. WebSocket server
126   std::unique_ptr<InspectorIo> io_;
127   std::unique_ptr<ParentInspectorHandle> parent_handle_;
128   std::string path_;
129 
130   // This is a copy of the debug options parsed from CLI in the Environment.
131   // Do not use the host_port in that, instead manipulate the shared host_port_
132   // pointer which is meant to store the actual host and port of the inspector
133   // server.
134   DebugOptions debug_options_;
135   std::shared_ptr<ExclusiveAccess<HostPort>> host_port_;
136 
137   bool pending_enable_async_hook_ = false;
138   bool pending_disable_async_hook_ = false;
139 };
140 
141 }  // namespace inspector
142 }  // namespace node
143 
144 #endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
145