Skip to content

Commit 33f1ece

Browse files
author
Daniel Balla
committed
Add the ability to throw an error to python debugger
This patch makes it possible to throw an error from the python debugger client using the `throw` command. JerryScript-DCO-1.0-Signed-off-by: Daniel Balla dballa@inf.u-szeged.hu
1 parent e860870 commit 33f1ece

File tree

8 files changed

+94
-8
lines changed

8 files changed

+94
-8
lines changed

jerry-core/debugger/debugger.c

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -142,14 +142,15 @@ jerry_debugger_send_backtrace (uint8_t *recv_buffer_p) /**< pointer the the rece
142142
} /* jerry_debugger_send_backtrace */
143143

144144
/**
145-
* Send result of evaluated expression.
145+
* Send result of evaluated expression or throw an error.
146146
*
147147
* @return true - if no error is occured
148148
* false - otherwise
149149
*/
150150
static bool
151-
jerry_debugger_send_eval (const lit_utf8_byte_t *eval_string_p, /**< evaluated string */
152-
size_t eval_string_size) /**< evaluated string size */
151+
jerry_debugger_send_eval_or_throw (const lit_utf8_byte_t *eval_string_p, /**< evaluated string */
152+
size_t eval_string_size, /**< evaluated string size */
153+
bool *is_eval) /**< throw or eval call*/
153154
{
154155
JERRY_ASSERT (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED);
155156
JERRY_ASSERT (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_VM_IGNORE));
@@ -160,11 +161,21 @@ jerry_debugger_send_eval (const lit_utf8_byte_t *eval_string_p, /**< evaluated s
160161

161162
if (!ECMA_IS_VALUE_ERROR (result))
162163
{
164+
if (!*is_eval)
165+
{
166+
JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_THROW_ERROR_FLAG);
167+
JERRY_CONTEXT (error_value) = result;
168+
JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_STOP);
169+
JERRY_CONTEXT (debugger_stop_context) = NULL;
170+
return true;
171+
}
172+
163173
ecma_value_t to_string_value = ecma_op_to_string (result);
164174
ecma_free_value (result);
165175
result = to_string_value;
166176
}
167177

178+
*is_eval = true;
168179
ecma_value_t message = result;
169180
uint8_t type = JERRY_DEBUGGER_EVAL_OK;
170181

@@ -215,7 +226,7 @@ jerry_debugger_send_eval (const lit_utf8_byte_t *eval_string_p, /**< evaluated s
215226
ecma_free_value (message);
216227

217228
return success;
218-
} /* jerry_debugger_send_eval */
229+
} /* jerry_debugger_send_eval_or_throw */
219230

