• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1## JerryScript debugger interface
2
3JerryScript provides a remote debugger which allows debugging
4JavaScript programs. The debugger has two main components:
5a server which is part of the JerryScript binary and a
6separate client application. Currently a Python-based debugger
7client is available in the /jerry-debugger subdirectory.
8This simple application demonstrates the communication protocol
9between the client and server, and can be reused by integrated
10development environments.
11
12## Setting up the debugger server
13
14The following arguments must be passed to `tools/build.py`:
15
16`--jerry-debugger=on`
17
18The transport layer of the communication protocol is pluggable.
19At the moment, a WebSocket-based implementation is provided as a
20JerryScript extension, which transmits messages over TCP/IP networks.
21If necessary/implemented, any reliable stream or datagram based
22protocol can be used for transmitting debugger messages.
23
24## Debugging JavaScript applications
25
26The debugger client must be connected to the server before the
27JavaScript application runs. On-the-fly attachment is supported
28for more than one file, right after the engine initialization
29(this feature is available with the python client). The debugging
30information (e.g. line index of each possible breakpoint location)
31is not preserved by JerryScript. The client is expected to be run
32on a system with much more resources and it should be capable of
33storing this information. JerryScript frees all debug information
34after it is transmitted to the client to save memory.
35
36The following argument makes JerryScript wait for a client
37connection:
38
39`--start-debug-server`
40
41The following argument makes JerryScript wait for a client
42source code:
43
44`--debugger-wait-source`
45
46It is also recommended to increase the log level to see
47the *Waiting for client connection* message:
48
49`--log-level 2`
50
51The Python client can connect to the server by specifying its
52IP address on the command line. The address can be localhost
53if the server and the client are running on the same machine.
54
55After the connection is established the execution can be
56controlled by the debugger. The debugger always stops at
57the first possible breakpoint location. The effect is the
58same as using the `stop` command. This allows inserting
59breakpoints right before the meaningful part of the execution
60starts.
61
62All available commands of the client can be queried by the
63`help` command.
64
65## Integrating debugger support into applications using JerryScript
66
67When using the extension-provided WebSocket transport layer, the
68debugger can be enabled by calling `jerryx_debugger_after_connect
69(jerryx_debugger_tcp_create (debug_port) && jerryx_debugger_ws_create ())`
70after the `jerry_init ()` function. It initializes the debugger and
71blocks until a client connects.
72(Custom transport layers may be implemented and initialized similarly.
73Currently, `jerryx_debugger_rp_create ()` for raw packet transport layer and
74`jerryx_debugger_serial_create (const char* config)` for serial protocol
75are also available.)
76
77The resource name provided to `jerry_parse ()` is used by the client
78to identify the resource name of the source code. This resource name
79is usually a file name.
80
81## JerryScript debugger C-API interface
82
83The following section describes the debugger functions
84available to the host application.
85
86## JerryScript debugger types
87
88## jerry_debugger_wait_for_source_callback_t
89
90**Summary**
91
92This callback function is called by
93[jerry_debugger_wait_for_client_source](#jerry_debugger_wait_for_client_source)
94when a source code is received successfully.
95
96**Prototype**
97
98```c
99typedef jerry_value_t
100(*jerry_debugger_wait_for_source_callback_t) (const jerry_char_t *resource_name_p,
101                                              size_t resource_name_size,
102                                              const jerry_char_t *source_p,
103                                              size_t source_size, void *user_p);
104```
105
106- `resource_name_p` - resource (usually a file) name of the source code
107- `resource_name_size` - size of resource name
108- `source_p` - source code character data
109- `source_size` - size of source code
110- `user_p` - custom pointer passed to [jerry_debugger_wait_for_client_source](#jerry_debugger_wait_for_client_source)
111
112
113## JerryScript debugger functions
114
115### jerry_debugger_is_connected
116
117**Summary**
118
119Returns true if a remote debugger client is connected.
120
121**Prototype**
122
123```c
124bool
125jerry_debugger_is_connected (void);
126```
127
128**Example**
129
130[doctest]: # (test="link")
131
132```c
133#include "jerryscript.h"
134#include "jerryscript-ext/debugger.h"
135
136int
137main (void)
138{
139  jerry_init (JERRY_INIT_EMPTY);
140  jerryx_debugger_after_connect (jerryx_debugger_tcp_create (5001)
141                                 && jerryx_debugger_ws_create ());
142
143  if (jerry_debugger_is_connected ())
144  {
145    printf ("A remote debugger client is connected.");
146  }
147
148  jerry_cleanup ();
149}
150```
151
152### jerry_debugger_stop
153
154**Summary**
155
156Stops execution at the next available breakpoint if a remote
157debugger client is connected and the engine is not waiting at
158a breakpoint. The engine will stop regardless the breakpoint
159is enabled or not.
160
161**Prototype**
162
163```c
164void
165jerry_debugger_stop (void)
166```
167
168**Example**
169
170[doctest]: # (test="link")
171
172```c
173#include "jerryscript.h"
174#include "jerryscript-ext/debugger.h"
175
176int
177main (void)
178{
179  jerry_init (JERRY_INIT_EMPTY);
180  jerryx_debugger_after_connect (jerryx_debugger_tcp_create (5001)
181                                 && jerryx_debugger_ws_create ());
182
183  jerry_debugger_stop ();
184
185  jerry_cleanup ();
186}
187```
188
189**See also**
190
191- [jerry_debugger_continue](#jerry_debugger_continue)
192
193### jerry_debugger_continue
194
195**Summary**
196
197If the engine would stop at the next available breakpoint it
198cancels this effect. The engine will still stop at enabled
199breakpoints. This function effectively negates the effect of
200[jerry_debugger_stop ()](#jerry_debugger_stop) calls or stop
201requests issued by the debugger client.
202
203**Prototype**
204
205```c
206void
207jerry_debugger_continue (void)
208```
209
210**Example**
211
212[doctest]: # (test="link")
213
214```c
215#include "jerryscript.h"
216#include "jerryscript-ext/debugger.h"
217
218int
219main (void)
220{
221  jerry_init (JERRY_INIT_EMPTY);
222  jerryx_debugger_after_connect (jerryx_debugger_tcp_create (5001)
223                                 && jerryx_debugger_ws_create ());
224
225  jerry_debugger_continue ();
226
227  jerry_cleanup ();
228}
229```
230
231**See also**
232
233- [jerry_debugger_stop](#jerry_debugger_stop)
234
235### jerry_debugger_stop_at_breakpoint
236
237**Summary**
238
239Enables or disables stopping at breakpoints. When stopping is
240disabled all breakpoints are ignored including user enabled
241breakpoints. This allows hidden execution of ECMAScript code.
242
243**Prototype**
244
245```c
246void
247jerry_debugger_stop_at_breakpoint (bool enable_stop_at_breakpoint)
248```
249
250- `enable_stop_at_breakpoint` - enable (=`true`) or disable (=`false`) stopping at breakpoints
251
252**Example**
253
254[doctest]: # (test="link")
255
256```c
257#include "jerryscript.h"
258#include "jerryscript-ext/debugger.h"
259
260int
261main (void)
262{
263  jerry_init (JERRY_INIT_EMPTY);
264  jerryx_debugger_after_connect (jerryx_debugger_tcp_create (5001)
265                                 && jerryx_debugger_ws_create ());
266
267  jerry_debugger_stop_at_breakpoint (true);
268
269  // Protected execution of JavaScript code.
270  const jerry_char_t script[] = "42";
271  jerry_eval (script, sizeof (script) - 1, JERRY_PARSE_NO_OPTS);
272
273  jerry_debugger_stop_at_breakpoint (false);
274
275  jerry_cleanup ();
276}
277```
278
279### jerry_debugger_wait_for_client_source
280
281**Summary**
282
283Asks the client to provide the next source code. The function
284waits until the whole source code is received. As a reply the
285the client may request a context reset or notify that no more
286source is available. These notifications are passed back as the
287return value of the function.
288
289**Prototype**
290
291```c
292jerry_debugger_wait_for_source_status_t
293jerry_debugger_wait_for_client_source (jerry_debugger_wait_for_source_callback_t callback_p,
294                                       void *user_p, jerry_value_t *return_value)
295```
296
297**Example**
298
299[doctest]: # (test="link")
300
301```c
302#include "jerryscript.h"
303#include "jerryscript-ext/debugger.h"
304
305/**
306 * Runs the source code received by jerry_debugger_wait_for_client_source.
307 */
308static jerry_value_t
309wait_for_source_callback (const jerry_char_t *resource_name_p, /**< resource name */
310                          size_t resource_name_size, /**< size of resource name */
311                          const jerry_char_t *source_p, /**< source code */
312                          size_t source_size, /**< source code size */
313                          void *user_p /**< user pointer */)
314{
315  (void) user_p;
316
317  jerry_value_t ret_val = jerry_parse (resource_name_p,
318                                       resource_name_size,
319                                       source_p,
320                                       source_size,
321                                       JERRY_PARSE_NO_OPTS);
322
323  if (!jerry_value_is_error (ret_val))
324  {
325    jerry_value_t func_val = ret_val;
326    ret_val = jerry_run (func_val);
327    jerry_release_value (func_val);
328  }
329
330  return ret_val;
331} /* wait_for_source_callback */
332
333int
334main (void)
335{
336  jerry_debugger_wait_for_source_status_t receive_status;
337
338  do
339  {
340    /* Create a new JerryScript instance when a context reset is
341     * received. Applications usually registers their core bindings
342     * here as well (e.g. print, setTimeout). */
343    jerry_init (JERRY_INIT_EMPTY);
344    jerryx_debugger_after_connect (jerryx_debugger_tcp_create (5001)
345                                   && jerryx_debugger_ws_create ());
346
347    do
348    {
349      jerry_value_t run_result;
350
351      receive_status = jerry_debugger_wait_for_client_source (wait_for_source_callback,
352                                                              NULL,
353                                                              &run_result);
354
355      jerry_release_value (run_result);
356    }
357    while (receive_status == JERRY_DEBUGGER_SOURCE_RECEIVED);
358
359    jerry_cleanup ();
360  }
361  while (receive_status == JERRY_DEBUGGER_CONTEXT_RESET_RECEIVED);
362
363  if (receive_status == JERRY_DEBUGGER_SOURCE_RECEIVE_FAILED)
364  {
365    // Handle the failure (e.g. display an error).
366  }
367  return 0;
368}
369```
370
371### jerry_debugger_send_output
372
373**Summary**
374
375Sends the program's output to the debugger client.
376
377**Prototype**
378
379```c
380void
381jerry_debugger_send_output (const jerry_char_t *buffer, jerry_size_t string_size)
382```
383
384**Example**
385
386[doctest]: # (test="link")
387
388```c
389#include "jerryscript.h"
390#include "jerryscript-ext/debugger.h"
391
392int
393main (void)
394{
395  jerry_init (JERRY_INIT_EMPTY);
396  jerryx_debugger_after_connect (jerryx_debugger_tcp_create (5001)
397                                 && jerryx_debugger_ws_create ());
398
399  jerry_char_t my_output[] = "Hey, this should be sent too!";
400  jerry_size_t my_output_size = sizeof (my_output);
401
402  jerry_debugger_send_output (my_output, my_output_size);
403
404  jerry_cleanup ();
405}
406```
407
408### jerry_debugger_send_log
409
410**Summary**
411
412Sends the program's log to the debugger client.
413
414**Prototype**
415
416```c
417void
418jerry_debugger_send_log (jerry_log_level_t level, const jerry_char_t *buffer, jerry_size_t string_size)
419```
420
421**Example**
422
423[doctest]: # (test="link")
424
425```c
426#include "jerryscript.h"
427#include "jerryscript-ext/debugger.h"
428
429int
430main (void)
431{
432  jerry_init (JERRY_INIT_EMPTY);
433  jerryx_debugger_after_connect (jerryx_debugger_tcp_create (5001)
434                                 && jerryx_debugger_ws_create ());
435
436  jerry_char_t my_log[] = "Custom diagnostics";
437  jerry_size_t my_log_size = sizeof (my_log);
438
439  jerry_debugger_send_log (JERRY_LOG_LEVEL_DEBUG, my_log, my_log_size);
440
441  jerry_cleanup ();
442}
443```
444