Skip to content

Commit 10399e3

Browse files
committed
Print exception hint in the debugger client when an exception is thrown.
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg [email protected]
1 parent eb2af2d commit 10399e3

File tree

8 files changed

+237
-25
lines changed

8 files changed

+237
-25
lines changed

jerry-core/debugger/jerry-debugger.c

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@
1616
#ifdef JERRY_DEBUGGER
1717

1818
#include "byte-code.h"
19+
#include "ecma-builtin-helpers.h"
1920
#include "ecma-conversion.h"
2021
#include "ecma-eval.h"
2122
#include "ecma-objects.h"
2223
#include "jcontext.h"
2324
#include "jerry-debugger.h"
2425
#include "jerryscript-port.h"
26+
#include "lit-char-helpers.h"
2527

2628
/**
2729
* Type cast the debugger send buffer into a specific type.
@@ -669,4 +671,151 @@ jerry_debugger_send_parse_function (uint32_t line, /**< line */
669671
return jerry_debugger_send (sizeof (jerry_debugger_send_parse_function_t));
670672
} /* jerry_debugger_send_parse_function */
671673

674+
/**
675+
* Converts an standard error into a string.
676+
*
677+
* @return standard error string
678+
*/
679+
static ecma_string_t *
680+
jerry_debugger_exception_object_to_string (ecma_value_t object_value)
681+
{
682+
ecma_object_t *object_p = ecma_get_object_from_value (object_value);
683+
684+
ecma_object_t *prototype_p = ecma_get_object_prototype (object_p);
685+
686+
if (prototype_p == NULL
687+
|| ecma_get_object_type (prototype_p) != ECMA_OBJECT_TYPE_GENERAL
688+
|| !ecma_get_object_is_builtin (prototype_p))
689+
{
690+
return NULL;
691+
}
692+
693+
lit_magic_string_id_t string_id;
694+
695+
switch (((ecma_extended_object_t *) prototype_p)->u.built_in.id)
696+
{
697+
#ifndef CONFIG_DISABLE_ERROR_BUILTINS
698+
case ECMA_BUILTIN_ID_EVAL_ERROR_PROTOTYPE:
699+
{
700+
string_id = LIT_MAGIC_STRING_EVAL_ERROR_UL;
701+
break;
702+
}
703+
case ECMA_BUILTIN_ID_RANGE_ERROR_PROTOTYPE:
704+
{
705+
string_id = LIT_MAGIC_STRING_RANGE_ERROR_UL;
706+
break;
707+
}
708+
case ECMA_BUILTIN_ID_REFERENCE_ERROR_PROTOTYPE:
709+
{
710+
string_id = LIT_MAGIC_STRING_REFERENCE_ERROR_UL;
711+
break;
712+
}
713+
case ECMA_BUILTIN_ID_SYNTAX_ERROR_PROTOTYPE:
714+
{
715+
string_id = LIT_MAGIC_STRING_SYNTAX_ERROR_UL;
716+
break;
717+
}
718+
case ECMA_BUILTIN_ID_TYPE_ERROR_PROTOTYPE:
719+
{
720+
string_id = LIT_MAGIC_STRING_TYPE_ERROR_UL;
721+
break;
722+
}
723+
case ECMA_BUILTIN_ID_URI_ERROR_PROTOTYPE:
724+
{
725+
string_id = LIT_MAGIC_STRING_URI_ERROR_UL;
726+
break;
727+
}
728+
#endif /* !CONFIG_DISABLE_ERROR_BUILTINS */
729+
case ECMA_BUILTIN_ID_ERROR_PROTOTYPE:
730+
{
731+
string_id = LIT_MAGIC_STRING_ERROR_UL;
732+
break;
733+
}
734+
default:
735+
{
736+
return NULL;
737+
}
738+
}
739+
740+
lit_utf8_size_t size = lit_get_magic_string_size (string_id);
741+
JERRY_ASSERT (size <= 14);
742+
743+
lit_utf8_byte_t data[16];
744+
memcpy (data, lit_get_magic_string_utf8 (string_id), size);
745+
746+
ecma_string_t message_string;
747+
ecma_init_ecma_magic_string (&message_string, LIT_MAGIC_STRING_MESSAGE);
748+
749+
ecma_property_t *property_p;
750+
property_p = ecma_find_named_property (ecma_get_object_from_value (object_value),
751+
&message_string);
752+
753+
if (property_p == NULL
754+
|| ECMA_PROPERTY_GET_TYPE (*property_p) != ECMA_PROPERTY_TYPE_NAMEDDATA)
755+
{
756+
return ecma_new_ecma_string_from_utf8 (data, size);
757+
}
758+
759+
ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
760+
761+
if (!ecma_is_value_string (prop_value_p->value))
762+
{
763+
return ecma_new_ecma_string_from_utf8 (data, size);
764+
}
765+
766+
data[size] = LIT_CHAR_COLON;
767+
data[size + 1] = LIT_CHAR_SP;
768+
769+
ecma_string_t *type_string_p = ecma_new_ecma_string_from_utf8 (data, size + 2);
770+
771+
ecma_string_t *string_p = ecma_concat_ecma_strings (type_string_p,
772+
ecma_get_string_from_value (prop_value_p->value));
773+
ecma_deref_ecma_string (type_string_p);
774+
return string_p;
775+
} /* jerry_debugger_exception_object_to_string */
776+
777+
/**
778+
* Send string representation of exception to the client.
779+
*
780+
* @return true - if the data sent successfully to the debugger client,
781+
* false - otherwise
782+
*/
783+
bool
784+
jerry_debugger_send_exception_string (ecma_value_t exception_value)
785+
{
786+
ecma_string_t *string_p = NULL;
787+
788+
if (ecma_is_value_object (exception_value))
789+
{
790+
ecma_value_t object_value = ecma_get_value_from_error_value (exception_value);
791+
792+
string_p = jerry_debugger_exception_object_to_string (object_value);
793+
if (string_p == NULL)
794+
{
795+
string_p = ecma_get_string_from_value (ecma_builtin_helper_object_to_string (object_value));
796+
}
797+
}
798+
else if (ecma_is_value_string (exception_value))
799+
{
800+
string_p = ecma_get_string_from_value (exception_value);
801+
ecma_ref_ecma_string (string_p);
802+
}
803+
else
804+
{
805+
exception_value = ecma_op_to_string (exception_value);
806+
string_p = ecma_get_string_from_value (exception_value);
807+
}
808+
809+
ECMA_STRING_TO_UTF8_STRING (string_p, string_data_p, string_size);
810+
811+
bool result = jerry_debugger_send_string (JERRY_DEBUGGER_EXCEPTION_STR,
812+
string_data_p,
813+
string_size);
814+
815+
ECMA_FINALIZE_UTF8_STRING (string_data_p, string_size);
816+
817+
ecma_deref_ecma_string (string_p);
818+
return result;
819+
} /* jerry_debugger_send_exception_string */
820+
672821
#endif /* JERRY_DEBUGGER */

