diff --git a/jerry-core/debugger/debugger.c b/jerry-core/debugger/debugger.c index f753d0101..0a128b31d 100644 --- a/jerry-core/debugger/debugger.c +++ b/jerry-core/debugger/debugger.c @@ -155,7 +155,7 @@ jerry_debugger_send_eval (const lit_utf8_byte_t *eval_string_p, /**< evaluated s { if (eval_string_p[0] != JERRY_DEBUGGER_EVAL_EVAL) { - JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_THROW_ERROR_FLAG); + JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_EXCEPTION_THROWN); JERRY_CONTEXT (error_value) = result; /* Stop where the error is caught. */ @@ -709,7 +709,7 @@ jerry_debugger_breakpoint_hit (uint8_t message_type) /**< message type */ return; } - JERRY_DEBUGGER_UPDATE_FLAGS (JERRY_DEBUGGER_BREAKPOINT_MODE, JERRY_DEBUGGER_THROW_ERROR_FLAG); + JERRY_DEBUGGER_UPDATE_FLAGS (JERRY_DEBUGGER_BREAKPOINT_MODE, JERRY_DEBUGGER_VM_EXCEPTION_THROWN); jerry_debugger_uint8_data_t *uint8_data = NULL; diff --git a/jerry-core/debugger/debugger.h b/jerry-core/debugger/debugger.h index 0c08b126b..94d701423 100644 --- a/jerry-core/debugger/debugger.h +++ b/jerry-core/debugger/debugger.h @@ -98,13 +98,13 @@ typedef enum JERRY_DEBUGGER_BREAKPOINT_MODE = 1u << 1, /**< debugger waiting at a breakpoint */ JERRY_DEBUGGER_VM_STOP = 1u << 2, /**< stop at the next breakpoint even if disabled */ JERRY_DEBUGGER_VM_IGNORE = 1u << 3, /**< ignore all breakpoints */ - JERRY_DEBUGGER_VM_IGNORE_EXCEPTION = 1u << 4, /**< debugger stop at an exception */ - JERRY_DEBUGGER_PARSER_WAIT = 1u << 5, /**< debugger should wait after parsing is completed */ - JERRY_DEBUGGER_PARSER_WAIT_MODE = 1u << 6, /**< debugger is waiting after parsing is completed */ - 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_VM_IGNORE_EXCEPTION = 1u << 4, /**< debugger doesn't stop at any exception */ + JERRY_DEBUGGER_VM_EXCEPTION_THROWN = 1u << 5, /**< no need to stop for this exception */ + JERRY_DEBUGGER_PARSER_WAIT = 1u << 6, /**< debugger should wait after parsing is completed */ + JERRY_DEBUGGER_PARSER_WAIT_MODE = 1u << 7, /**< debugger is waiting after parsing is completed */ + JERRY_DEBUGGER_CLIENT_SOURCE_MODE = 1u << 8, /**< debugger waiting for client code */ + JERRY_DEBUGGER_CLIENT_NO_SOURCE = 1u << 9, /**< debugger leaving the client source loop */ + JERRY_DEBUGGER_CONTEXT_RESET_MODE = 1u << 10, /**< debugger and engine reinitialization mode */ } jerry_debugger_flags_t; /** diff --git a/jerry-core/ecma/operations/ecma-function-object.c b/jerry-core/ecma/operations/ecma-function-object.c index 90e76103b..30e475837 100644 --- a/jerry-core/ecma/operations/ecma-function-object.c +++ b/jerry-core/ecma/operations/ecma-function-object.c @@ -566,6 +566,12 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */ JERRY_CONTEXT (error_value) = ecma_clear_error_reference (ret_value, true); ret_value = ECMA_VALUE_ERROR; } + else + { +#ifdef JERRY_DEBUGGER + JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_EXCEPTION_THROWN); +#endif /* JERRY_DEBUGGER */ + } } else { diff --git a/jerry-core/vm/vm.c b/jerry-core/vm/vm.c index f7b60e4a1..6755fb504 100644 --- a/jerry-core/vm/vm.c +++ b/jerry-core/vm/vm.c @@ -2472,6 +2472,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ PARSER_TRY_CONTEXT_STACK_ALLOCATION); stack_top_p -= PARSER_TRY_CONTEXT_STACK_ALLOCATION; result = ECMA_VALUE_ERROR; + +#ifdef JERRY_DEBUGGER + JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_EXCEPTION_THROWN); +#endif /* JERRY_DEBUGGER */ goto error; } case VM_CONTEXT_FINALLY_RETURN: @@ -2530,7 +2534,7 @@ 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) + if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_VM_EXCEPTION_THROWN) { result = ECMA_VALUE_ERROR; goto error; @@ -2557,7 +2561,7 @@ 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) + if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_VM_EXCEPTION_THROWN) { result = ECMA_VALUE_ERROR; goto error; @@ -2583,7 +2587,7 @@ 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) + if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_VM_EXCEPTION_THROWN) { result = ECMA_VALUE_ERROR; goto error; @@ -2725,7 +2729,7 @@ error: #ifdef JERRY_DEBUGGER const uint32_t dont_stop = (JERRY_DEBUGGER_VM_IGNORE_EXCEPTION | JERRY_DEBUGGER_VM_IGNORE - | JERRY_DEBUGGER_THROW_ERROR_FLAG); + | JERRY_DEBUGGER_VM_EXCEPTION_THROWN); if ((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED) && !(frame_ctx_p->bytecode_header_p->status_flags & CBC_CODE_FLAGS_DEBUGGER_IGNORE) @@ -2739,7 +2743,7 @@ error: { jerry_debugger_breakpoint_hit (JERRY_DEBUGGER_EXCEPTION_HIT); - if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_THROW_ERROR_FLAG) + if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_VM_EXCEPTION_THROWN) { ecma_free_value (current_error_value); } @@ -2747,6 +2751,8 @@ error: { JERRY_CONTEXT (error_value) = current_error_value; } + + JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_EXCEPTION_THROWN); } } #endif /* JERRY_DEBUGGER */ @@ -2786,6 +2792,10 @@ error: { JERRY_ASSERT (frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth == stack_top_p); +#ifdef JERRY_DEBUGGER + JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_EXCEPTION_THROWN); +#endif /* JERRY_DEBUGGER */ + byte_code_p = frame_ctx_p->byte_code_p; if (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_CATCH) diff --git a/tests/debugger/do_throw_adv.cmd b/tests/debugger/do_throw_adv.cmd new file mode 100644 index 000000000..227f4849e --- /dev/null +++ b/tests/debugger/do_throw_adv.cmd @@ -0,0 +1,11 @@ +c +s +c +c +c +c +c +c +c +c +c diff --git a/tests/debugger/do_throw_adv.expected b/tests/debugger/do_throw_adv.expected new file mode 100644 index 000000000..9884f434a --- /dev/null +++ b/tests/debugger/do_throw_adv.expected @@ -0,0 +1,42 @@ +Connecting to: localhost:5001 +Stopped at tests/debugger/do_throw_adv.js:15 +(jerry-debugger) c +Exception throw detected (to disable automatic stop type exception 0) +Exception hint: 2 +Stopped at tests/debugger/do_throw_adv.js:18 (in f() at line:17, col:1) +(jerry-debugger) s +Stopped at tests/debugger/do_throw_adv.js:32 +(jerry-debugger) c +Exception throw detected (to disable automatic stop type exception 0) +Exception hint: 4 +Stopped at tests/debugger/do_throw_adv.js:18 (in f() at line:17, col:1) +(jerry-debugger) c +Exception throw detected (to disable automatic stop type exception 0) +Exception hint: Catch again +Stopped at tests/debugger/do_throw_adv.js:41 +(jerry-debugger) c +Exception throw detected (to disable automatic stop type exception 0) +Exception hint: 7 +Stopped at tests/debugger/do_throw_adv.js:18 (in f() at line:17, col:1) +(jerry-debugger) c +Exception throw detected (to disable automatic stop type exception 0) +Exception hint: 10 +Stopped at tests/debugger/do_throw_adv.js:18 (in f() at line:17, col:1) +(jerry-debugger) c +Exception throw detected (to disable automatic stop type exception 0) +Exception hint: Replace the other error +Stopped at tests/debugger/do_throw_adv.js:63 +(jerry-debugger) c +Exception throw detected (to disable automatic stop type exception 0) +Exception hint: 13 +Stopped at tests/debugger/do_throw_adv.js:18 (in f() at line:17, col:1) +(jerry-debugger) c +Exception throw detected (to disable automatic stop type exception 0) +Exception hint: Should be caught +Stopped at tests/debugger/do_throw_adv.js:76 +(jerry-debugger) c +Exception throw detected (to disable automatic stop type exception 0) +Exception hint: 16 +Stopped at tests/debugger/do_throw_adv.js:18 (in f() at line:17, col:1) +(jerry-debugger) c +err: Script Error: 16 diff --git a/tests/debugger/do_throw_adv.js b/tests/debugger/do_throw_adv.js new file mode 100644 index 000000000..38ca1af12 --- /dev/null +++ b/tests/debugger/do_throw_adv.js @@ -0,0 +1,81 @@ +// 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. + +var a = 1; + +function f() { + throw ++a; +} + +function g() { + f(); +} + +function h() { + g(); +} + +try { + h(); +} catch (e) { + ++a; +} + +try { + h(); +} catch (e) { + ++a; + + try { + throw "Catch again"; + } catch (e) { + ++a; + } +} + +try { + try { + h(); + } finally { + ++a; + } + ++a; /* Should not happen. */ +} catch (e) { + ++a; +} + +try { + try { + h(); + } finally { + ++a; + throw "Replace the other error"; + } +} catch (e) { + ++a; +} + +try { + break_try_label: try { + h(); + } finally { + ++a; + break break_try_label; + } + throw "Should be caught"; +} catch (e) { + ++a; +} + +h();