-
Notifications
You must be signed in to change notification settings - Fork 8
/
README
970 lines (783 loc) · 32.4 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
JavaScript Remote Debugger
==========================
The following chapters describe some of the most important features of
the project.
What it is for?
---------------
This is an implementation of a high level debugging protocol for
SpiderMonkey engine which is available as a shared library. The library
can be used to integrate debugging facilities into an existing
application leveraging SpiderMonkey engine. There are several
integration possibilities including exposition of the high level
debugger API locally directly to the application and even exposing it to
remote clients using full duplex TCP/IP communication.
The project consists of two main parts. The debugger engine itself in a
form of shared library and the standalone console client application
used to connect to the debugger remotely. It's a simple console based
implementation whose idea is similar to GNU debugger.
Architecture, integration and remote client are described in the
following chapters.
Install
-------
### Linux
#### Dependencies
Besides a working C++ compiler you need a few additional dependencies to
compile jsrdbg.
On Fedora:
~~~~ {.sh}
sudo dnf install \
autoconf \
autoconf-archive \
automake \
gettext-devel \
libtool \
mozjs24-devel \
readline-devel
~~~~
On Ubuntu:
~~~~ {.sh}
sudo apt-get install \
autoconf \
autoconf-archive \
build-essential \
gettext \
libmozjs-24-dev \
libreadline-dev \
libtool \
pkg-config
~~~~
Note: If you haven't installed mozjs-24 with your distribution's package
manager you probably have to tell pkg-config where to find the
`mozjs-24.pc` file. You can do this by setting the `PKG_CONFIG_PATH`
environment variable appropriately, e.g.
~~~~ {.sh}
$ PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
~~~~
On Linux, you can build jsrdbg with the usual
`./configure && make && make install` like so
~~~~ {.sh}
$ autoreconf -i
$ ./configure
$ make
$ sudo make install
~~~~
### Windows
On Windows, jsrdbg provides Visual Studio project files in the `win/`
directory to create a Windows DLL. We have tested building jsrdbg with
Visual Studio 2012 but it should work with any later version as well.
It is important that you checkout the win-iconv submodule that is
referenced by the jsrdbg Git repository when compiling on Windows. You
can do this by either cloning the repository as follows
git clone --recursive https://github.com/swojtasiak/jsrdbg.git
or by checking out the submodule after the fact like this:
git submodule init
git submodule update
Additionally, you need to set two environment variables to let Visual
Studio know where to find the SpiderMonkey header files at compile-time
and the SpiderMonkey import library at link-time. Make sure to set both
environment variables to the appropriate paths before opening Visual
Studio.
set MOZJS_INCLUDE_DIR=C:\mozjs-24\include\js
set MOZJS_LIB_PATH=C:\mozjs-24\lib\mozjs-24.lib
Then build the solution with Visual Studio Solution as usual.
Note: On Windows, jsrdbg logs to a file by default. (On Linux, jsrdbg
logs via the syslog(3) facility, which is of course unavailable on
Windows.) You can specify the log file by setting the
`JSRDBG_LOG_FILE_PATH` environment variable before starting your
program, e.g.
set JSRDBG_LOG_FILE_PATH=C:\Users\test\Desktop\jsrdbg.log
If the environment variable is not set, jsrdbg does not write any logs.
How to integrate
----------------
There are plenty of ways how an application can be integrated with a
debugger, but the easier one is probably to integrate it with a remote
debugger which is based on TCP/IP connections. It's probably the best
choice, due to the fact that integration is really simple and the
debugger is fully functional without any additional work, which is
needed in case of the local debugger implementation. In order to
integrate with the local debugger you have to inherit from an abstract
debugger implementation and provide some methods that are exposed by the
class.
As has been said, the integration process is really simple and can be
completed in a few lines of code. The working example is available in
the "example" directory in the project root directory. The example
itself is really simple, the character encoding is broken and there is
almost no error handling, but it shows how the process of integration
looks like.
Having working SpiderMonkey engine embedded in your code, everything you
have to do is to create a new instance of the JSRemoteDebugger class
which needs JSRemoteDebuggerCfg instance when initialized. Notice that
the debugger itself is not connected to any specific JSRuntime and
JSContext instance. It's designed to make integration of various
JSContexts as simple as possible. Everything you have to care about is
to make sure that you call debuggers methods using the same threads that
are to run JS runtimes. So it's entirely possible to use only one
debugger instance bounded to one specific TCP/IP port to handle all
JSContexts within a process.
Initializing a remote debugger instance you can provide dedicated
configuration for the remote debugger itself as well as directly for a
debugger engine. That is, two of the available implementations (local
and remote) use the same high level debugger engine under the hood, so
they share the same set of configuration options.
So being familiar with that, we can try to prepare fully configured
remote debugger instance for our own application. Let's say we need to
bind it only to the localhost and to the default TCP/IP port 8089. We
also would like the debugger to suspend as soon as a debuggee started in
order to debug the script from the beginning. Nothing easier than that:
~~~~ {.cpp}
JSRemoteDebuggerCfg cfg;
cfg.setTcpHost("localhost");
cfg.setTcpPort(JSR_DEFAULT_TCP_PORT);
cfg.setScriptLoader(&loader);
JSRemoteDebugger dbg( cfg );
~~~~
In the first line the new configuration object is created. It's the
mentioned dedicated configuration for the remote debugger
implementation. In the second and third line two configuration options
are set. The first one is the host we would like to listen on and the
next one is the TCP/IP port. That's basically all we have to do here.
There is one more important option around: 'scriptLoader', which can be
used to provide scripts source code for the debugging engine, but let's
leave it for now. The last one can be used to choose between available
protocols supported by the debugger, but currently only TCP/IP is
supported which is a default protocol, so for now this option is
useless.
In the last line an instance of remote debugger is being created for our
configuration options prepared earlier.
Having the debugger created you have to install it. In order to
understand the installation process you have to be aware of one
important fact. The core of the debugger engine is implemented in
JavaScript language and it runs in the same virtual machine which is
debugged by the debugger engine. Of course there is plenty of C++ code
which handles whole communication etc., but the debugger itself is a
pure JavaScript code which uses some provided native interfaces to
exchange communicates with the C++ part. Therefore the installation
procedure of the debugger engine is neither more nor less about creating
dedicated compartment inside existing SpiderMonkey engine and running a
bootstrapping code which registers the debugger. In order to do it you
have to call a dedicated method: 'install' exposed by debugger instance.
The method gets three arguments: JSContext which we would like to debug.
A name of the context which is just a kind of identifier used on the
client level just in order to communicate with concrete context
instance. The last one holds debugger engine configuration parameters
JSDbgEngineOptions.
When the installation is completed you have your debugger engine up and
running, but we need a way to do some interaction with it. Protocol
mentioned before is responsible for exposing communication interface. In
our case it's TCP/IP protocol, so the next thing we have to do is to
start the TCP/IP server handling the communication logic. Of course this
logic is also hidden under a layer of abstraction, therefore everything
that has to be done is to call another parameter-free method: 'start' on
debugger instance. Remember that the protocol exposed by the debugger is
fully asynchronous one and the whole communication is handled by a full
duplex TCP/IP server. It's why there is a new thread started in the
background after calling 'start' method.
OK, that's pretty much everything you have to do in order to connect to
the debugger remotely. So let's look at the source code:
~~~~ {.cpp}
JSDbgEngineOptions dbgOptions;
dbgOptions.suspended();
if( dbg.install( cx, 'example-js-context', dbgOptions ) != JSR_ERROR_NO_ERROR ) {
cout << "Cannot install debugger." << endl;
return false;
}
if( dbg.start() != JSR_ERROR_NO_ERROR ) {
dbg.uninstall();
cout << "Cannot start debugger." << endl;
return false;
}
~~~~
The lines first and second are responsible for providing options for the
debugger engine. Currently only three options are available. The first
one called 'suspended' can be used to start debugger in the suspended
mode mentioned before, 'continueWhenNoConnections' which should be set
if we would like to make the debugging application continue when all
remote client have disconnected and the last one 'sourceDisplacement'
used to synchronize source code position if JS engine being debugged
messes up with line numbers.
The rest of the code explains itself. Only one thing that might be
really interesting here is the model of error handling. Every method
exposed by the debugging engine returns one of the unified error codes.
All the codes are available in the following header file:
jsrdbg/jsdbg\_common.h. Bear in mind that it's up to you to uninstall
every context correctly before deleting the debugger. Debugger cannot do
it automatically just because every 'uninstall' invocation has to be
done on dedicated thread, the same which runs the JS engine being
unregistered.
Debugger is up and running now, but you have to add every compartment
you would like to debug into the debugger, by providing its JS global
object. It can be done using 'addDebuggee' method like as in the
following code:
~~~~ {.cpp}
if( dbg.addDebuggee( cx, global ) != JSR_ERROR_NO_ERROR ) {
dbg.uninstall( cx );
cout << "Cannot add debuggee." << endl;
return false;
}
~~~~
That's all. If you have done all the steps correctly there is much a
chance that everything works and you should be able to use jrdb client
in order to make a remote connection to the debugger.
Of curse it's a very young project, so there is always a risk of a nasty
bug or something, so do not hesitate to report everything or provide a
patch if you find something.
As was said before, there is also a local debugger available, but its
integration is quite complex. There is 'check' subproject which is used
to run all unit tests. Take a look at it in order to get a real example
of its usage.
Remote client
-------------
Inside 'jrdb' directory, there is a simple remote debugger client
available. It was designed and implemented having gdb in mind, so it's
quite similar to the gdb, but only a small subset of all gdb commands is
implemented for now.
Anyway the client is not the most convenient one as it doesn't use
ncurses, but it's definitely better than nothing :-). I will probably
prepare a client with a real GUI in the future, but I don't have time
for it now.
Ok, so let's start with a simple example.
First of all go to the example directory and build the provided example.
It's a very simple application which runs an embedded JS script and
exposing remote debugger instance. The application binds to all
interfaces and uses the default TCP/IP port 8089. In order to build
everything go to the example directory and run:
~~~~ {.sh}
$ autoreconf -i
$ ./configure
$ make
~~~~
Bear in mind that the project uses pkg-config to find libjsrdbg shared
library. So you have to install jsrdbg and make sure that
`PKG_CONFIG_PATH` is set correctly. For instance, if you are installing
the project in /usr/local, then there is always a risk that you will
have to set the following environment variable:
~~~~ {.sh}
$ export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
~~~~
It depends if your system handles this location by default.
Now after building the example, you have the following application in
the "src" directory: jsrdbg\_example.
Just run it.
It should print the following messages into the standard output:
$ src/jsrdbg_example
Use jrdb command in order to connect to the debugger.
Application is suspended.
OK, it means that application has been started in the suspended mode
described before and is waiting for new connections. It uses the default
TCP/IP port, so everything that has to be done to connect it is to run
jrdb.
First of all type --help parameter in order to get all available
arguments:
~~~~ {.sh}
$ jrdb --help
~~~~
Then start the client:
$ jrdb
JavaScript Remote Debugger Client connected to a remote debugger.
Waiting for a list of JavaScript contexts being debugged.
Type "help context" for more information.
Available JSContext instances:
0) example-JS (PAUSED)
There is only one JSContext managed by the debugger, so it has been chosen as
the current one. You can change it using the "context" command.
jrdb>
As you can see the client informed us that debugger we are connected to
provides one paused JSContext which can be debugged. As there is only
one context, it has been chosen as the current one by default. Type
'help context' in order to get more comprehensive explanation.
The jsrd\> prompt means that the client is waiting for commands. So try
to type the most important one:
jrdb> help
List of available commands.
set - Sets environment variables
env - Prints environment variables
pc - Prints information about current frame
step - Steps to a next instruction
next - Steps to a next instructions going through subroutines
continue - Continues execution of the program being debugged
stop - Terminates a debuggee.
break,pause - Pauses the program being debugged or sets breakpoints
delete - Deletes breakpoints
info - List information about program being debugged
list - Prints source code of the script being debugged
backtrace - Prints backtrace of stack frames
print - Evaluates expressions
version - Shows application version
source - Loads script source code
animation - Enables/disables stepping animation
jrdb>
As you can see it's not the most sophisticated one. It just prints some
information about supported commands, so it's definitely one of the most
helpful ones :-). In order to get more comprehensive description of
every command you can type its name as an argument:
jrdb> help list
Lists number of source code lines starting from the
location where debuggee is paused. When run first time
it requests for the whole source code of the script being
debugged and caches it. It's why first call for a particular
script can be a bit slower.
Usage:
list [n]
l [n]
[n] - Number of source lines to print.
jrdb>
OK, so instead of describing every command available, let's do some
exercises using the example application started a moment ago. First of
all type 'pc' and hit enter. You should see something like that:
jrdb> pc
Script: example.js
Line: 0
jrdb>
It means that we are paused inside the "example.js" script at line 0.
Ok, so it would be definitelly helpful if we have an opportunity to see
a piece of source code at this location. Nothing easier than that:
jrdb> l
0* debugger;
1 print('Hello. ');
2 (function(fn) {
3 print('Yes, ');
4 fn('this is dog.');
5 })(function(msg) {
6 print(msg);
7 });
8 print('Woof, woof.');
9 debugger;
jrdb>
The 'list' command can be used to show a number of source lines just
after the point where debugger is currently paused. The asterisk after
the line number tells us where we are paused. In this particular case we
are paused on 'debugger' statement which is quite interesting one,
because it can be used directly in the code as a breakpoint in order to
make the debugger pause the application. OK, so let's step through the
next few instructions.
jrdb> s
1 print('Hello. ');
jrdb> s
2 (function(fn) {
jrdb> s
5 })(function(msg) {
jrdb> s
2 (function(fn) {
jrdb> s
3 print('Yes, ');
jrdb> l
3* print('Yes, ');
4 fn('this is dog.');
5 })(function(msg) {
6 print(msg);
7 });
8 print('Woof, woof.');
9 debugger;
10
jrdb>
As you can see we have gone through a few source code lines using 'step'
instruction and after doing it we are paused at the third line. There is
one argument to the function we are in. It's 'fn'. Let's see what it is.
It can be done using print function, which is used to evaluate code:
jrdb> p fn
{
"___jsrdbg_function_desc___": {
"parameterNames": [
"msg"
]
},
"prototype": {
"___jsrdbg_collapsed___": true
},
"length": 1,
"name": "",
"arguments": null,
"caller": null
}
jrdb>
So it's an anonymous function with one argument 'msg'.
Hmm, 'print' evaluates code. So let's try to do something strange:
jrdb> p fn = function() { debugger; };
{
"___jsrdbg_function_desc___": {
"displayName": "fn",
"parameterNames": []
},
"prototype": {
"___jsrdbg_collapsed___": true
},
"length": 0,
"name": "",
"arguments": null,
"caller": null
}
jrdb> c
debugger eval code
1
jrdb>
What has just happened? It's a bit tricky but in fact very simple. The
mentioned print method is used to evaluate the code as it is. So by
evaluating the following instruction: 'fn = function() { debugger; };'
we replaced the original function passed to the method using the 'fn'
argument by a new one, which does only one thing pauses when executed.
It's why the debugger paused in the evaluated code after we continued
execution using 'continue' command. So as you can see you have really
pretty much control over the debugged code. But remember that with great
power comes great responsibility, it's not really hard to break the
whole debugged application using such evaluation. OK, let's go out from
the evaluated code. Remember that you can display all local variables
using 'info locals' command, but head over to the 'help' description,
because it can be a quite tricky instruction and you probably will be
interested how to control the depth of displayed variables.
That's should be enough for now. With such a knowledge you should be
able to play with the debugger on your own using 'help' command.
jrdb> s
1
jrdb> s
example.js
4 fn('this is dog.');
jrdb>
Some interesting commands:
*set debug=true* - Enables debug mode. All sent and received packets
will be displayed in the console as well as log messages from the
client.
*animation* - If enabled, every time when client receives information
that debugger has paused, it displays bigger source context and
highlights the line where debugger is paused. For instance:
jrdb> s
0 debugger;
1> print('Hello. ');
2 (function(fn) {
3 print('Yes, ');
4 fn('this is dog.');
5 })(function(msg) {
6 print(msg);
7 });
8 print('Woof, woof.');
9 debugger;
10
jrdb> s
0 debugger;
1 print('Hello. ');
2> (function(fn) {
3 print('Yes, ');
4 fn('this is dog.');
5 })(function(msg) {
6 print(msg);
7 });
8 print('Woof, woof.');
9 debugger;
10
jrdb>
*source* - Returns list of available script files.
jrdb> source
/home/tas/workspace_gnome/gjs/examples/gtk.js
resource:///org/gnome/gjs/modules/overrides/GLib.js
resource:///org/gnome/gjs/modules/lang.js
Protocol
--------
The whole protocol is based on full duplex TCP/IP communication. Almost
every command and response is encoded using JSON. So after implementing
transport layer everything you have to do to communicate with a debugger
is to send and receive JSON encoded objects. For instance the following
packets show how a few step commands look like on the protocol level:
Sending command: {"id":1,"type":"command","name":"step"}
Got packet: {"type":"info","subtype":"paused","url":"test_script.js","line":5,
"source":"Utils.sum = function(x, y) {"}
Sending command: {"id":2,"type":"command","name":"step"}
Got packet: {"type":"info","subtype":"paused","url":"test_script.js","line":12,
"source":"Manager.prototype = {"}
Sending command: {"id":3,"type":"command","name":"step"}
Got packet: {"type":"info","subtype":"paused","url":"test_script.js","line":13,
"source":" calculate: function( x ) {"}
Sending command: {"id":4,"type":"command","name":"step"}
Got packet: {"type":"info","subtype":"paused","url":"test_script.js","line":20,
"source":" show: function(x) {"}
"source":"manager.calculate(5);"}
This chapter describes all available commands and responses, so after
reading it you should be able to implement a client application for the
debugger.
There are also two special commands, which are not encoded using JSON.
These are: get\_available\_contexts and exit.
### Request
Request is normalized and consists of following parts:
\*[context id]/(JSON PACKET)\n*
- *context id* - Numerical identifier of the JSContext we would like
to send packet to. It's optional parameter in case of non-existence
the packet is sent to all the contexts.
- *JSON PACKET* - Command itself, mandatory.
- \*\n* - Commands are separated by new-line characters.
JSON packet consists of the following properties:
- *type* - Currently it has to be set to 'command'.
- *name* - Command name. For instance 'step'.
- *id* - Optional packet ID. It's just sent back with a response and
can be used to pair them.
The rest of properties are optional.
Examples:
~~~~ {.js}
{"type":"command","name":"step"}
{"type":"command","name":"set_breakpoint","breakpoint":{"url":"test.js",
"line":22}}
~~~~
### Response
Response if normalized and consists of the following parts:
- *type* - Response type: 'error, 'info'. Info for plain responses,
error for errors.
- *subtype* - Name of the response.
The rest of the properties are optional.
Examples:
~~~~ {.js}
{"type":"info","subtype":"pc","script":"example.js","line":2,"source":null,
"id":"95D892FEC352D9AF"}
~~~~
### Supported commands
Standard parameters described above have been omitted intentionally.
----
Name: pc
Description: Gets current program counter.
Request:
name - 'pc'
source (boolean) - True if current source line (code, not a number)
should be returned in response.
Response:
subtype - 'pc'
script - Script's URL.
line - Line number.
source - A line of source code pointed by PC.
Req: {"type":"command","name":"pc","source":false,"id":"CE2DA6CB1B6AFC7A"}
Res: {"type":"info","subtype":"pc","script":"example.js","line":2,"source":null,
"id":"CE2DA6CB1B6AFC7A"}
----
Name: step
Description: Steps program until it reaches a different source line.
Request:
name - 'step'
Response: None.
Req: {"type":"command","name":"step"}
----
Name: next
Description: Steps program proceeding through subroutines.
Request:
name - 'next'
Response: None.
Req: {"type":"command","name":"next"}
----
Name: continue
Description: Continues execution.
Request:
name - 'continue'
Response: None.
Req: {"type":"command","name":"continue"}
----
Name: stop
Description: Terminates a debuggee.
Request:
name - 'stop'
Response: None.
Req: {"type":"command","name":"stop"}
----
Name: source_code
Description: Gets source code for given URL.
Request:
name - 'get_source'
url - Script's URL.
Response:
subtype - 'source_code'
script - Script's URL.
source - Source code.
displacement - Source code displacement, see debugger engine options.
Example:
Req: {"type":"command","name":"get_source","url":"example.js","id":
"CCE548813F631269"}
Res: {"type":"info","subtype":"source_code","script":"example.js","source":
["debugger;","..."],"displacement":0,"id":"DFF3E74BE6BF7DD7"}
----
Name: delete_all_breakpoints
Description: Deletes all registered breakpoints.
Request:
name - 'delete_all_breakpoints'
Response:
subtype - 'all_breakpoints_deleted'
Example:
Req: {"type":"command","name":"delete_all_breakpoints",
"id":"6DE62B9327DDEFEA"}
Res: {"type":"info","subtype":"all_breakpoints_deleted","id":"6DE62B9327DDEFEA"
}
----
Name: pause
Description: Pauses debuggee as soon as possible.
Request:
name - 'pause'
Response: None
Example:
Req: {"type":"command","name":"pause","id":"F37C8BF4BCBCEAE4"}
----
Name: set_breakpoint
Description: Registers a new breakpoint.
Request:
name - 'set_breakpoint'
Response:
subtype - 'breakpoint_set'
bid - Numeric breakpoint identifier.
url - Script file where breakpoint has been set.
line - Line at which breakpoint has been set.
pending - False if breakpoint has been already registered, true if it's a
pending breakpoint which waits for the script for being loaded.
Example:
Req: {"type":"command","name":"set_breakpoint","breakpoint":{
"url":"/home/tas/workspace_gnome/gjs/examples/gtk.js","line":2,
"pending":true}
Res: {"type":"info","subtype":"breakpoint_set","bid":0,
"url":"/home/tas/workspace_gnome/gjs/examples/gtk.js","line":2,
"pending":false,"id":"46287654F429A626"}
----
Name: delete_breakpoint
Description: Deletes given breakpoint.
Request:
name - 'delete_breakpoint'
ids - Array of numeric breakpoints identifiers to be deleted.
Response:
subtype - 'breakpoint_deleted'
ids - Array of numeric breakpoints identifiers to be deleted.
Example:
Req: {"type":"command","name":"delete_breakpoint","ids":[1],
"id":"9C59281AB28B5678"}
Res: {"type":"info","subtype":"breakpoint_deleted","ids":[],
"id":"9C59281AB28B5678"}
----
Name: get_stacktrace
Description: Gets current JSContext stacktrace.
Request:
name - 'get_stacktrace'
Response:
subtype - 'stacktrace'
stacktrace - Array of stacktrace elements.
url - Script's URL.
line - Line number.
rDepth - Stacktrace depth.
Example:
Req: {"type":"command","name":"get_stacktrace","id":"857B3B96591A5163"}
Res: {"type":"info","subtype":"stacktrace","stacktrace":
[{"url":"/home/tas/workspace_gnome/gjs/examples/gtk.js","line":96,
"rDepth":0}],"id":"857B3B96591A5163"}
----
Name: get_variables
Description: Get list of variables from given frame.
Request:
name - 'get_variables'
query - Query.
depth - Frame depth.
options - Retrieving options.
show-hierarchy - Evaluates hierarchy of variables.
evaluation-depth - How depth to evaluate.
Response:
subtype - 'variables'
variables - Array of stack elements.
stackElement - Describes variables for given frame.
url - Script's URL.
line - Source line.
rDepth - Frame depth.
variables - Array of variables.
name - Name of a variable.
value - Value of the variable.
Response:
subtype - 'stacktrace'
stacktrace - Array of stacktrace elements.
url - Script's URL.
line - Line number.
rDepth - Stacktrace depth.
Example:
Req: {"type":"command","name":"get_variables","query":{"depth":0,"options":{
"show-hierarchy":true,"evaluation-depth":1}},"id":"63DFE5D533FD5EB4"}
Res: {"type":"info","subtype":"variables","variables":[{
"stackElement":{"url":"/home/tas/workspace_gnome/gjs/examples/gtk.js",
"line":96,"rDepth":0},"variables":[{"name":"name","value":1}}]}],
"id":"63DFE5D533FD5EB4"}
----
Name: evaluate
Description: Evaluates variable.
Request:
name - 'evaluate'
path - Code to evaluate.
options - Retrieving options.
show-hierarchy - Evaluates hierarchy of variables.
evaluation-depth - How depth to evaluate.
Response:
subtype - 'evaluated'
result - Evaluation result.
Example:
Req: {"type":"command","name":"evaluate","path":"toString","options":
{"show-hierarchy":true,"evaluation-depth":1},"id":"5791287CABE43BF6"}
Res: {"type":"info","subtype":"evaluated","result":{
"___jsrdbg_function_desc___":{"displayName":"toString","name":"toString",
"parameterNames":[]},"length":0,"name":"toString","arguments":null,
"caller":null},"id":"5791287CABE43BF6"}
----
Name: get_all_source_urls
Description: Get list of source scripts handled by a debugger.
Request:
name - 'get_all_source_urls'
Response:
subtype - 'all_source_urls'
urls - Array of script URLs.
Example:
Req: {"type":"command","name":"get_all_source_urls","id":"AD9CD9D1C76D8EC4"}
Res: {"type":"info","subtype":"all_source_urls","urls":
["/home/tas/workspace_gnome/gjs/examples/gtk.js","debugger eval code",
"resource:///org/gnome/gjs/modules/overrides/GLib.js",
"resource:///org/gnome/gjs/modules/lang.js"],"id":"AD9CD9D1C76D8EC4"}
----
Name: get_breakpoints
Description: Gets list of all registered breakpoints.
Request:
name - 'get_breakpoints'
Response:
subtype - 'breakpoints_list'
breakpoints - Array of available breakpoints.
bid - Numeric breakpoint identifier.
url - Script file where breakpoint has been set.
line - Line at which breakpoint has been set.
pending (boolean) - False if breakpoint has been already registered,
true if it's a pending breakpoint which waits for the script
for being loaded.
Example:
Req: {"type":"command","name":"get_breakpoints","id":"3E5D8A1A168E11F5"}
Res: {"type":"info","subtype":"breakpoints_list","breakpoints":[{"bid":0,
"url":"/home/tas/workspace_gnome/gjs/examples/gtk.js","line":2,
"pending":false}],"id":"3E5D8A1A168E11F5"}
----
Name: get_available_contexts
Description: Gets list of all handled JSContexts.
Request: Plain string: get_available_contexts\n
Response:
subtype - 'contexts_list'
contexts - Array of contexts.
contextId - Numerical context ID.
contextName - Context name, the same which has to be passed to the
install method.
paused (boolean ) - True if context is already paused.
Res: {"type":"info","subtype":"contexts_list","contexts":[{"contextId":0,
"contextName":"example-JS","paused":true}]}
----
Name: exit
Description: Closes debugger.
Request: Plain string: exit\n
Common packets:
Packed sent every time when debugger switches to PAUSED state.
{"type":"info","subtype":"paused",
"url":"/home/tas/workspace_gnome/gjs/examples/gtk.js",
"line":2,"source":"const Gtk = imports.gi.Gtk;"}
source - Source code line.
line - Line number.
url - Script's URL.
Packed sent every time when error occurred.
{"type":"error","message":"Error message.","code":1,"id":"65855F75466DA4A6"}
message - Textual error message.
code - One of the supported error codes:
ERROR_CODE_UNKNOWN_COMMAND = 1
ERROR_CODE_NO_COMMAND_NAME = 2
ERROR_CODE_NOT_A_COMMAND_PACKAGE = 3
ERROR_CODE_NOT_PAUSED = 4
ERROR_CODE_BAD_ARGS = 5
ERROR_CODE_SCRIPT_NOT_FOUND = 6
ERROR_CODE_CANNOT_SET_BREAKPOINT = 8
ERROR_CODE_IS_PAUSED = 9
ERROR_CODE_UNEXPECTED_EXC = 10
ERROR_CODE_EVALUATION_FAILED = 11
ERROR_CODE_PC_NOT_AVAILABLE = 12
ERROR_CODE_NO_ACTIVE_FRAME = 13