jerry-core/debugger/jerry-debugger.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,14 @@ typedef enum
101101
JERRY_DEBUGGER_RELEASE_BYTE_CODE_CP = 13, /**< invalidate byte code compressed pointer */
102102
JERRY_DEBUGGER_BREAKPOINT_HIT = 14, /**< notify breakpoint hit */
103103
JERRY_DEBUGGER_EXCEPTION_HIT = 15, /**< notify exception hit */
104-
JERRY_DEBUGGER_BACKTRACE = 16, /**< backtrace data */
105-
JERRY_DEBUGGER_BACKTRACE_END = 17, /**< last backtrace data */
106-
JERRY_DEBUGGER_EVAL_RESULT = 18, /**< eval result */
107-
JERRY_DEBUGGER_EVAL_RESULT_END = 19, /**< last part of eval result */
108-
JERRY_DEBUGGER_EVAL_ERROR = 20, /**< eval result when an error is occured */
109-
JERRY_DEBUGGER_EVAL_ERROR_END = 21, /**< last part of eval result when an error is occured */
104+
JERRY_DEBUGGER_EXCEPTION_STR = 16, /**< exception string fragment */
105+
JERRY_DEBUGGER_EXCEPTION_STR_END = 17, /**< exception string last fragment */
106+
JERRY_DEBUGGER_BACKTRACE = 18, /**< backtrace data */
107+
JERRY_DEBUGGER_BACKTRACE_END = 19, /**< last backtrace data */
108+
JERRY_DEBUGGER_EVAL_RESULT = 20, /**< eval result */
109+
JERRY_DEBUGGER_EVAL_RESULT_END = 21, /**< last part of eval result */
110+
JERRY_DEBUGGER_EVAL_ERROR = 22, /**< eval result when an error is occured */
111+
JERRY_DEBUGGER_EVAL_ERROR_END = 23, /**< last part of eval result when an error is occured */
110112

111113
/* Messages sent by the client to server. */
112114

