From 733f0ceea02b53e19f963b59f37c6c2d266221cf Mon Sep 17 00:00:00 2001 From: Daniel Balla Date: Wed, 30 Aug 2017 16:01:06 +0200 Subject: [PATCH] Send output to debugger client (#1955) Sending the output to the debugger client, at the moment only the JS side prints are sent over. JerryScript-DCO-1.0-Signed-off-by: Daniel Balla dballa@inf.u-szeged.hu --- docs/07.DEBUGGER.md | 36 +++++++++++++++--- jerry-core/debugger/debugger.c | 18 +++++++++ jerry-core/debugger/debugger.h | 16 +++++++- jerry-debugger/jerry-client-ws.html | 38 +++++++++++++++++++ jerry-debugger/jerry-client-ws.py | 35 +++++++++++++++++ jerry-ext/handler/handler-print.c | 4 ++ tests/debugger/client_source.expected | 6 +++ .../debugger/client_source_multiple.expected | 7 ++++ tests/debugger/do_backtrace.expected | 4 ++ tests/debugger/do_break.expected | 3 ++ tests/debugger/do_delete.expected | 1 + tests/debugger/do_display.expected | 4 ++ tests/debugger/do_eval_syntax.expected | 1 + tests/debugger/do_exception.expected | 1 + tests/debugger/do_next.expected | 2 + .../debugger/do_pending_breakpoints.expected | 1 + tests/debugger/do_src.expected | 2 + 17 files changed, 172 insertions(+), 7 deletions(-) diff --git a/docs/07.DEBUGGER.md b/docs/07.DEBUGGER.md index 5985710d9..465468aae 100644 --- a/docs/07.DEBUGGER.md +++ b/docs/07.DEBUGGER.md @@ -26,9 +26,9 @@ can be used for transmitting debugger messages. The debugger client must be connected to the server before the JavaScript application runs. On-the-fly attachment is supported -for more than one file, right after of engine initialization -(this feature available with the python client). The debugging -information (e.g. line index of each possible -breakpoint location) +for more than one file, right after the engine initialization +(this feature is available with the python client). The debugging +information (e.g. line index of each possible breakpoint location) is not preserved by JerryScript. The client is expected to be run on a system with much more resources and it should be capable of storing this information. JerryScript frees all debug information @@ -206,8 +206,8 @@ jerry_debugger_stop_at_breakpoint (bool enable_stop_at_breakpoint) **Summary** -Stops the engine and puts that into a waiting loop. If the client send -a source code and the JerryScript receive that, then the function will +Stops the engine and puts it into a waiting loop. If the client sends +a source code and JerryScript receives that, then the function will run the source with the initialized options, after that the engine will wait for a new source until the client send a close signal. @@ -232,10 +232,34 @@ jerry_debugger_wait_and_run_client_source (jerry_value_t *return_value) if (receive_status == JERRY_DEBUGGER_SOURCE_RECEIVE_FAILED) { - // Handle the fail (e.g. create an error). + // Handle the failure (e.g. create an error). } + } jerry_release_value (run_result); } while (receive_status == JERRY_DEBUGGER_SOURCE_RECEIVED); ``` + +### jerry_debugger_send_output + +**Summary** + +Sends the program's output to the debugger client. +At the moment only the JS print size is implemented. + +**Prototype** + +```c + void + jerry_debugger_send_output (jerry_char_t buffer[], jerry_size_t string_size, uint8_t type) +``` + +**Example** + +```c + jerry_char_t my_output = "Hey, this should be sent too!"; + jerry_size_t my_output_size = sizeof (my_output); + + jerry_debugger_send_output (my_output, my_output_size, JERRY_DEBUGGER_OUTPUT_OK); +``` diff --git a/jerry-core/debugger/debugger.c b/jerry-core/debugger/debugger.c index aad857166..b8c51dc7c 100644 --- a/jerry-core/debugger/debugger.c +++ b/jerry-core/debugger/debugger.c @@ -814,6 +814,24 @@ jerry_debugger_send_parse_function (uint32_t line, /**< line */ return jerry_debugger_send (sizeof (jerry_debugger_send_parse_function_t)); } /* jerry_debugger_send_parse_function */ +/** + * Send the output of the program to the debugger client. + * Currently only sends print output. + */ +void +jerry_debugger_send_output (jerry_char_t buffer[], /**< buffer */ + jerry_size_t str_size, /**< string size */ + uint8_t type) /**< type of output */ +{ + if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED) + { + jerry_debugger_send_string (JERRY_DEBUGGER_OUTPUT_RESULT, + type, + (const uint8_t *) buffer, + sizeof (uint8_t) * str_size); + } +} /* jerry_debugger_send_output */ + /** * Send memory statistics to the debugger client. */ diff --git a/jerry-core/debugger/debugger.h b/jerry-core/debugger/debugger.h index 74c58d260..c9392d1f9 100644 --- a/jerry-core/debugger/debugger.h +++ b/jerry-core/debugger/debugger.h @@ -18,6 +18,7 @@ #include "debugger-ws.h" #include "ecma-globals.h" +#include "jerryscript-core.h" #ifdef JERRY_DEBUGGER @@ -121,6 +122,8 @@ typedef enum JERRY_DEBUGGER_EVAL_RESULT = 21, /**< eval result */ JERRY_DEBUGGER_EVAL_RESULT_END = 22, /**< last part of eval result */ JERRY_DEBUGGER_WAIT_FOR_SOURCE = 23, /**< engine waiting for a source code */ + JERRY_DEBUGGER_OUTPUT_RESULT = 24, /**< output sent by the program to the debugger */ + JERRY_DEBUGGER_OUTPUT_RESULT_END = 25, /**< last output result data */ /* Messages sent by the client to server. */ @@ -146,7 +149,7 @@ typedef enum } jerry_debugger_header_type_t; /** - * Subtypes of send_eval. + * Subtypes of eval_result. */ typedef enum { @@ -154,6 +157,16 @@ typedef enum JERRY_DEBUGGER_EVAL_ERROR = 2, /**< eval result when an error is occured */ } jerry_debugger_eval_subtype_t; +/** + * Subtypes of output_result. + */ +typedef enum +{ + JERRY_DEBUGGER_OUTPUT_OK = 1, /**< output result, no error */ + JERRY_DEBUGGER_OUTPUT_WARNING = 2, /**< output result, warning */ + JERRY_DEBUGGER_OUTPUT_ERROR = 3, /**< output result, error */ +} jerry_debugger_output_subtype_t; + /** * Delayed free of byte code data. */ @@ -337,6 +350,7 @@ bool jerry_debugger_send_function_cp (jerry_debugger_header_type_t type, ecma_co bool jerry_debugger_send_parse_function (uint32_t line, uint32_t column); void jerry_debugger_send_memstats (void); bool jerry_debugger_send_exception_string (ecma_value_t exception_value); +void jerry_debugger_send_output (jerry_char_t buffer[], jerry_size_t str_size, uint8_t type); #endif /* JERRY_DEBUGGER */ diff --git a/jerry-debugger/jerry-client-ws.html b/jerry-debugger/jerry-client-ws.html index d483f26b8..7dc2679e2 100644 --- a/jerry-debugger/jerry-client-ws.html +++ b/jerry-debugger/jerry-client-ws.html @@ -59,11 +59,18 @@ var JERRY_DEBUGGER_BACKTRACE_END = 20; var JERRY_DEBUGGER_EVAL_RESULT = 21; var JERRY_DEBUGGER_EVAL_RESULT_END = 22; var JERRY_DEBUGGER_WAIT_FOR_SOURCE = 23; +var JERRY_DEBUGGER_OUTPUT_RESULT = 24; +var JERRY_DEBUGGER_OUTPUT_RESULT_END = 25; // Subtypes of eval var JERRY_DEBUGGER_EVAL_OK = 1; var JERRY_DEBUGGER_EVAL_ERROR = 2; +// Subtypes of output result +var JERRY_DEBUGGER_OUTPUT_OK = 1; +var JERRY_DEBUGGER_OUTPUT_WARNING = 2; +var JERRY_DEBUGGER_OUTPUT_ERROR = 3; + // Messages sent by the client to server. var JERRY_DEBUGGER_FREE_BYTE_CODE_CP = 1; var JERRY_DEBUGGER_UPDATE_BREAKPOINT = 2; @@ -123,6 +130,7 @@ function DebuggerClient(address) var pendingBreakpoints = [ ]; var backtraceFrame = 0; var evalResult = null; + var outputResult = null; var exceptionData = null; var display = 0; @@ -922,6 +930,36 @@ function DebuggerClient(address) return; } + case JERRY_DEBUGGER_OUTPUT_RESULT: + case JERRY_DEBUGGER_OUTPUT_RESULT_END: + { + outputResult = concatUint8Arrays(outputResult, message); + + if (message[0] == JERRY_DEBUGGER_OUTPUT_RESULT_END) + { + var subType = outputResult[outputResult.length - 1]; + var outString; + outputResult = outputResult.slice(0, -1); + + switch (subType) + { + case JERRY_DEBUGGER_OUTPUT_OK: + outString = "out: " + cesu8ToString(outputResult); + break; + case JERRY_DEBUGGER_OUTPUT_WARNING: + outString = "warning: " + cesu8ToString(outputResult); + break; + case JERRY_DEBUGGER_OUTPUT_ERROR: + outString = "err: " + cesu8ToString(outputResult); + break; + } + + appendLog(outString); + outputResult = null; + } + + return; + } case JERRY_DEBUGGER_WAIT_FOR_SOURCE: { diff --git a/jerry-debugger/jerry-client-ws.py b/jerry-debugger/jerry-client-ws.py index 65a6fb8ee..4a0e3264f 100755 --- a/jerry-debugger/jerry-client-ws.py +++ b/jerry-debugger/jerry-client-ws.py @@ -49,11 +49,18 @@ JERRY_DEBUGGER_BACKTRACE_END = 20 JERRY_DEBUGGER_EVAL_RESULT = 21 JERRY_DEBUGGER_EVAL_RESULT_END = 22 JERRY_DEBUGGER_WAIT_FOR_SOURCE = 23 +JERRY_DEBUGGER_OUTPUT_RESULT = 24 +JERRY_DEBUGGER_OUTPUT_RESULT_END = 25 # Subtypes of eval JERRY_DEBUGGER_EVAL_OK = 1 JERRY_DEBUGGER_EVAL_ERROR = 2 +# Subtypes of output +JERRY_DEBUGGER_OUTPUT_OK = 1 +JERRY_DEBUGGER_OUTPUT_WARNING = 2 +JERRY_DEBUGGER_OUTPUT_ERROR = 3 + # Messages sent by the client to server. JERRY_DEBUGGER_FREE_BYTE_CODE_CP = 1 @@ -511,6 +518,7 @@ class JerryDebugger(object): self.yellow = '' self.green_bg = '' self.yellow_bg = '' + self.blue = '' self.nocolor = '' self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.client_socket.connect((self.host, self.port)) @@ -658,6 +666,7 @@ class JerryDebugger(object): self.yellow = '\033[93m' self.green_bg = '\033[42m' self.yellow_bg = '\033[43m' + self.blue = '\033[94m' def get_message(self, blocking): # Connection was closed @@ -1124,6 +1133,32 @@ def main(): elif buffer_type == JERRY_DEBUGGER_WAIT_FOR_SOURCE: prompt.send_client_source() + elif buffer_type in [JERRY_DEBUGGER_OUTPUT_RESULT, JERRY_DEBUGGER_OUTPUT_RESULT_END]: + message = "" + msg_type = buffer_type + while True: + if buffer_type == JERRY_DEBUGGER_OUTPUT_RESULT_END: + subtype = ord(data[-1]) + message += data[3:-1] + break + else: + message += data[3:] + + data = debugger.get_message(True) + buffer_type = ord(data[2]) + buffer_size = ord(data[1]) - 1 + + if buffer_type not in [msg_type, msg_type + 1]: + raise Exception("Output data expected") + + if subtype == JERRY_DEBUGGER_OUTPUT_OK: + print("%sout: %s%s" % (debugger.blue, debugger.nocolor, message)) + elif subtype == JERRY_DEBUGGER_OUTPUT_WARNING: + print("%swarning: %s%s" % (debugger.yellow, debugger.nocolor, message)) + elif subtype == JERRY_DEBUGGER_OUTPUT_ERROR: + print("%serr: %s%s" % (debugger.red, debugger.nocolor, message)) + + else: raise Exception("Unknown message") diff --git a/jerry-ext/handler/handler-print.c b/jerry-ext/handler/handler-print.c index 1f198f324..dc5a2d584 100644 --- a/jerry-ext/handler/handler-print.c +++ b/jerry-ext/handler/handler-print.c @@ -14,6 +14,7 @@ */ #include "jerryscript-ext/handler.h" +#include "debugger.h" /** * Provide a 'print' implementation for scripts. @@ -70,6 +71,9 @@ jerryx_handler_print (const jerry_value_t func_obj_val, /**< function object */ substr_buf, 256)) != 0) { +#ifdef JERRY_DEBUGGER + jerry_debugger_send_output (substr_buf, substr_size, JERRY_DEBUGGER_OUTPUT_OK); +#endif /* JERRY_DEBUGGER */ for (jerry_size_t chr_index = 0; chr_index < substr_size; chr_index++) { char chr = (char) substr_buf[chr_index]; diff --git a/tests/debugger/client_source.expected b/tests/debugger/client_source.expected index 9259a2806..d062652a5 100644 --- a/tests/debugger/client_source.expected +++ b/tests/debugger/client_source.expected @@ -1,9 +1,15 @@ Connecting to: localhost:5001 Stopped at tests/debugger/client_source.js:15 (jerry-debugger) s +out: client-source-test Stopped at tests/debugger/client_source.js:40 (jerry-debugger) s Stopped at tests/debugger/client_source.js:35 (in test() at line:33, col:1) (jerry-debugger) s +out: function test Stopped at tests/debugger/client_source.js:36 (in test() at line:33, col:1) (jerry-debugger) continue +out: function foo +out: function bar +out: function finish +out: finish: test-foo-bar diff --git a/tests/debugger/client_source_multiple.expected b/tests/debugger/client_source_multiple.expected index 2953f02d6..76e52b825 100644 --- a/tests/debugger/client_source_multiple.expected +++ b/tests/debugger/client_source_multiple.expected @@ -1,15 +1,22 @@ Connecting to: localhost:5001 Stopped at tests/debugger/client_source_multiple_2.js:15 (jerry-debugger) n +out: multiple-client-source-test-file-2 Stopped at tests/debugger/client_source_multiple_1.js:15 (jerry-debugger) n +out: multiple-client-source-test-file-1 Stopped at tests/debugger/client_source_multiple_1.js:27 (jerry-debugger) s Stopped at tests/debugger/client_source_multiple_1.js:18 (in foo() at line:17, col:1) (jerry-debugger) s +out: foo Stopped at tests/debugger/client_source_multiple_1.js:19 (in foo() at line:17, col:1) (jerry-debugger) s Stopped at tests/debugger/client_source_multiple_2.js:18 (in bar() at line:17, col:1) (jerry-debugger) s +out: bar Stopped at tests/debugger/client_source_multiple_2.js:19 (in bar() at line:17, col:1) (jerry-debugger) c +out: str-argument: called-from-test-file-1 +out: crossFoo +out: str-argument: called-from-test-file-2 diff --git a/tests/debugger/do_backtrace.expected b/tests/debugger/do_backtrace.expected index d5810f322..69424bd6d 100644 --- a/tests/debugger/do_backtrace.expected +++ b/tests/debugger/do_backtrace.expected @@ -1,6 +1,7 @@ Connecting to: localhost:5001 Stopped at tests/debugger/do_backtrace.js:15 (jerry-debugger) next +out: backtrace-test Stopped at tests/debugger/do_backtrace.js:28 (jerry-debugger) n Stopped at tests/debugger/do_backtrace.js:37 @@ -9,6 +10,7 @@ Stopped at tests/debugger/do_backtrace.js:40 (jerry-debugger) step Stopped at tests/debugger/do_backtrace.js:32 (in test() at line:30, col:1) (jerry-debugger) next +out: function test Stopped at tests/debugger/do_backtrace.js:33 (in test() at line:30, col:1) (jerry-debugger) s Stopped at tests/debugger/do_backtrace.js:23 (in foo() at line:21, col:1) @@ -17,6 +19,7 @@ Frame 0: tests/debugger/do_backtrace.js:23 (in foo() at line:21, col:1) Frame 1: tests/debugger/do_backtrace.js:33 (in test() at line:30, col:1) Frame 2: tests/debugger/do_backtrace.js:40 (jerry-debugger) n +out: function foo Stopped at tests/debugger/do_backtrace.js:24 (in foo() at line:21, col:1) (jerry-debugger) n Stopped at tests/debugger/do_backtrace.js:25 (in foo() at line:21, col:1) @@ -28,3 +31,4 @@ Frame 1: tests/debugger/do_backtrace.js:25 (in foo() at line:21, col:1) Frame 2: tests/debugger/do_backtrace.js:33 (in test() at line:30, col:1) Frame 3: tests/debugger/do_backtrace.js:40 (jerry-debugger) c +out: function f4 diff --git a/tests/debugger/do_break.expected b/tests/debugger/do_break.expected index 178285196..6e5560ee3 100644 --- a/tests/debugger/do_break.expected +++ b/tests/debugger/do_break.expected @@ -14,6 +14,8 @@ Breakpoint 4 at tests/debugger/do_break.js:45 (in f() at line:43, col:1) 3: tests/debugger/do_break.js:33 (in f() at line:31, col:3) 4: tests/debugger/do_break.js:45 (in f() at line:43, col:1) (jerry-debugger) c +out: break test +out: var cat Stopped at breakpoint:1 tests/debugger/do_break.js:51 (jerry-debugger) delete 1 (jerry-debugger) list @@ -24,5 +26,6 @@ Stopped at breakpoint:1 tests/debugger/do_break.js:51 (jerry-debugger) c Stopped at breakpoint:2 tests/debugger/do_break.js:36 (in test() at line:20, col:1) (jerry-debugger) continue +out: function test Stopped at breakpoint:3 tests/debugger/do_break.js:33 (in f() at line:31, col:3) (jerry-debugger) c diff --git a/tests/debugger/do_delete.expected b/tests/debugger/do_delete.expected index 68644446c..bfa158e1b 100644 --- a/tests/debugger/do_delete.expected +++ b/tests/debugger/do_delete.expected @@ -1,6 +1,7 @@ Connecting to: localhost:5001 Stopped at tests/debugger/do_delete.js:15 (jerry-debugger) next +out: delete tests Stopped at tests/debugger/do_delete.js:17 (jerry-debugger) b do_delete.js:17 Breakpoint 1 at tests/debugger/do_delete.js:17 diff --git a/tests/debugger/do_display.expected b/tests/debugger/do_display.expected index ac5a42944..5cef2b3c5 100644 --- a/tests/debugger/do_display.expected +++ b/tests/debugger/do_display.expected @@ -14,6 +14,7 @@ Non-negative integer number expected, 0 turns off this function Stopped at breakpoint:1 tests/debugger/do_display.js:15 (in a() at line:15, col:1) (jerry-debugger) display 2 (jerry-debugger) c +out: hi Stopped at breakpoint:2 tests/debugger/do_display.js:16 (in b() at line:16, col:1) Source: tests/debugger/do_display.js 15 function a() { print("hi"); } @@ -21,6 +22,7 @@ Source: tests/debugger/do_display.js 17 function c() { print("hello"); } (jerry-debugger) display 5435 (jerry-debugger) c +out: welcome Stopped at breakpoint:3 tests/debugger/do_display.js:17 (in c() at line:17, col:1) Source: tests/debugger/do_display.js 1 // Copyright JS Foundation and other contributors, http://js.foundation @@ -48,5 +50,7 @@ Source: tests/debugger/do_display.js 23 d(); (jerry-debugger) display 0 (jerry-debugger) c +out: hello Stopped at breakpoint:4 tests/debugger/do_display.js:18 (in d() at line:18, col:1) (jerry-debugger) c +out: goodbye diff --git a/tests/debugger/do_eval_syntax.expected b/tests/debugger/do_eval_syntax.expected index d944d68e9..f078975eb 100644 --- a/tests/debugger/do_eval_syntax.expected +++ b/tests/debugger/do_eval_syntax.expected @@ -5,3 +5,4 @@ Stopped at tests/debugger/do_eval_syntax.js:26 (jerry-debugger) eval loop Uncaught exception: Error (jerry-debugger) c +out: bar function diff --git a/tests/debugger/do_exception.expected b/tests/debugger/do_exception.expected index beb78e2da..8899b84ef 100644 --- a/tests/debugger/do_exception.expected +++ b/tests/debugger/do_exception.expected @@ -1,6 +1,7 @@ Connecting to: localhost:5001 Stopped at tests/debugger/do_exception.js:15 (jerry-debugger) c +out: exception handler configuration test Exception throw detected (to disable automatic stop type exception 0) Exception hint: TypeError Stopped around tests/debugger/do_exception.js:19 (in foo() at line:17, col:1) diff --git a/tests/debugger/do_next.expected b/tests/debugger/do_next.expected index 4a87f1120..483f2ba69 100644 --- a/tests/debugger/do_next.expected +++ b/tests/debugger/do_next.expected @@ -1,7 +1,9 @@ Connecting to: localhost:5001 Stopped at tests/debugger/do_next.js:15 (jerry-debugger) next +out: next test Stopped at tests/debugger/do_next.js:17 (jerry-debugger) next +out: var cat Stopped at tests/debugger/do_next.js:18 (jerry-debugger) c diff --git a/tests/debugger/do_pending_breakpoints.expected b/tests/debugger/do_pending_breakpoints.expected index e4283d4f5..e5bbea63f 100644 --- a/tests/debugger/do_pending_breakpoints.expected +++ b/tests/debugger/do_pending_breakpoints.expected @@ -7,6 +7,7 @@ Pending breakpoint at f() === Pending breakpoints === 1: f() (pending) (jerry-debugger) n +out: pending-breakpoints Stopped at tests/debugger/do_pending_breakpoints.js:17 (jerry-debugger) n Breakpoint 2 at :1 (in f() at line:1, col:1) diff --git a/tests/debugger/do_src.expected b/tests/debugger/do_src.expected index a80f4ba47..512f376a9 100644 --- a/tests/debugger/do_src.expected +++ b/tests/debugger/do_src.expected @@ -5,6 +5,7 @@ Breakpoint 1 at tests/debugger/do_src.js:16 (in f() at line:15, col:1) (jerry-debugger) n Stopped at breakpoint:1 tests/debugger/do_src.js:16 (in f() at line:15, col:1) (jerry-debugger) next +out: F1 Stopped at tests/debugger/do_src.js:20 (jerry-debugger) s Stopped at :1 @@ -16,3 +17,4 @@ Stopped at tests/debugger/do_src.js:21 Stopped at :2 (in f() at line:1, col:5) (jerry-debugger) src (jerry-debugger) c +out: F2