1// Copyright 2008 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_V8_DEBUG_H_
29#define V8_V8_DEBUG_H_
30
31#include "v8.h"
32
33/**
34 * Debugger support for the V8 JavaScript engine.
35 */
36namespace v8 {
37
38// Debug events which can occur in the V8 JavaScript engine.
39enum DebugEvent {
40  Break = 1,
41  Exception = 2,
42  NewFunction = 3,
43  BeforeCompile = 4,
44  AfterCompile  = 5,
45  ScriptCollected = 6,
46  BreakForCommand = 7
47};
48
49
50class V8_EXPORT Debug {
51 public:
52  /**
53   * A client object passed to the v8 debugger whose ownership will be taken by
54   * it. v8 is always responsible for deleting the object.
55   */
56  class ClientData {
57   public:
58    virtual ~ClientData() {}
59  };
60
61
62  /**
63   * A message object passed to the debug message handler.
64   */
65  class Message {
66   public:
67    /**
68     * Check type of message.
69     */
70    virtual bool IsEvent() const = 0;
71    virtual bool IsResponse() const = 0;
72    virtual DebugEvent GetEvent() const = 0;
73
74    /**
75     * Indicate whether this is a response to a continue command which will
76     * start the VM running after this is processed.
77     */
78    virtual bool WillStartRunning() const = 0;
79
80    /**
81     * Access to execution state and event data. Don't store these cross
82     * callbacks as their content becomes invalid. These objects are from the
83     * debugger event that started the debug message loop.
84     */
85    virtual Handle<Object> GetExecutionState() const = 0;
86    virtual Handle<Object> GetEventData() const = 0;
87
88    /**
89     * Get the debugger protocol JSON.
90     */
91    virtual Handle<String> GetJSON() const = 0;
92
93    /**
94     * Get the context active when the debug event happened. Note this is not
95     * the current active context as the JavaScript part of the debugger is
96     * running in its own context which is entered at this point.
97     */
98    virtual Handle<Context> GetEventContext() const = 0;
99
100    /**
101     * Client data passed with the corresponding request if any. This is the
102     * client_data data value passed into Debug::SendCommand along with the
103     * request that led to the message or NULL if the message is an event. The
104     * debugger takes ownership of the data and will delete it even if there is
105     * no message handler.
106     */
107    virtual ClientData* GetClientData() const = 0;
108
109    virtual Isolate* GetIsolate() const = 0;
110
111    virtual ~Message() {}
112  };
113
114
115  /**
116   * An event details object passed to the debug event listener.
117   */
118  class EventDetails {
119   public:
120    /**
121     * Event type.
122     */
123    virtual DebugEvent GetEvent() const = 0;
124
125    /**
126     * Access to execution state and event data of the debug event. Don't store
127     * these cross callbacks as their content becomes invalid.
128     */
129    virtual Handle<Object> GetExecutionState() const = 0;
130    virtual Handle<Object> GetEventData() const = 0;
131
132    /**
133     * Get the context active when the debug event happened. Note this is not
134     * the current active context as the JavaScript part of the debugger is
135     * running in its own context which is entered at this point.
136     */
137    virtual Handle<Context> GetEventContext() const = 0;
138
139    /**
140     * Client data passed with the corresponding callback when it was
141     * registered.
142     */
143    virtual Handle<Value> GetCallbackData() const = 0;
144
145    /**
146     * Client data passed to DebugBreakForCommand function. The
147     * debugger takes ownership of the data and will delete it even if
148     * there is no message handler.
149     */
150    virtual ClientData* GetClientData() const = 0;
151
152    virtual ~EventDetails() {}
153  };
154
155  /**
156   * Debug event callback function.
157   *
158   * \param event_details object providing information about the debug event
159   *
160   * A EventCallback2 does not take possession of the event data,
161   * and must not rely on the data persisting after the handler returns.
162   */
163  typedef void (*EventCallback2)(const EventDetails& event_details);
164
165  /**
166   * Debug message callback function.
167   *
168   * \param message the debug message handler message object
169   *
170   * A MessageHandler2 does not take possession of the message data,
171   * and must not rely on the data persisting after the handler returns.
172   */
173  typedef void (*MessageHandler2)(const Message& message);
174
175  /**
176   * Debug host dispatch callback function.
177   */
178  typedef void (*HostDispatchHandler)();
179
180  /**
181   * Callback function for the host to ensure debug messages are processed.
182   */
183  typedef void (*DebugMessageDispatchHandler)();
184
185  static bool SetDebugEventListener2(EventCallback2 that,
186                                     Handle<Value> data = Handle<Value>());
187
188  // Set a JavaScript debug event listener.
189  static bool SetDebugEventListener(v8::Handle<v8::Object> that,
190                                    Handle<Value> data = Handle<Value>());
191
192  // Schedule a debugger break to happen when JavaScript code is run
193  // in the given isolate. If no isolate is provided the default
194  // isolate is used.
195  static void DebugBreak(Isolate* isolate = NULL);
196
197  // Remove scheduled debugger break in given isolate if it has not
198  // happened yet. If no isolate is provided the default isolate is
199  // used.
200  static void CancelDebugBreak(Isolate* isolate = NULL);
201
202  // Break execution of JavaScript in the given isolate (this method
203  // can be invoked from a non-VM thread) for further client command
204  // execution on a VM thread. Client data is then passed in
205  // EventDetails to EventCallback2 at the moment when the VM actually
206  // stops. If no isolate is provided the default isolate is used.
207  static void DebugBreakForCommand(ClientData* data = NULL,
208                                   Isolate* isolate = NULL);
209
210  // Message based interface. The message protocol is JSON.
211  static void SetMessageHandler2(MessageHandler2 handler);
212
213  // If no isolate is provided the default isolate is
214  // used.
215  // TODO(dcarney): remove
216  static void SendCommand(const uint16_t* command, int length,
217                          ClientData* client_data = NULL,
218                          Isolate* isolate = NULL);
219  static void SendCommand(Isolate* isolate,
220                          const uint16_t* command, int length,
221                          ClientData* client_data = NULL);
222
223  // Dispatch interface.
224  static void SetHostDispatchHandler(HostDispatchHandler handler,
225                                     int period = 100);
226
227  /**
228   * Register a callback function to be called when a debug message has been
229   * received and is ready to be processed. For the debug messages to be
230   * processed V8 needs to be entered, and in certain embedding scenarios this
231   * callback can be used to make sure V8 is entered for the debug message to
232   * be processed. Note that debug messages will only be processed if there is
233   * a V8 break. This can happen automatically by using the option
234   * --debugger-auto-break.
235   * \param provide_locker requires that V8 acquires v8::Locker for you before
236   *        calling handler
237   */
238  static void SetDebugMessageDispatchHandler(
239      DebugMessageDispatchHandler handler, bool provide_locker = false);
240
241 /**
242  * Run a JavaScript function in the debugger.
243  * \param fun the function to call
244  * \param data passed as second argument to the function
245  * With this call the debugger is entered and the function specified is called
246  * with the execution state as the first argument. This makes it possible to
247  * get access to information otherwise not available during normal JavaScript
248  * execution e.g. details on stack frames. Receiver of the function call will
249  * be the debugger context global object, however this is a subject to change.
250  * The following example shows a JavaScript function which when passed to
251  * v8::Debug::Call will return the current line of JavaScript execution.
252  *
253  * \code
254  *   function frame_source_line(exec_state) {
255  *     return exec_state.frame(0).sourceLine();
256  *   }
257  * \endcode
258  */
259  static Local<Value> Call(v8::Handle<v8::Function> fun,
260                           Handle<Value> data = Handle<Value>());
261
262  /**
263   * Returns a mirror object for the given object.
264   */
265  static Local<Value> GetMirror(v8::Handle<v8::Value> obj);
266
267 /**
268  * Enable the V8 builtin debug agent. The debugger agent will listen on the
269  * supplied TCP/IP port for remote debugger connection.
270  * \param name the name of the embedding application
271  * \param port the TCP/IP port to listen on
272  * \param wait_for_connection whether V8 should pause on a first statement
273  *   allowing remote debugger to connect before anything interesting happened
274  */
275  static bool EnableAgent(const char* name, int port,
276                          bool wait_for_connection = false);
277
278  /**
279    * Disable the V8 builtin debug agent. The TCP/IP connection will be closed.
280    */
281  static void DisableAgent();
282
283  /**
284   * Makes V8 process all pending debug messages.
285   *
286   * From V8 point of view all debug messages come asynchronously (e.g. from
287   * remote debugger) but they all must be handled synchronously: V8 cannot
288   * do 2 things at one time so normal script execution must be interrupted
289   * for a while.
290   *
291   * Generally when message arrives V8 may be in one of 3 states:
292   * 1. V8 is running script; V8 will automatically interrupt and process all
293   * pending messages (however auto_break flag should be enabled);
294   * 2. V8 is suspended on debug breakpoint; in this state V8 is dedicated
295   * to reading and processing debug messages;
296   * 3. V8 is not running at all or has called some long-working C++ function;
297   * by default it means that processing of all debug messages will be deferred
298   * until V8 gets control again; however, embedding application may improve
299   * this by manually calling this method.
300   *
301   * It makes sense to call this method whenever a new debug message arrived and
302   * V8 is not already running. Method v8::Debug::SetDebugMessageDispatchHandler
303   * should help with the former condition.
304   *
305   * Technically this method in many senses is equivalent to executing empty
306   * script:
307   * 1. It does nothing except for processing all pending debug messages.
308   * 2. It should be invoked with the same precautions and from the same context
309   * as V8 script would be invoked from, because:
310   *   a. with "evaluate" command it can do whatever normal script can do,
311   *   including all native calls;
312   *   b. no other thread should call V8 while this method is running
313   *   (v8::Locker may be used here).
314   *
315   * "Evaluate" debug command behavior currently is not specified in scope
316   * of this method.
317   */
318  static void ProcessDebugMessages();
319
320  /**
321   * Debugger is running in its own context which is entered while debugger
322   * messages are being dispatched. This is an explicit getter for this
323   * debugger context. Note that the content of the debugger context is subject
324   * to change.
325   */
326  static Local<Context> GetDebugContext();
327
328
329  /**
330   * Enable/disable LiveEdit functionality for the given Isolate
331   * (default Isolate if not provided). V8 will abort if LiveEdit is
332   * unexpectedly used. LiveEdit is enabled by default.
333   */
334  static void SetLiveEditEnabled(bool enable, Isolate* isolate = NULL);
335};
336
337
338}  // namespace v8
339
340
341#undef EXPORT
342
343
344#endif  // V8_V8_DEBUG_H_
345