@@ -299,6 +301,7 @@ void jerry_debugger_send_data (jerry_debugger_header_type_t type, const void *da
299301
bool jerry_debugger_send_string (uint8_t message_type, const uint8_t *string_p, size_t string_length);
300302
bool jerry_debugger_send_function_cp (jerry_debugger_header_type_t type, ecma_compiled_code_t *compiled_code_p);
301303
bool jerry_debugger_send_parse_function (uint32_t line, uint32_t column);
304+
bool jerry_debugger_send_exception_string (ecma_value_t exception_value);
302305

303306
#endif /* JERRY_DEBUGGER */
304307

jerry-core/vm/vm.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2550,7 +2550,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
25502550
&& !(frame_ctx_p->bytecode_header_p->status_flags & CBC_CODE_FLAGS_DEBUGGER_IGNORE)
25512551
&& !(JERRY_CONTEXT (debugger_flags) & (JERRY_DEBUGGER_VM_IGNORE_EXCEPTION | JERRY_DEBUGGER_VM_IGNORE)))
25522552
{
2553-
jerry_debugger_breakpoint_hit (JERRY_DEBUGGER_EXCEPTION_HIT);
2553+
if (jerry_debugger_send_exception_string (result))
2554+
{
2555+
jerry_debugger_breakpoint_hit (JERRY_DEBUGGER_EXCEPTION_HIT);
2556+
}
25542557
}
25552558
#endif /* JERRY_DEBUGGER */
25562559
}

jerry-debugger/jerry-client-ws.html

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,14 @@ <h2>JerryScript HTML (WebSocket) Debugger Client</h2>
5050
var JERRY_DEBUGGER_RELEASE_BYTE_CODE_CP = 13;
5151
var JERRY_DEBUGGER_BREAKPOINT_HIT = 14;
5252
var JERRY_DEBUGGER_EXCEPTION_HIT = 15;
53-
var JERRY_DEBUGGER_BACKTRACE = 16;
54-
var JERRY_DEBUGGER_BACKTRACE_END = 17;
55-
var JERRY_DEBUGGER_EVAL_RESULT = 18;
56-
var JERRY_DEBUGGER_EVAL_RESULT_END = 19;
57-
var JERRY_DEBUGGER_EVAL_ERROR = 20;
58-
var JERRY_DEBUGGER_EVAL_ERROR_END = 21;
53+
var JERRY_DEBUGGER_EXCEPTION_STR = 16;
54+
var JERRY_DEBUGGER_EXCEPTION_STR_END = 17;
55+
var JERRY_DEBUGGER_BACKTRACE = 18;
56+
var JERRY_DEBUGGER_BACKTRACE_END = 19;
57+
var JERRY_DEBUGGER_EVAL_RESULT = 20;
58+
var JERRY_DEBUGGER_EVAL_RESULT_END = 21;
59+
var JERRY_DEBUGGER_EVAL_ERROR = 22;
60+
var JERRY_DEBUGGER_EVAL_ERROR_END = 23;
5961

6062
var JERRY_DEBUGGER_FREE_BYTE_CODE_CP = 1;
6163
var JERRY_DEBUGGER_UPDATE_BREAKPOINT = 2;
@@ -111,6 +113,7 @@ <h2>JerryScript HTML (WebSocket) Debugger Client</h2>
111113
var pendingBreakpoints = [ ];
112114
var backtraceFrame = 0;
113115
var evalResult = null;
116+
var exceptionData = null;
114117

115118
function assert(expr)
116119
{
@@ -816,6 +819,11 @@ <h2>JerryScript HTML (WebSocket) Debugger Client</h2>
816819
if (message[0] == JERRY_DEBUGGER_EXCEPTION_HIT)
817820
{
818821
appendLog("Exception throw detected (to disable automatic stop type exception 0)");
822+
if (exceptionData)
823+
{
824+
appendLog("Exception hint: " + cesu8ToString(exceptionData));
825+
exceptionData = null;
826+
}
819827
}
820828

821829
lastBreakpointHit = breakpoint;
@@ -833,6 +841,13 @@ <h2>JerryScript HTML (WebSocket) Debugger Client</h2>
833841
return;
834842
}
835843

