mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Print exception hint in the debugger client when an exception is thrown. (#1841)
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
parent
7770b6237a
commit
29f57ec58f
@ -16,12 +16,14 @@
|
||||
#ifdef JERRY_DEBUGGER
|
||||
|
||||
#include "byte-code.h"
|
||||
#include "ecma-builtin-helpers.h"
|
||||
#include "ecma-conversion.h"
|
||||
#include "ecma-eval.h"
|
||||
#include "ecma-objects.h"
|
||||
#include "jcontext.h"
|
||||
#include "jerry-debugger.h"
|
||||
#include "jerryscript-port.h"
|
||||
#include "lit-char-helpers.h"
|
||||
|
||||
/**
|
||||
* Type cast the debugger send buffer into a specific type.
|
||||
@ -715,4 +717,151 @@ jerry_debugger_send_memstats (void)
|
||||
jerry_debugger_send (sizeof (jerry_debugger_send_memstats_t));
|
||||
} /* jerry_debugger_send_memstats */
|
||||
|
||||
/*
|
||||
* Converts an standard error into a string.
|
||||
*
|
||||
* @return standard error string
|
||||
*/
|
||||
static ecma_string_t *
|
||||
jerry_debugger_exception_object_to_string (ecma_value_t exception_obj_value) /**< exception object */
|
||||
{
|
||||
ecma_object_t *object_p = ecma_get_object_from_value (exception_obj_value);
|
||||
|
||||
ecma_object_t *prototype_p = ecma_get_object_prototype (object_p);
|
||||
|
||||
if (prototype_p == NULL
|
||||
|| ecma_get_object_type (prototype_p) != ECMA_OBJECT_TYPE_GENERAL
|
||||
|| !ecma_get_object_is_builtin (prototype_p))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lit_magic_string_id_t string_id;
|
||||
|
||||
switch (((ecma_extended_object_t *) prototype_p)->u.built_in.id)
|
||||
{
|
||||
#ifndef CONFIG_DISABLE_ERROR_BUILTINS
|
||||
case ECMA_BUILTIN_ID_EVAL_ERROR_PROTOTYPE:
|
||||
{
|
||||
string_id = LIT_MAGIC_STRING_EVAL_ERROR_UL;
|
||||
break;
|
||||
}
|
||||
case ECMA_BUILTIN_ID_RANGE_ERROR_PROTOTYPE:
|
||||
{
|
||||
string_id = LIT_MAGIC_STRING_RANGE_ERROR_UL;
|
||||
break;
|
||||
}
|
||||
case ECMA_BUILTIN_ID_REFERENCE_ERROR_PROTOTYPE:
|
||||
{
|
||||
string_id = LIT_MAGIC_STRING_REFERENCE_ERROR_UL;
|
||||
break;
|
||||
}
|
||||
case ECMA_BUILTIN_ID_SYNTAX_ERROR_PROTOTYPE:
|
||||
{
|
||||
string_id = LIT_MAGIC_STRING_SYNTAX_ERROR_UL;
|
||||
break;
|
||||
}
|
||||
case ECMA_BUILTIN_ID_TYPE_ERROR_PROTOTYPE:
|
||||
{
|
||||
string_id = LIT_MAGIC_STRING_TYPE_ERROR_UL;
|
||||
break;
|
||||
}
|
||||
case ECMA_BUILTIN_ID_URI_ERROR_PROTOTYPE:
|
||||
{
|
||||
string_id = LIT_MAGIC_STRING_URI_ERROR_UL;
|
||||
break;
|
||||
}
|
||||
#endif /* !CONFIG_DISABLE_ERROR_BUILTINS */
|
||||
case ECMA_BUILTIN_ID_ERROR_PROTOTYPE:
|
||||
{
|
||||
string_id = LIT_MAGIC_STRING_ERROR_UL;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
lit_utf8_size_t size = lit_get_magic_string_size (string_id);
|
||||
JERRY_ASSERT (size <= 14);
|
||||
|
||||
lit_utf8_byte_t data[16];
|
||||
memcpy (data, lit_get_magic_string_utf8 (string_id), size);
|
||||
|
||||
ecma_string_t message_string;
|
||||
ecma_init_ecma_magic_string (&message_string, LIT_MAGIC_STRING_MESSAGE);
|
||||
|
||||
ecma_property_t *property_p;
|
||||
property_p = ecma_find_named_property (ecma_get_object_from_value (exception_obj_value),
|
||||
&message_string);
|
||||
|
||||
if (property_p == NULL
|
||||
|| ECMA_PROPERTY_GET_TYPE (*property_p) != ECMA_PROPERTY_TYPE_NAMEDDATA)
|
||||
{
|
||||
return ecma_new_ecma_string_from_utf8 (data, size);
|
||||
}
|
||||
|
||||
ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
|
||||
if (!ecma_is_value_string (prop_value_p->value))
|
||||
{
|
||||
return ecma_new_ecma_string_from_utf8 (data, size);
|
||||
}
|
||||
|
||||
data[size] = LIT_CHAR_COLON;
|
||||
data[size + 1] = LIT_CHAR_SP;
|
||||
|
||||
ecma_string_t *type_string_p = ecma_new_ecma_string_from_utf8 (data, size + 2);
|
||||
|
||||
ecma_string_t *string_p = ecma_concat_ecma_strings (type_string_p,
|
||||
ecma_get_string_from_value (prop_value_p->value));
|
||||
ecma_deref_ecma_string (type_string_p);
|
||||
return string_p;
|
||||
} /* jerry_debugger_exception_object_to_string */
|
||||
|
||||
/**
|
||||
* Send string representation of exception to the client.
|
||||
*
|
||||
* @return true - if the data sent successfully to the debugger client,
|
||||
* false - otherwise
|
||||
*/
|
||||
bool
|
||||
jerry_debugger_send_exception_string (ecma_value_t exception_value) /**< error value */
|
||||
{
|
||||
ecma_string_t *string_p = NULL;
|
||||
|
||||
if (ecma_is_value_object (exception_value))
|
||||
{
|
||||
ecma_value_t object_value = ecma_get_value_from_error_value (exception_value);
|
||||
|
||||
string_p = jerry_debugger_exception_object_to_string (object_value);
|
||||
if (string_p == NULL)
|
||||
{
|
||||
string_p = ecma_get_string_from_value (ecma_builtin_helper_object_to_string (object_value));
|
||||
}
|
||||
}
|
||||
else if (ecma_is_value_string (exception_value))
|
||||
{
|
||||
string_p = ecma_get_string_from_value (exception_value);
|
||||
ecma_ref_ecma_string (string_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
exception_value = ecma_op_to_string (exception_value);
|
||||
string_p = ecma_get_string_from_value (exception_value);
|
||||
}
|
||||
|
||||
ECMA_STRING_TO_UTF8_STRING (string_p, string_data_p, string_size);
|
||||
|
||||
bool result = jerry_debugger_send_string (JERRY_DEBUGGER_EXCEPTION_STR,
|
||||
string_data_p,
|
||||
string_size);
|
||||
|
||||
ECMA_FINALIZE_UTF8_STRING (string_data_p, string_size);
|
||||
|
||||
ecma_deref_ecma_string (string_p);
|
||||
return result;
|
||||
} /* jerry_debugger_send_exception_string */
|
||||
|
||||
#endif /* JERRY_DEBUGGER */
|
||||
|
||||
@ -102,12 +102,14 @@ typedef enum
|
||||
JERRY_DEBUGGER_MEMSTATS_RECEIVE = 14, /**< memstats sent to the client*/
|
||||
JERRY_DEBUGGER_BREAKPOINT_HIT = 15, /**< notify breakpoint hit */
|
||||
JERRY_DEBUGGER_EXCEPTION_HIT = 16, /**< notify exception hit */
|
||||
JERRY_DEBUGGER_BACKTRACE = 17, /**< backtrace data */
|
||||
JERRY_DEBUGGER_BACKTRACE_END = 18, /**< last backtrace data */
|
||||
JERRY_DEBUGGER_EVAL_RESULT = 19, /**< eval result */
|
||||
JERRY_DEBUGGER_EVAL_RESULT_END = 20, /**< last part of eval result */
|
||||
JERRY_DEBUGGER_EVAL_ERROR = 21, /**< eval result when an error is occured */
|
||||
JERRY_DEBUGGER_EVAL_ERROR_END = 22, /**< last part of eval result when an error is occured */
|
||||
JERRY_DEBUGGER_EXCEPTION_STR = 17, /**< exception string fragment */
|
||||
JERRY_DEBUGGER_EXCEPTION_STR_END = 18, /**< exception string last fragment */
|
||||
JERRY_DEBUGGER_BACKTRACE = 19, /**< backtrace data */
|
||||
JERRY_DEBUGGER_BACKTRACE_END = 20, /**< last backtrace data */
|
||||
JERRY_DEBUGGER_EVAL_RESULT = 21, /**< eval result */
|
||||
JERRY_DEBUGGER_EVAL_RESULT_END = 22, /**< last part of eval result */
|
||||
JERRY_DEBUGGER_EVAL_ERROR = 23, /**< eval result when an error is occured */
|
||||
JERRY_DEBUGGER_EVAL_ERROR_END = 24, /**< last part of eval result when an error is occured */
|
||||
|
||||
/* Messages sent by the client to server. */
|
||||
|
||||
@ -316,6 +318,7 @@ bool jerry_debugger_send_string (uint8_t message_type, const uint8_t *string_p,
|
||||
bool jerry_debugger_send_function_cp (jerry_debugger_header_type_t type, ecma_compiled_code_t *compiled_code_p);
|
||||
bool jerry_debugger_send_parse_function (uint32_t line, uint32_t column);
|
||||
void jerry_debugger_send_memstats (void);
|
||||
bool jerry_debugger_send_exception_string (ecma_value_t exception_value);
|
||||
|
||||
#endif /* JERRY_DEBUGGER */
|
||||
|
||||
|
||||
@ -2550,7 +2550,10 @@ 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)))
|
||||
{
|
||||
jerry_debugger_breakpoint_hit (JERRY_DEBUGGER_EXCEPTION_HIT);
|
||||
if (jerry_debugger_send_exception_string (result))
|
||||
{
|
||||
jerry_debugger_breakpoint_hit (JERRY_DEBUGGER_EXCEPTION_HIT);
|
||||
}
|
||||
}
|
||||
#endif /* JERRY_DEBUGGER */
|
||||
}
|
||||
|
||||
@ -51,12 +51,14 @@ var JERRY_DEBUGGER_RELEASE_BYTE_CODE_CP = 13;
|
||||
var JERRY_DEBUGGER_MEMSTATS_RECEIVE = 14;
|
||||
var JERRY_DEBUGGER_BREAKPOINT_HIT = 15;
|
||||
var JERRY_DEBUGGER_EXCEPTION_HIT = 16;
|
||||
var JERRY_DEBUGGER_BACKTRACE = 17;
|
||||
var JERRY_DEBUGGER_BACKTRACE_END = 18;
|
||||
var JERRY_DEBUGGER_EVAL_RESULT = 19;
|
||||
var JERRY_DEBUGGER_EVAL_RESULT_END = 20;
|
||||
var JERRY_DEBUGGER_EVAL_ERROR = 21;
|
||||
var JERRY_DEBUGGER_EVAL_ERROR_END = 22;
|
||||
var JERRY_DEBUGGER_EXCEPTION_STR = 17;
|
||||
var JERRY_DEBUGGER_EXCEPTION_STR_END = 18;
|
||||
var JERRY_DEBUGGER_BACKTRACE = 19;
|
||||
var JERRY_DEBUGGER_BACKTRACE_END = 20;
|
||||
var JERRY_DEBUGGER_EVAL_RESULT = 21;
|
||||
var JERRY_DEBUGGER_EVAL_RESULT_END = 22;
|
||||
var JERRY_DEBUGGER_EVAL_ERROR = 23;
|
||||
var JERRY_DEBUGGER_EVAL_ERROR_END = 24;
|
||||
|
||||
var JERRY_DEBUGGER_FREE_BYTE_CODE_CP = 1;
|
||||
var JERRY_DEBUGGER_UPDATE_BREAKPOINT = 2;
|
||||
@ -113,6 +115,7 @@ function DebuggerClient(address)
|
||||
var pendingBreakpoints = [ ];
|
||||
var backtraceFrame = 0;
|
||||
var evalResult = null;
|
||||
var exceptionData = null;
|
||||
|
||||
function assert(expr)
|
||||
{
|
||||
@ -830,6 +833,11 @@ function DebuggerClient(address)
|
||||
if (message[0] == JERRY_DEBUGGER_EXCEPTION_HIT)
|
||||
{
|
||||
appendLog("Exception throw detected (to disable automatic stop type exception 0)");
|
||||
if (exceptionData)
|
||||
{
|
||||
appendLog("Exception hint: " + cesu8ToString(exceptionData));
|
||||
exceptionData = null;
|
||||
}
|
||||
}
|
||||
|
||||
lastBreakpointHit = breakpoint;
|
||||
@ -847,6 +855,13 @@ function DebuggerClient(address)
|
||||
return;
|
||||
}
|
||||
|
||||
case JERRY_DEBUGGER_EXCEPTION_STR:
|
||||
case JERRY_DEBUGGER_EXCEPTION_STR_END:
|
||||
{
|
||||
exceptionData = concatUint8Arrays(exceptionData, message);
|
||||
return;
|
||||
}
|
||||
|
||||
case JERRY_DEBUGGER_BACKTRACE:
|
||||
case JERRY_DEBUGGER_BACKTRACE_END:
|
||||
{
|
||||
|
||||
@ -42,12 +42,14 @@ JERRY_DEBUGGER_RELEASE_BYTE_CODE_CP = 13
|
||||
JERRY_DEBUGGER_MEMSTATS_RECEIVE = 14
|
||||
JERRY_DEBUGGER_BREAKPOINT_HIT = 15
|
||||
JERRY_DEBUGGER_EXCEPTION_HIT = 16
|
||||
JERRY_DEBUGGER_BACKTRACE = 17
|
||||
JERRY_DEBUGGER_BACKTRACE_END = 18
|
||||
JERRY_DEBUGGER_EVAL_RESULT = 19
|
||||
JERRY_DEBUGGER_EVAL_RESULT_END = 20
|
||||
JERRY_DEBUGGER_EVAL_ERROR = 21
|
||||
JERRY_DEBUGGER_EVAL_ERROR_END = 22
|
||||
JERRY_DEBUGGER_EXCEPTION_STR = 17
|
||||
JERRY_DEBUGGER_EXCEPTION_STR_END = 18
|
||||
JERRY_DEBUGGER_BACKTRACE = 19
|
||||
JERRY_DEBUGGER_BACKTRACE_END = 20
|
||||
JERRY_DEBUGGER_EVAL_RESULT = 21
|
||||
JERRY_DEBUGGER_EVAL_RESULT_END = 22
|
||||
JERRY_DEBUGGER_EVAL_ERROR = 23
|
||||
JERRY_DEBUGGER_EVAL_ERROR_END = 24
|
||||
|
||||
|
||||
# Messages sent by the client to server.
|
||||
@ -813,6 +815,7 @@ def main():
|
||||
args = arguments_parse()
|
||||
|
||||
debugger = JerryDebugger(args.address)
|
||||
exception_string = ""
|
||||
|
||||
non_interactive = args.non_interactive
|
||||
|
||||
@ -865,6 +868,9 @@ def main():
|
||||
|
||||
if buffer_type == JERRY_DEBUGGER_EXCEPTION_HIT:
|
||||
print("Exception throw detected (to disable automatic stop type exception 0)")
|
||||
if exception_string:
|
||||
print("Exception hint: %s" % (exception_string))
|
||||
exception_string = ""
|
||||
|
||||
if breakpoint[1]:
|
||||
breakpoint_info = "at"
|
||||
@ -880,6 +886,12 @@ def main():
|
||||
if prompt.quit:
|
||||
break
|
||||
|
||||
elif buffer_type == JERRY_DEBUGGER_EXCEPTION_STR:
|
||||
exception_string += data[3:]
|
||||
|
||||
elif buffer_type == JERRY_DEBUGGER_EXCEPTION_STR_END:
|
||||
exception_string += data[3:]
|
||||
|
||||
elif buffer_type in [JERRY_DEBUGGER_BACKTRACE, JERRY_DEBUGGER_BACKTRACE_END]:
|
||||
frame_index = 0
|
||||
|
||||
|
||||
@ -1,2 +1,5 @@
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
quit
|
||||
|
||||
@ -2,5 +2,18 @@ Connecting to: localhost:5001
|
||||
Stopped at tests/debugger/do_exception.js:15
|
||||
(jerry-debugger) c
|
||||
Exception throw detected (to disable automatic stop type exception 0)
|
||||
Stopped at tests/debugger/do_exception.js:19 (in foo() at line:17, col:1)
|
||||
Exception hint: TypeError
|
||||
Stopped around tests/debugger/do_exception.js:19 (in foo() at line:17, col:1)
|
||||
(jerry-debugger) c
|
||||
Exception throw detected (to disable automatic stop type exception 0)
|
||||
Exception hint: ReferenceError
|
||||
Stopped at tests/debugger/do_exception.js:24 (in foo() at line:17, col:1)
|
||||
(jerry-debugger) c
|
||||
Exception throw detected (to disable automatic stop type exception 0)
|
||||
Exception hint: 456
|
||||
Stopped at tests/debugger/do_exception.js:29 (in foo() at line:17, col:1)
|
||||
(jerry-debugger) c
|
||||
Exception throw detected (to disable automatic stop type exception 0)
|
||||
Exception hint: RangeError: Bad range!
|
||||
Stopped around tests/debugger/do_exception.js:34 (in foo() at line:17, col:1)
|
||||
(jerry-debugger) quit
|
||||
|
||||
@ -15,11 +15,25 @@
|
||||
print("exception handler configuration test")
|
||||
|
||||
function foo() {
|
||||
try {
|
||||
b = a / c;
|
||||
} catch (e) {
|
||||
print(e); // pass exception object to err handler
|
||||
}
|
||||
try {
|
||||
undefined();
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
try {
|
||||
xxx();
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
try {
|
||||
throw 456;
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
try {
|
||||
throw new RangeError("Bad range!");
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
|
||||
foo()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user