220231
/**
221232
* Suspend execution for a given time.
@@ -272,6 +283,7 @@ jerry_debugger_process_message (uint8_t *recv_buffer_p, /**< pointer the the rec
272283
if (*expected_message_type_p != 0)
273284
{
274285
JERRY_ASSERT (*expected_message_type_p == JERRY_DEBUGGER_EVAL_PART
286+
|| *expected_message_type_p == JERRY_DEBUGGER_THROW_PART
275287
|| *expected_message_type_p == JERRY_DEBUGGER_CLIENT_SOURCE_PART);
276288

277289
jerry_debugger_uint8_data_t *uint8_data_p = (jerry_debugger_uint8_data_t *) *message_data_p;
@@ -318,9 +330,15 @@ jerry_debugger_process_message (uint8_t *recv_buffer_p, /**< pointer the the rec
318330
}
319331

320332
bool result = false;
333+
bool is_eval = true;
321334
if (*expected_message_type_p == JERRY_DEBUGGER_EVAL_PART)
322335
{
323-
result = jerry_debugger_send_eval (string_p, uint8_data_p->uint8_size);
336+
result = jerry_debugger_send_eval_or_throw (string_p, uint8_data_p->uint8_size, &is_eval);
337+
}
338+
else if (*expected_message_type_p == JERRY_DEBUGGER_THROW_PART)
339+
{
340+
is_eval = false;
341+
result = jerry_debugger_send_eval_or_throw (string_p, uint8_data_p->uint8_size, &is_eval);
324342
}
325343
else
326344
{
@@ -504,6 +522,7 @@ jerry_debugger_process_message (uint8_t *recv_buffer_p, /**< pointer the the rec
504522
}
505523

506524
case JERRY_DEBUGGER_EVAL:
525+
case JERRY_DEBUGGER_THROW:
507526
{
508527
if (message_size < sizeof (jerry_debugger_receive_eval_first_t) + 1)
509528
{
@@ -516,6 +535,7 @@ jerry_debugger_process_message (uint8_t *recv_buffer_p, /**< pointer the the rec
516535

517536
uint32_t eval_size;
518537
memcpy (&eval_size, eval_first_p->eval_size, sizeof (uint32_t));
538+
bool is_eval = (recv_buffer_p[0] == JERRY_DEBUGGER_EVAL);
519539

520540
if (eval_size <= JERRY_DEBUGGER_MAX_RECEIVE_SIZE - sizeof (jerry_debugger_receive_eval_first_t))
521541
{
@@ -525,8 +545,13 @@ jerry_debugger_process_message (uint8_t *recv_buffer_p, /**< pointer the the rec
525545
jerry_debugger_close_connection ();
526546
return false;
527547
}
548+
bool ret_val = jerry_debugger_send_eval_or_throw ((lit_utf8_byte_t *) (eval_first_p + 1), eval_size, &is_eval);
549+
if (!is_eval)
550+
{
551+
*resume_exec_p = true;
552+
}
528553

529-
return jerry_debugger_send_eval ((lit_utf8_byte_t *) (eval_first_p + 1), eval_size);
554+
return ret_val;
530555
}
531556

532557
jerry_debugger_uint8_data_t *eval_uint8_data_p;
@@ -543,7 +568,9 @@ jerry_debugger_process_message (uint8_t *recv_buffer_p, /**< pointer the the rec
543568
message_size - sizeof (jerry_debugger_receive_eval_first_t));
544569

545570
*message_data_p = eval_uint8_data_p;
546-
*expected_message_type_p = JERRY_DEBUGGER_EVAL_PART;
571+
*expected_message_type_p = is_eval ? JERRY_DEBUGGER_EVAL_PART
572+
: JERRY_DEBUGGER_THROW_PART;
573+
547574
return true;
548575
}
549576

jerry-core/debugger/debugger.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ typedef enum
9898
JERRY_DEBUGGER_CLIENT_SOURCE_MODE = 1u << 7, /**< debugger waiting for client code */
9999
JERRY_DEBUGGER_CLIENT_NO_SOURCE = 1u << 8, /**< debugger leaving the client source loop */
100100
JERRY_DEBUGGER_CONTEXT_RESET_MODE = 1u << 9, /**< debugger and engine reinitialization mode */
101+
JERRY_DEBUGGER_THROW_ERROR_FLAG = 1u << 10, /**< debugger client sent an error throw */
101102
} jerry_debugger_flags_t;
102103

103104
/**
@@ -185,6 +186,8 @@ typedef enum
185186
JERRY_DEBUGGER_EVAL_PART = 17, /**< next message of evaluating a string */
186187

187188
JERRY_DEBUGGER_MESSAGES_IN_MAX_COUNT, /**< number of different type of input messages */
189+
JERRY_DEBUGGER_THROW = 18, /**< first message of the throw string */
190+
JERRY_DEBUGGER_THROW_PART = 19, /**< next part of the throw message */
188191
} jerry_debugger_header_type_t;
189192

190193
/**

jerry-core/vm/vm.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2517,6 +2517,11 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
25172517
frame_ctx_p->byte_code_p = byte_code_start_p;
25182518

25192519
jerry_debugger_breakpoint_hit (JERRY_DEBUGGER_BREAKPOINT_HIT);
2520+
if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_THROW_ERROR_FLAG)
2521+
{
2522+
result = JERRY_CONTEXT (error_value);
2523+
goto error;
2524+
}
25202525
#endif /* JERRY_DEBUGGER */
25212526
continue;
25222527
}
@@ -2539,6 +2544,11 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
25392544
|| JERRY_CONTEXT (debugger_stop_context) == JERRY_CONTEXT (vm_top_context_p)))
25402545
{
25412546
jerry_debugger_breakpoint_hit (JERRY_DEBUGGER_BREAKPOINT_HIT);
2547+
if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_THROW_ERROR_FLAG)
2548+
{
2549+
result = JERRY_CONTEXT (error_value);
2550+
goto error;
2551+
}
25422552
continue;
25432553
}
25442554

