Skip to content

Commit e545934

Browse files
committed
Splitting the debugger and console part of the python debugger
Move DebuggerPrompt to jerry_client.py Implement JerryDebugger functions in the jerry_client_ws.py file Server response is displayed by jerry_client.py JerryScript-DCO-1.0-Signed-off-by: Tamas Zakor [email protected]
1 parent dfc0757 commit e545934

File tree

3 files changed

+756
-645
lines changed

3 files changed

+756
-645
lines changed

jerry-debugger/jerry_client.py

Lines changed: 327 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,327 @@
1+
#!/usr/bin/env python
2+
3+
# Copyright JS Foundation and other contributors, http://js.foundation
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
from __future__ import print_function
18+
from cmd import Cmd
19+
from pprint import pprint
20+
import math
21+
import socket
22+
import sys
23+
import logging
24+
import time
25+
import jerry_client_ws
26+
27+
class DebuggerPrompt(Cmd):
28+
# pylint: disable=too-many-instance-attributes,too-many-arguments
29+
def __init__(self, debugger):
30+
Cmd.__init__(self)
31+
self.debugger = debugger
32+
self.stop = False
33+
self.quit = False
34+
self.debugger.non_interactive = False
35+
36+
def precmd(self, line):
37+
self.stop = False
38+
if self.debugger.non_interactive:
39+
print("%s" % line)
40+
return line
41+
42+
def postcmd(self, stop, line):
43+
return self.stop
44+
45+
def do_quit(self, _):
46+
""" Exit JerryScript debugger """
47+
self.debugger.quit()
48+
self.quit = True
49+
self.stop = True
50+
51+
def do_display(self, args):
52+
""" Toggle source code display after breakpoints """
53+
if args:
54+
line_num = src_check_args(args)
55+
if line_num >= 0:
56+
self.debugger.display = line_num
57+
else:
58+
print("Non-negative integer number expected, 0 turns off this function")
59+
60+
def do_break(self, args):
61+
""" Insert breakpoints on the given lines or functions """
62+
sbreak = ""
63+
if args == "":
64+
print("Error: Breakpoint index expected")
65+
elif ':' in args:
66+
try:
67+
args_second = int(args.split(':', 1)[1])
68+
if args_second < 0:
69+
print("Error: Positive breakpoint index expected")
70+
else:
71+
sbreak = self.debugger.set_break(args)
72+
except ValueError as val_errno:
73+
print("Error: Positive breakpoint index expected: %s" % val_errno)
74+
else:
75+
sbreak = self.debugger.set_break(args)
76+
if sbreak is not None:
77+
print(sbreak)
78+
do_b = do_break
79+
80+
def do_list(self, _):
81+
""" Lists the available breakpoints """
82+
if self.debugger.active_breakpoint_list:
83+
print("=== %sActive breakpoints %s ===" % (self.debugger.green_bg, self.debugger.nocolor))
84+
for breakpoint in self.debugger.active_breakpoint_list.values():
85+
print(" %d: %s" % (breakpoint.active_index, breakpoint))
86+
87+
if self.debugger.pending_breakpoint_list:
88+
print("=== %sPending breakpoints%s ===" % (self.debugger.yellow_bg, self.debugger.nocolor))
89+
for breakpoint in self.debugger.pending_breakpoint_list.values():
90+
print(" %d: %s (pending)" % (breakpoint.index, breakpoint))
91+
92+
if not self.debugger.active_breakpoint_list and not self.debugger.pending_breakpoint_list:
93+
print("No breakpoints")
94+
95+
def do_delete(self, args):
96+
""" Delete the given breakpoint, use 'delete all|active|pending' to clear all the given breakpoints """
97+
result = ''
98+
if not args:
99+
print("Error: Breakpoint index expected")
100+
print("Delete the given breakpoint, use 'delete all|active|pending' to clear all the given breakpoints ")
101+
elif args in ['all', 'pending', 'active']:
102+
result = self.debugger.delete(args)
103+
else:
104+
try:
105+
result = self.debugger.delete(args)
106+
except ValueError as val_errno:
107+
result = "Error: Integer number expected, %s" % (val_errno)
108+
if result != '':
109+
print(result)
110+
111+
def do_next(self, args):
112+
""" Next breakpoint in the same context """
113+
self.stop = True
114+
if not args:
115+
args = 0
116+
self.debugger.next()
117+
else:
118+
try:
119+
args = int(args)
120+
if args <= 0:
121+
raise ValueError(args)
122+
else:
123+
while int(args) != 0:
124+
self.debugger.next()
125+
time.sleep(0.25)
126+
result = self.debugger.mainloop()
127+
if result[-1:] == '\n':
128+
result = result[:-1]
129+
if result != '':
130+
print(result)
131+
self.debugger.smessage = ''
132+
if self.debugger.display > 0:
133+
print(self.debugger.print_source(self.debugger.display,
134+
self.debugger.src_offset))
135+
args = int(args) - 1
136+
self.cmdloop()
137+
except ValueError as val_errno:
138+
print("Error: expected a positive integer: %s" % val_errno)
139+
self.cmdloop()
140+
do_n = do_next
141+
142+
def do_step(self, _):
143+
""" Next breakpoint, step into functions """
144+
self.debugger.step()
145+
self.stop = True
146+
do_s = do_step
147+
148+
def do_backtrace(self, args):
149+
""" Get backtrace data from debugger """
150+
self.debugger.backtrace(args)
151+
self.stop = True
152+
do_bt = do_backtrace
153+
154+
def do_src(self, args):
155+
""" Get current source code """
156+
if args:
157+
line_num = src_check_args(args)
158+
if line_num >= 0:
159+
print(self.debugger.print_source(line_num, 0))
160+
do_source = do_src
161+
162+
def do_scroll(self, _):
163+
""" Scroll the source up or down """
164+
while True:
165+
key = sys.stdin.readline()
166+
if key == 'w\n':
167+
_scroll_direction(self.debugger, "up")
168+
elif key == 's\n':
169+
_scroll_direction(self.debugger, "down")
170+
elif key == 'q\n':
171+
break
172+
else:
173+
print("Invalid key")
174+
175+
def do_continue(self, _):
176+
""" Continue execution """
177+
self.debugger.get_continue()
178+
self.stop = True
179+
if not self.debugger.non_interactive:
180+
print("Press enter to stop JavaScript execution.")
181+
do_c = do_continue
182+
183+
def do_finish(self, _):
184+
""" Continue running until the current function returns """
185+
self.debugger.finish()
186+
self.stop = True
187+
do_f = do_finish
188+
189+
def do_dump(self, args):
190+
""" Dump all of the debugger data """
191+
if args:
192+
print("Error: No argument expected")
193+
else:
194+
pprint(self.debugger.function_list)
195+
196+
def do_eval(self, args):
197+
""" Evaluate JavaScript source code """
198+
self.debugger.eval(args)
199+
self.stop = True
200+
do_e = do_eval
201+
202+
def do_memstats(self, _):
203+
""" Memory statistics """
204+
self.debugger.memstats()
205+
self.stop = True
206+
do_ms = do_memstats
207+
208+
def do_abort(self, args):
209+
""" Throw an exception """
210+
self.debugger.abort(args)
211+
self.stop = True
212+
213+
def do_restart(self, _):
214+
""" Restart the engine's debug session """
215+
self.debugger.restart()
216+
self.stop = True
217+
do_res = do_restart
218+
219+
def do_throw(self, args):
220+
""" Throw an exception """
221+
self.debugger.throw(args)
222+
self.stop = True
223+
224+
def do_exception(self, args):
225+
""" Config the exception handler module """
226+
print(self.debugger.exception(args))
227+
228+
def _scroll_direction(debugger, direction):
229+
""" Helper function for do_scroll """
230+
debugger.src_offset_diff = int(max(math.floor(debugger.display / 3), 1))
231+
if direction == "up":
232+
debugger.src_offset -= debugger.src_offset_diff
233+
else:
234+
debugger.src_offset += debugger.src_offset_diff
235+
print(debugger.print_source(debugger.display, debugger.src_offset))
236+
237+
def src_check_args(args):
238+
try:
239+
line_num = int(args)
240+
if line_num < 0:
241+
print("Error: Non-negative integer number expected")
242+
return -1
243+
244+
return line_num
245+
except ValueError as val_errno:
246+
print("Error: Non-negative integer number expected: %s" % (val_errno))
247+
return -1
248+
249+
# pylint: disable=too-many-branches,too-many-locals,too-many-statements
250+
def main():
251+
args = jerry_client_ws.arguments_parse()
252+
253+
debugger = jerry_client_ws.JerryDebugger(args.address)
254+
255+
non_interactive = args.non_interactive
256+
257+
logging.debug("Connected to JerryScript on %d port", debugger.port)
258+
259+
prompt = DebuggerPrompt(debugger)
260+
prompt.prompt = "(jerry-debugger) "
261+
prompt.debugger.non_interactive = non_interactive
262+
263+
if args.color:
264+
debugger.set_colors()
265+
266+
if args.display:
267+
prompt.debugger.display = args.display
268+
prompt.do_display(args.display)
269+
else:
270+
prompt.stop = False
271+
if not args.client_source:
272+
prompt.debugger.mainloop()
273+
result = prompt.debugger.smessage
274+
print(result)
275+
prompt.debugger.smessage = ''
276+
prompt.cmdloop()
277+
278+
if args.exception is not None:
279+
prompt.do_exception(str(args.exception))
280+
281+
if args.client_source:
282+
prompt.debugger.store_client_sources(args.client_source)
283+
284+
while True:
285+
if prompt.quit:
286+
break
287+
288+
result = prompt.debugger.mainloop()
289+
290+
if result == '':
291+
break
292+
if result is None:
293+
continue
294+
elif jerry_client_ws.JERRY_DEBUGGER_DATA_END in result:
295+
result = result.replace(jerry_client_ws.JERRY_DEBUGGER_DATA_END, '')
296+
if result.endswith('\n'):
297+
result = result.rstrip()
298+
if result:
299+
print(result)
300+
prompt.debugger.smessage = ''
301+
if prompt.debugger.display > 0:
302+
print(prompt.debugger.print_source(prompt.debugger.display, prompt.debugger.src_offset))
303+
break
304+
else:
305+
if result.endswith('\n'):
306+
result = result.rstrip()
307+
if result:
308+
print(result)
309+
prompt.debugger.smessage = ''
310+
if prompt.debugger.display > 0:
311+
print(prompt.debugger.print_source(prompt.debugger.display, prompt.debugger.src_offset))
312+
prompt.cmdloop()
313+
continue
314+
315+
316+
if __name__ == "__main__":
317+
try:
318+
main()
319+
except socket.error as error_msg:
320+
ERRNO = error_msg.errno
321+
MSG = str(error_msg)
322+
if ERRNO == 111:
323+
sys.exit("Failed to connect to the JerryScript debugger.")
324+
elif ERRNO == 32 or ERRNO == 104:
325+
sys.exit("Connection closed.")
326+
else:
327+
sys.exit("Failed to connect to the JerryScript debugger.\nError: %s" % (MSG))

0 commit comments

Comments
 (0)