Skip to content

Commit 24c12e5

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 24c12e5

File tree

8 files changed

+97
-8
lines changed

8 files changed

+97
-8
lines changed

jerry-core/debugger/debugger.c

Lines changed: 37 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,19 @@ 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);
342+
if (!is_eval)
343+
{
344+
*resume_exec_p = true;
345+
}
324346
}
325347
else
326348
{
@@ -504,6 +526,7 @@ jerry_debugger_process_message (uint8_t *recv_buffer_p, /**< pointer the the rec
504526
}
505527

506528
case JERRY_DEBUGGER_EVAL:
529+
case JERRY_DEBUGGER_THROW:
507530
{
508531
if (message_size < sizeof (jerry_debugger_receive_eval_first_t) + 1)
509532
{
@@ -516,6 +539,7 @@ jerry_debugger_process_message (uint8_t *recv_buffer_p, /**< pointer the the rec
516539

517540
uint32_t eval_size;
518541
memcpy (&eval_size, eval_first_p->eval_size, sizeof (uint32_t));
542+
bool is_eval = (recv_buffer_p[0] == JERRY_DEBUGGER_EVAL);
519543

520544
if (eval_size <= JERRY_DEBUGGER_MAX_RECEIVE_SIZE - sizeof (jerry_debugger_receive_eval_first_t))
521545
{
@@ -525,8 +549,13 @@ jerry_debugger_process_message (uint8_t *recv_buffer_p, /**< pointer the the rec
525549
jerry_debugger_close_connection ();
526550
return false;
527551
}
552+
bool ret_val = jerry_debugger_send_eval_or_throw ((lit_utf8_byte_t *) (eval_first_p + 1), eval_size, &is_eval);
553+
if (!is_eval)
554+
{
555+
*resume_exec_p = true;
556+
}
528557

529-
return jerry_debugger_send_eval ((lit_utf8_byte_t *) (eval_first_p + 1), eval_size);
558+
return ret_val;
530559
}
531560

532561
jerry_debugger_uint8_data_t *eval_uint8_data_p;
@@ -543,7 +572,8 @@ jerry_debugger_process_message (uint8_t *recv_buffer_p, /**< pointer the the rec
543572
message_size - sizeof (jerry_debugger_receive_eval_first_t));
544573

545574
*message_data_p = eval_uint8_data_p;
546-
*expected_message_type_p = JERRY_DEBUGGER_EVAL_PART;
575+
*expected_message_type_p = is_eval ? JERRY_DEBUGGER_EVAL_PART : JERRY_DEBUGGER_THROW_PART;
576+
547577
return true;
548578
}
549579

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)