@@ -2560,6 +2570,11 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
25602570
|| JERRY_CONTEXT (debugger_stop_context) == JERRY_CONTEXT (vm_top_context_p)))
25612571
{
25622572
jerry_debugger_breakpoint_hit (JERRY_DEBUGGER_BREAKPOINT_HIT);
2573+
if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_THROW_ERROR_FLAG)
2574+
{
2575+
result = JERRY_CONTEXT (error_value);
2576+
goto error;
2577+
}
25632578
}
25642579
#endif /* JERRY_DEBUGGER */
25652580
continue;
@@ -2699,9 +2714,19 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
26992714
&& !(frame_ctx_p->bytecode_header_p->status_flags & CBC_CODE_FLAGS_DEBUGGER_IGNORE)
27002715
&& !(JERRY_CONTEXT (debugger_flags) & (JERRY_DEBUGGER_VM_IGNORE_EXCEPTION | JERRY_DEBUGGER_VM_IGNORE)))
27012716
{
2717+
/* Save the error to a local value, because the engine enters breakpoint mode after,
2718+
therefore an evaluation error, or user-created error throw would overwrite it. */
2719+
ecma_value_t local_err = JERRY_CONTEXT (error_value);
27022720
if (jerry_debugger_send_exception_string ())
27032721
{
27042722
jerry_debugger_breakpoint_hit (JERRY_DEBUGGER_EXCEPTION_HIT);
2723+
if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_THROW_ERROR_FLAG)
2724+
{
2725+
result = JERRY_CONTEXT (error_value);
2726+
ecma_free_value (local_err);
2727+
goto error;
2728+
}
2729+
JERRY_CONTEXT (error_value) = local_err;
27052730
}
27062731
}
27072732
#endif /* JERRY_DEBUGGER */

jerry-debugger/jerry-client-ws.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@
8787
JERRY_DEBUGGER_GET_BACKTRACE = 15
8888
JERRY_DEBUGGER_EVAL = 16
8989
JERRY_DEBUGGER_EVAL_PART = 17
90+
JERRY_DEBUGGER_THROW = 18
91+
JERRY_DEBUGGER_THROW_PART = 19
9092

9193
MAX_BUFFER_SIZE = 128
9294
WEBSOCKET_BINARY_FRAME = 2
@@ -435,6 +437,8 @@ def send_string(self, args, message_type):
435437

436438
if message_type == JERRY_DEBUGGER_EVAL:
437439
message_type = JERRY_DEBUGGER_EVAL_PART
440+
elif message_type == JERRY_DEBUGGER_THROW:
441+
message_type = JERRY_DEBUGGER_THROW_PART
438442
else:
439443
message_type = JERRY_DEBUGGER_CLIENT_SOURCE_PART
440444

@@ -463,6 +467,10 @@ def do_eval(self, args):
463467

464468
do_e = do_eval
465469

470+
def do_throw(self, args):
471+
""" Throw an exception """
472+
self.send_string(args, JERRY_DEBUGGER_THROW)
473+
466474
def do_exception(self, args):
467475
""" Config the exception handler module """
468476
if not args:

tests/debugger/do_help.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Stopped at tests/debugger/do_help.js:15
44

55
Documented commands (type help <topic>):
66
========================================
7-
b bt delete e help ms quit source
7+
b bt delete e help ms quit source throw
88
backtrace c display eval list n s src
99
break continue dump exception memstats next scroll step
1010

tests/debugger/do_throw.cmd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
throw new Error('Once upon a time there lived in a certain village a little country girl, the prettiest creature who was ever seen. Her mother was excessively fond of her; and her grandmother doted on her still more. This good woman had a little red riding hood made for her. It suited the girl so extremely well that everybody called her Little Red Riding Hood. One day her mother, having made some cakes, said to her, "Go, my dear, and see how your grandmother is doing, for I hear she has been very ill. Take her a cake, and this little pot of butter."')

tests/debugger/do_throw.expected

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Connecting to: localhost:5001
2+
Stopped at tests/debugger/do_throw.js:19
3+
(jerry-debugger) throw new Error('Once upon a time there lived in a certain village a little country girl, the prettiest creature who was ever seen. Her mother was excessively fond of her; and her grandmother doted on her still more. This good woman had a little red riding hood made for her. It suited the girl so extremely well that everybody called her Little Red Riding Hood. One day her mother, having made some cakes, said to her, "Go, my dear, and see how your grandmother is doing, for I hear she has been very ill. Take her a cake, and this little pot of butter."')

tests/debugger/do_throw.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright JS Foundation and other contributors, http://js.foundation
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
function inevitable() {
16+
print("An error will be thrown.");
17+
}
18+
19+
inevitable();

0 commit comments

Comments
 (0)