Improve python debugger client. (#2441)

Replace DisplayData to DebuggerAction. The new class has only four type
options. Furthermore several functions returning with DisplayData is
changed to return with string.

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg
2018-08-22 17:34:32 +02:00
committed by GitHub
parent b2cf7eb659
commit 300e40ba9d
8 changed files with 267 additions and 318 deletions
+1 -1
View File
@@ -367,7 +367,7 @@ typedef struct
typedef struct typedef struct
{ {
uint8_t type; /**< type of the message */ uint8_t type; /**< type of the message */
uint8_t frame_count[sizeof (uint32_t)]; /**< total number of frames*/ uint8_t frame_count[sizeof (uint32_t)]; /**< total number of frames */
} jerry_debugger_send_backtrace_total_t; } jerry_debugger_send_backtrace_total_t;
/** /**
+49 -85
View File
@@ -24,6 +24,9 @@ import logging
import time import time
import jerry_client_ws import jerry_client_ws
def write(string):
print(string, end='')
class DebuggerPrompt(Cmd): class DebuggerPrompt(Cmd):
# pylint: disable=too-many-instance-attributes,too-many-arguments # pylint: disable=too-many-instance-attributes,too-many-arguments
def __init__(self, debugger): def __init__(self, debugger):
@@ -31,8 +34,6 @@ class DebuggerPrompt(Cmd):
self.debugger = debugger self.debugger = debugger
self.stop = False self.stop = False
self.quit = False self.quit = False
self.backtrace = True
self.debugger.non_interactive = False
def precmd(self, line): def precmd(self, line):
self.stop = False self.stop = False
@@ -60,54 +61,49 @@ class DebuggerPrompt(Cmd):
def do_break(self, args): def do_break(self, args):
""" Insert breakpoints on the given lines or functions """ """ Insert breakpoints on the given lines or functions """
result = "" write(self.debugger.set_break(args))
result = self.debugger.set_break(args)
if self.debugger.not_empty(result):
print(result.get_data())
do_b = do_break do_b = do_break
def do_list(self, _): def do_list(self, _):
""" Lists the available breakpoints """ """ Lists the available breakpoints """
result = self.debugger.show_breakpoint_list() write(self.debugger.breakpoint_list())
print(result.get_data())
def do_delete(self, args): def do_delete(self, args):
""" Delete the given breakpoint, use 'delete all|active|pending' to clear all the given breakpoints """ """ Delete the given breakpoint, use 'delete all|active|pending' to clear all the given breakpoints """
result = self.debugger.delete(args) write(self.debugger.delete(args))
if self.debugger.not_empty(result):
print(result.get_data())
def do_next(self, args): def do_next(self, args):
""" Next breakpoint in the same context """ """ Next breakpoint in the same context """
self.stop = True self.stop = True
if self.debugger.check_empty_data(args): if not args:
args = 0 args = 0
self.debugger.next() self.debugger.next()
else: return
try:
args = int(args) try:
if args <= 0: args = int(args)
raise ValueError(args) if args <= 0:
else: raise ValueError(args)
while int(args) != 0:
self.debugger.next() while args > 0:
time.sleep(0.5) self.debugger.next()
result = self.debugger.mainloop().get_data() time.sleep(0.1)
if result.endswith('\n'):
result = result.rstrip() while True:
if jerry_client_ws.JERRY_DEBUGGER_DATA_END in result: result = self.debugger.process_messages()
result = result.replace(jerry_client_ws.JERRY_DEBUGGER_DATA_END, '') res_type = result.get_type()
if result:
print(result) if res_type == result.END:
self.debugger.smessage = '' self.quit = True
if self.debugger.display > 0: return
print(self.debugger.print_source(self.debugger.display, elif res_type == result.TEXT:
self.debugger.src_offset).get_data()) write(result.get_text())
args = int(args) - 1 elif res_type == result.PROMPT:
self.cmdloop() break
except ValueError as val_errno:
print("Error: expected a positive integer: %s" % val_errno) args -= 1
self.cmdloop() except ValueError as val_errno:
print("Error: expected a positive integer: %s" % val_errno)
do_n = do_next do_n = do_next
def do_step(self, _): def do_step(self, _):
@@ -118,14 +114,8 @@ class DebuggerPrompt(Cmd):
def do_backtrace(self, args): def do_backtrace(self, args):
""" Get backtrace data from debugger """ """ Get backtrace data from debugger """
result = self.debugger.backtrace(args) write(self.debugger.backtrace(args))
if self.debugger.not_empty(result): self.stop = True
print(result.get_data())
self.stop = True
self.cmdloop()
else:
self.stop = True
self.backtrace = True
do_bt = do_backtrace do_bt = do_backtrace
def do_src(self, args): def do_src(self, args):
@@ -133,7 +123,7 @@ class DebuggerPrompt(Cmd):
if args: if args:
line_num = src_check_args(args) line_num = src_check_args(args)
if line_num >= 0: if line_num >= 0:
print(self.debugger.print_source(line_num, 0).get_data()) write(self.debugger.print_source(line_num, 0))
do_source = do_src do_source = do_src
def do_scroll(self, _): def do_scroll(self, _):
@@ -153,7 +143,7 @@ class DebuggerPrompt(Cmd):
""" Continue execution """ """ Continue execution """
self.debugger.get_continue() self.debugger.get_continue()
self.stop = True self.stop = True
if self.debugger.check_empty_data(self.debugger.non_interactive): if not self.debugger.non_interactive:
print("Press enter to stop JavaScript execution.") print("Press enter to stop JavaScript execution.")
do_c = do_continue do_c = do_continue
@@ -200,8 +190,7 @@ class DebuggerPrompt(Cmd):
def do_exception(self, args): def do_exception(self, args):
""" Config the exception handler module """ """ Config the exception handler module """
result = self.debugger.exception(args) write(self.debugger.exception(args))
print(result.get_data())
def _scroll_direction(debugger, direction): def _scroll_direction(debugger, direction):
""" Helper function for do_scroll """ """ Helper function for do_scroll """
@@ -229,66 +218,41 @@ def main():
args = jerry_client_ws.arguments_parse() args = jerry_client_ws.arguments_parse()
debugger = jerry_client_ws.JerryDebugger(args.address) debugger = jerry_client_ws.JerryDebugger(args.address)
debugger.non_interactive = args.non_interactive
logging.debug("Connected to JerryScript on %d port", debugger.port) logging.debug("Connected to JerryScript on %d port", debugger.port)
prompt = DebuggerPrompt(debugger) prompt = DebuggerPrompt(debugger)
prompt.prompt = "(jerry-debugger) " prompt.prompt = "(jerry-debugger) "
prompt.debugger.non_interactive = args.non_interactive
if args.color: if args.color:
debugger.set_colors() debugger.set_colors()
if args.display: if args.display:
prompt.debugger.display = args.display debugger.display = args.display
prompt.do_display(args.display) prompt.do_display(args.display)
else: else:
prompt.stop = False prompt.stop = False
if prompt.debugger.check_empty_data(args.client_source):
prompt.debugger.mainloop()
result = prompt.debugger.smessage
print(result)
prompt.debugger.smessage = ''
prompt.cmdloop()
if prompt.debugger.not_empty(args.exception): if args.exception is not None:
prompt.do_exception(str(args.exception)) prompt.do_exception(str(args.exception))
if args.client_source: if args.client_source:
prompt.debugger.store_client_sources(args.client_source) debugger.store_client_sources(args.client_source)
while True: while True:
if prompt.quit: if prompt.quit:
break break
result = prompt.debugger.mainloop().get_data() result = debugger.process_messages()
res_type = result.get_type()
if prompt.debugger.check_empty_data(result) and prompt.backtrace is False: if res_type == result.END:
break break
elif res_type == result.PROMPT:
if prompt.debugger.wait_data(result): prompt.cmdloop()
continue elif res_type == result.TEXT:
write(result.get_text())
elif jerry_client_ws.JERRY_DEBUGGER_DATA_END in result:
result = result.replace(jerry_client_ws.JERRY_DEBUGGER_DATA_END, '')
if result.endswith('\n'):
result = result.rstrip()
if result:
print(result)
prompt.debugger.smessage = ''
if prompt.debugger.display > 0:
print(prompt.debugger.print_source(prompt.debugger.display, prompt.debugger.src_offset).get_data())
prompt.backtrace = False
break
else:
if result.endswith('\n'):
result = result.rstrip()
if result:
print(result)
prompt.debugger.smessage = ''
if prompt.debugger.display > 0:
print(prompt.debugger.print_source(prompt.debugger.display, prompt.debugger.src_offset).get_data())
prompt.cmdloop()
continue continue
if __name__ == "__main__": if __name__ == "__main__":
+206 -224
View File
@@ -225,17 +225,21 @@ class Multimap(object):
return "Multimap(%r)" % (self.map) return "Multimap(%r)" % (self.map)
class DisplayData(object): class DebuggerAction(object):
END = 0
WAIT = 1
TEXT = 2
PROMPT = 3
def __init__(self, stype, sdata): def __init__(self, action_type, action_text):
self.stype = stype self.action_type = action_type
self.sdata = sdata self.action_text = action_text
def get_type(self): def get_type(self):
return self.stype return self.action_type
def get_data(self): def get_text(self):
return self.sdata return self.action_text
class JerryDebugger(object): class JerryDebugger(object):
@@ -252,9 +256,12 @@ class JerryDebugger(object):
print("Connecting to: %s:%s" % (self.host, self.port)) print("Connecting to: %s:%s" % (self.host, self.port))
self.message_data = b"" self.message_data = b""
self.prompt = False
self.function_list = {} self.function_list = {}
self.source = '' self.source = ''
self.source_name = '' self.source_name = ''
self.exception_string = ''
self.frame_index = 0
self.client_sources = [] self.client_sources = []
self.last_breakpoint_hit = None self.last_breakpoint_hit = None
self.next_breakpoint_index = 0 self.next_breakpoint_index = 0
@@ -274,11 +281,6 @@ class JerryDebugger(object):
self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.client_socket.connect((self.host, self.port)) self.client_socket.connect((self.host, self.port))
self.non_interactive = False self.non_interactive = False
self.breakpoint_info = ''
self.smessage = ''
self.min_depth = 0
self.max_depth = 0
self.get_total = 0
self.send_message(b"GET /jerry-debugger HTTP/1.1\r\n" + self.send_message(b"GET /jerry-debugger HTTP/1.1\r\n" +
b"Upgrade: websocket\r\n" + b"Upgrade: websocket\r\n" +
@@ -363,53 +365,53 @@ class JerryDebugger(object):
self.send_command(command_id) self.send_command(command_id)
def quit(self): def quit(self):
self._exec_command(JERRY_DEBUGGER_CONTINUE) self.prompt = False
def get_continue(self):
self._exec_command(JERRY_DEBUGGER_CONTINUE) self._exec_command(JERRY_DEBUGGER_CONTINUE)
def stop(self): def stop(self):
self.send_command(JERRY_DEBUGGER_STOP) self.send_command(JERRY_DEBUGGER_STOP)
def get_continue(self):
self.prompt = False
self._exec_command(JERRY_DEBUGGER_CONTINUE)
def finish(self): def finish(self):
self.prompt = False
self._exec_command(JERRY_DEBUGGER_FINISH) self._exec_command(JERRY_DEBUGGER_FINISH)
def next(self): def next(self):
self.prompt = False
self._exec_command(JERRY_DEBUGGER_NEXT) self._exec_command(JERRY_DEBUGGER_NEXT)
def step(self): def step(self):
self.prompt = False
self._exec_command(JERRY_DEBUGGER_STEP) self._exec_command(JERRY_DEBUGGER_STEP)
def memstats(self): def memstats(self):
self.prompt = False
self._exec_command(JERRY_DEBUGGER_MEMSTATS) self._exec_command(JERRY_DEBUGGER_MEMSTATS)
def set_break(self, args): def set_break(self, args):
if args == "": if not args:
return DisplayData("break", "Error: Breakpoint index expected") return "Error: Breakpoint index expected"
elif ':' in args:
try:
args_second = int(args.split(':', 1)[1])
if args_second < 0:
return DisplayData("break", "Error: Positive breakpoint index expected")
else:
_set_breakpoint(self, args, False)
except ValueError as val_errno:
return DisplayData("break", "Positive breakpoint index expected: %s" % val_errno)
else:
_set_breakpoint(self, args, False)
if self.breakpoint_info == '':
return None
sbp = self.breakpoint_info if ':' in args:
self.breakpoint_info = '' try:
return DisplayData("break", sbp) if int(args.split(':', 1)[1]) <= 0:
return "Error: Positive breakpoint index expected"
return _set_breakpoint(self, args, False)
except ValueError as val_errno:
return "Error: Positive breakpoint index expected: %s" % (val_errno)
return _set_breakpoint(self, args, False)
def delete(self, args): def delete(self, args):
if not args: if not args:
result = "Error: Breakpoint index expected\n" \ return "Error: Breakpoint index expected\n" \
"Delete the given breakpoint, use 'delete all|active|pending' \ "Delete the given breakpoint, use 'delete all|active|pending' " \
to clear all the given breakpoints " "to clear all the given breakpoints\n "
return DisplayData("delete", result)
elif args in ['all', 'pending', 'active']: elif args in ['all', 'pending', 'active']:
if args == "all": if args == "all":
self.delete_active() self.delete_active()
@@ -418,25 +420,28 @@ class JerryDebugger(object):
self.delete_pending() self.delete_pending()
elif args == "active": elif args == "active":
self.delete_active() self.delete_active()
return ""
try:
breakpoint_index = int(args)
except ValueError as val_errno:
return "Error: Integer number expected, %s\n" % (val_errno)
if breakpoint_index in self.active_breakpoint_list:
breakpoint = self.active_breakpoint_list[breakpoint_index]
del self.active_breakpoint_list[breakpoint_index]
breakpoint.active_index = -1
self.send_breakpoint(breakpoint)
return "Breakpoint %d deleted\n" % (breakpoint_index)
elif breakpoint_index in self.pending_breakpoint_list:
del self.pending_breakpoint_list[breakpoint_index]
if not self.pending_breakpoint_list:
self.send_parser_config(0)
return "Pending breakpoint %d deleted\n" % (breakpoint_index)
else: else:
try: return "Error: Breakpoint %d not found\n" % (breakpoint_index)
breakpoint_index = int(args)
except ValueError as val_errno:
return DisplayData("delete", "Error: Integer number expected, %s" % (val_errno))
if breakpoint_index in self.active_breakpoint_list: def breakpoint_list(self):
breakpoint = self.active_breakpoint_list[breakpoint_index]
del self.active_breakpoint_list[breakpoint_index]
breakpoint.active_index = -1
self.send_breakpoint(breakpoint)
elif breakpoint_index in self.pending_breakpoint_list:
del self.pending_breakpoint_list[breakpoint_index]
if not self.pending_breakpoint_list:
self.send_parser_config(0)
else:
return DisplayData("delete", "Error: Breakpoint %d not found" % (breakpoint_index))
def show_breakpoint_list(self):
result = '' result = ''
if self.active_breakpoint_list: if self.active_breakpoint_list:
result += "=== %sActive breakpoints %s ===\n" % (self.green_bg, self.nocolor) result += "=== %sActive breakpoints %s ===\n" % (self.green_bg, self.nocolor)
@@ -448,82 +453,87 @@ class JerryDebugger(object):
result += " %d: %s (pending)\n" % (breakpoint.index, breakpoint) result += " %d: %s (pending)\n" % (breakpoint.index, breakpoint)
if not self.active_breakpoint_list and not self.pending_breakpoint_list: if not self.active_breakpoint_list and not self.pending_breakpoint_list:
result += "No breakpoints" result += "No breakpoints\n"
if result[-1:] == '\n':
result = result[:-1] return result
return DisplayData("delete", result)
def backtrace(self, args): def backtrace(self, args):
self.min_depth = 0 max_depth = 0
self.max_depth = 0 min_depth = 0
self.get_total = 0 get_total = 0
if args: if args:
args = args.split(" ") args = args.split(" ")
try: try:
if "t" in args: if "t" in args:
self.get_total = 1 get_total = 1
args = args[:-1] args.remove("t")
if len(args) == 2:
self.min_depth = int(args[0])
self.max_depth = int(args[1])
if self.max_depth <= 0 or self.min_depth < 0:
return DisplayData("backtrace", "Error: Positive integer number expected")
if self.min_depth > self.max_depth:
return DisplayData("backtrace", "Error: Start depth needs to be lower than or equal to max" \
" depth")
elif len(args) == 1: if len(args) >= 2:
self.max_depth = int(args[0]) min_depth = int(args[0])
if self.max_depth <= 0: max_depth = int(args[1])
return DisplayData("backtrace", "Error: Positive integer number expected") if max_depth <= 0 or min_depth < 0:
return "Error: Positive integer number expected\n"
if min_depth > max_depth:
return "Error: Start depth needs to be lower than or equal to max depth\n"
elif len(args) >= 1:
max_depth = int(args[0])
if max_depth <= 0:
return "Error: Positive integer number expected\n"
except ValueError as val_errno: except ValueError as val_errno:
return DisplayData("backtrace", "Error: Positive integer number expected, %s" % (val_errno)) return "Error: Positive integer number expected, %s\n" % (val_errno)
message = struct.pack(self.byte_order + "BBIB" + self.idx_format + self.idx_format + "B", self.frame_index = min_depth
message = struct.pack(self.byte_order + "BBIB" + self.idx_format + self.idx_format + "B",
WEBSOCKET_BINARY_FRAME | WEBSOCKET_FIN_BIT, WEBSOCKET_BINARY_FRAME | WEBSOCKET_FIN_BIT,
WEBSOCKET_FIN_BIT + 1 + 4 + 4 + 1, WEBSOCKET_FIN_BIT + 1 + 4 + 4 + 1,
0, 0,
JERRY_DEBUGGER_GET_BACKTRACE, JERRY_DEBUGGER_GET_BACKTRACE,
self.min_depth, min_depth,
self.max_depth, max_depth,
self.get_total) get_total)
self.send_message(message) self.send_message(message)
self.prompt = False
return ""
def eval(self, code): def eval(self, code):
self._send_string(JERRY_DEBUGGER_EVAL_EVAL + code, JERRY_DEBUGGER_EVAL) self._send_string(JERRY_DEBUGGER_EVAL_EVAL + code, JERRY_DEBUGGER_EVAL)
self.prompt = False
def throw(self, code): def throw(self, code):
self._send_string(JERRY_DEBUGGER_EVAL_THROW + code, JERRY_DEBUGGER_EVAL) self._send_string(JERRY_DEBUGGER_EVAL_THROW + code, JERRY_DEBUGGER_EVAL)
self.prompt = False
def abort(self, args): def abort(self, args):
self.delete("all") self.delete("all")
self.exception("0") # disable the exception handler self.exception("0") # disable the exception handler
self._send_string(JERRY_DEBUGGER_EVAL_ABORT + args, JERRY_DEBUGGER_EVAL) self._send_string(JERRY_DEBUGGER_EVAL_ABORT + args, JERRY_DEBUGGER_EVAL)
self.prompt = False
def restart(self): def restart(self):
self._send_string(JERRY_DEBUGGER_EVAL_ABORT + "\"r353t\"", JERRY_DEBUGGER_EVAL) self._send_string(JERRY_DEBUGGER_EVAL_ABORT + "\"r353t\"", JERRY_DEBUGGER_EVAL)
self.prompt = False
def exception(self, args): def exception(self, args):
try: try:
enabled = int(args) enabled = int(args)
except (ValueError, TypeError) as val_errno: except (ValueError, TypeError):
return DisplayData("exception", "Error: Positive integer number expected, %s" % (val_errno)) enabled = -1
if enabled not in [0, 1]: if enabled not in [0, 1]:
return DisplayData("delete", "Error: Invalid input! Usage 1: [Enable] or 0: [Disable].") return "Error: Invalid input! Usage 1: [Enable] or 0: [Disable]\n"
if enabled: if enabled:
logging.debug("Stop at exception enabled") logging.debug("Stop at exception enabled")
self.send_exception_config(enabled) self.send_exception_config(enabled)
return DisplayData("exception", "Stop at exception enabled") return "Stop at exception enabled\n"
logging.debug("Stop at exception disabled") logging.debug("Stop at exception disabled")
self.send_exception_config(enabled) self.send_exception_config(enabled)
return DisplayData("exception", "Stop at exception disabled") return "Stop at exception disabled\n"
def _send_string(self, args, message_type): def _send_string(self, args, message_type):
size = len(args) size = len(args)
@@ -705,10 +715,9 @@ class JerryDebugger(object):
def send_no_more_source(self): def send_no_more_source(self):
self._exec_command(JERRY_DEBUGGER_NO_MORE_SOURCES) self._exec_command(JERRY_DEBUGGER_NO_MORE_SOURCES)
# pylint: disable=too-many-branches,too-many-locals,too-many-statements # pylint: disable=too-many-branches,too-many-locals,too-many-statements,too-many-return-statements
def mainloop(self): def process_messages(self):
result = '' result = ""
exception_string = ""
while True: while True:
data = self.get_message(False) data = self.get_message(False)
@@ -717,17 +726,13 @@ class JerryDebugger(object):
if sys.stdin in select.select([sys.stdin], [], [], 0)[0]: if sys.stdin in select.select([sys.stdin], [], [], 0)[0]:
sys.stdin.readline() sys.stdin.readline()
self.stop() self.stop()
continue
if data == b'': if data == b'':
continue action_type = DebuggerAction.PROMPT if self.prompt else DebuggerAction.WAIT
return DebuggerAction(action_type, "")
if not data: # Break the while loop if there is no more data. if not data: # Break the while loop if there is no more data.
if result[-1:] == '\n': return DebuggerAction(DebuggerAction.END, "")
result = result[:-1]
result += JERRY_DEBUGGER_DATA_END
self.smessage = result
return DisplayData("EOF", self.smessage)
buffer_type = ord(data[2]) buffer_type = ord(data[2])
buffer_size = ord(data[1]) - 1 buffer_size = ord(data[1]) - 1
@@ -744,7 +749,9 @@ class JerryDebugger(object):
JERRY_DEBUGGER_SOURCE_CODE_NAME_END, JERRY_DEBUGGER_SOURCE_CODE_NAME_END,
JERRY_DEBUGGER_FUNCTION_NAME, JERRY_DEBUGGER_FUNCTION_NAME,
JERRY_DEBUGGER_FUNCTION_NAME_END]: JERRY_DEBUGGER_FUNCTION_NAME_END]:
_parse_source(self, data) result = _parse_source(self, data)
if result:
return DebuggerAction(DebuggerAction.TEXT, result)
elif buffer_type == JERRY_DEBUGGER_WAITING_AFTER_PARSE: elif buffer_type == JERRY_DEBUGGER_WAITING_AFTER_PARSE:
self.send_command(JERRY_DEBUGGER_PARSER_RESUME) self.send_command(JERRY_DEBUGGER_PARSER_RESUME)
@@ -760,9 +767,9 @@ class JerryDebugger(object):
if buffer_type == JERRY_DEBUGGER_EXCEPTION_HIT: if buffer_type == JERRY_DEBUGGER_EXCEPTION_HIT:
result += "Exception throw detected (to disable automatic stop type exception 0)\n" result += "Exception throw detected (to disable automatic stop type exception 0)\n"
if exception_string: if self.exception_string:
result += "Exception hint: %s\n" % (exception_string) result += "Exception hint: %s\n" % (self.exception_string)
exception_string = "" self.exception_string = ""
if breakpoint[1]: if breakpoint[1]:
breakpoint_info = "at" breakpoint_info = "at"
@@ -771,70 +778,48 @@ class JerryDebugger(object):
if breakpoint[0].active_index >= 0: if breakpoint[0].active_index >= 0:
breakpoint_info += " breakpoint:%s%d%s" % (self.red, breakpoint[0].active_index, self.nocolor) breakpoint_info += " breakpoint:%s%d%s" % (self.red, breakpoint[0].active_index, self.nocolor)
if self.breakpoint_info != '':
result += self.breakpoint_info + '\n' result += "Stopped %s %s\n" % (breakpoint_info, breakpoint[0])
self.breakpoint_info = ''
result += "Stopped %s %s" % (breakpoint_info, breakpoint[0]) if self.display > 0:
self.smessage = result result += self.print_source(self.display, self.src_offset)
return DisplayData("break/exception", self.smessage)
self.prompt = True
return DebuggerAction(DebuggerAction.TEXT, result)
elif buffer_type == JERRY_DEBUGGER_EXCEPTION_STR: elif buffer_type == JERRY_DEBUGGER_EXCEPTION_STR:
exception_string += data[3:] self.exception_string += data[3:]
elif buffer_type == JERRY_DEBUGGER_EXCEPTION_STR_END: elif buffer_type == JERRY_DEBUGGER_EXCEPTION_STR_END:
exception_string += data[3:] self.exception_string += data[3:]
elif buffer_type in [JERRY_DEBUGGER_BACKTRACE, elif buffer_type == JERRY_DEBUGGER_BACKTRACE_TOTAL:
JERRY_DEBUGGER_BACKTRACE_END, total = struct.unpack(self.byte_order + self.idx_format, data[3:])[0]
JERRY_DEBUGGER_BACKTRACE_TOTAL]: result += "Total number of frames: %d\n" % (total)
if self.min_depth != 0: return DebuggerAction(DebuggerAction.TEXT, result)
frame_index = self.min_depth
elif buffer_type in [JERRY_DEBUGGER_BACKTRACE, JERRY_DEBUGGER_BACKTRACE_END]:
frame_index = self.frame_index
buffer_pos = 3
while buffer_size > 0:
breakpoint_data = struct.unpack(self.byte_order + self.cp_format + self.idx_format,
data[buffer_pos: buffer_pos + self.cp_size + 4])
breakpoint = _get_breakpoint(self, breakpoint_data)
result += "Frame %d: %s\n" % (frame_index, breakpoint[0])
frame_index += 1
buffer_pos += 6
buffer_size -= 6
if buffer_type == JERRY_DEBUGGER_BACKTRACE_END:
self.prompt = True
else: else:
frame_index = 0 self.frame_index = frame_index
total_frames = 0 return DebuggerAction(DebuggerAction.TEXT, result)
while True:
if buffer_type == JERRY_DEBUGGER_BACKTRACE_TOTAL:
total_frames = struct.unpack(self.byte_order + self.idx_format, data[3:7])[0]
buffer_pos = 3
while buffer_size > 4:
breakpoint_data = struct.unpack(self.byte_order + self.cp_format + self.idx_format,
data[buffer_pos: buffer_pos + self.cp_size + 4])
breakpoint = _get_breakpoint(self, breakpoint_data)
result += "Frame %d: %s" % (frame_index, breakpoint[0])
frame_index += 1
buffer_pos += 6
buffer_size -= 6
if buffer_size > 0:
result += '\n'
if buffer_type == JERRY_DEBUGGER_BACKTRACE_END:
if self.get_total == 1:
if self.max_depth > total_frames:
self.max_depth = total_frames
if self.max_depth == 0:
result += ("\nTotal Frames: %d" % total_frames)
elif self.min_depth != 0 and self.max_depth != 0 and \
(self.max_depth - self.min_depth) > 0:
result += ("\nGetting %d frames. There are %d in total." %
((self.max_depth - self.min_depth), total_frames))
elif self.min_depth == 0 and self.max_depth != 0:
result += ("\nGetting the first %d frames out of %d." % (self.max_depth, total_frames))
break
data = self.get_message(True)
buffer_type = ord(data[2])
buffer_size = ord(data[1]) - 1
if buffer_type not in [JERRY_DEBUGGER_BACKTRACE,
JERRY_DEBUGGER_BACKTRACE_END]:
raise Exception("Backtrace data expected")
self.smessage = result
return DisplayData("backtrace", self.smessage)
elif buffer_type in [JERRY_DEBUGGER_EVAL_RESULT, elif buffer_type in [JERRY_DEBUGGER_EVAL_RESULT,
JERRY_DEBUGGER_EVAL_RESULT_END, JERRY_DEBUGGER_EVAL_RESULT_END,
@@ -859,31 +844,35 @@ class JerryDebugger(object):
if buffer_type not in [msg_type, msg_type + 1]: if buffer_type not in [msg_type, msg_type + 1]:
raise Exception("Invalid data caught") raise Exception("Invalid data caught")
if not message.endswith("\n"):
message += "\n"
# Subtypes of output # Subtypes of output
if buffer_type == JERRY_DEBUGGER_OUTPUT_RESULT_END: if buffer_type == JERRY_DEBUGGER_OUTPUT_RESULT_END:
message = message.rstrip('\n')
if subtype in [JERRY_DEBUGGER_OUTPUT_OK, if subtype in [JERRY_DEBUGGER_OUTPUT_OK,
JERRY_DEBUGGER_OUTPUT_DEBUG]: JERRY_DEBUGGER_OUTPUT_DEBUG]:
result += "%sout: %s%s\n" % (self.blue, self.nocolor, message) result += "%sout: %s%s" % (self.blue, self.nocolor, message)
elif subtype == JERRY_DEBUGGER_OUTPUT_WARNING: elif subtype == JERRY_DEBUGGER_OUTPUT_WARNING:
result += "%swarning: %s%s\n" % (self.yellow, self.nocolor, message) result += "%swarning: %s%s" % (self.yellow, self.nocolor, message)
elif subtype == JERRY_DEBUGGER_OUTPUT_ERROR: elif subtype == JERRY_DEBUGGER_OUTPUT_ERROR:
result += "%serr: %s%s\n" % (self.red, self.nocolor, message) result += "%serr: %s%s" % (self.red, self.nocolor, message)
elif subtype == JERRY_DEBUGGER_OUTPUT_TRACE: elif subtype == JERRY_DEBUGGER_OUTPUT_TRACE:
result += "%strace: %s%s\n" % (self.blue, self.nocolor, message) result += "%strace: %s%s" % (self.blue, self.nocolor, message)
# Subtypes of eval # Subtypes of eval
elif buffer_type == JERRY_DEBUGGER_EVAL_RESULT_END: else:
self.prompt = True
if subtype == JERRY_DEBUGGER_EVAL_ERROR: if subtype == JERRY_DEBUGGER_EVAL_ERROR:
result += "Uncaught exception: %s" % (message) result += "Uncaught exception: %s" % (message)
else: else:
result += message result += message
self.smessage = result
return DisplayData("eval_result", self.smessage) return DebuggerAction(DebuggerAction.TEXT, result)
elif buffer_type == JERRY_DEBUGGER_MEMSTATS_RECEIVE: elif buffer_type == JERRY_DEBUGGER_MEMSTATS_RECEIVE:
memory_stats = struct.unpack(self.byte_order + self.idx_format *5, memory_stats = struct.unpack(self.byte_order + self.idx_format * 5,
data[3: 3 + 4 *5]) data[3: 3 + 4 * 5])
result += "Allocated bytes: %s\n" % memory_stats[0] result += "Allocated bytes: %s\n" % memory_stats[0]
result += "Byte code bytes: %s\n" % memory_stats[1] result += "Byte code bytes: %s\n" % memory_stats[1]
@@ -891,8 +880,8 @@ class JerryDebugger(object):
result += "Object bytes: %s\n" % memory_stats[3] result += "Object bytes: %s\n" % memory_stats[3]
result += "Property bytes: %s\n" % memory_stats[4] result += "Property bytes: %s\n" % memory_stats[4]
self.smessage = str(result) self.prompt = True
return DisplayData("memstats", self.smessage) return DebuggerAction(DebuggerAction.TEXT, result)
elif buffer_type == JERRY_DEBUGGER_WAIT_FOR_SOURCE: elif buffer_type == JERRY_DEBUGGER_WAIT_FOR_SOURCE:
self.send_client_source() self.send_client_source()
@@ -900,11 +889,11 @@ class JerryDebugger(object):
raise Exception("Unknown message") raise Exception("Unknown message")
def print_source(self, line_num, offset): def print_source(self, line_num, offset):
msg = '' msg = ""
last_bp = self.last_breakpoint_hit last_bp = self.last_breakpoint_hit
if not last_bp: if not last_bp:
return None return ""
lines = last_bp.function.source lines = last_bp.function.source
if last_bp.function.source_name: if last_bp.function.source_name:
@@ -933,20 +922,9 @@ class JerryDebugger(object):
self.nocolor, lines[i]) self.nocolor, lines[i])
else: else:
msg += "%s%4d%s %s\n" % (self.green, i + 1, self.nocolor, lines[i]) msg += "%s%4d%s %s\n" % (self.green, i + 1, self.nocolor, lines[i])
msg = msg[:-1]
return DisplayData("print_source", msg)
def not_empty(self, args): return msg
if args is not None:
return True
def wait_data(self, args):
if args is None:
return True
def check_empty_data(self, args):
if not args:
return True
# pylint: disable=too-many-branches,too-many-locals,too-many-statements # pylint: disable=too-many-branches,too-many-locals,too-many-statements
def _parse_source(debugger, data): def _parse_source(debugger, data):
@@ -962,7 +940,7 @@ def _parse_source(debugger, data):
while True: while True:
if data is None: if data is None:
return return "Error: connection lost during source code receiving"
buffer_type = ord(data[2]) buffer_type = ord(data[2])
buffer_size = ord(data[1]) - 1 buffer_size = ord(data[1]) - 1
@@ -970,8 +948,8 @@ def _parse_source(debugger, data):
logging.debug("Parser buffer type: %d, message size: %d", buffer_type, buffer_size) logging.debug("Parser buffer type: %d, message size: %d", buffer_type, buffer_size)
if buffer_type == JERRY_DEBUGGER_PARSE_ERROR: if buffer_type == JERRY_DEBUGGER_PARSE_ERROR:
logging.error("Parser error!") logging.error("Syntax error found")
return return ""
elif buffer_type in [JERRY_DEBUGGER_SOURCE_CODE, JERRY_DEBUGGER_SOURCE_CODE_END]: elif buffer_type in [JERRY_DEBUGGER_SOURCE_CODE, JERRY_DEBUGGER_SOURCE_CODE_END]:
source_code += data[3:] source_code += data[3:]
@@ -1054,7 +1032,7 @@ def _parse_source(debugger, data):
else: else:
logging.error("Parser error!") logging.error("Parser error!")
return raise Exception("Unexpected message")
data = debugger.get_message(True) data = debugger.get_message(True)
@@ -1067,31 +1045,39 @@ def _parse_source(debugger, data):
# Try to set the pending breakpoints # Try to set the pending breakpoints
if debugger.pending_breakpoint_list: if debugger.pending_breakpoint_list:
result = ""
logging.debug("Pending breakpoints list: %s", debugger.pending_breakpoint_list) logging.debug("Pending breakpoints list: %s", debugger.pending_breakpoint_list)
bp_list = debugger.pending_breakpoint_list bp_list = debugger.pending_breakpoint_list
for breakpoint_index, breakpoint in bp_list.items(): for breakpoint_index, breakpoint in bp_list.items():
for src in debugger.function_list.values(): source_lines = 0
for src in new_function_list.values():
if src.source_name == breakpoint.source_name: if src.source_name == breakpoint.source_name:
source_lines = len(src.source) source_lines = len(src.source)
else: break
source_lines = 0
if breakpoint.line: if breakpoint.line:
if breakpoint.line <= source_lines: if breakpoint.line <= source_lines:
command = breakpoint.source_name + ":" + str(breakpoint.line) command = breakpoint.source_name + ":" + str(breakpoint.line)
if _set_breakpoint(debugger, command, True): set_result = _set_breakpoint(debugger, command, True)
if set_result:
result += set_result
del bp_list[breakpoint_index] del bp_list[breakpoint_index]
elif breakpoint.function: elif breakpoint.function:
command = breakpoint.function command = breakpoint.function
if _set_breakpoint(debugger, command, True): set_result = _set_breakpoint(debugger, command, True)
if set_result:
result += set_result
del bp_list[breakpoint_index] del bp_list[breakpoint_index]
if not bp_list: if not bp_list:
debugger.send_parser_config(0) debugger.send_parser_config(0)
return result
else: logging.debug("No pending breakpoints")
logging.debug("No pending breakpoints") return ""
def _release_function(debugger, data): def _release_function(debugger, data):
@@ -1112,30 +1098,31 @@ def _release_function(debugger, data):
def _enable_breakpoint(debugger, breakpoint): def _enable_breakpoint(debugger, breakpoint):
if isinstance(breakpoint, JerryPendingBreakpoint): if isinstance(breakpoint, JerryPendingBreakpoint):
if not debugger.breakpoint_pending_exists(breakpoint): if debugger.breakpoint_pending_exists(breakpoint):
debugger.next_breakpoint_index += 1 return "%sPending breakpoint%s already exists\n" % (debugger.yellow, debugger.nocolor)
breakpoint.index = debugger.next_breakpoint_index
debugger.pending_breakpoint_list[debugger.next_breakpoint_index] = breakpoint debugger.next_breakpoint_index += 1
print("%sPending breakpoint%s at %s" % (debugger.yellow, debugger.nocolor, breakpoint)) breakpoint.index = debugger.next_breakpoint_index
else: debugger.pending_breakpoint_list[debugger.next_breakpoint_index] = breakpoint
print("%sPending breakpoint%s already exists" % (debugger.yellow, debugger.nocolor)) return ("%sPending breakpoint %d%s at %s\n" % (debugger.yellow,
else: breakpoint.index,
if breakpoint.active_index < 0: debugger.nocolor,
debugger.next_breakpoint_index += 1 breakpoint))
debugger.active_breakpoint_list[debugger.next_breakpoint_index] = breakpoint if breakpoint.active_index < 0:
breakpoint.active_index = debugger.next_breakpoint_index debugger.next_breakpoint_index += 1
debugger.send_breakpoint(breakpoint) debugger.active_breakpoint_list[debugger.next_breakpoint_index] = breakpoint
if debugger.breakpoint_info: breakpoint.active_index = debugger.next_breakpoint_index
debugger.breakpoint_info += '\n' debugger.send_breakpoint(breakpoint)
debugger.breakpoint_info += "%sBreakpoint %d %sat %s" % (debugger.green,
breakpoint.active_index, return "%sBreakpoint %d%s at %s\n" % (debugger.green,
debugger.nocolor, breakpoint.active_index,
breakpoint) debugger.nocolor,
breakpoint)
def _set_breakpoint(debugger, string, pending): def _set_breakpoint(debugger, string, pending):
line = re.match("(.*):(\\d+)$", string) line = re.match("(.*):(\\d+)$", string)
found = False result = ""
if line: if line:
source_name = line.group(1) source_name = line.group(1)
@@ -1147,16 +1134,14 @@ def _set_breakpoint(debugger, string, pending):
func_source.endswith("/" + source_name) or func_source.endswith("/" + source_name) or
func_source.endswith("\\" + source_name)): func_source.endswith("\\" + source_name)):
_enable_breakpoint(debugger, breakpoint) result += _enable_breakpoint(debugger, breakpoint)
found = True
else: else:
for function in debugger.function_list.values(): for function in debugger.function_list.values():
if function.name == string: if function.name == string:
_enable_breakpoint(debugger, function.lines[function.first_breakpoint_line]) result += _enable_breakpoint(debugger, function.lines[function.first_breakpoint_line])
found = True
if not found and not pending: if not result and not pending:
print("No breakpoint found, do you want to add a %spending breakpoint%s? (y or [n])" % \ print("No breakpoint found, do you want to add a %spending breakpoint%s? (y or [n])" % \
(debugger.yellow, debugger.nocolor)) (debugger.yellow, debugger.nocolor))
@@ -1169,12 +1154,9 @@ def _set_breakpoint(debugger, string, pending):
breakpoint = JerryPendingBreakpoint(int(line.group(2)), line.group(1)) breakpoint = JerryPendingBreakpoint(int(line.group(2)), line.group(1))
else: else:
breakpoint = JerryPendingBreakpoint(function=string) breakpoint = JerryPendingBreakpoint(function=string)
_enable_breakpoint(debugger, breakpoint) result += _enable_breakpoint(debugger, breakpoint)
elif not found and pending: return result
return False
return True
def _get_breakpoint(debugger, breakpoint_data): def _get_breakpoint(debugger, breakpoint_data):
+3 -3
View File
@@ -15,15 +15,15 @@ Stopped at tests/debugger/do_backtrace.js:33 (in test() at line:30, col:1)
(jerry-debugger) s (jerry-debugger) s
Stopped at tests/debugger/do_backtrace.js:23 (in foo() at line:21, col:1) Stopped at tests/debugger/do_backtrace.js:23 (in foo() at line:21, col:1)
(jerry-debugger) bt 1 2 t (jerry-debugger) bt 1 2 t
Total number of frames: 3
Frame 1: tests/debugger/do_backtrace.js:33 (in test() at line:30, col:1) Frame 1: tests/debugger/do_backtrace.js:33 (in test() at line:30, col:1)
Getting 1 frames. There are 3 in total.
(jerry-debugger) bt 1 2 (jerry-debugger) bt 1 2
Frame 1: tests/debugger/do_backtrace.js:33 (in test() at line:30, col:1) Frame 1: tests/debugger/do_backtrace.js:33 (in test() at line:30, col:1)
(jerry-debugger) bt 0 3 t (jerry-debugger) bt 0 3 t
Total number of frames: 3
Frame 0: tests/debugger/do_backtrace.js:23 (in foo() at line:21, col:1) 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 1: tests/debugger/do_backtrace.js:33 (in test() at line:30, col:1)
Frame 2: tests/debugger/do_backtrace.js:40 Frame 2: tests/debugger/do_backtrace.js:40
Getting the first 3 frames out of 3.
(jerry-debugger) bt (jerry-debugger) bt
Frame 0: tests/debugger/do_backtrace.js:23 (in foo() at line:21, col:1) 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 1: tests/debugger/do_backtrace.js:33 (in test() at line:30, col:1)
@@ -32,9 +32,9 @@ Frame 2: tests/debugger/do_backtrace.js:40
Frame 0: tests/debugger/do_backtrace.js:23 (in foo() at line:21, col:1) 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 1: tests/debugger/do_backtrace.js:33 (in test() at line:30, col:1)
(jerry-debugger) bt 2 t (jerry-debugger) bt 2 t
Total number of frames: 3
Frame 0: tests/debugger/do_backtrace.js:23 (in foo() at line:21, col:1) 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 1: tests/debugger/do_backtrace.js:33 (in test() at line:30, col:1)
Getting the first 2 frames out of 3.
(jerry-debugger) n (jerry-debugger) n
out: function foo out: function foo
Stopped at tests/debugger/do_backtrace.js:24 (in foo() at line:21, col:1) Stopped at tests/debugger/do_backtrace.js:24 (in foo() at line:21, col:1)
+1
View File
@@ -18,6 +18,7 @@ out: break test
out: var cat out: var cat
Stopped at breakpoint:1 tests/debugger/do_break.js:51 Stopped at breakpoint:1 tests/debugger/do_break.js:51
(jerry-debugger) delete 1 (jerry-debugger) delete 1
Breakpoint 1 deleted
(jerry-debugger) list (jerry-debugger) list
=== Active breakpoints === === Active breakpoints ===
2: tests/debugger/do_break.js:36 (in test() at line:20, col:1) 2: tests/debugger/do_break.js:36 (in test() at line:20, col:1)
+3 -1
View File
@@ -7,7 +7,7 @@ Stopped at tests/debugger/do_delete.js:17
Breakpoint 1 at tests/debugger/do_delete.js:17 Breakpoint 1 at tests/debugger/do_delete.js:17
(jerry-debugger) b do_delete.js:21 (jerry-debugger) b do_delete.js:21
No breakpoint found, do you want to add a pending breakpoint? (y or [n]) No breakpoint found, do you want to add a pending breakpoint? (y or [n])
Pending breakpoint at do_delete.js:21 Pending breakpoint 2 at do_delete.js:21
(jerry-debugger) b do_delete.js:19 (jerry-debugger) b do_delete.js:19
Breakpoint 3 at tests/debugger/do_delete.js:19 Breakpoint 3 at tests/debugger/do_delete.js:19
(jerry-debugger) b do_delete.js:18 (jerry-debugger) b do_delete.js:18
@@ -20,7 +20,9 @@ Breakpoint 4 at tests/debugger/do_delete.js:18
=== Pending breakpoints === === Pending breakpoints ===
2: do_delete.js:21 (pending) 2: do_delete.js:21 (pending)
(jerry-debugger) delete 2 (jerry-debugger) delete 2
Pending breakpoint 2 deleted
(jerry-debugger) delete 3 (jerry-debugger) delete 3
Breakpoint 3 deleted
(jerry-debugger) list (jerry-debugger) list
=== Active breakpoints === === Active breakpoints ===
1: tests/debugger/do_delete.js:17 1: tests/debugger/do_delete.js:17
+2 -2
View File
@@ -8,10 +8,10 @@ Breakpoint 2 at tests/debugger/do_delete_all.js:18
Breakpoint 3 at tests/debugger/do_delete_all.js:21 (in delete_test() at line:20, col:1) Breakpoint 3 at tests/debugger/do_delete_all.js:21 (in delete_test() at line:20, col:1)
(jerry-debugger) b do_delete_all:350 (jerry-debugger) b do_delete_all:350
No breakpoint found, do you want to add a pending breakpoint? (y or [n]) No breakpoint found, do you want to add a pending breakpoint? (y or [n])
Pending breakpoint at do_delete_all:350 Pending breakpoint 4 at do_delete_all:350
(jerry-debugger) b do_delete_all:37 (jerry-debugger) b do_delete_all:37
No breakpoint found, do you want to add a pending breakpoint? (y or [n]) No breakpoint found, do you want to add a pending breakpoint? (y or [n])
Pending breakpoint at do_delete_all:37 Pending breakpoint 5 at do_delete_all:37
(jerry-debugger) list (jerry-debugger) list
=== Active breakpoints === === Active breakpoints ===
1: tests/debugger/do_delete_all.js:17 1: tests/debugger/do_delete_all.js:17
@@ -2,10 +2,10 @@ Connecting to: localhost:5001
Stopped at tests/debugger/do_pending_breakpoints.js:15 Stopped at tests/debugger/do_pending_breakpoints.js:15
(jerry-debugger) break :1 (jerry-debugger) break :1
No breakpoint found, do you want to add a pending breakpoint? (y or [n]) No breakpoint found, do you want to add a pending breakpoint? (y or [n])
Pending breakpoint at :1 Pending breakpoint 1 at :1
(jerry-debugger) break f (jerry-debugger) break f
No breakpoint found, do you want to add a pending breakpoint? (y or [n]) No breakpoint found, do you want to add a pending breakpoint? (y or [n])
Pending breakpoint at f() Pending breakpoint 2 at f()
(jerry-debugger) list (jerry-debugger) list
=== Pending breakpoints === === Pending breakpoints ===
1: :1 (pending) 1: :1 (pending)