844+
case JERRY_DEBUGGER_EXCEPTION_STR:
845+
case JERRY_DEBUGGER_EXCEPTION_STR_END:
846+
{
847+
exceptionData = concatUint8Arrays(exceptionData, message);
848+
return;
849+
}
850+
836851
case JERRY_DEBUGGER_BACKTRACE:
837852
case JERRY_DEBUGGER_BACKTRACE_END:
838853
{

jerry-debugger/jerry-client-ws.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,14 @@
4141
JERRY_DEBUGGER_RELEASE_BYTE_CODE_CP = 13
4242
JERRY_DEBUGGER_BREAKPOINT_HIT = 14
4343
JERRY_DEBUGGER_EXCEPTION_HIT = 15
44-
JERRY_DEBUGGER_BACKTRACE = 16
45-
JERRY_DEBUGGER_BACKTRACE_END = 17
46-
JERRY_DEBUGGER_EVAL_RESULT = 18
47-
JERRY_DEBUGGER_EVAL_RESULT_END = 19
48-
JERRY_DEBUGGER_EVAL_ERROR = 20
49-
JERRY_DEBUGGER_EVAL_ERROR_END = 21
44+
JERRY_DEBUGGER_EXCEPTION_STR = 16
45+
JERRY_DEBUGGER_EXCEPTION_STR_END = 17
46+
JERRY_DEBUGGER_BACKTRACE = 18
47+
JERRY_DEBUGGER_BACKTRACE_END = 19
48+
JERRY_DEBUGGER_EVAL_RESULT = 20
49+
JERRY_DEBUGGER_EVAL_RESULT_END = 21
50+
JERRY_DEBUGGER_EVAL_ERROR = 22
51+
JERRY_DEBUGGER_EVAL_ERROR_END = 23
5052

5153

5254
# Messages sent by the client to server.
@@ -805,6 +807,7 @@ def main():
805807
args = arguments_parse()
806808

807809
debugger = JerryDebugger(args.address)
810+
exception_string = ""
808811

809812
non_interactive = args.non_interactive
810813

@@ -857,6 +860,9 @@ def main():
857860

858861
if buffer_type == JERRY_DEBUGGER_EXCEPTION_HIT:
859862
print("Exception throw detected (to disable automatic stop type exception 0)")
863+
if exception_string:
864+
print("Exception hint: %s" % (exception_string))
865+
exception_string = ""
860866

861867
if breakpoint[1]:
862868
breakpoint_info = "at"
@@ -872,6 +878,12 @@ def main():
872878
if prompt.quit:
873879
break
874880

881+
elif buffer_type == JERRY_DEBUGGER_EXCEPTION_STR:
882+
exception_string += data[3:]
883+
884+
elif buffer_type == JERRY_DEBUGGER_EXCEPTION_STR_END:
885+
exception_string += data[3:]
886+
875887
elif buffer_type in [JERRY_DEBUGGER_BACKTRACE, JERRY_DEBUGGER_BACKTRACE_END]:
876888
frame_index = 0
877889

tests/debugger/do_exception.cmd

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
c
2+
c
3+
c
4+
c
25
quit

tests/debugger/do_exception.expected

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,18 @@ Connecting to: localhost:5001
22
Stopped at tests/debugger/do_exception.js:15
33
(jerry-debugger) c
44
Exception throw detected (to disable automatic stop type exception 0)
5-
Stopped at tests/debugger/do_exception.js:19 (in foo() at line:17, col:1)
5+
Exception hint: TypeError
6+
Stopped around tests/debugger/do_exception.js:19 (in foo() at line:17, col:1)
7+
(jerry-debugger) c
8+
Exception throw detected (to disable automatic stop type exception 0)
9+
Exception hint: ReferenceError
10+
Stopped at tests/debugger/do_exception.js:24 (in foo() at line:17, col:1)
11+
(jerry-debugger) c
12+
Exception throw detected (to disable automatic stop type exception 0)
13+
Exception hint: 456
14+
Stopped at tests/debugger/do_exception.js:29 (in foo() at line:17, col:1)
15+
(jerry-debugger) c
16+
Exception throw detected (to disable automatic stop type exception 0)
17+
Exception hint: RangeError: Bad range!
18+
Stopped around tests/debugger/do_exception.js:34 (in foo() at line:17, col:1)
619
(jerry-debugger) quit

tests/debugger/do_exception.js

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,25 @@
1515
print("exception handler configuration test")
1616

1717
function foo() {
18-
try {
19-
b = a / c;
20-
} catch (e) {
21-
print(e); // pass exception object to err handler
22-
}
18+
try {
19+
undefined();
20+
} catch (e) {
21+
}
22+
23+
try {
24+
xxx();
25+
} catch (e) {
26+
}
27+
28+
try {
29+
throw 456;
30+
} catch (e) {
31+
}
32+
33+
try {
34+
throw new RangeError("Bad range!");
35+
} catch (e) {
36+
}
2337
}
2438

2539
foo()

0 commit comments

Comments
 (0)