• 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   // Option is set to wait for session connection
63   bool WillWaitForConnect();
64   // Blocks till frontend connects and sends "runIfWaitingForDebugger"
65   void WaitForConnect();
66   // Blocks till all the sessions with "WaitForDisconnectOnShutdown" disconnect
67   void WaitForDisconnect();
68   void ReportUncaughtException(v8::Local<v8::Value> error,
69                                v8::Local<v8::Message> message);
70 
71   // Async stack traces instrumentation.
72   void AsyncTaskScheduled(const v8_inspector::StringView& taskName, void* task,
73                           bool recurring);
74   void AsyncTaskCanceled(void* task);
75   void AsyncTaskStarted(void* task);
76   void AsyncTaskFinished(void* task);
77   void AllAsyncTasksCanceled();
78 
79   void RegisterAsyncHook(v8::Isolate* isolate,
80     v8::Local<v8::Function> enable_function,
81     v8::Local<v8::Function> disable_function);
82   void EnableAsyncHook();
83   void DisableAsyncHook();
84 
85   void SetParentHandle(std::unique_ptr<ParentInspectorHandle> parent_handle);
86   std::unique_ptr<ParentInspectorHandle> GetParentHandle(
87       int thread_id, const std::string& url);
88 
89   // Called to create inspector sessions that can be used from the same thread.
90   // The inspector responds by using the delegate to send messages back.
91   std::unique_ptr<InspectorSession> Connect(
92       std::unique_ptr<InspectorSessionDelegate> delegate,
93       bool prevent_shutdown);
94 
95   // Called from the worker to create inspector sessions that is connected
96   // to the main thread.
97   // The inspector responds by using the delegate to send messages back.
98   std::unique_ptr<InspectorSession> ConnectToMainThread(
99       std::unique_ptr<InspectorSessionDelegate> delegate,
100       bool prevent_shutdown);
101 
102   void PauseOnNextJavascriptStatement(const std::string& reason);
103 
104   std::string GetWsUrl() const;
105 
106   // Can only be called from the main thread.
107   bool StartIoThread();
108 
109   // Calls StartIoThread() from off the main thread.
110   void RequestIoThreadStart();
111 
options()112   const DebugOptions& options() { return debug_options_; }
host_port()113   std::shared_ptr<ExclusiveAccess<HostPort>> host_port() { return host_port_; }
114   void ContextCreated(v8::Local<v8::Context> context, const ContextInfo& info);
115 
116   // Interface for interacting with inspectors in worker threads
117   std::shared_ptr<WorkerManager> GetWorkerManager();
118 
env()119   inline Environment* env() const { return parent_env_; }
120 
121  private:
122   void ToggleAsyncHook(v8::Isolate* isolate,
123                        const v8::Global<v8::Function>& fn);
124 
125   node::Environment* parent_env_;
126   // Encapsulates majority of the Inspector functionality
127   std::shared_ptr<NodeInspectorClient> client_;
128   // Interface for transports, e.g. WebSocket server
129   std::unique_ptr<InspectorIo> io_;
130   std::unique_ptr<ParentInspectorHandle> parent_handle_;
131   std::string path_;
132 
133   // This is a copy of the debug options parsed from CLI in the Environment.
134   // Do not use the host_port in that, instead manipulate the shared host_port_
135   // pointer which is meant to store the actual host and port of the inspector
136   // server.
137   DebugOptions debug_options_;
138   std::shared_ptr<ExclusiveAccess<HostPort>> host_port_;
139 
140   bool pending_enable_async_hook_ = false;
141   bool pending_disable_async_hook_ = false;
142   v8::Global<v8::Function> enable_async_hook_function_;
143   v8::Global<v8::Function> disable_async_hook_function_;
144 };
145 
146 }  // namespace inspector
147 }  // namespace node
148 
149 #endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
150