Skip to content

Commit c9d5031

Browse files
committed
Debugger: add dedicated message for VSCode watch
Processing VSCode watches skips waitForResolvingPendingBreakpoints (previously having multiple watches in VSC would call this when processing the first watch, which would process pending messages while trying to wait for break point changes while in eval mode (not in waiting mode) and cause and Invalid message error and the closure of the debgger connection when hitting the second watch message) Allow '*.mjs' files in the python debugger Add watches to the python debugger, add test Signed-off-by: Máté Tokodi mate.tokodi@szteszoftver.hu
1 parent af4c67a commit c9d5031

File tree

7 files changed

+187
-7
lines changed

7 files changed

+187
-7
lines changed

src/debugger/Debugger.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ void DebuggerRemote::parseCompleted(String* source, String* srcName, size_t orig
189189

190190
sendType(ESCARGOT_MESSAGE_PARSE_DONE);
191191

192-
if (enabled() && pendingWait()) {
192+
if (enabled() && pendingWait() && !m_watchEval) {
193193
waitForResolvingPendingBreakpoints();
194194
}
195195
}
@@ -371,9 +371,9 @@ bool DebuggerRemote::doEval(ExecutionState* state, Optional<ByteCodeBlock*> byte
371371
}
372372

373373
String* str;
374-
if (type == ESCARGOT_MESSAGE_EVAL_8BIT || type == ESCARGOT_MESSAGE_EVAL_WITHOUT_STOP_8BIT) {
374+
if (type == ESCARGOT_MESSAGE_EVAL_8BIT || type == ESCARGOT_MESSAGE_EVAL_WITHOUT_STOP_8BIT || type == ESCARGOT_MESSAGE_WATCH_8BIT) {
375375
str = new Latin1String(data, size);
376-
} else if (type == ESCARGOT_MESSAGE_EVAL_16BIT || type == ESCARGOT_MESSAGE_EVAL_WITHOUT_STOP_16BIT) {
376+
} else if (type == ESCARGOT_MESSAGE_EVAL_16BIT || type == ESCARGOT_MESSAGE_EVAL_WITHOUT_STOP_16BIT || type == ESCARGOT_MESSAGE_WATCH_16BIT) {
377377
str = new UTF16String((char16_t*)data, size / 2);
378378
} else if (type == ESCARGOT_DEBUGGER_CLIENT_SOURCE_8BIT) {
379379
char* sourceNameSrc = (char*)memchr(data, '\0', size);
@@ -401,6 +401,9 @@ bool DebuggerRemote::doEval(ExecutionState* state, Optional<ByteCodeBlock*> byte
401401
return false;
402402
}
403403

404+
if (type == ESCARGOT_MESSAGE_WATCH_8BIT || type == ESCARGOT_MESSAGE_WATCH_16BIT) {
405+
m_watchEval = true;
406+
}
404407
m_stopState = ESCARGOT_DEBUGGER_IN_EVAL_MODE;
405408

406409
try {
@@ -411,14 +414,15 @@ bool DebuggerRemote::doEval(ExecutionState* state, Optional<ByteCodeBlock*> byte
411414
} else {
412415
result = state->context()->globalObject()->evalLocal(*state, asValue, state->thisValue(), byteCodeBlock->m_codeBlock, true);
413416
}
414-
type = ESCARGOT_MESSAGE_EVAL_RESULT_8BIT;
417+
type = m_watchEval ? ESCARGOT_MESSAGE_WATCH_RESULT_8BIT : ESCARGOT_MESSAGE_EVAL_RESULT_8BIT;
415418
str = result.toStringWithoutException(*state);
416419
} catch (const Value& val) {
417420
type = ESCARGOT_MESSAGE_EVAL_FAILED_8BIT;
418421
str = val.toStringWithoutException(*state);
419422
}
420423

421424
m_stopState = ESCARGOT_DEBUGGER_IN_WAIT_MODE;
425+
m_watchEval = false;
422426

423427
if (enabled()) {
424428
sendString(type, str);
@@ -923,6 +927,8 @@ bool DebuggerRemote::processEvents(ExecutionState* state, Optional<ByteCodeBlock
923927
m_stopState = stopState;
924928
return false;
925929
}
930+
case ESCARGOT_MESSAGE_WATCH_8BIT_START:
931+
case ESCARGOT_MESSAGE_WATCH_16BIT_START:
926932
case ESCARGOT_MESSAGE_EVAL_8BIT_START:
927933
case ESCARGOT_MESSAGE_EVAL_16BIT_START: {
928934
if ((length <= 1 + sizeof(uint32_t)) || m_stopState != ESCARGOT_DEBUGGER_IN_WAIT_MODE) {

src/debugger/Debugger.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,11 @@ class DebuggerRemote : public Debugger {
268268
ESCARGOT_DEBUGGER_WAIT_FOR_SOURCE = 43,
269269
ESCARGOT_DEBUGGER_WAITING_AFTER_PENDING = 44,
270270
ESCARGOT_DEBUGGER_WAIT_FOR_WAIT_EXIT = 45,
271+
// These four must be in the same order.
272+
ESCARGOT_MESSAGE_WATCH_RESULT_8BIT = 46,
273+
ESCARGOT_MESSAGE_WATCH_RESULT_8BIT_END = 47,
274+
ESCARGOT_MESSAGE_WATCH_RESULT_16BIT = 48,
275+
ESCARGOT_MESSAGE_WATCH_RESULT_16BIT_END = 49
271276
};
272277

273278
// Messages sent by the debugger client to Escargot
@@ -301,6 +306,12 @@ class DebuggerRemote : public Debugger {
301306
ESCARGOT_DEBUGGER_PENDING_CONFIG = 23,
302307
ESCARGOT_DEBUGGER_PENDING_RESUME = 24,
303308
ESCARGOT_DEBUGGER_WAIT_BEFORE_EXIT = 25,
309+
ESCARGOT_DEBUGGER_STOP = 26,
310+
// These four must be in the same order.
311+
ESCARGOT_MESSAGE_WATCH_8BIT_START = 27,
312+
ESCARGOT_MESSAGE_WATCH_8BIT = 28,
313+
ESCARGOT_MESSAGE_WATCH_16BIT_START = 29,
314+
ESCARGOT_MESSAGE_WATCH_16BIT = 30
304315
};
305316

306317
// Environment record types
@@ -374,6 +385,7 @@ class DebuggerRemote : public Debugger {
374385
: m_exitClient(false)
375386
, m_pendingWait(false)
376387
, m_waitForResume(false)
388+
, m_watchEval(false)
377389
, m_clientSourceData(nullptr)
378390
, m_clientSourceName(nullptr)
379391
{
@@ -431,6 +443,7 @@ class DebuggerRemote : public Debugger {
431443
bool m_exitClient : 1;
432444
bool m_pendingWait : 1;
433445
bool m_waitForResume : 1;
446+
bool m_watchEval : 1;
434447
String* m_clientSourceData;
435448
String* m_clientSourceName;
436449

tools/debugger/debugger.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,23 @@ def do_display(self, args):
6969
else:
7070
print("Non-negative integer number expected, 0 turns off this function")
7171

72+
def do_watch(self, args):
73+
""" Add value to watched values display after breakpoints """
74+
if not args:
75+
write("Error: Argument expected\n")
76+
else:
77+
write(self.debugger.set_watch(args))
78+
do_w = do_watch
79+
80+
def do_print_watches(self, _):
81+
self.debugger.print_watches()
82+
do_pw = do_print_watches
83+
84+
def do_watches(self, _):
85+
self.debugger.list_watches()
86+
do_list_watches = do_watches
87+
do_lw = do_watches
88+
7289
def do_break(self, args):
7390
""" Insert breakpoints on the given lines or functions """
7491
if not args:
@@ -85,6 +102,10 @@ def do_delete(self, args):
85102
""" Delete the given breakpoint, use 'delete all|active|pending' to clear all the given breakpoints """
86103
write(self.debugger.delete(args))
87104

105+
def do_delete_watch(self, args):
106+
""" Delete the given watch """
107+
write(self.debugger.delete_watch(args))
108+
88109
def do_continue(self, _):
89110
""" Continue execution """
90111
self.debugger.do_continue()

tools/debugger/debugger_core.py

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@
7272
ESCARGOT_DEBUGGER_WAIT_FOR_SOURCE = 43
7373
ESCARGOT_DEBUGGER_WAITING_AFTER_PENDING = 44
7474
ESCARGOT_DEBUGGER_WAIT_FOR_WAIT_EXIT = 45
75+
ESCARGOT_MESSAGE_WATCH_RESULT_8BIT = 46
76+
ESCARGOT_MESSAGE_WATCH_RESULT_8BIT_END = 47
77+
ESCARGOT_MESSAGE_WATCH_RESULT_16BIT = 48
78+
ESCARGOT_MESSAGE_WATCH_RESULT_16BIT_END = 49
7579

7680

7781
# Messages sent by the debugger client to Escargot.
@@ -101,6 +105,11 @@
101105
ESCARGOT_DEBUGGER_PENDING_CONFIG = 23
102106
ESCARGOT_DEBUGGER_PENDING_RESUME = 24
103107
ESCARGOT_DEBUGGER_WAIT_BEFORE_EXIT = 25
108+
ESCARGOT_DEBUGGER_STOP = 26
109+
ESCARGOT_MESSAGE_WATCH_8BIT_START = 27
110+
ESCARGOT_MESSAGE_WATCH_8BIT = 28
111+
ESCARGOT_MESSAGE_WATCH_16BIT_START = 29
112+
ESCARGOT_MESSAGE_WATCH_16BIT = 30
104113

105114

106115
# Environment record types
@@ -300,6 +309,8 @@ def __init__(self, channel):
300309
self.next_breakpoint_index = 0
301310
self.active_breakpoint_list = {}
302311
self.pending_breakpoint_list = {}
312+
self.watched_values_list = []
313+
self.waiting_for_watched_values_count = 0
303314
self.line_list = Multimap()
304315
self.display = 0
305316
self.green = ''
@@ -442,6 +453,15 @@ def process_messages(self):
442453
self.prompt = True
443454
return DebuggerAction(DebuggerAction.TEXT, self._receive_string(ESCARGOT_MESSAGE_EVAL_RESULT_8BIT, data))
444455

456+
elif buffer_type in [ESCARGOT_MESSAGE_WATCH_RESULT_8BIT,
457+
ESCARGOT_MESSAGE_WATCH_RESULT_8BIT_END,
458+
ESCARGOT_MESSAGE_WATCH_RESULT_16BIT,
459+
ESCARGOT_MESSAGE_WATCH_RESULT_16BIT_END]:
460+
self.prompt = True
461+
self.waiting_for_watched_values_count -= 1
462+
print("Watch: " + self._receive_string(ESCARGOT_MESSAGE_WATCH_RESULT_8BIT, data))
463+
return DebuggerAction(DebuggerAction.WAIT, "")
464+
445465
elif buffer_type in [ESCARGOT_MESSAGE_EVAL_FAILED_8BIT,
446466
ESCARGOT_MESSAGE_EVAL_FAILED_8BIT_END,
447467
ESCARGOT_MESSAGE_EVAL_FAILED_16BIT,
@@ -588,7 +608,7 @@ def send_client_source(self):
588608
self._exec_command(ESCARGOT_DEBUGGER_THERE_WAS_NO_SOURCE)
589609
return
590610
path = self.client_sources.pop(0)
591-
if not path.endswith('.js'):
611+
if not path.endswith('.js') and not path.endswith('.mjs'):
592612
sys.exit("Error: Javascript file expected!")
593613
with open(path, 'r') as src_file:
594614
content = path + '\0'+ src_file.read()
@@ -646,6 +666,16 @@ def set_break(self, args):
646666

647667
return self._set_breakpoint(args, False)
648668

669+
def set_watch(self, args):
670+
if not args:
671+
return "Error: Value name expected"
672+
673+
if args not in self.watched_values_list:
674+
self.watched_values_list.append(args)
675+
return "Added watch: %s\n" % args
676+
else:
677+
return "Already watching: %s\n" % args
678+
649679
def delete(self, args):
650680
if not args:
651681
return "Error: Breakpoint index expected\n" \
@@ -734,8 +764,21 @@ def print_source(self, line_num, offset):
734764

735765
return msg
736766

737-
def eval(self, code):
738-
self._send_string(code, ESCARGOT_MESSAGE_EVAL_8BIT_START)
767+
def print_watches(self):
768+
if self.watched_values_list:
769+
for var_name in self.watched_values_list:
770+
self.eval(var_name, watch=True)
771+
self.waiting_for_watched_values_count += 1
772+
while self.waiting_for_watched_values_count > 0:
773+
self.process_messages()
774+
775+
def list_watches(self):
776+
print("Watched values:")
777+
for var_name in self.watched_values_list:
778+
print(var_name)
779+
780+
def eval(self, code, watch=False):
781+
self._send_string(code, ESCARGOT_MESSAGE_EVAL_8BIT_START if not watch else ESCARGOT_MESSAGE_WATCH_8BIT_START)
739782
self.prompt = False
740783

741784
def backtrace(self, args):
@@ -1165,3 +1208,7 @@ def breakpoint_pending_exists(self, breakpoint):
11651208
return True
11661209

11671210
return False
1211+
1212+
def delete_watch(self, var_name):
1213+
self.watched_values_list.remove(var_name)
1214+
return "Removed watch: %s\n" % var_name

tools/debugger/tests/do_watch.cmd

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
b do_watch.js:8
2+
watch num_a
3+
w num_b
4+
watches
5+
c
6+
watch num_c
7+
list_watches
8+
c
9+
print_watches
10+
c
11+
delete_watch num_b
12+
lw
13+
c
14+
c
15+
pw
16+
c
17+
c
18+
pw
19+
c
20+
c
21+
c
22+
pw
23+
c
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
Connecting to: localhost:6501
2+
Connection created!!!
3+
Stopped at tools/debugger/tests/do_watch.js:1
4+
(escargot-debugger) b do_watch.js:8
5+
Breakpoint 1 at tools/debugger/tests/do_watch.js:8
6+
(escargot-debugger) watch num_a
7+
Added watch: num_a
8+
(escargot-debugger) w num_b
9+
Added watch: num_b
10+
(escargot-debugger) watches
11+
Watched values:
12+
num_a
13+
num_b
14+
(escargot-debugger) c
15+
Stopped at breakpoint:1 tools/debugger/tests/do_watch.js:8
16+
(escargot-debugger) watch num_c
17+
Added watch: num_c
18+
(escargot-debugger) list_watches
19+
Watched values:
20+
num_a
21+
num_b
22+
num_c
23+
(escargot-debugger) c
24+
Stopped at breakpoint:1 tools/debugger/tests/do_watch.js:8
25+
(escargot-debugger) print_watches
26+
Watch: 190
27+
Watch: 0
28+
Watch: 3333
29+
(escargot-debugger) c
30+
Stopped at breakpoint:1 tools/debugger/tests/do_watch.js:8
31+
(escargot-debugger) delete_watch num_b
32+
Removed watch: num_b
33+
(escargot-debugger) lw
34+
Watched values:
35+
num_a
36+
num_c
37+
(escargot-debugger) c
38+
Stopped at breakpoint:1 tools/debugger/tests/do_watch.js:8
39+
(escargot-debugger) c
40+
Stopped at breakpoint:1 tools/debugger/tests/do_watch.js:8
41+
(escargot-debugger) pw
42+
Watch: 325
43+
Watch: 3433993233
44+
(escargot-debugger) c
45+
Stopped at breakpoint:1 tools/debugger/tests/do_watch.js:8
46+
(escargot-debugger) c
47+
Stopped at breakpoint:1 tools/debugger/tests/do_watch.js:8
48+
(escargot-debugger) pw
49+
Watch: 415
50+
Watch: 35030164969833
51+
(escargot-debugger) c
52+
Stopped at breakpoint:1 tools/debugger/tests/do_watch.js:8
53+
(escargot-debugger) c
54+
Stopped at breakpoint:1 tools/debugger/tests/do_watch.js:8
55+
(escargot-debugger) c
56+
Stopped at breakpoint:1 tools/debugger/tests/do_watch.js:8
57+
(escargot-debugger) pw
58+
Watch: 550
59+
Watch: 36091613998583910000
60+
(escargot-debugger) c
61+
Connection closed.

tools/debugger/tests/do_watch.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
let num_a = 100;
2+
let num_b = 2;
3+
var num_c = 33;
4+
5+
for (let i = 0; i < 10; i++) {
6+
num_a = num_a + 45;
7+
num_b -= 1;
8+
num_c *= 101
9+
}

0 commit comments

Comments
 (0)