2 * Example program using the dvalue debug transport.
9 #include "duk_trans_dvalue.h"
11 void my_cooperate(duk_trans_dvalue_ctx
*ctx
, int block
) {
12 static int first_blocked
= 1;
15 /* Duktape is not blocked; you can cooperate with e.g. a user
16 * interface here and send dvalues to Duktape, but don't block.
21 /* Duktape is blocked on a read and won't continue until debug
22 * command(s) are sent.
24 * Normally you'd enter your own event loop here, and process
25 * events until something needs to be sent to Duktape. For
26 * example, the user might press a "Step over" button in the
27 * UI which would cause dvalues to be sent. You can then
28 * return from this callback.
30 * The code below sends some example messages for testing the
31 * dvalue handling of the transport.
33 * If you create dvalues manually and send them using
34 * duk_trans_dvalue_send(), you must free the dvalues after
35 * the send call returns using duk_dvalue_free().
42 /* First time Duktape becomes blocked, send DumpHeap which
43 * exercises a lot of parsing code.
45 * NOTE: Valgrind may complain about reading uninitialized
46 * bytes. This is caused by the DumpHeap command writing out
47 * verbatim duk_tval values which are intentionally not
48 * always fully initialized for performance reasons.
52 fprintf(stderr
, "Duktape is blocked, send DumpHeap\n");
55 duk_trans_dvalue_send_req(ctx
);
56 duk_trans_dvalue_send_integer(ctx
, 0x20); /* DumpHeap */
57 duk_trans_dvalue_send_eom(ctx
);
59 /* Also send a dummy TriggerStatus request with trailing dvalues
60 * ignored by Duktape; Duktape will parse the dvalues to be able to
61 * skip them, so that the dvalue encoding is exercised.
64 tmp
= malloc(100000); /* long buffer, >= 65536 chars */
65 for (i
= 0; i
< 100000; i
++) {
68 duk_trans_dvalue_send_req(ctx
);
69 duk_trans_dvalue_send_integer(ctx
, 0x11); /* TriggerStatus */
70 duk_trans_dvalue_send_string(ctx
, "dummy"); /* short, <= 31 chars */
71 duk_trans_dvalue_send_string(ctx
, "123456789012345678901234567890foobar"); /* medium, >= 32 chars */
72 duk_trans_dvalue_send_lstring(ctx
, (const char *) tmp
, 65535UL);
73 duk_trans_dvalue_send_lstring(ctx
, (const char *) tmp
, 65536UL);
74 duk_trans_dvalue_send_lstring(ctx
, (const char *) tmp
, 100000UL);
75 duk_trans_dvalue_send_buffer(ctx
, (const char *) tmp
, 255U);
76 duk_trans_dvalue_send_buffer(ctx
, (const char *) tmp
, 65535UL);
77 duk_trans_dvalue_send_buffer(ctx
, (const char *) tmp
, 65536UL);
78 duk_trans_dvalue_send_buffer(ctx
, (const char *) tmp
, 100000UL);
79 duk_trans_dvalue_send_unused(ctx
);
80 duk_trans_dvalue_send_undefined(ctx
);
81 duk_trans_dvalue_send_null(ctx
);
82 duk_trans_dvalue_send_true(ctx
);
83 duk_trans_dvalue_send_false(ctx
);
84 duk_trans_dvalue_send_number(ctx
, 123.456);
85 duk_trans_dvalue_send_object(ctx
, 12 /*classnum*/, (const char *) tmp
, 8); /* fake ptr len */
86 duk_trans_dvalue_send_pointer(ctx
, (const char *) tmp
, 8); /* fake ptr len */
87 duk_trans_dvalue_send_lightfunc(ctx
, 0xdabc /*lf_flags*/, (const char *) tmp
, 8); /* fake ptr len */
88 duk_trans_dvalue_send_heapptr(ctx
, (const char *) tmp
, 8); /* fake ptr len */
90 duk_trans_dvalue_send_eom(ctx
);
93 fprintf(stderr
, "Duktape is blocked, send Eval and StepInto to resume execution\n");
96 /* duk_trans_dvalue_send_req_cmd() sends a REQ dvalue followed by
97 * an integer dvalue (command) for convenience.
100 duk_trans_dvalue_send_req_cmd(ctx
, 0x1e); /* 0x1e = Eval */
101 duk_trans_dvalue_send_string(ctx
, "evalMe");
102 duk_trans_dvalue_send_eom(ctx
);
104 duk_trans_dvalue_send_req_cmd(ctx
, 0x14); /* 0x14 = StepOver */
105 duk_trans_dvalue_send_eom(ctx
);
108 void my_received(duk_trans_dvalue_ctx
*ctx
, duk_dvalue
*dv
) {
109 char buf
[DUK_DVALUE_TOSTRING_BUFLEN
];
112 duk_dvalue_to_string(dv
, buf
);
113 fprintf(stderr
, "Received dvalue: %s\n", buf
);
116 /* Here a normal debug client would wait for dvalues until an EOM
117 * dvalue was received (which completes a debug message). The
118 * debug message would then be handled, possibly causing UI changes
119 * and/or causing debug commands to be sent to Duktape.
121 * The callback is responsible for eventually freeing the dvalue.
122 * Here we free it immediately, but an actual client would probably
123 * gather dvalues into an array or linked list to handle when the
124 * debug message was complete.
130 void my_handshake(duk_trans_dvalue_ctx
*ctx
, const char *line
) {
133 /* The Duktape handshake line is given in 'line' (without LF).
134 * The 'line' argument can be accessed for the duration of the
135 * callback (read only). Don't free 'line' here, the transport
139 fprintf(stderr
, "Received handshake line: '%s'\n", line
);
143 void my_detached(duk_trans_dvalue_ctx
*ctx
) {
146 /* Detached call forwarded as is. */
148 fprintf(stderr
, "Debug transport detached\n");
152 int main(int argc
, char *argv
[]) {
154 duk_trans_dvalue_ctx
*trans_ctx
;
157 (void) argc
; (void) argv
; /* suppress warning */
159 ctx
= duk_create_heap_default();
161 fprintf(stderr
, "Failed to create Duktape heap\n");
167 trans_ctx
= duk_trans_dvalue_init();
169 fprintf(stderr
, "Failed to create debug transport context\n");
174 trans_ctx
->cooperate
= my_cooperate
;
175 trans_ctx
->received
= my_received
;
176 trans_ctx
->handshake
= my_handshake
;
177 trans_ctx
->detached
= my_detached
;
179 /* Attach debugger; this will fail with a fatal error here unless
180 * debugger support is compiled in. To fail more gracefully, call
181 * this under a duk_safe_call() to catch the error.
183 duk_debugger_attach(ctx
,
184 duk_trans_dvalue_read_cb
,
185 duk_trans_dvalue_write_cb
,
186 duk_trans_dvalue_peek_cb
,
187 duk_trans_dvalue_read_flush_cb
,
188 duk_trans_dvalue_write_flush_cb
,
189 duk_trans_dvalue_detached_cb
,
192 fprintf(stderr
, "Debugger attached, running eval\n");
195 /* Evaluate simple test code, callbacks will "step over" until end.
197 * The test code here is just for exercising the debug transport.
198 * The 'evalMe' variable is evaluated (using debugger command Eval)
199 * before every step to force different dvalues to be carried over
206 "print('Hello world!');\n"
207 "[ undefined, null, true, false, 123, -123, 123.1, 0, -0, 1/0, 0/0, -1/0, \n"
208 " 'foo', Duktape.Buffer('bar'), Duktape.Pointer('dummy'), Math.cos, \n"
209 "].forEach(function (val) {\n"
215 "for (i = 0; i < 10; i++) {\n"
218 " evalMe = Duktape.Buffer(str);\n"
219 " str = str + str;\n"
224 duk_debugger_detach(ctx
);
228 duk_trans_dvalue_free(trans_ctx
);
232 duk_destroy_heap(ctx
);