1 // Copyright 2008 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_V8_DEBUG_H_ 6 #define V8_V8_DEBUG_H_ 7 8 #include "v8.h" // NOLINT(build/include) 9 10 /** 11 * Debugger support for the V8 JavaScript engine. 12 */ 13 namespace v8 { 14 15 // Debug events which can occur in the V8 JavaScript engine. 16 enum DebugEvent { 17 Break = 1, 18 Exception = 2, 19 NewFunction = 3, 20 BeforeCompile = 4, 21 AfterCompile = 5, 22 CompileError = 6, 23 AsyncTaskEvent = 7, 24 }; 25 26 class V8_EXPORT Debug { 27 public: 28 /** 29 * A client object passed to the v8 debugger whose ownership will be taken by 30 * it. v8 is always responsible for deleting the object. 31 */ 32 class ClientData { 33 public: ~ClientData()34 virtual ~ClientData() {} 35 }; 36 37 38 /** 39 * A message object passed to the debug message handler. 40 */ 41 class Message { 42 public: 43 /** 44 * Check type of message. 45 */ 46 virtual bool IsEvent() const = 0; 47 virtual bool IsResponse() const = 0; 48 virtual DebugEvent GetEvent() const = 0; 49 50 /** 51 * Indicate whether this is a response to a continue command which will 52 * start the VM running after this is processed. 53 */ 54 virtual bool WillStartRunning() const = 0; 55 56 /** 57 * Access to execution state and event data. Don't store these cross 58 * callbacks as their content becomes invalid. These objects are from the 59 * debugger event that started the debug message loop. 60 */ 61 virtual Local<Object> GetExecutionState() const = 0; 62 virtual Local<Object> GetEventData() const = 0; 63 64 /** 65 * Get the debugger protocol JSON. 66 */ 67 virtual Local<String> GetJSON() const = 0; 68 69 /** 70 * Get the context active when the debug event happened. Note this is not 71 * the current active context as the JavaScript part of the debugger is 72 * running in its own context which is entered at this point. 73 */ 74 virtual Local<Context> GetEventContext() const = 0; 75 76 /** 77 * Client data passed with the corresponding request if any. This is the 78 * client_data data value passed into Debug::SendCommand along with the 79 * request that led to the message or NULL if the message is an event. The 80 * debugger takes ownership of the data and will delete it even if there is 81 * no message handler. 82 */ 83 virtual ClientData* GetClientData() const = 0; 84 85 virtual Isolate* GetIsolate() const = 0; 86 ~Message()87 virtual ~Message() {} 88 }; 89 90 91 /** 92 * An event details object passed to the debug event listener. 93 */ 94 class EventDetails { 95 public: 96 /** 97 * Event type. 98 */ 99 virtual DebugEvent GetEvent() const = 0; 100 101 /** 102 * Access to execution state and event data of the debug event. Don't store 103 * these cross callbacks as their content becomes invalid. 104 */ 105 virtual Local<Object> GetExecutionState() const = 0; 106 virtual Local<Object> GetEventData() const = 0; 107 108 /** 109 * Get the context active when the debug event happened. Note this is not 110 * the current active context as the JavaScript part of the debugger is 111 * running in its own context which is entered at this point. 112 */ 113 virtual Local<Context> GetEventContext() const = 0; 114 115 /** 116 * Client data passed with the corresponding callback when it was 117 * registered. 118 */ 119 virtual Local<Value> GetCallbackData() const = 0; 120 121 /** 122 * Client data passed to DebugBreakForCommand function. The 123 * debugger takes ownership of the data and will delete it even if 124 * there is no message handler. 125 */ 126 virtual ClientData* GetClientData() const = 0; 127 128 virtual Isolate* GetIsolate() const = 0; 129 ~EventDetails()130 virtual ~EventDetails() {} 131 }; 132 133 /** 134 * Debug event callback function. 135 * 136 * \param event_details object providing information about the debug event 137 * 138 * A EventCallback2 does not take possession of the event data, 139 * and must not rely on the data persisting after the handler returns. 140 */ 141 typedef void (*EventCallback)(const EventDetails& event_details); 142 143 /** 144 * Debug message callback function. 145 * 146 * \param message the debug message handler message object 147 * 148 * A MessageHandler2 does not take possession of the message data, 149 * and must not rely on the data persisting after the handler returns. 150 */ 151 typedef void (*MessageHandler)(const Message& message); 152 153 /** 154 * Callback function for the host to ensure debug messages are processed. 155 */ 156 typedef void (*DebugMessageDispatchHandler)(); 157 158 static bool SetDebugEventListener(Isolate* isolate, EventCallback that, 159 Local<Value> data = Local<Value>()); 160 161 // Schedule a debugger break to happen when JavaScript code is run 162 // in the given isolate. 163 static void DebugBreak(Isolate* isolate); 164 165 // Remove scheduled debugger break in given isolate if it has not 166 // happened yet. 167 static void CancelDebugBreak(Isolate* isolate); 168 169 // Check if a debugger break is scheduled in the given isolate. 170 static bool CheckDebugBreak(Isolate* isolate); 171 172 // Message based interface. The message protocol is JSON. 173 static void SetMessageHandler(Isolate* isolate, MessageHandler handler); 174 175 static void SendCommand(Isolate* isolate, 176 const uint16_t* command, int length, 177 ClientData* client_data = NULL); 178 179 /** 180 * Run a JavaScript function in the debugger. 181 * \param fun the function to call 182 * \param data passed as second argument to the function 183 * With this call the debugger is entered and the function specified is called 184 * with the execution state as the first argument. This makes it possible to 185 * get access to information otherwise not available during normal JavaScript 186 * execution e.g. details on stack frames. Receiver of the function call will 187 * be the debugger context global object, however this is a subject to change. 188 * The following example shows a JavaScript function which when passed to 189 * v8::Debug::Call will return the current line of JavaScript execution. 190 * 191 * \code 192 * function frame_source_line(exec_state) { 193 * return exec_state.frame(0).sourceLine(); 194 * } 195 * \endcode 196 */ 197 // TODO(dcarney): data arg should be a MaybeLocal 198 static MaybeLocal<Value> Call(Local<Context> context, 199 v8::Local<v8::Function> fun, 200 Local<Value> data = Local<Value>()); 201 202 /** 203 * Returns a mirror object for the given object. 204 */ 205 static MaybeLocal<Value> GetMirror(Local<Context> context, 206 v8::Local<v8::Value> obj); 207 208 /** 209 * Makes V8 process all pending debug messages. 210 * 211 * From V8 point of view all debug messages come asynchronously (e.g. from 212 * remote debugger) but they all must be handled synchronously: V8 cannot 213 * do 2 things at one time so normal script execution must be interrupted 214 * for a while. 215 * 216 * Generally when message arrives V8 may be in one of 3 states: 217 * 1. V8 is running script; V8 will automatically interrupt and process all 218 * pending messages; 219 * 2. V8 is suspended on debug breakpoint; in this state V8 is dedicated 220 * to reading and processing debug messages; 221 * 3. V8 is not running at all or has called some long-working C++ function; 222 * by default it means that processing of all debug messages will be deferred 223 * until V8 gets control again; however, embedding application may improve 224 * this by manually calling this method. 225 * 226 * Technically this method in many senses is equivalent to executing empty 227 * script: 228 * 1. It does nothing except for processing all pending debug messages. 229 * 2. It should be invoked with the same precautions and from the same context 230 * as V8 script would be invoked from, because: 231 * a. with "evaluate" command it can do whatever normal script can do, 232 * including all native calls; 233 * b. no other thread should call V8 while this method is running 234 * (v8::Locker may be used here). 235 * 236 * "Evaluate" debug command behavior currently is not specified in scope 237 * of this method. 238 */ 239 static void ProcessDebugMessages(Isolate* isolate); 240 241 /** 242 * Debugger is running in its own context which is entered while debugger 243 * messages are being dispatched. This is an explicit getter for this 244 * debugger context. Note that the content of the debugger context is subject 245 * to change. The Context exists only when the debugger is active, i.e. at 246 * least one DebugEventListener or MessageHandler is set. 247 */ 248 static Local<Context> GetDebugContext(Isolate* isolate); 249 250 /** 251 * While in the debug context, this method returns the top-most non-debug 252 * context, if it exists. 253 */ 254 static MaybeLocal<Context> GetDebuggedContext(Isolate* isolate); 255 256 /** 257 * Enable/disable LiveEdit functionality for the given Isolate 258 * (default Isolate if not provided). V8 will abort if LiveEdit is 259 * unexpectedly used. LiveEdit is enabled by default. 260 */ 261 static void SetLiveEditEnabled(Isolate* isolate, bool enable); 262 263 /** 264 * Returns array of internal properties specific to the value type. Result has 265 * the following format: [<name>, <value>,...,<name>, <value>]. Result array 266 * will be allocated in the current context. 267 */ 268 static MaybeLocal<Array> GetInternalProperties(Isolate* isolate, 269 Local<Value> value); 270 271 /** 272 * Defines if the ES2015 tail call elimination feature is enabled or not. 273 * The change of this flag triggers deoptimization of all functions that 274 * contain calls at tail position. 275 */ 276 static bool IsTailCallEliminationEnabled(Isolate* isolate); 277 static void SetTailCallEliminationEnabled(Isolate* isolate, bool enabled); 278 }; 279 280 281 } // namespace v8 282 283 284 #undef EXPORT 285 286 287 #endif // V8_V8_DEBUG_H_ 288