mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Fix logging issues in the debugger. (#2483)
- Properly handle logging during transport close - Properly display data during parse Furthermore hide global functions of the debugger. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
parent
d270f82ecb
commit
2ad883ea48
@ -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 ();
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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 */
|
||||
|
||||
1
tests/debugger/do_print.cmd
Normal file
1
tests/debugger/do_print.cmd
Normal file
@ -0,0 +1 @@
|
||||
c
|
||||
112
tests/debugger/do_print.expected
Normal file
112
tests/debugger/do_print.expected
Normal file
@ -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:
|
||||
28
tests/debugger/do_print.js
Normal file
28
tests/debugger/do_print.js
Normal file
@ -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);
|
||||
Loading…
x
Reference in New Issue
Block a user