Skip to content

Commit 479a8d1

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 479a8d1

File tree

3 files changed

+755
-645
lines changed

3 files changed

+755
-645
lines changed

jerry-debugger/jerry_client.py

Lines changed: 326 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,326 @@
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+
if args == "":
63+
print("Error: Breakpoint index expected")
64+
elif ':' in args:
65+
try:
66+
args_second = int(args.split(':', 1)[1])
67+
if args_second < 0:
68+
print("Error: Positive breakpoint index expected")
69+
else:
70+
sbreak = self.debugger.set_break(args)
71+
except ValueError as val_errno:
72+
print("Error: Positive breakpoint index expected: %s" % val_errno)
73+
else:
74+
sbreak = self.debugger.set_break(args)
75+
if sbreak is not None:
76+
print(sbreak)
77+
do_b = do_break
78+
79+
def do_list(self, _):
80+
""" Lists the available breakpoints """
81+
if self.debugger.active_breakpoint_list:
82+
print("=== %sActive breakpoints %s ===" % (self.debugger.green_bg, self.debugger.nocolor))
83+
for breakpoint in self.debugger.active_breakpoint_list.values():
84+
print(" %d: %s" % (breakpoint.active_index, breakpoint))
85+
86+
if self.debugger.pending_breakpoint_list:
87+
print("=== %sPending breakpoints%s ===" % (self.debugger.yellow_bg, self.debugger.nocolor))
88+
for breakpoint in self.debugger.pending_breakpoint_list.values():
89+
print(" %d: %s (pending)" % (breakpoint.index, breakpoint))
90+
91+
if not self.debugger.active_breakpoint_list and not self.debugger.pending_breakpoint_list:
92+
print("No breakpoints")
93+
94+
def do_delete(self, args):
95+
""" Delete the given breakpoint, use 'delete all|active|pending' to clear all the given breakpoints """
96+
result = ''
97+
if not args:
98+
print("Error: Breakpoint index expected")
99+
print("Delete the given breakpoint, use 'delete all|active|pending' to clear all the given breakpoints ")
100+
elif args in ['all', 'pending', 'active']:
101+
result = self.debugger.delete(args)
102+
else:
103+
try:
104+
result = self.debugger.delete(args)
105+
except ValueError as val_errno:
106+
result = "Error: Integer number expected, %s" % (val_errno)
107+
if result != '':
108+
print(result)
109+
110+
def do_next(self, args):
111+
""" Next breakpoint in the same context """
112+
self.stop = True
113+
if not args:
114+
args = 0
115+
self.debugger.next()
116+
else:
117+
try:
118+
args = int(args)
119+
if args <= 0:
120+
raise ValueError(args)
121+
else:
122+
while int(args) != 0:
123+
self.debugger.next()
124+
time.sleep(0.25)
125+
result = self.debugger.mainloop()
126+
if result[-1:] == '\n':
127+
result = result[:-1]
128+
if result != '':
129+
print(result)
130+
self.debugger.smessage = ''
131+
if self.debugger.display > 0:
132+
print(self.debugger.print_source(self.debugger.display,
133+
self.debugger.src_offset))
134+
args = int(args) - 1
135+
self.cmdloop()
136+
except ValueError as val_errno:
137+
print("Error: expected a positive integer: %s" % val_errno)
138+
self.cmdloop()
139+
do_n = do_next
140+
141+
def do_step(self, _):
142+
""" Next breakpoint, step into functions """
143+
self.debugger.step()
144+
self.stop = True
145+
do_s = do_step
146+
147+
def do_backtrace(self, args):
148+
""" Get backtrace data from debugger """
149+
self.debugger.backtrace(args)
150+
self.stop = True
151+
do_bt = do_backtrace
152+
153+
def do_src(self, args):
154+
""" Get current source code """
155+
if args:
156+
line_num = src_check_args(args)
157+
if line_num >= 0:
158+
print(self.debugger.print_source(line_num, 0))
159+
do_source = do_src
160+
161+
def do_scroll(self, _):
162+
""" Scroll the source up or down """
163+
while True:
164+
key = sys.stdin.readline()
165+
if key == 'w\n':
166+
_scroll_direction(self.debugger, "up")
167+
elif key == 's\n':
168+
_scroll_direction(self.debugger, "down")
169+
elif key == 'q\n':
170+
break
171+
else:
172+
print("Invalid key")
173+
174+
def do_continue(self, _):
175+
""" Continue execution """
176+
self.debugger.get_continue()
177+
self.stop = True
178+
if not self.debugger.non_interactive:
179+
print("Press enter to stop JavaScript execution.")
180+
do_c = do_continue
181+
182+
def do_finish(self, _):
183+
""" Continue running until the current function returns """
184+
self.debugger.finish()
185+
self.stop = True
186+
do_f = do_finish
187+
188+
def do_dump(self, args):
189+
""" Dump all of the debugger data """
190+
if args:
191+
print("Error: No argument expected")
192+
else:
193+
pprint(self.debugger.function_list)
194+
195+
def do_eval(self, args):
196+
""" Evaluate JavaScript source code """
197+
self.debugger.eval(args)
198+
self.stop = True
199+
do_e = do_eval
200+
201+
def do_memstats(self, _):
202+
""" Memory statistics """
203+
self.debugger.memstats()
204+
self.stop = True
205+
do_ms = do_memstats
206+
207+
def do_abort(self, args):
208+
""" Throw an exception """
209+
self.debugger.abort(args)
210+
self.stop = True
211+
212+
def do_restart(self, _):
213+
""" Restart the engine's debug session """
214+
self.debugger.restart()
215+
self.stop = True
216+
do_res = do_restart
217+
218+
def do_throw(self, args):
219+
""" Throw an exception """
220+
self.debugger.throw(args)
221+
self.stop = True
222+
223+
def do_exception(self, args):
224+
""" Config the exception handler module """
225+
print(self.debugger.exception(args))
226+
227+
def _scroll_direction(debugger, direction):
228+
""" Helper function for do_scroll """
229+
debugger.src_offset_diff = int(max(math.floor(debugger.display / 3), 1))
230+
if direction == "up":
231+
debugger.src_offset -= debugger.src_offset_diff
232+
else:
233+
debugger.src_offset += debugger.src_offset_diff
234+
print(debugger.print_source(debugger.display, debugger.src_offset))
235+
236+
def src_check_args(args):
237+
try:
238+
line_num = int(args)
239+
if line_num < 0:
240+
print("Error: Non-negative integer number expected")
241+
return -1
242+
243+
return line_num
244+
except ValueError as val_errno:
245+
print("Error: Non-negative integer number expected: %s" % (val_errno))
246+
return -1
247+
248+
# pylint: disable=too-many-branches,too-many-locals,too-many-statements
249+
def main():
250+
args = jerry_client_ws.arguments_parse()
251+
252+
debugger = jerry_client_ws.JerryDebugger(args.address)
253+
254+
non_interactive = args.non_interactive
255+
256+
logging.debug("Connected to JerryScript on %d port", debugger.port)
257+
258+
prompt = DebuggerPrompt(debugger)
259+
prompt.prompt = "(jerry-debugger) "
260+
prompt.debugger.non_interactive = non_interactive
261+
262+
if args.color:
263+
debugger.set_colors()
264+
265+
if args.display:
266+
prompt.debugger.display = args.display
267+
prompt.do_display(args.display)
268+
else:
269+
prompt.stop = False
270+
if not args.client_source:
271+
prompt.debugger.mainloop()
272+
result = prompt.debugger.smessage
273+
print(result)
274+
prompt.debugger.smessage = ''
275+
prompt.cmdloop()
276+
277+
if args.exception is not None:
278+
prompt.do_exception(str(args.exception))
279+
280+
if args.client_source:
281+
prompt.debugger.store_client_sources(args.client_source)
282+
283+
while True:
284+
if prompt.quit:
285+
break
286+
287+
result = prompt.debugger.mainloop()
288+
289+
if result == '':
290+
break
291+
if result is None:
292+
continue
293+
elif jerry_client_ws.JERRY_DEBUGGER_DATA_END in result:
294+
result = result.replace(jerry_client_ws.JERRY_DEBUGGER_DATA_END, '')
295+
if result.endswith('\n'):
296+
result = result.rstrip()
297+
if result:
298+
print(result)
299+
prompt.debugger.smessage = ''
300+
if prompt.debugger.display > 0:
301+
print(prompt.debugger.print_source(prompt.debugger.display, prompt.debugger.src_offset))
302+
break
303+
else:
304+
if result.endswith('\n'):
305+
result = result.rstrip()
306+
if result:
307+
print(result)
308+
prompt.debugger.smessage = ''
309+
if prompt.debugger.display > 0:
310+
print(prompt.debugger.print_source(prompt.debugger.display, prompt.debugger.src_offset))
311+
prompt.cmdloop()
312+
continue
313+
314+
315+
if __name__ == "__main__":
316+
try:
317+
main()
318+
except socket.error as error_msg:
319+
ERRNO = error_msg.errno
320+
MSG = str(error_msg)
321+
if ERRNO == 111:
322+
sys.exit("Failed to connect to the JerryScript debugger.")
323+
elif ERRNO == 32 or ERRNO == 104:
324+
sys.exit("Connection closed.")
325+
else:
326+
sys.exit("Failed to connect to the JerryScript debugger.\nError: %s" % (MSG))

0 commit comments

Comments
 (0)