diff --git a/jerry-core/api/jerry-debugger-transport.c b/jerry-core/api/jerry-debugger-transport.c index a14794ecf..a8df778e6 100644 --- a/jerry-core/api/jerry-debugger-transport.c +++ b/jerry-core/api/jerry-debugger-transport.c @@ -146,6 +146,8 @@ jerry_debugger_transport_close (void) return; } + JERRY_CONTEXT (debugger_flags) = JERRY_DEBUGGER_VM_IGNORE; + jerry_debugger_transport_header_t *current_p = JERRY_CONTEXT (debugger_transport_header_p); JERRY_ASSERT (current_p != NULL); @@ -160,8 +162,6 @@ jerry_debugger_transport_close (void) } while (current_p != NULL); - JERRY_CONTEXT (debugger_flags) = JERRY_DEBUGGER_VM_IGNORE; - jerry_port_log (JERRY_LOG_LEVEL_DEBUG, "Debugger client connection closed.\n"); jerry_debugger_free_unreferenced_byte_code (); diff --git a/jerry-debugger/jerry_client_ws.py b/jerry-debugger/jerry_client_ws.py index 4e3bf170d..ff24e8487 100644 --- a/jerry-debugger/jerry_client_ws.py +++ b/jerry-debugger/jerry_client_ws.py @@ -280,6 +280,8 @@ class JerryDebugger(object): self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.client_socket.connect((self.host, self.port)) self.non_interactive = False + self.current_out = b"" + self.current_log = b"" self.send_message(b"GET /jerry-debugger HTTP/1.1\r\n" + b"Upgrade: websocket\r\n" + @@ -824,48 +826,8 @@ class JerryDebugger(object): JERRY_DEBUGGER_EVAL_RESULT_END, JERRY_DEBUGGER_OUTPUT_RESULT, JERRY_DEBUGGER_OUTPUT_RESULT_END]: - message = b"" - msg_type = buffer_type - while True: - if buffer_type in [JERRY_DEBUGGER_EVAL_RESULT_END, - JERRY_DEBUGGER_OUTPUT_RESULT_END]: - subtype = ord(data[-1]) - message += data[3:-1] - break - else: - message += data[3:] - - data = self.get_message(True) - buffer_type = ord(data[2]) - buffer_size = ord(data[1]) - 1 - # Checks if the next frame would be an invalid data frame. - # If it is not the message type, or the end type of it, an exception is thrown. - if buffer_type not in [msg_type, msg_type + 1]: - raise Exception("Invalid data caught") - - if not message.endswith("\n"): - message += "\n" - - # Subtypes of output - if buffer_type == JERRY_DEBUGGER_OUTPUT_RESULT_END: - if subtype in [JERRY_DEBUGGER_OUTPUT_OK, - JERRY_DEBUGGER_OUTPUT_DEBUG]: - result += "%sout: %s%s" % (self.blue, self.nocolor, message) - elif subtype == JERRY_DEBUGGER_OUTPUT_WARNING: - result += "%swarning: %s%s" % (self.yellow, self.nocolor, message) - elif subtype == JERRY_DEBUGGER_OUTPUT_ERROR: - result += "%serr: %s%s" % (self.red, self.nocolor, message) - elif subtype == JERRY_DEBUGGER_OUTPUT_TRACE: - result += "%strace: %s%s" % (self.blue, self.nocolor, message) - # Subtypes of eval - else: - self.prompt = True - - if subtype == JERRY_DEBUGGER_EVAL_ERROR: - result += "Uncaught exception: %s" % (message) - else: - result += message + result = self._process_incoming_text(buffer_type, data) return DebuggerAction(DebuggerAction.TEXT, result) elif buffer_type == JERRY_DEBUGGER_MEMSTATS_RECEIVE: @@ -936,6 +898,7 @@ class JerryDebugger(object): "lines": [], "offsets": []}] new_function_list = {} + result = "" while True: if data is None: @@ -1029,6 +992,10 @@ class JerryDebugger(object): else: self._release_function(data) + elif buffer_type in [JERRY_DEBUGGER_OUTPUT_RESULT, + JERRY_DEBUGGER_OUTPUT_RESULT_END]: + result += self._process_incoming_text(buffer_type, data) + else: logging.error("Parser error!") raise Exception("Unexpected message") @@ -1044,8 +1011,7 @@ class JerryDebugger(object): # Try to set the pending breakpoints if self.pending_breakpoint_list: - result = "" - logging.debug("Pending breakpoints list: %s", self.pending_breakpoint_list) + logging.debug("Pending breakpoints available") bp_list = self.pending_breakpoint_list for breakpoint_index, breakpoint in bp_list.items(): @@ -1076,7 +1042,7 @@ class JerryDebugger(object): return result logging.debug("No pending breakpoints") - return "" + return result def _release_function(self, data): @@ -1176,3 +1142,62 @@ class JerryDebugger(object): nearest_offset = current_offset return (function.offsets[nearest_offset], False) + + def _process_incoming_text(self, buffer_type, data): + message = b"" + msg_type = buffer_type + while True: + if buffer_type in [JERRY_DEBUGGER_EVAL_RESULT_END, + JERRY_DEBUGGER_OUTPUT_RESULT_END]: + subtype = ord(data[-1]) + message += data[3:-1] + break + else: + message += data[3:] + + data = self.get_message(True) + buffer_type = ord(data[2]) + # Checks if the next frame would be an invalid data frame. + # If it is not the message type, or the end type of it, an exception is thrown. + if buffer_type not in [msg_type, msg_type + 1]: + raise Exception("Invalid data caught") + + # Subtypes of output + if buffer_type == JERRY_DEBUGGER_OUTPUT_RESULT_END: + if subtype == JERRY_DEBUGGER_OUTPUT_OK: + log_type = "%sout:%s " % (self.blue, self.nocolor) + + message = self.current_out + message + lines = message.split("\n") + self.current_out = lines.pop() + + return "".join(["%s%s\n" % (log_type, line) for line in lines]) + + if subtype == JERRY_DEBUGGER_OUTPUT_DEBUG: + log_type = "%slog:%s " % (self.yellow, self.nocolor) + + message = self.current_log + message + lines = message.split("\n") + self.current_log = lines.pop() + + return "".join(["%s%s\n" % (log_type, line) for line in lines]) + + if not message.endswith("\n"): + message += "\n" + + if subtype == JERRY_DEBUGGER_OUTPUT_WARNING: + return "%swarning: %s%s" % (self.yellow, self.nocolor, message) + elif subtype == JERRY_DEBUGGER_OUTPUT_ERROR: + return "%serr: %s%s" % (self.red, self.nocolor, message) + elif subtype == JERRY_DEBUGGER_OUTPUT_TRACE: + return "%strace: %s%s" % (self.blue, self.nocolor, message) + + # Subtypes of eval + self.prompt = True + + if not message.endswith("\n"): + message += "\n" + + if subtype == JERRY_DEBUGGER_EVAL_ERROR: + return "Uncaught exception: %s" % (message) + return message diff --git a/jerry-ext/debugger/debugger-tcp.c b/jerry-ext/debugger/debugger-tcp.c index 866e15650..42d89f396 100644 --- a/jerry-ext/debugger/debugger-tcp.c +++ b/jerry-ext/debugger/debugger-tcp.c @@ -48,7 +48,7 @@ jerryx_debugger_tcp_log_error (int err_val) static void jerryx_debugger_tcp_close (jerry_debugger_transport_header_t *header_p) /**< tcp implementation */ { - JERRYX_ASSERT (jerry_debugger_transport_is_connected ()); + JERRYX_ASSERT (!jerry_debugger_transport_is_connected ()); jerryx_debugger_transport_tcp_t *tcp_p = (jerryx_debugger_transport_tcp_t *) header_p; diff --git a/jerry-ext/debugger/debugger-ws.c b/jerry-ext/debugger/debugger-ws.c index 0a6c32843..ec32a9d85 100644 --- a/jerry-ext/debugger/debugger-ws.c +++ b/jerry-ext/debugger/debugger-ws.c @@ -275,7 +275,7 @@ jerryx_process_handshake (uint8_t *request_buffer_p) /**< temporary buffer */ static void jerryx_debugger_ws_close (jerry_debugger_transport_header_t *header_p) /**< tcp implementation */ { - JERRYX_ASSERT (jerry_debugger_transport_is_connected ()); + JERRYX_ASSERT (!jerry_debugger_transport_is_connected ()); jerry_debugger_transport_free ((void *) header_p, sizeof (jerry_debugger_transport_header_t)); } /* jerryx_debugger_ws_close */ diff --git a/jerry-ext/handler/handler-print.c b/jerry-ext/handler/handler-print.c index b8e875db1..e37e88d6a 100644 --- a/jerry-ext/handler/handler-print.c +++ b/jerry-ext/handler/handler-print.c @@ -48,60 +48,95 @@ jerryx_handler_print (const jerry_value_t func_obj_val, /**< function object */ jerry_value_t ret_val = jerry_create_undefined (); - for (jerry_length_t arg_index = 0; - jerry_value_is_undefined (ret_val) && arg_index < args_cnt; - arg_index++) + for (jerry_length_t arg_index = 0; arg_index < args_cnt; arg_index++) { jerry_value_t str_val = jerry_value_to_string (args_p[arg_index]); - if (!jerry_value_is_error (str_val)) + if (jerry_value_is_error (str_val)) { - if (arg_index != 0) + /* There is no need to free the undefined value. */ + ret_val = str_val; + break; + } + + jerry_length_t length = jerry_get_utf8_string_length (str_val); + jerry_length_t substr_pos = 0; + jerry_char_t substr_buf[256]; + + do + { + jerry_size_t substr_size = jerry_substring_to_utf8_char_buffer (str_val, + substr_pos, + length, + substr_buf, + 256 - 1); + + jerry_char_t *buf_end_p = substr_buf + substr_size; + + /* Update start position by the number of utf-8 characters. */ + for (jerry_char_t *buf_p = substr_buf; buf_p < buf_end_p; buf_p++) { - jerryx_port_handler_print_char (' '); + /* Skip intermediate utf-8 octets. */ + if ((*buf_p & 0xc0) != 0x80) + { + substr_pos++; + } } - jerry_size_t substr_size; - jerry_length_t substr_pos = 0; - jerry_char_t substr_buf[256]; - - while ((substr_size = jerry_substring_to_utf8_char_buffer (str_val, - substr_pos, - substr_pos + 256, - substr_buf, - 256)) != 0) + if (substr_pos == length) { + *buf_end_p++ = (arg_index < args_cnt - 1) ? ' ' : '\n'; + } + #ifdef JERRY_DEBUGGER - jerry_debugger_send_output (substr_buf, substr_size); + jerry_char_t *debugger_start_p = substr_buf; #endif /* JERRY_DEBUGGER */ - for (jerry_size_t chr_index = 0; chr_index < substr_size; chr_index++) + + for (jerry_char_t *buf_p = substr_buf; buf_p < buf_end_p; buf_p++) + { + char chr = (char) *buf_p; + + if (chr != '\0') { - char chr = (char) substr_buf[chr_index]; - if (chr == '\0') - { - for (jerry_size_t null_index = 0; null_str[null_index] != 0; null_index++) - { - jerryx_port_handler_print_char (null_str[null_index]); - } - } - else - { - jerryx_port_handler_print_char (chr); - } + jerryx_port_handler_print_char (chr); + continue; } - substr_pos += substr_size; + for (jerry_size_t null_index = 0; null_str[null_index] != '\0'; null_index++) + { + jerryx_port_handler_print_char (null_str[null_index]); + } + +#ifdef JERRY_DEBUGGER + if (debugger_start_p < buf_p) + { + jerry_debugger_send_output (debugger_start_p, (jerry_size_t) (buf_p - debugger_start_p)); + } + + jerry_debugger_send_output ((jerry_char_t *) null_str, 6); + debugger_start_p = buf_p + 1; +#endif /* JERRY_DEBUGGER */ } - jerry_release_value (str_val); - } - else - { - ret_val = str_val; +#ifdef JERRY_DEBUGGER + if (debugger_start_p < buf_end_p) + { + jerry_debugger_send_output (debugger_start_p, (jerry_size_t) (buf_end_p - debugger_start_p)); + } +#endif /* JERRY_DEBUGGER */ } + while (substr_pos < length); + + jerry_release_value (str_val); } - jerryx_port_handler_print_char ('\n'); + if (args_cnt == 0 || jerry_value_is_error (ret_val)) + { + jerryx_port_handler_print_char ('\n'); +#ifdef JERRY_DEBUGGER + jerry_debugger_send_output ((jerry_char_t *) "\n", 1); +#endif /* JERRY_DEBUGGER */ + } return ret_val; } /* jerryx_handler_print */ diff --git a/tests/debugger/do_print.cmd b/tests/debugger/do_print.cmd new file mode 100644 index 000000000..f2ad6c76f --- /dev/null +++ b/tests/debugger/do_print.cmd @@ -0,0 +1 @@ +c diff --git a/tests/debugger/do_print.expected b/tests/debugger/do_print.expected new file mode 100644 index 000000000..c551d6529 --- /dev/null +++ b/tests/debugger/do_print.expected @@ -0,0 +1,112 @@ +Connecting to: localhost:5001 +Stopped at tests/debugger/do_print.js:15 +(jerry-debugger) c +out: Hello world! +out: A [ ] 110 null true undefined +out: +out: [A +out: B C +out: D E +out: F +out: G] +out: 1: Az élet gyönyörű. +out: 2: Az élet gyönyörű. +out: 3: Az élet gyönyörű. +out: 4: Az élet gyönyörű. +out: 5: Az élet gyönyörű. +out: 6: Az élet gyönyörű. +out: 7: Az élet gyönyörű. +out: 8: Az élet gyönyörű. +out: 9: Az élet gyönyörű. +out: 10: Az élet gyönyörű. +out: 11: Az élet gyönyörű. +out: 12: Az élet gyönyörű. +out: 13: Az élet gyönyörű. +out: 14: Az élet gyönyörű. +out: 15: Az élet gyönyörű. +out: 16: Az élet gyönyörű. +out: 17: Az élet gyönyörű. +out: 18: Az élet gyönyörű. +out: 19: Az élet gyönyörű. +out: 20: Az élet gyönyörű. +out: 21: Az élet gyönyörű. +out: 22: Az élet gyönyörű. +out: 23: Az élet gyönyörű. +out: 24: Az élet gyönyörű. +out: 25: Az élet gyönyörű. +out: 26: Az élet gyönyörű. +out: 27: Az élet gyönyörű. +out: 28: Az élet gyönyörű. +out: 29: Az élet gyönyörű. +out: 30: Az élet gyönyörű. +out: 31: Az élet gyönyörű. +out: 32: Az élet gyönyörű. +out: 33: Az élet gyönyörű. +out: 34: Az élet gyönyörű. +out: 35: Az élet gyönyörű. +out: 36: Az élet gyönyörű. +out: 37: Az élet gyönyörű. +out: 38: Az élet gyönyörű. +out: 39: Az élet gyönyörű. +out: 40: Az élet gyönyörű. +out: 41: Az élet gyönyörű. +out: 42: Az élet gyönyörű. +out: 43: Az élet gyönyörű. +out: 44: Az élet gyönyörű. +out: 45: Az élet gyönyörű. +out: 46: Az élet gyönyörű. +out: 47: Az élet gyönyörű. +out: 48: Az élet gyönyörű. +out: 49: Az élet gyönyörű. +out: 50: Az élet gyönyörű. +out: 51: Az élet gyönyörű. +out: 52: Az élet gyönyörű. +out: 53: Az élet gyönyörű. +out: 54: Az élet gyönyörű. +out: 55: Az élet gyönyörű. +out: 56: Az élet gyönyörű. +out: 57: Az élet gyönyörű. +out: 58: Az élet gyönyörű. +out: 59: Az élet gyönyörű. +out: 60: Az élet gyönyörű. +out: 61: Az élet gyönyörű. +out: 62: Az élet gyönyörű. +out: 63: Az élet gyönyörű. +out: 64: Az élet gyönyörű. +out: 65: Az élet gyönyörű. +out: 66: Az élet gyönyörű. +out: 67: Az élet gyönyörű. +out: 68: Az élet gyönyörű. +out: 69: Az élet gyönyörű. +out: 70: Az élet gyönyörű. +out: 71: Az élet gyönyörű. +out: 72: Az élet gyönyörű. +out: 73: Az élet gyönyörű. +out: 74: Az élet gyönyörű. +out: 75: Az élet gyönyörű. +out: 76: Az élet gyönyörű. +out: 77: Az élet gyönyörű. +out: 78: Az élet gyönyörű. +out: 79: Az élet gyönyörű. +out: 80: Az élet gyönyörű. +out: 81: Az élet gyönyörű. +out: 82: Az élet gyönyörű. +out: 83: Az élet gyönyörű. +out: 84: Az élet gyönyörű. +out: 85: Az élet gyönyörű. +out: 86: Az élet gyönyörű. +out: 87: Az élet gyönyörű. +out: 88: Az élet gyönyörű. +out: 89: Az élet gyönyörű. +out: 90: Az élet gyönyörű. +out: 91: Az élet gyönyörű. +out: 92: Az élet gyönyörű. +out: 93: Az élet gyönyörű. +out: 94: Az élet gyönyörű. +out: 95: Az élet gyönyörű. +out: 96: Az élet gyönyörű. +out: 97: Az élet gyönyörű. +out: 98: Az élet gyönyörű. +out: 99: Az élet gyönyörű. +out: 100: Az élet gyönyörű. +out: diff --git a/tests/debugger/do_print.js b/tests/debugger/do_print.js new file mode 100644 index 000000000..9b7496e4e --- /dev/null +++ b/tests/debugger/do_print.js @@ -0,0 +1,28 @@ +// Copyright JS Foundation and other contributors, http://js.foundation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +print("Hello world!"); +print("A", "[", "", "]", 1.1e2, null, true, undefined); +print(); +print("[A\nB", "C\nD", "E\nF\nG]"); + +var s = ""; + +for (i = 1; i <= 100; i++) { + /* Translated from hungarian: life is beautiful */ + s += i + ": Az élet gyönyörű.\n"; +} + +/* Long string with non-ascii characters. */ +print(s);