mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Add the ability to throw an error to python debugger (#2188)
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
This commit is contained in:
parent
79289714dc
commit
8af89d951e
@ -136,14 +136,15 @@ jerry_debugger_send_backtrace (uint8_t *recv_buffer_p) /**< pointer to the recei
|
||||
} /* jerry_debugger_send_backtrace */
|
||||
|
||||
/**
|
||||
* Send result of evaluated expression.
|
||||
* Send result of evaluated expression or throw an error.
|
||||
*
|
||||
* @return true - if no error is occured
|
||||
* false - otherwise
|
||||
*/
|
||||
static bool
|
||||
jerry_debugger_send_eval (const lit_utf8_byte_t *eval_string_p, /**< evaluated string */
|
||||
size_t eval_string_size) /**< evaluated string size */
|
||||
jerry_debugger_send_eval_or_throw (const lit_utf8_byte_t *eval_string_p, /**< evaluated string */
|
||||
size_t eval_string_size, /**< evaluated string size */
|
||||
bool *is_eval) /**< [in,out] throw or eval call */
|
||||
{
|
||||
JERRY_ASSERT (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED);
|
||||
JERRY_ASSERT (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_VM_IGNORE));
|
||||
@ -154,11 +155,21 @@ jerry_debugger_send_eval (const lit_utf8_byte_t *eval_string_p, /**< evaluated s
|
||||
|
||||
if (!ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
if (!*is_eval)
|
||||
{
|
||||
JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_THROW_ERROR_FLAG);
|
||||
JERRY_CONTEXT (error_value) = result;
|
||||
JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_STOP);
|
||||
JERRY_CONTEXT (debugger_stop_context) = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
ecma_value_t to_string_value = ecma_op_to_string (result);
|
||||
ecma_free_value (result);
|
||||
result = to_string_value;
|
||||
}
|
||||
|
||||
*is_eval = true;
|
||||
ecma_value_t message = result;
|
||||
uint8_t type = JERRY_DEBUGGER_EVAL_OK;
|
||||
|
||||
@ -205,7 +216,7 @@ jerry_debugger_send_eval (const lit_utf8_byte_t *eval_string_p, /**< evaluated s
|
||||
ecma_free_value (message);
|
||||
|
||||
return success;
|
||||
} /* jerry_debugger_send_eval */
|
||||
} /* jerry_debugger_send_eval_or_throw */
|
||||
|
||||
/**
|
||||
* Suspend execution for a given time.
|
||||
@ -254,6 +265,7 @@ jerry_debugger_process_message (uint8_t *recv_buffer_p, /**< pointer to the rece
|
||||
if (*expected_message_type_p != 0)
|
||||
{
|
||||
JERRY_ASSERT (*expected_message_type_p == JERRY_DEBUGGER_EVAL_PART
|
||||
|| *expected_message_type_p == JERRY_DEBUGGER_THROW_PART
|
||||
|| *expected_message_type_p == JERRY_DEBUGGER_CLIENT_SOURCE_PART);
|
||||
|
||||
jerry_debugger_uint8_data_t *uint8_data_p = (jerry_debugger_uint8_data_t *) *message_data_p;
|
||||
@ -300,9 +312,19 @@ jerry_debugger_process_message (uint8_t *recv_buffer_p, /**< pointer to the rece
|
||||
}
|
||||
|
||||
bool result = false;
|
||||
bool is_eval = true;
|
||||
if (*expected_message_type_p == JERRY_DEBUGGER_EVAL_PART)
|
||||
{
|
||||
result = jerry_debugger_send_eval (string_p, uint8_data_p->uint8_size);
|
||||
result = jerry_debugger_send_eval_or_throw (string_p, uint8_data_p->uint8_size, &is_eval);
|
||||
}
|
||||
else if (*expected_message_type_p == JERRY_DEBUGGER_THROW_PART)
|
||||
{
|
||||
is_eval = false;
|
||||
result = jerry_debugger_send_eval_or_throw (string_p, uint8_data_p->uint8_size, &is_eval);
|
||||
if (!is_eval)
|
||||
{
|
||||
*resume_exec_p = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -499,6 +521,7 @@ jerry_debugger_process_message (uint8_t *recv_buffer_p, /**< pointer to the rece
|
||||
}
|
||||
|
||||
case JERRY_DEBUGGER_EVAL:
|
||||
case JERRY_DEBUGGER_THROW:
|
||||
{
|
||||
if (message_size < sizeof (jerry_debugger_receive_eval_first_t) + 1)
|
||||
{
|
||||
@ -511,6 +534,7 @@ jerry_debugger_process_message (uint8_t *recv_buffer_p, /**< pointer to the rece
|
||||
|
||||
uint32_t eval_size;
|
||||
memcpy (&eval_size, eval_first_p->eval_size, sizeof (uint32_t));
|
||||
bool is_eval = (recv_buffer_p[0] == JERRY_DEBUGGER_EVAL);
|
||||
|
||||
if (eval_size <= JERRY_DEBUGGER_MAX_RECEIVE_SIZE - sizeof (jerry_debugger_receive_eval_first_t))
|
||||
{
|
||||
@ -520,8 +544,13 @@ jerry_debugger_process_message (uint8_t *recv_buffer_p, /**< pointer to the rece
|
||||
jerry_debugger_close_connection ();
|
||||
return false;
|
||||
}
|
||||
bool ret_val = jerry_debugger_send_eval_or_throw ((lit_utf8_byte_t *) (eval_first_p + 1), eval_size, &is_eval);
|
||||
if (!is_eval)
|
||||
{
|
||||
*resume_exec_p = true;
|
||||
}
|
||||
|
||||
return jerry_debugger_send_eval ((lit_utf8_byte_t *) (eval_first_p + 1), eval_size);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
jerry_debugger_uint8_data_t *eval_uint8_data_p;
|
||||
@ -538,7 +567,8 @@ jerry_debugger_process_message (uint8_t *recv_buffer_p, /**< pointer to the rece
|
||||
message_size - sizeof (jerry_debugger_receive_eval_first_t));
|
||||
|
||||
*message_data_p = eval_uint8_data_p;
|
||||
*expected_message_type_p = JERRY_DEBUGGER_EVAL_PART;
|
||||
*expected_message_type_p = is_eval ? JERRY_DEBUGGER_EVAL_PART : JERRY_DEBUGGER_THROW_PART;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -98,6 +98,7 @@ typedef enum
|
||||
JERRY_DEBUGGER_CLIENT_SOURCE_MODE = 1u << 7, /**< debugger waiting for client code */
|
||||
JERRY_DEBUGGER_CLIENT_NO_SOURCE = 1u << 8, /**< debugger leaving the client source loop */
|
||||
JERRY_DEBUGGER_CONTEXT_RESET_MODE = 1u << 9, /**< debugger and engine reinitialization mode */
|
||||
JERRY_DEBUGGER_THROW_ERROR_FLAG = 1u << 10, /**< debugger client sent an error throw */
|
||||
} jerry_debugger_flags_t;
|
||||
|
||||
/**
|
||||
@ -186,6 +187,8 @@ typedef enum
|
||||
JERRY_DEBUGGER_EVAL_PART = 18, /**< next message of evaluating a string */
|
||||
|
||||
JERRY_DEBUGGER_MESSAGES_IN_MAX_COUNT, /**< number of different type of input messages */
|
||||
JERRY_DEBUGGER_THROW = 19, /**< first message of the throw string */
|
||||
JERRY_DEBUGGER_THROW_PART = 20, /**< next part of the throw message */
|
||||
} jerry_debugger_header_type_t;
|
||||
|
||||
/**
|
||||
|
||||
@ -2530,6 +2530,11 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
frame_ctx_p->byte_code_p = byte_code_start_p;
|
||||
|
||||
jerry_debugger_breakpoint_hit (JERRY_DEBUGGER_BREAKPOINT_HIT);
|
||||
if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_THROW_ERROR_FLAG)
|
||||
{
|
||||
result = JERRY_CONTEXT (error_value);
|
||||
goto error;
|
||||
}
|
||||
#endif /* JERRY_DEBUGGER */
|
||||
continue;
|
||||
}
|
||||
@ -2552,6 +2557,11 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
|| JERRY_CONTEXT (debugger_stop_context) == JERRY_CONTEXT (vm_top_context_p)))
|
||||
{
|
||||
jerry_debugger_breakpoint_hit (JERRY_DEBUGGER_BREAKPOINT_HIT);
|
||||
if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_THROW_ERROR_FLAG)
|
||||
{
|
||||
result = JERRY_CONTEXT (error_value);
|
||||
goto error;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -2573,6 +2583,11 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
|| JERRY_CONTEXT (debugger_stop_context) == JERRY_CONTEXT (vm_top_context_p)))
|
||||
{
|
||||
jerry_debugger_breakpoint_hit (JERRY_DEBUGGER_BREAKPOINT_HIT);
|
||||
if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_THROW_ERROR_FLAG)
|
||||
{
|
||||
result = JERRY_CONTEXT (error_value);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
#endif /* JERRY_DEBUGGER */
|
||||
continue;
|
||||
@ -2712,9 +2727,20 @@ error:
|
||||
&& !(frame_ctx_p->bytecode_header_p->status_flags & CBC_CODE_FLAGS_DEBUGGER_IGNORE)
|
||||
&& !(JERRY_CONTEXT (debugger_flags) & (JERRY_DEBUGGER_VM_IGNORE_EXCEPTION | JERRY_DEBUGGER_VM_IGNORE)))
|
||||
{
|
||||
/* Save the error to a local value, because the engine enters breakpoint mode after,
|
||||
therefore an evaluation error, or user-created error throw would overwrite it. */
|
||||
ecma_value_t current_error_value = JERRY_CONTEXT (error_value);
|
||||
if (jerry_debugger_send_exception_string ())
|
||||
{
|
||||
jerry_debugger_breakpoint_hit (JERRY_DEBUGGER_EXCEPTION_HIT);
|
||||
if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_THROW_ERROR_FLAG)
|
||||
{
|
||||
ecma_free_value (current_error_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_CONTEXT (error_value) = current_error_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* JERRY_DEBUGGER */
|
||||
|
||||
@ -89,6 +89,8 @@ JERRY_DEBUGGER_FINISH = 15
|
||||
JERRY_DEBUGGER_GET_BACKTRACE = 16
|
||||
JERRY_DEBUGGER_EVAL = 17
|
||||
JERRY_DEBUGGER_EVAL_PART = 18
|
||||
JERRY_DEBUGGER_THROW = 19
|
||||
JERRY_DEBUGGER_THROW_PART = 20
|
||||
|
||||
MAX_BUFFER_SIZE = 128
|
||||
WEBSOCKET_BINARY_FRAME = 2
|
||||
@ -449,6 +451,8 @@ class DebuggerPrompt(Cmd):
|
||||
|
||||
if message_type == JERRY_DEBUGGER_EVAL:
|
||||
message_type = JERRY_DEBUGGER_EVAL_PART
|
||||
elif message_type == JERRY_DEBUGGER_THROW:
|
||||
message_type = JERRY_DEBUGGER_THROW_PART
|
||||
else:
|
||||
message_type = JERRY_DEBUGGER_CLIENT_SOURCE_PART
|
||||
|
||||
@ -477,6 +481,10 @@ class DebuggerPrompt(Cmd):
|
||||
|
||||
do_e = do_eval
|
||||
|
||||
def do_throw(self, args):
|
||||
""" Throw an exception """
|
||||
self._send_string(args, JERRY_DEBUGGER_THROW)
|
||||
|
||||
def do_exception(self, args):
|
||||
""" Config the exception handler module """
|
||||
if not args:
|
||||
|
||||
@ -4,8 +4,8 @@ Stopped at tests/debugger/do_help.js:15
|
||||
|
||||
Documented commands (type help <topic>):
|
||||
========================================
|
||||
b bt delete e f list n s src
|
||||
backtrace c display eval finish memstats next scroll step
|
||||
break continue dump exception help ms quit source
|
||||
b bt delete e f list n s src
|
||||
backtrace c display eval finish memstats next scroll step
|
||||
break continue dump exception help ms quit source throw
|
||||
|
||||
(jerry-debugger) quit
|
||||
|
||||
1
tests/debugger/do_throw.cmd
Normal file
1
tests/debugger/do_throw.cmd
Normal file
@ -0,0 +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."')
|
||||
3
tests/debugger/do_throw.expected
Normal file
3
tests/debugger/do_throw.expected
Normal file
@ -0,0 +1,3 @@
|
||||
Connecting to: localhost:5001
|
||||
Stopped at tests/debugger/do_throw.js:19
|
||||
(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."')
|
||||
19
tests/debugger/do_throw.js
Normal file
19
tests/debugger/do_throw.js
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright JS Foundation and other contributors, http://js.foundation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
function inevitable() {
|
||||
print("An error will be thrown.");
|
||||
}
|
||||
|
||||
inevitable();
|
||||
Loading…
x
Reference in New Issue
Block a user